external/boringssl: Sync to 3743aafdacff2f7b083615a043a37101f740fa53.

This includes the following changes:

https://boringssl.googlesource.com/boringssl/+log/2fb729d4f36beaf263ad85e24a790b571652679c..3743aafdacff2f7b083615a043a37101f740fa53

* Add SSL_CIPHER_get_protocol_id.
* Add TrustTokenV2.
* Add X509_get_pathlen and X509_REVOKED_get0_extensions.
* Add some accommodations for FreeRDP
* Require non-NULL store in X509_STORE_CTX_init.
Update-Note: X509_STORE_CTX_init will now fail when the store is NULL,
rather than report success, only to crash later in X509_verify_cert.
Breakage should thus be limited to code which was passing in a NULL
store but never used the resulting X509_STORE_CTX.
* Const-correct X509V3_CONF_METHOD.
Update-Note: External definitions of X509V3_CONF_METHOD will need fix
the types of their functions. There should not be any of these (probably
hide this struct), but if there are, this aligns with upstream OpenSSL.
* Avoid unions in X509_NAME logic.
* Bump OPENSSL_VERSION_NUMBER to 1.1.1.
Update-Note: Some OPENSSL_VERSION_NUMBER/OPENSSL_IS_BORINGSSL checks may
need to be updated. Hopefully even more can go away.
* Document more of x509.h.
* Fix potential leak in bssl::Array::Shrink.
* Remove ASN1_STRING_length_set.
Update-Note: Use ASN1_STRING_set instead, though this function appears
to be unused.
* Revert "Check AlgorithmIdentifier parameters for RSA and ECDSA signatures."
* Implement PSK variants of HPKE setup functions.
* acvp: support working with files.
* Document a few more functions in x509.h.
* Add subject key ID and authority key ID accessors.
* Remove sxnet and pkey_usage_period extensions.
Update-Note: Parsers for these two extensions are removed. Parsing the
types directly or passing NID_sxnet and NID_pkey_usage_period into
X509V3_get_d2i, or *_get_ext_d2i will no longer work.
* Const-correct various X509 functions.
* Make X509_set_not{Before,After} functions rather than macros.
* Add X509_get0_uids from OpenSSL 1.1.0.
* Bound RSA and DSA key sizes better.
Update-Note: Some invalid or overly large RSA and DSA keys may
previously have been accepted that are now rejected at parse time. For
public keys, this only moves the error from verification to parsing. In
some private key cases, we would previously allow signing with those
keys, but the resulting signatures would not be accepted by BoringSSL
anyway. This CL makes us behave more consistently.
* Add set1 versions of X509 timestamp setters.
* Consistently sort generated build files.
* delocate: use 64-bit GOT offsets in the large memory model.
* Update HPKE implementation and test vectors to draft-irtf-cfrg-hpke-05.
* Handle NULL arguments in some i2d_* functions.
* aarch64: support BTI and pointer authentication in assembly
* Support delegated credentials verison 06
* delocation: large memory model support.
* Enforce presence of ALPN when QUIC is in use.
Update-Note: If an SSL_QUIC_METHOD is set, connections will now fail if
ALPN is not negotiated. This new behavior can be detected by checking
if the value of BORINGSSL_API_VERSION is greater than 10.
* Fix the naming of alert error codes.
Update-Note: The renamed alerts will log slightly different strings, but
the constants used by external code are still there.
* Use golang.org/x/crypto in runner.
Update-Note: The tests now have a golang.org/x/crypto dependency. This
should be fetched transparently with Go modules. Monorepos with
different import path conventions may need to rewrite these imports.
* Disable ClientHello padding for QUIC.
* Add X509_SIG_get0 and X509_SIG_getm.
* Implement HPKE.
* Disallow TLS 1.3 compatibility mode in QUIC.
* Switch clang-format IncludeBlocks to Preserve.
* Fix unterminated clang-format off.
* Add line number to doc.go error messages.
* Kick the bots.
* Add a JSON output to generate_build_files.py.
* Add details of 20190808 FIPS certification.
* Link to ws2_32 more consistently.
* Allow explicitly-encoded X.509v1 versions for now.
* Opaquify PKCS8_PRIV_KEY_INFO.
Update-Note: Direct accesses of PKCS8_PRIV_KEY_INFO now need to use the
accessors. Code search suggests no one uses the fields. Even the
accessors are virtually unused (the one thing which uses it doesn't need
it).
* Implement i2d_PUBKEY and friends without crypto/asn1.
* Remove TRUST_TOKEN_experiment_v0.
Update-Note: This gets rid of TRUST_TOKEN_experiment_v0. Existing callers
should be updated to call TRUST_TOKEN_experiment_v1.
* Clarify in-place rules for low-level AES mode functions.
* acvp: add CMAC-AES support.
* acvp: add SP800-108 KDF support.
* Remove x509->name.
Update-Note: instead of x509->name, use X509_NAME_oneline and
X509_get_subject_name.
* Maybe build for AArch64 Windows.
* sha1-x86_64: fix CFI.
* Use |crypto_word_t| and |size_t| more consistently in ECC scalar recoding.
* Enable shaext path for sha1.
* Avoid relying on SSL_get_session's behavior during the handshake.
Update-Note: SSL_generate_key_block will now fail mid-handshake. It is
ambiguous which key block to use and, in some cases, we may not even be
able to compute the right key block.
* Add a -wait-for-debugger flag to runner.
* Add missing OPENSSL_EXPORT to X509_get_X509_PUBKEY.
* Const-correct various functions in crypto/asn1.
* Remove uneeded switch statement.
* Convert X.509 accessor macros to proper functions.
Update-Note: This should be compatible, but it is possible that someone,
e.g., passed in a bssl::UniquePtr<X509> to an accessor and relied on
operator->. Callers may also run afoul of const correctness. I mirrored
OpenSSL 1.1.1's consts, so it should at least be compatible with
third-party code.
* Remove X509_CINF_get_issuer and X509_CINF_get_extensions.
Update-Note: Two unused macros were removed. If there were uses, the
X509-level accessors can be used instead.
* Remove X509_get_signature_type.
Update-Note: If there are any calls to X509_get_signature_type, remove
them. It more-or-less always returned NID_undef.
* clang-format x509.h and run comment converter.
* Check AlgorithmIdentifier parameters for RSA and ECDSA signatures.
* Remove some unimplemented prototypes.
* Check the X.509 version when parsing.
Update-Note: The X.509 parser is now a bit stricter. This may break some
malformed certificates which were previously incorrectly accepted.
* Fix x509v3_cache_extensions error-handling.
Update-Note: The X.509 verifier now correctly rejects syntax errors in
important certificate extensions. This may break some malformed
certificates which were incorrectly accepted before.
* Work around Windows command-line limits in embed_test_data.go.
* Move crypto/x509 test data into its own directory.
* Test resumability of same, different, and default ticket keys.
* Fixes warning when redefining PATH_MAX when building with MINGW.
* Abstract fd operations better in tool.
* Use CMAKE_SIZEOF_VOID_P instead of CMAKE_CL_64
* Enforce the keyUsage extension in TLS 1.2 client certs.
Update-Note: Client certificates which do not support the
digitalSignature key usage will be rejected. They should either include
that bit or omit the keyUsage extension.
* Reword some comments.
* Add “Z Computation” KAT.
* acvptool: handle negative sizeConstraint.
* Let memory hooks override the size prefix.
* acvptool: go fmt
* Assert md_size > 0.
* Remove -enable-ed25519 compat hack.
* Add a |SSL_process_tls13_new_session_ticket|.
* Use ctr32 optimizations for AES_ctr128_encrypt.
* Test AES mode wrappers.
* Bump minimum CMake version.
* Modify how QUIC 0-RTT go/no-go decision is made.
* Remove RAND_set_urandom_fd.
Update-Note: RAND_set_urandom_fd no longer exists. This was only called
by Chromium, which now uses CRYPTO_pre_sandbox_init.
* Document that getrandom support must be consistent.
* Fix docs link for SSL_CTX_load_verify_locations
* Fix TRUST_TOKEN experiment_v1 SRR map.
* Add CRYPTO_pre_sandbox_init.
* Still query getauxval if reading /proc/cpuinfo fails.
* Add missing header to ec/wnaf.c
* Fix OPENSSL_TSAN typo.
* Fix p256-x86_64-table.h indentation.
* Enable avx2 implementation of sha1.
* Trim Z coordinates from the OPENSSL_SMALL P-256 tables.
* Use public multi-scalar mults in Trust Tokens where applicable.
* Use batched DLEQ proofs for Trust Token.
* Restrict when 0-RTT will be accepted in QUIC.
* Disable TLS 1.3 compatibility mode for QUIC.
* Use a 5-bit comb for some Trust Tokens multiplications.
* Use a (mostly) constant-time multi-scalar mult for Trust Tokens.
* Batch inversions in Trust Tokens.
* Rearrange the DLEQ logic slightly.
* Use token hash to encode private metadata for Trust Token Experiment V1.
* Introduce an EC_AFFINE abstraction.
* Make the fuzzer PRNG thread-safe.
* Disable fork-detect tests under TSAN.
* Introduce TRUST_TOKENS_experiment_v1.
* Route PMBToken calls through TRUST_TOKEN_METHOD.
* Introduce a TRUST_TOKEN_METHOD hook to select TRUST_TOKEN variations.
Update-Note: Pass TRUST_TOKEN_experiment_v0() into any existing code
that now needs a TRUST_TOKEN_METHOD.
* fork_detect: be robust to qemu.
* Move serialization of points inside pmbtoken.c.
* Introduce PMBTOKENS key abstractions.
* Fix the types used in token counts.
Update-Note: Fix callers of TRUST_TOKEN_ISSUER_issue to use size_t
instead of uint8_t. The max_batchsize changes should go through without
changes to the caller.
* Remove unused code from ghash-x86_64.pl.
* Switch the P-384 hash-to-curve to draft-07.
* Add hash-to-curve code for P384.
* Write down the expressions for all the NIST primes.
* Move fork_detect files into rand/
* Harden against fork via MADV_WIPEONFORK.
* Fix typo in comment.
* Use faster addition chains for P-256 field inversion.
* Tidy up third_party/fiat.
* Prefix g_pre_comp in p256.c as well.
* Add missing curve check to ec_hash_to_scalar_p521_xmd_sha512.
* Add a tool to compare the output of bssl speed.
* Benchmark ECDH slightly more accurately.
* Align remaining Intel copyright notice.
* Don't retain T in PMBTOKEN_PRETOKEN.
* Check for trailing data in TRUST_TOKEN_CLIENT_finish_issuance.
* Properly namespace everything in third_party/fiat/p256.c.
* Update fiat-crypto.
* Add missing ERR_LIB_TRUST_TOKEN constants.
* Add bssl speed support for hashtocurve and trusttoken.
* Implement DLEQ checks for Trust Token.
* Fix error-handling in EVP_BytesToKey.
* Fix Trust Token CBOR.
* Match parameter names between header and source.
* Trust Token Implementation.
* Include mem.h for |CRYPTO_memcmp|
* acvptool: add subprocess tests.
* Add SHA-512-256.
* Make ec_GFp_simple_cmp constant-time.
Update-Note: This does mean that we pay a 6M+2S Jacobian comparison
where comparing two publicly affine points should cost no field
operations at all. Code which compares two EC public keys for equality
will be slightly slower. I wouldn't expect this to matter (if you
actually use the public keys, you'll pay much much more) If it does, we
can restore this optimization by keeping better track of affine vs.
Jacobian forms. See https://crbug.com/boringssl/326.
* Tidy up CRYPTO_sysrand variants.
* Do a better job testing EC_POINT_cmp.
* Follow-up comments to hash_to_scalar.
* Add a hash_to_scalar variation of P-521's hash_to_field.
* Add SSL_SESSION_copy_without_early_data.
* Double-check secret EC point multiplications.
* Make ec_felem_equal constant-time.
* Fix hash-to-curve comment.
* Make ec_GFp_simple_is_on_curve constant-time.
* Implement draft-irtf-cfrg-hash-to-curve-06.
* Update list of tested SDE configurations.
* Only draw from RDRAND for additional_data if it's fast.
* Generalize bn_from_montgomery_small.
* Remove BIGNUM from uncompressed coordinate parsing.
* Add EC_RAW_POINT serialization function.
* Base EC_FELEM conversions on bytes rather than BIGNUMs.
* runner: Replace supportsVersions calls with allVersions.
* Enable QUIC for some perMessageTest runner tests
* Move BN_nnmod calls out of low-level group_set_curve.
* Clean up various EC inversion functions.
* Start to organize ec/internal.h a little.
* Fix CFI for AVX2 ChaCha20-Poly1305.
* Remove unused function prototype.
* Enable more runner tests for QUIC
* Require QUIC method with Transport Parameters and vice versa
* acvptool: support non-interactive mode.
* Add is_quic bit to SSL_SESSION
* Update SDE.
* Update tools.
* Add simpler getters for DH and DSA.
* Don't define default implementations for weak symbols.
* Don't automatically run all tests for ABI testing.
* Fix test build with recent Clang.
* Remove LCM dependency from RSA_check_key.
* Simplify bn_sub_part_words.
* No-op commit to test Windows SDE bots.
* ABI-test each AEAD.
* Add memory tracking and sanitization hooks
* Add X509_STORE_CTX_get0_chain.
* Add DH_set_length.
* Static assert that CRYPTO_MUTEX is sufficiently aligned.
* [bazel] Format toplevel BUILD file with buildifier
* Add |SSL_CTX_get0_chain|.
* Configure QUIC secrets inside set_{read,write}_state.
Update-Note: See b/151142920#comment9
Change-Id: I4bbb76e15b5d95615ea643bccf796db87fae4989
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40244
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Steven Valdez <svaldez@google.com>
* Allow setting QUIC transport parameters after parsing the client's
* Fix comment for |BORINGSSL_self_test|.
* Trust Token Key Generation.
* Revise QUIC encryption secret APIs.
Update-Note: This is an incompatible change to SSL_QUIC_METHOD.
BORINGSSL_API_VERSION can be used to distinguish the two revisions.
* Fix ec_point_mul_scalar_public's documentation.

Test: atest CtsLibcoreTestCases CtsLibcoreTestCases
Change-Id: I754169828a3e1cb461bf0d4a64d4d7b46951d730
diff --git a/src/ssl/dtls_method.cc b/src/ssl/dtls_method.cc
index ae26de7..d179bae 100644
--- a/src/ssl/dtls_method.cc
+++ b/src/ssl/dtls_method.cc
@@ -78,7 +78,9 @@
 }
 
 static bool dtls1_set_read_state(SSL *ssl, ssl_encryption_level_t level,
-                                 UniquePtr<SSLAEADContext> aead_ctx) {
+                                 UniquePtr<SSLAEADContext> aead_ctx,
+                                 Span<const uint8_t> secret_for_quic) {
+  assert(secret_for_quic.empty());  // QUIC does not use DTLS.
   // Cipher changes are forbidden if the current epoch has leftover data.
   if (dtls_has_unprocessed_handshake_data(ssl)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESS_HANDSHAKE_DATA);
@@ -97,7 +99,9 @@
 }
 
 static bool dtls1_set_write_state(SSL *ssl, ssl_encryption_level_t level,
-                                  UniquePtr<SSLAEADContext> aead_ctx) {
+                                  UniquePtr<SSLAEADContext> aead_ctx,
+                                  Span<const uint8_t> secret_for_quic) {
+  assert(secret_for_quic.empty());  // QUIC does not use DTLS.
   ssl->d1->w_epoch++;
   OPENSSL_memcpy(ssl->d1->last_write_sequence, ssl->s3->write_sequence,
                  sizeof(ssl->s3->write_sequence));
diff --git a/src/ssl/handoff.cc b/src/ssl/handoff.cc
index fdbac18..977fcc5 100644
--- a/src/ssl/handoff.cc
+++ b/src/ssl/handoff.cc
@@ -632,7 +632,7 @@
     case handback_after_session_resumption:
       // The write keys are installed after server Finished, but the client
       // keys must wait for ChangeCipherSpec.
-      if (!tls1_configure_aead(ssl, evp_aead_seal, &key_block, session->cipher,
+      if (!tls1_configure_aead(ssl, evp_aead_seal, &key_block, session,
                                write_iv)) {
         return false;
       }
@@ -642,9 +642,9 @@
       break;
     case handback_after_handshake:
       // The handshake is complete, so both keys are installed.
-      if (!tls1_configure_aead(ssl, evp_aead_seal, &key_block, session->cipher,
+      if (!tls1_configure_aead(ssl, evp_aead_seal, &key_block, session,
                                write_iv) ||
-          !tls1_configure_aead(ssl, evp_aead_open, &key_block, session->cipher,
+          !tls1_configure_aead(ssl, evp_aead_open, &key_block, session,
                                read_iv)) {
         return false;
       }
diff --git a/src/ssl/handshake.cc b/src/ssl/handshake.cc
index 27fc3af..7bceb1d 100644
--- a/src/ssl/handshake.cc
+++ b/src/ssl/handshake.cc
@@ -441,7 +441,7 @@
   uint8_t finished[EVP_MAX_MD_SIZE];
   size_t finished_len;
   if (!hs->transcript.GetFinishedMAC(finished, &finished_len,
-                                     SSL_get_session(ssl), !ssl->server) ||
+                                     ssl_handshake_session(hs), !ssl->server) ||
       !ssl_hash_message(hs, msg)) {
     return ssl_hs_error;
   }
@@ -484,7 +484,7 @@
 
 bool ssl_send_finished(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
-  const SSL_SESSION *session = SSL_get_session(ssl);
+  const SSL_SESSION *session = ssl_handshake_session(hs);
 
   uint8_t finished[EVP_MAX_MD_SIZE];
   size_t finished_len;
@@ -541,6 +541,13 @@
   return true;
 }
 
+const SSL_SESSION *ssl_handshake_session(const SSL_HANDSHAKE *hs) {
+  if (hs->new_session) {
+    return hs->new_session.get();
+  }
+  return hs->ssl->session.get();
+}
+
 int ssl_run_handshake(SSL_HANDSHAKE *hs, bool *out_early_return) {
   SSL *const ssl = hs->ssl;
   for (;;) {
diff --git a/src/ssl/handshake_client.cc b/src/ssl/handshake_client.cc
index fa692c5..1b7bb1b 100644
--- a/src/ssl/handshake_client.cc
+++ b/src/ssl/handshake_client.cc
@@ -259,7 +259,7 @@
         continue;
       }
       any_enabled = true;
-      if (!CBB_add_u16(&child, ssl_cipher_get_value(cipher))) {
+      if (!CBB_add_u16(&child, SSL_CIPHER_get_protocol_id(cipher))) {
         return false;
       }
     }
@@ -406,7 +406,8 @@
         (ssl->session->session_id_length == 0 &&
          ssl->session->ticket.empty()) ||
         ssl->session->not_resumable ||
-        !ssl_session_is_time_valid(ssl, ssl->session.get())) {
+        !ssl_session_is_time_valid(ssl, ssl->session.get()) ||
+        (ssl->quic_method != nullptr) != ssl->session->is_quic) {
       ssl_set_session(ssl, NULL);
     }
   }
@@ -415,17 +416,20 @@
     return ssl_hs_error;
   }
 
-  if (ssl->session != nullptr &&
-      !ssl->s3->initial_handshake_complete &&
-      ssl->session->session_id_length > 0) {
-    hs->session_id_len = ssl->session->session_id_length;
-    OPENSSL_memcpy(hs->session_id, ssl->session->session_id,
-                   hs->session_id_len);
-  } else if (hs->max_version >= TLS1_3_VERSION) {
-    // Initialize a random session ID.
-    hs->session_id_len = sizeof(hs->session_id);
-    if (!RAND_bytes(hs->session_id, hs->session_id_len)) {
-      return ssl_hs_error;
+  // Never send a session ID in QUIC. QUIC uses TLS 1.3 at a minimum and
+  // disables TLS 1.3 middlebox compatibility mode.
+  if (ssl->quic_method == nullptr) {
+    if (ssl->session != nullptr && !ssl->s3->initial_handshake_complete &&
+        ssl->session->session_id_length > 0) {
+      hs->session_id_len = ssl->session->session_id_length;
+      OPENSSL_memcpy(hs->session_id, ssl->session->session_id,
+                     hs->session_id_len);
+    } else if (hs->max_version >= TLS1_3_VERSION) {
+      // Initialize a random session ID.
+      hs->session_id_len = sizeof(hs->session_id);
+      if (!RAND_bytes(hs->session_id, hs->session_id_len)) {
+        return ssl_hs_error;
+      }
     }
   }
 
@@ -461,11 +465,6 @@
       !tls13_derive_early_secret(hs)) {
     return ssl_hs_error;
   }
-  if (ssl->quic_method == nullptr &&
-      !tls13_set_traffic_key(ssl, ssl_encryption_early_data, evp_aead_seal,
-                             ssl->session.get(), hs->early_traffic_secret())) {
-    return ssl_hs_error;
-  }
 
   // Stash the early data session, so connection properties may be queried out
   // of it.
@@ -496,7 +495,9 @@
 
   // Defer releasing the 0-RTT key to after certificate reverification, so the
   // QUIC implementation does not accidentally write data too early.
-  if (!tls13_set_early_secret_for_quic(hs)) {
+  if (!tls13_set_traffic_key(hs->ssl, ssl_encryption_early_data, evp_aead_seal,
+                             hs->early_session.get(),
+                             hs->early_traffic_secret())) {
     return ssl_hs_error;
   }
 
@@ -1267,10 +1268,10 @@
   uint32_t alg_k = hs->new_cipher->algorithm_mkey;
   uint32_t alg_a = hs->new_cipher->algorithm_auth;
   if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
-    CRYPTO_BUFFER *leaf =
+    const CRYPTO_BUFFER *leaf =
         sk_CRYPTO_BUFFER_value(hs->new_session->certs.get(), 0);
     CBS leaf_cbs;
-    CBS_init(&leaf_cbs, CRYPTO_BUFFER_data(leaf), CRYPTO_BUFFER_len(leaf));
+    CRYPTO_BUFFER_init_CBS(leaf, &leaf_cbs);
 
     // Check the key usage matches the cipher suite. We do this unconditionally
     // for non-RSA certificates. In particular, it's needed to distinguish ECDH
diff --git a/src/ssl/handshake_server.cc b/src/ssl/handshake_server.cc
index 924701f..26227d3 100644
--- a/src/ssl/handshake_server.cc
+++ b/src/ssl/handshake_server.cc
@@ -908,7 +908,7 @@
       !CBB_add_u8_length_prefixed(&body, &session_id) ||
       !CBB_add_bytes(&session_id, session->session_id,
                      session->session_id_length) ||
-      !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
+      !CBB_add_u16(&body, SSL_CIPHER_get_protocol_id(hs->new_cipher)) ||
       !CBB_add_u8(&body, 0 /* no compression */) ||
       !ssl_add_serverhello_tlsext(hs, &body) ||
       !ssl_add_message_cbb(ssl, cbb.get())) {
@@ -1436,6 +1436,15 @@
     return ssl_hs_error;
   }
 
+  // The peer certificate must be valid for signing.
+  const CRYPTO_BUFFER *leaf =
+      sk_CRYPTO_BUFFER_value(hs->new_session->certs.get(), 0);
+  CBS leaf_cbs;
+  CRYPTO_BUFFER_init_CBS(leaf, &leaf_cbs);
+  if (!ssl_cert_check_key_usage(&leaf_cbs, key_usage_digital_signature)) {
+    return ssl_hs_error;
+  }
+
   CBS certificate_verify = msg.body, signature;
 
   // Determine the signature algorithm.
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 78c56b6..ffc18a5 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -345,6 +345,9 @@
     if (new_size > size_) {
       abort();
     }
+    for (size_t i = new_size; i < size_; i++) {
+      data_[i].~T();
+    }
     size_ = new_size;
   }
 
@@ -631,9 +634,6 @@
 bool ssl_create_cipher_list(UniquePtr<SSLCipherPreferenceList> *out_cipher_list,
                             const char *rule_str, bool strict);
 
-// ssl_cipher_get_value returns the cipher suite id of |cipher|.
-uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher);
-
 // ssl_cipher_auth_mask_for_key returns the mask of cipher |algorithm_auth|
 // values suitable for use with |key| in TLS 1.2 and below.
 uint32_t ssl_cipher_auth_mask_for_key(const EVP_PKEY *key);
@@ -1364,17 +1364,9 @@
                            Span<const uint8_t> traffic_secret);
 
 // tls13_derive_early_secret derives the early traffic secret. It returns true
-// on success and false on error. Unlike with other traffic secrets, this
-// function does not pass the keys to QUIC. Call
-// |tls13_set_early_secret_for_quic| to do so. This is done to due to an
-// ordering complication around resolving HelloRetryRequest on the server.
+// on success and false on error.
 bool tls13_derive_early_secret(SSL_HANDSHAKE *hs);
 
-// tls13_set_early_secret_for_quic passes the early traffic secrets, as
-// derived by |tls13_derive_early_secret|, to QUIC. It returns true on success
-// and false on error.
-bool tls13_set_early_secret_for_quic(SSL_HANDSHAKE *hs);
-
 // tls13_derive_handshake_secrets derives the handshake traffic secret. It
 // returns true on success and false on error.
 bool tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs);
@@ -1658,6 +1650,10 @@
   // advertise this extension to the client.
   Array<uint16_t> peer_supported_group_list;
 
+  // peer_delegated_credential_sigalgs are the signature algorithms the peer
+  // supports with delegated credentials.
+  Array<uint16_t> peer_delegated_credential_sigalgs;
+
   // peer_key is the peer's ECDH key for a TLS 1.2 client.
   Array<uint8_t> peer_key;
 
@@ -1871,6 +1867,8 @@
 
 bool tls13_add_finished(SSL_HANDSHAKE *hs);
 bool tls13_process_new_session_ticket(SSL *ssl, const SSLMessage &msg);
+bssl::UniquePtr<SSL_SESSION> tls13_create_session_with_ticket(SSL *ssl,
+                                                              CBS *body);
 
 bool ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs,
                                          Array<uint8_t> *out_secret,
@@ -1946,6 +1944,11 @@
 bool ssl_send_finished(SSL_HANDSHAKE *hs);
 bool ssl_output_cert_chain(SSL_HANDSHAKE *hs);
 
+// ssl_handshake_session returns the |SSL_SESSION| corresponding to the current
+// handshake. Note, in TLS 1.2 resumptions, this session is immutable.
+const SSL_SESSION *ssl_handshake_session(const SSL_HANDSHAKE *hs);
+
+
 // SSLKEYLOGFILE functions.
 
 // ssl_log_secret logs |secret| with label |label|, if logging is enabled for
@@ -2148,15 +2151,19 @@
   // on_handshake_complete is called when the handshake is complete.
   void (*on_handshake_complete)(SSL *ssl);
   // set_read_state sets |ssl|'s read cipher state and level to |aead_ctx| and
-  // |level|. It returns true on success and false if changing the read state is
-  // forbidden at this point.
+  // |level|. In QUIC, |aead_ctx| is a placeholder object and |secret_for_quic|
+  // is the original secret. This function returns true on success and false on
+  // error.
   bool (*set_read_state)(SSL *ssl, ssl_encryption_level_t level,
-                         UniquePtr<SSLAEADContext> aead_ctx);
+                         UniquePtr<SSLAEADContext> aead_ctx,
+                         Span<const uint8_t> secret_for_quic);
   // set_write_state sets |ssl|'s write cipher state and level to |aead_ctx| and
-  // |level|. It returns true on success and false if changing the write state
-  // is forbidden at this point.
+  // |level|. In QUIC, |aead_ctx| is a placeholder object and |secret_for_quic|
+  // is the original secret. This function returns true on success and false on
+  // error.
   bool (*set_write_state)(SSL *ssl, ssl_encryption_level_t level,
-                          UniquePtr<SSLAEADContext> aead_ctx);
+                          UniquePtr<SSLAEADContext> aead_ctx,
+                          Span<const uint8_t> secret_for_quic);
 };
 
 // The following wrappers call |open_*| but handle |read_shutdown| correctly.
@@ -2689,6 +2696,9 @@
   // Contains the QUIC transport params that this endpoint will send.
   Array<uint8_t> quic_transport_params;
 
+  // Contains the context used to decide whether to accept early data in QUIC.
+  Array<uint8_t> quic_early_data_context;
+
   // verify_sigalgs, if not empty, is the set of signature algorithms
   // accepted from the peer in decreasing order of preference.
   Array<uint16_t> verify_sigalgs;
@@ -2920,13 +2930,14 @@
 // determined by |direction|) using the keys generated by the TLS KDF. The
 // |key_block_cache| argument is used to store the generated key block, if
 // empty. Otherwise it's assumed that the key block is already contained within
-// it. Returns one on success or zero on error.
-int tls1_configure_aead(SSL *ssl, evp_aead_direction_t direction,
-                        Array<uint8_t> *key_block_cache,
-                        const SSL_CIPHER *cipher,
-                        Span<const uint8_t> iv_override);
+// it. It returns true on success or false on error.
+bool tls1_configure_aead(SSL *ssl, evp_aead_direction_t direction,
+                         Array<uint8_t> *key_block_cache,
+                         const SSL_SESSION *session,
+                         Span<const uint8_t> iv_override);
 
-int tls1_change_cipher_state(SSL_HANDSHAKE *hs, evp_aead_direction_t direction);
+bool tls1_change_cipher_state(SSL_HANDSHAKE *hs,
+                              evp_aead_direction_t direction);
 int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
                                 Span<const uint8_t> premaster);
 
@@ -3552,6 +3563,13 @@
   // is_server is whether this session was created by a server.
   bool is_server : 1;
 
+  // is_quic indicates whether this session was created using QUIC.
+  bool is_quic : 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;
+
  private:
   ~ssl_session_st();
   friend void SSL_SESSION_free(SSL_SESSION *);
diff --git a/src/ssl/ssl_asn1.cc b/src/ssl/ssl_asn1.cc
index ea02cf4..e6274f1 100644
--- a/src/ssl/ssl_asn1.cc
+++ b/src/ssl/ssl_asn1.cc
@@ -129,6 +129,8 @@
 //     ticketMaxEarlyData      [24] INTEGER OPTIONAL,
 //     authTimeout             [25] INTEGER OPTIONAL, -- defaults to timeout
 //     earlyALPN               [26] OCTET STRING OPTIONAL,
+//     isQuic                  [27] BOOLEAN OPTIONAL,
+//     quicEarlyDataHash       [28] OCTET STRING OPTIONAL,
 // }
 //
 // Note: historically this serialization has included other optional
@@ -188,6 +190,10 @@
     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 25;
 static const unsigned kEarlyALPNTag =
     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 26;
+static const unsigned kIsQuicTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 27;
+static const unsigned kQuicEarlyDataContextTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 28;
 
 static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, CBB *cbb,
                                      int for_ticket) {
@@ -388,6 +394,23 @@
     }
   }
 
+  if (in->is_quic) {
+    if (!CBB_add_asn1(&session, &child, kIsQuicTag) ||
+        !CBB_add_asn1_bool(&child, true)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      return 0;
+    }
+  }
+
+  if (!in->quic_early_data_context.empty()) {
+    if (!CBB_add_asn1(&session, &child, kQuicEarlyDataContextTag) ||
+        !CBB_add_asn1_octet_string(&child, in->quic_early_data_context.data(),
+                                   in->quic_early_data_context.size())) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      return 0;
+    }
+  }
+
   return CBB_flush(cbb);
 }
 
@@ -718,6 +741,7 @@
 
   ret->is_server = is_server;
 
+  int is_quic;
   if (!SSL_SESSION_parse_u16(&session, &ret->peer_signature_algorithm,
                              kPeerSignatureAlgorithmTag, 0) ||
       !SSL_SESSION_parse_u32(&session, &ret->ticket_max_early_data,
@@ -726,10 +750,15 @@
                              ret->timeout) ||
       !SSL_SESSION_parse_octet_string(&session, &ret->early_alpn,
                                       kEarlyALPNTag) ||
+      !CBS_get_optional_asn1_bool(&session, &is_quic, kIsQuicTag,
+                                  /*default_value=*/false) ||
+      !SSL_SESSION_parse_octet_string(&session, &ret->quic_early_data_context,
+                                      kQuicEarlyDataContextTag) ||
       CBS_len(&session) != 0) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     return nullptr;
   }
+  ret->is_quic = is_quic;
 
   if (!x509_method->session_cache_objects(ret.get())) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
diff --git a/src/ssl/ssl_cert.cc b/src/ssl/ssl_cert.cc
index 4f80382..c64303a 100644
--- a/src/ssl/ssl_cert.cc
+++ b/src/ssl/ssl_cert.cc
@@ -821,16 +821,13 @@
   }
 
   // Check that the DC signature algorithm is supported by the peer.
-  Span<const uint16_t> peer_sigalgs = tls1_get_peer_verify_algorithms(hs);
-  bool sigalg_found = false;
+  Span<const uint16_t> peer_sigalgs = hs->peer_delegated_credential_sigalgs;
   for (uint16_t peer_sigalg : peer_sigalgs) {
     if (dc->expected_cert_verify_algorithm == peer_sigalg) {
-      sigalg_found = true;
-      break;
+      return true;
     }
   }
-
-  return sigalg_found;
+  return false;
 }
 
 bool ssl_signing_with_dc(const SSL_HANDSHAKE *hs) {
@@ -896,6 +893,10 @@
                                 privkey_method);
 }
 
+const STACK_OF(CRYPTO_BUFFER)* SSL_CTX_get0_chain(const SSL_CTX *ctx) {
+  return ctx->cert->chain.get();
+}
+
 int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
                                  const uint8_t *der) {
   UniquePtr<CRYPTO_BUFFER> buffer(CRYPTO_BUFFER_new(der, der_len, NULL));
diff --git a/src/ssl/ssl_cipher.cc b/src/ssl/ssl_cipher.cc
index c421292..4f5049c 100644
--- a/src/ssl/ssl_cipher.cc
+++ b/src/ssl/ssl_cipher.cc
@@ -1279,14 +1279,6 @@
   return true;
 }
 
-uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher) {
-  uint32_t id = cipher->id;
-  // All OpenSSL cipher IDs are prefaced with 0x03. Historically this referred
-  // to SSLv2 vs SSLv3.
-  assert((id & 0xff000000) == 0x03000000);
-  return id & 0xffff;
-}
-
 uint32_t ssl_cipher_auth_mask_for_key(const EVP_PKEY *key) {
   switch (EVP_PKEY_id(key)) {
     case EVP_PKEY_RSA:
@@ -1376,10 +1368,17 @@
 
 uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher) { return cipher->id; }
 
-uint16_t SSL_CIPHER_get_value(const SSL_CIPHER *cipher) {
+uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *cipher) {
+  // All OpenSSL cipher IDs are prefaced with 0x03. Historically this referred
+  // to SSLv2 vs SSLv3.
+  assert((cipher->id & 0xff000000) == 0x03000000);
   return static_cast<uint16_t>(cipher->id);
 }
 
+uint16_t SSL_CIPHER_get_value(const SSL_CIPHER *cipher) {
+  return SSL_CIPHER_get_protocol_id(cipher);
+}
+
 int SSL_CIPHER_is_aead(const SSL_CIPHER *cipher) {
   return (cipher->algorithm_mac & SSL_AEAD) != 0;
 }
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 3cebfe0..10a97ea 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -1248,6 +1248,12 @@
   *out_params_len = ssl->s3->peer_quic_transport_params.size();
 }
 
+int SSL_set_quic_early_data_context(SSL *ssl, const uint8_t *context,
+                                    size_t context_len) {
+  return ssl->config && ssl->config->quic_early_data_context.CopyFrom(
+                            MakeConstSpan(context, context_len));
+}
+
 void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled) {
   ctx->enable_early_data = !!enabled;
 }
@@ -2354,6 +2360,16 @@
   return sigalgs.size();
 }
 
+size_t SSL_get0_peer_delegation_algorithms(const SSL *ssl,
+                                           const uint16_t **out_sigalgs){
+  Span<const uint16_t> sigalgs;
+  if (ssl->s3->hs != nullptr) {
+    sigalgs = ssl->s3->hs->peer_delegated_credential_sigalgs;
+  }
+  *out_sigalgs = sigalgs.data();
+  return sigalgs.size();
+}
+
 EVP_PKEY *SSL_get_privatekey(const SSL *ssl) {
   if (!ssl->config) {
     assert(ssl->config);
@@ -2962,6 +2978,34 @@
   ctx->ticket_aead_method = aead_method;
 }
 
+SSL_SESSION *SSL_process_tls13_new_session_ticket(SSL *ssl, const uint8_t *buf,
+                                                  size_t buf_len) {
+  if (SSL_in_init(ssl) ||
+      ssl_protocol_version(ssl) != TLS1_3_VERSION ||
+      ssl->server) {
+    // Only TLS 1.3 clients are supported.
+    OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return nullptr;
+  }
+
+  CBS cbs, body;
+  CBS_init(&cbs, buf, buf_len);
+  uint8_t type;
+  if (!CBS_get_u8(&cbs, &type) ||
+      !CBS_get_u24_length_prefixed(&cbs, &body) ||
+      CBS_len(&cbs) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return nullptr;
+  }
+
+  UniquePtr<SSL_SESSION> session = tls13_create_session_with_ticket(ssl, &body);
+  if (!session) {
+    // |tls13_create_session_with_ticket| puts the correct error.
+    return nullptr;
+  }
+  return session.release();
+}
+
 int SSL_set_tlsext_status_type(SSL *ssl, int type) {
   if (!ssl->config) {
     return 0;
diff --git a/src/ssl/ssl_session.cc b/src/ssl/ssl_session.cc
index 6635703..4c6d045 100644
--- a/src/ssl/ssl_session.cc
+++ b/src/ssl/ssl_session.cc
@@ -197,6 +197,7 @@
 
   new_session->is_server = session->is_server;
   new_session->ssl_version = session->ssl_version;
+  new_session->is_quic = session->is_quic;
   new_session->sid_ctx_length = session->sid_ctx_length;
   OPENSSL_memcpy(new_session->sid_ctx, session->sid_ctx, session->sid_ctx_length);
 
@@ -267,6 +268,11 @@
     if (!new_session->early_alpn.CopyFrom(session->early_alpn)) {
       return nullptr;
     }
+
+    if (!new_session->quic_early_data_context.CopyFrom(
+            session->quic_early_data_context)) {
+      return nullptr;
+    }
   }
 
   // Copy the ticket.
@@ -357,6 +363,13 @@
 
   session->is_server = is_server;
   session->ssl_version = ssl->version;
+  session->is_quic = ssl->quic_method != nullptr;
+  if (is_server && ssl->enable_early_data && session->is_quic) {
+    if (!session->quic_early_data_context.CopyFrom(
+            hs->config->quic_early_data_context)) {
+      return 0;
+    }
+  }
 
   // Fill in the time from the |SSL_CTX|'s clock.
   struct OPENSSL_timeval now;
@@ -639,7 +652,10 @@
          ((sk_CRYPTO_BUFFER_num(session->certs.get()) == 0 &&
            !session->peer_sha256_valid) ||
           session->peer_sha256_valid ==
-              hs->config->retain_only_sha256_of_client_certs);
+              hs->config->retain_only_sha256_of_client_certs) &&
+         // Only resume if the underlying transport protocol hasn't changed.
+         // This is to prevent cross-protocol resumption between QUIC and TCP.
+         (hs->ssl->quic_method != nullptr) == session->is_quic;
 }
 
 // ssl_lookup_session looks up |session_id| in the session cache and sets
@@ -853,7 +869,8 @@
       peer_sha256_valid(false),
       not_resumable(false),
       ticket_age_add_valid(false),
-      is_server(false) {
+      is_server(false),
+      is_quic(false) {
   CRYPTO_new_ex_data(&ex_data);
   time = ::time(nullptr);
 }
@@ -1054,6 +1071,24 @@
          session->ticket_max_early_data != 0;
 }
 
+SSL_SESSION *SSL_SESSION_copy_without_early_data(SSL_SESSION *session) {
+  if (!SSL_SESSION_early_data_capable(session)) {
+    return UpRef(session).release();
+  }
+
+  bssl::UniquePtr<SSL_SESSION> copy =
+      SSL_SESSION_dup(session, SSL_SESSION_DUP_ALL);
+  if (!copy) {
+    return nullptr;
+  }
+
+  copy->ticket_max_early_data = 0;
+  // Copied sessions are non-resumable until they're completely filled in.
+  copy->not_resumable = session->not_resumable;
+  assert(!SSL_SESSION_early_data_capable(copy.get()));
+  return copy.release();
+}
+
 SSL_SESSION *SSL_magic_pending_session_ptr(void) {
   return (SSL_SESSION *)&g_pending_session_magic;
 }
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 9104bc1..eb45700 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -3284,6 +3284,8 @@
   bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_with_buffers_method()));
   ASSERT_TRUE(server_ctx);
 
+  ASSERT_EQ(nullptr, SSL_CTX_get0_chain(server_ctx.get()));
+
   bssl::UniquePtr<EVP_PKEY> key = GetChainTestKey();
   ASSERT_TRUE(key);
   bssl::UniquePtr<CRYPTO_BUFFER> leaf = GetChainTestCertificateBuffer();
@@ -3297,6 +3299,9 @@
   ASSERT_TRUE(SSL_CTX_set_chain_and_key(server_ctx.get(), &chain[0],
                                         chain.size(), key.get(), nullptr));
 
+  ASSERT_EQ(chain.size(),
+            sk_CRYPTO_BUFFER_num(SSL_CTX_get0_chain(server_ctx.get())));
+
   SSL_CTX_set_custom_verify(
       client_ctx.get(), SSL_VERIFY_PEER,
       [](SSL *ssl, uint8_t *out_alert) -> ssl_verify_result_t {
@@ -4806,6 +4811,20 @@
 static_assert(ssl_encryption_application < kNumQUICLevels,
               "kNumQUICLevels is wrong");
 
+const char *LevelToString(ssl_encryption_level_t level) {
+  switch (level) {
+    case ssl_encryption_initial:
+      return "initial";
+    case ssl_encryption_early_data:
+      return "early data";
+    case ssl_encryption_handshake:
+      return "handshake";
+    case ssl_encryption_application:
+      return "application";
+  }
+  return "<unknown>";
+}
+
 class MockQUICTransport {
  public:
   enum class Role { kClient, kServer };
@@ -4828,61 +4847,70 @@
            levels_[level].cipher == peer_->levels_[level].cipher;
   }
 
-  bool HasSecrets(ssl_encryption_level_t level) const {
-    return !levels_[level].write_secret.empty() ||
-           !levels_[level].read_secret.empty();
+  bool HasReadSecret(ssl_encryption_level_t level) const {
+    return !levels_[level].read_secret.empty();
   }
 
-  bool SetEncryptionSecrets(ssl_encryption_level_t level,
-                            const uint8_t *read_secret,
-                            const uint8_t *write_secret, size_t secret_len,
-                            const SSL_CIPHER *cipher) {
-    if (HasSecrets(level)) {
-      ADD_FAILURE() << "duplicate keys configured";
+  bool HasWriteSecret(ssl_encryption_level_t level) const {
+    return !levels_[level].write_secret.empty();
+  }
+
+  void AllowOutOfOrderWrites() { allow_out_of_order_writes_ = true; }
+
+  bool SetReadSecret(ssl_encryption_level_t level, const SSL_CIPHER *cipher,
+                     Span<const uint8_t> secret) {
+    if (HasReadSecret(level)) {
+      ADD_FAILURE() << LevelToString(level) << " read secret configured twice";
+      return false;
+    }
+
+    if (role_ == Role::kClient && level == ssl_encryption_early_data) {
+      ADD_FAILURE() << "Unexpected early data read secret";
+      return false;
+    }
+
+    ssl_encryption_level_t ack_level =
+        level == ssl_encryption_early_data ? ssl_encryption_application : level;
+    if (!HasWriteSecret(ack_level)) {
+      ADD_FAILURE() << LevelToString(level)
+                    << " read secret configured before ACK write secret";
       return false;
     }
 
     if (cipher == nullptr) {
-      ADD_FAILURE() << "current cipher unavailable";
+      ADD_FAILURE() << "Unexpected null cipher";
       return false;
     }
 
-    bool expect_read_secret = true, expect_write_secret = true;
-    if (level == ssl_encryption_early_data) {
-      if (role_ == Role::kClient) {
-        expect_read_secret = false;
-      } else {
-        expect_write_secret = false;
-        if (!HasSecrets(ssl_encryption_application)) {
-          ADD_FAILURE() << "early secrets installed without keys to ACK them";
-          return false;
-        }
-      }
-    }
-
-    if (expect_read_secret) {
-      if (read_secret == nullptr) {
-        ADD_FAILURE() << "read secret was unexpectedly null";
-        return false;
-      }
-      levels_[level].read_secret.assign(read_secret, read_secret + secret_len);
-    } else if (read_secret != nullptr) {
-      ADD_FAILURE() << "unexpected read secret";
+    if (level != ssl_encryption_early_data &&
+        SSL_CIPHER_get_id(cipher) != levels_[level].cipher) {
+      ADD_FAILURE() << "Cipher suite inconsistent";
       return false;
     }
 
-    if (expect_write_secret) {
-      if (write_secret == nullptr) {
-        ADD_FAILURE() << "write secret was unexpectedly null";
-        return false;
-      }
-      levels_[level].write_secret.assign(write_secret,
-                                         write_secret + secret_len);
-    } else if (write_secret != nullptr) {
-      ADD_FAILURE() << "unexpected write secret";
+    levels_[level].read_secret.assign(secret.begin(), secret.end());
+    levels_[level].cipher = SSL_CIPHER_get_id(cipher);
+    return true;
+  }
+
+  bool SetWriteSecret(ssl_encryption_level_t level, const SSL_CIPHER *cipher,
+                      Span<const uint8_t> secret) {
+    if (HasWriteSecret(level)) {
+      ADD_FAILURE() << LevelToString(level) << " write secret configured twice";
       return false;
     }
 
+    if (role_ == Role::kServer && level == ssl_encryption_early_data) {
+      ADD_FAILURE() << "Unexpected early data write secret";
+      return false;
+    }
+
+    if (cipher == nullptr) {
+      ADD_FAILURE() << "Unexpected null cipher";
+      return false;
+    }
+
+    levels_[level].write_secret.assign(secret.begin(), secret.end());
     levels_[level].cipher = SSL_CIPHER_get_id(cipher);
     return true;
   }
@@ -4890,9 +4918,39 @@
   bool WriteHandshakeData(ssl_encryption_level_t level,
                           Span<const uint8_t> data) {
     if (levels_[level].write_secret.empty()) {
-      ADD_FAILURE() << "data written before keys configured";
+      ADD_FAILURE() << LevelToString(level)
+                    << " write secret not yet configured";
       return false;
     }
+
+    // Although the levels are conceptually separate, BoringSSL finishes writing
+    // data from a previous level before installing keys for the next level.
+    if (!allow_out_of_order_writes_) {
+      switch (level) {
+        case ssl_encryption_early_data:
+          ADD_FAILURE() << "unexpected handshake data at early data level";
+          return false;
+        case ssl_encryption_initial:
+          if (!levels_[ssl_encryption_handshake].write_secret.empty()) {
+            ADD_FAILURE()
+                << LevelToString(level)
+                << " handshake data written after handshake keys installed";
+            return false;
+          }
+          OPENSSL_FALLTHROUGH;
+        case ssl_encryption_handshake:
+          if (!levels_[ssl_encryption_application].write_secret.empty()) {
+            ADD_FAILURE()
+                << LevelToString(level)
+                << " handshake data written after application keys installed";
+            return false;
+          }
+          OPENSSL_FALLTHROUGH;
+        case ssl_encryption_application:
+          break;
+      }
+    }
+
     levels_[level].write_data.insert(levels_[level].write_data.end(),
                                      data.begin(), data.end());
     return true;
@@ -4905,7 +4963,8 @@
     }
 
     if (levels_[level].write_secret.empty()) {
-      ADD_FAILURE() << "alert sent before keys configured";
+      ADD_FAILURE() << LevelToString(level)
+                    << " write secret not yet configured";
       return false;
     }
 
@@ -4948,6 +5007,7 @@
   Role role_;
   MockQUICTransport *peer_ = nullptr;
 
+  bool allow_out_of_order_writes_ = false;
   bool has_alert_ = false;
   ssl_encryption_level_t alert_level_ = ssl_encryption_initial;
   uint8_t alert_ = 0;
@@ -4979,8 +5039,11 @@
   MockQUICTransport *server() { return &server_; }
 
   bool SecretsMatch(ssl_encryption_level_t level) const {
-    return client_.HasSecrets(level) && server_.HasSecrets(level) &&
-           client_.PeerSecretsMatch(level);
+    // We only need to check |HasReadSecret| and |HasWriteSecret| on |client_|.
+    // |PeerSecretsMatch| checks that |server_| is analogously configured.
+    return client_.PeerSecretsMatch(level) &&
+           client_.HasWriteSecret(level) &&
+           (level == ssl_encryption_early_data || client_.HasReadSecret(level));
   }
 
  private:
@@ -5007,6 +5070,22 @@
     SSL_CTX_set_max_proto_version(server_ctx_.get(), TLS1_3_VERSION);
     SSL_CTX_set_min_proto_version(client_ctx_.get(), TLS1_3_VERSION);
     SSL_CTX_set_max_proto_version(client_ctx_.get(), TLS1_3_VERSION);
+
+    static const uint8_t kALPNProtos[] = {0x03, 'f', 'o', 'o'};
+    ASSERT_EQ(SSL_CTX_set_alpn_protos(client_ctx_.get(), kALPNProtos,
+                                      sizeof(kALPNProtos)),
+              0);
+    SSL_CTX_set_alpn_select_cb(
+        server_ctx_.get(),
+        [](SSL *ssl, const uint8_t **out, uint8_t *out_len, const uint8_t *in,
+           unsigned in_len, void *arg) -> int {
+          return SSL_select_next_proto(
+                     const_cast<uint8_t **>(out), out_len, in, in_len,
+                     kALPNProtos, sizeof(kALPNProtos)) == OPENSSL_NPN_NEGOTIATED
+                     ? SSL_TLSEXT_ERR_OK
+                     : SSL_TLSEXT_ERR_NOACK;
+        },
+        nullptr);
   }
 
   static MockQUICTransport *TransportFromSSL(const SSL *ssl) {
@@ -5022,6 +5101,10 @@
            SSL_provide_quic_data(ssl, level, data.data(), data.size());
   }
 
+  void AllowOutOfOrderWrites() {
+    allow_out_of_order_writes_ = true;
+  }
+
   bool CreateClientAndServer() {
     client_.reset(SSL_new(client_ctx_.get()));
     server_.reset(SSL_new(server_ctx_.get()));
@@ -5035,13 +5118,42 @@
     transport_.reset(new MockQUICTransportPair);
     ex_data_.Set(client_.get(), transport_->client());
     ex_data_.Set(server_.get(), transport_->server());
+    if (allow_out_of_order_writes_) {
+      transport_->client()->AllowOutOfOrderWrites();
+      transport_->server()->AllowOutOfOrderWrites();
+    }
+    static const uint8_t client_transport_params[] = {0};
+    if (!SSL_set_quic_transport_params(client_.get(), client_transport_params,
+                                       sizeof(client_transport_params)) ||
+        !SSL_set_quic_transport_params(server_.get(),
+                                       server_transport_params_.data(),
+                                       server_transport_params_.size()) ||
+        !SSL_set_quic_early_data_context(
+            server_.get(), server_quic_early_data_context_.data(),
+            server_quic_early_data_context_.size())) {
+      return false;
+    }
     return true;
   }
 
+  enum class ExpectedError {
+    kNoError,
+    kClientError,
+    kServerError,
+  };
+
   // CompleteHandshakesForQUIC runs |SSL_do_handshake| on |client_| and
   // |server_| until each completes once. It returns true on success and false
   // on failure.
   bool CompleteHandshakesForQUIC() {
+    return RunQUICHandshakesAndExpectError(ExpectedError::kNoError);
+  }
+
+  // Runs |SSL_do_handshake| on |client_| and |server_| until each completes
+  // once. If |expect_client_error| is true, it will return true only if the
+  // client handshake failed. Otherwise, it returns true if both handshakes
+  // succeed and false otherwise.
+  bool RunQUICHandshakesAndExpectError(ExpectedError expected_error) {
     bool client_done = false, server_done = false;
     while (!client_done || !server_done) {
       if (!client_done) {
@@ -5054,6 +5166,9 @@
         if (client_ret == 1) {
           client_done = true;
         } else if (client_ret != -1 || client_err != SSL_ERROR_WANT_READ) {
+          if (expected_error == ExpectedError::kClientError) {
+            return true;
+          }
           ADD_FAILURE() << "Unexpected client output: " << client_ret << " "
                         << client_err;
           return false;
@@ -5070,13 +5185,16 @@
         if (server_ret == 1) {
           server_done = true;
         } else if (server_ret != -1 || server_err != SSL_ERROR_WANT_READ) {
+          if (expected_error == ExpectedError::kServerError) {
+            return true;
+          }
           ADD_FAILURE() << "Unexpected server output: " << server_ret << " "
                         << server_err;
           return false;
         }
       }
     }
-    return true;
+    return expected_error == ExpectedError::kNoError;
   }
 
   bssl::UniquePtr<SSL_SESSION> CreateClientSessionForQUIC() {
@@ -5110,16 +5228,27 @@
     EXPECT_EQ(SSL_do_handshake(server_.get()), 1);
   }
 
-  // The following functions may be configured on an |SSL_QUIC_METHOD| as
-  // default implementations.
+  // Returns a default SSL_QUIC_METHOD. Individual methods may be overwritten by
+  // the test.
+  SSL_QUIC_METHOD DefaultQUICMethod() {
+    return SSL_QUIC_METHOD{
+        SetReadSecretCallback, SetWriteSecretCallback, AddHandshakeDataCallback,
+        FlushFlightCallback,   SendAlertCallback,
+    };
+  }
 
-  static int SetEncryptionSecretsCallback(SSL *ssl,
-                                          ssl_encryption_level_t level,
-                                          const uint8_t *read_key,
-                                          const uint8_t *write_key,
-                                          size_t key_len) {
-    return TransportFromSSL(ssl)->SetEncryptionSecrets(
-        level, read_key, write_key, key_len, SSL_get_current_cipher(ssl));
+  static int SetReadSecretCallback(SSL *ssl, ssl_encryption_level_t level,
+                                   const SSL_CIPHER *cipher,
+                                   const uint8_t *secret, size_t secret_len) {
+    return TransportFromSSL(ssl)->SetReadSecret(
+        level, cipher, MakeConstSpan(secret, secret_len));
+  }
+
+  static int SetWriteSecretCallback(SSL *ssl, ssl_encryption_level_t level,
+                                    const SSL_CIPHER *cipher,
+                                    const uint8_t *secret, size_t secret_len) {
+    return TransportFromSSL(ssl)->SetWriteSecret(
+        level, cipher, MakeConstSpan(secret, secret_len));
   }
 
   static int AddHandshakeDataCallback(SSL *ssl,
@@ -5146,18 +5275,18 @@
 
   bssl::UniquePtr<SSL> client_;
   bssl::UniquePtr<SSL> server_;
+
+  std::vector<uint8_t> server_transport_params_ = {1};
+  std::vector<uint8_t> server_quic_early_data_context_ = {2};
+
+  bool allow_out_of_order_writes_ = false;
 };
 
 UnownedSSLExData<MockQUICTransport> QUICMethodTest::ex_data_;
 
 // Test a full handshake and resumption work.
 TEST_F(QUICMethodTest, Basic) {
-  const SSL_QUIC_METHOD quic_method = {
-      SetEncryptionSecretsCallback,
-      AddHandshakeDataCallback,
-      FlushFlightCallback,
-      SendAlertCallback,
-  };
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
 
   g_last_session = nullptr;
 
@@ -5193,12 +5322,7 @@
 
 // Test that HelloRetryRequest in QUIC works.
 TEST_F(QUICMethodTest, HelloRetryRequest) {
-  const SSL_QUIC_METHOD quic_method = {
-      SetEncryptionSecretsCallback,
-      AddHandshakeDataCallback,
-      FlushFlightCallback,
-      SendAlertCallback,
-  };
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
 
   ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
   ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
@@ -5217,13 +5341,58 @@
   ExpectHandshakeSuccess();
 }
 
+// Test that the client does not send a legacy_session_id in the ClientHello.
+TEST_F(QUICMethodTest, NoLegacySessionId) {
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+
+  ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+  // Check that the session ID length is 0 in an early callback.
+  SSL_CTX_set_select_certificate_cb(
+      server_ctx_.get(),
+      [](const SSL_CLIENT_HELLO *client_hello) -> ssl_select_cert_result_t {
+        EXPECT_EQ(client_hello->session_id_len, 0u);
+        return ssl_select_cert_success;
+      });
+
+  ASSERT_TRUE(CreateClientAndServer());
+  ASSERT_TRUE(CompleteHandshakesForQUIC());
+
+  ExpectHandshakeSuccess();
+}
+
+// Test that, even in a 1-RTT handshake, the server installs keys at the right
+// time. Half-RTT keys are available early, but 1-RTT read keys are deferred.
+TEST_F(QUICMethodTest, HalfRTTKeys) {
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+
+  ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+  ASSERT_TRUE(CreateClientAndServer());
+
+  // The client sends ClientHello.
+  ASSERT_EQ(SSL_do_handshake(client_.get()), -1);
+  ASSERT_EQ(SSL_ERROR_WANT_READ, SSL_get_error(client_.get(), -1));
+
+  // The server reads ClientHello and sends ServerHello..Finished.
+  ASSERT_TRUE(ProvideHandshakeData(server_.get()));
+  ASSERT_EQ(SSL_do_handshake(server_.get()), -1);
+  ASSERT_EQ(SSL_ERROR_WANT_READ, SSL_get_error(server_.get(), -1));
+
+  // At this point, the server has half-RTT write keys, but it cannot access
+  // 1-RTT read keys until client Finished.
+  EXPECT_TRUE(transport_->server()->HasWriteSecret(ssl_encryption_application));
+  EXPECT_FALSE(transport_->server()->HasReadSecret(ssl_encryption_application));
+
+  // Finish up the client and server handshakes.
+  ASSERT_TRUE(CompleteHandshakesForQUIC());
+
+  // Both sides can now exchange 1-RTT data.
+  ExpectHandshakeSuccess();
+}
+
 TEST_F(QUICMethodTest, ZeroRTTAccept) {
-  const SSL_QUIC_METHOD quic_method = {
-      SetEncryptionSecretsCallback,
-      AddHandshakeDataCallback,
-      FlushFlightCallback,
-      SendAlertCallback,
-  };
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
 
   SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
   SSL_CTX_set_early_data_enabled(client_ctx_.get(), 1);
@@ -5241,8 +5410,7 @@
   ASSERT_EQ(SSL_do_handshake(client_.get()), 1);
   EXPECT_TRUE(SSL_in_early_data(client_.get()));
   // The transport should have keys for sending 0-RTT data.
-  EXPECT_TRUE(
-      transport_->client()->HasSecrets(ssl_encryption_early_data));
+  EXPECT_TRUE(transport_->client()->HasWriteSecret(ssl_encryption_early_data));
 
   // The server will consume the ClientHello and also enter the early data
   // state.
@@ -5250,9 +5418,10 @@
   ASSERT_EQ(SSL_do_handshake(server_.get()), 1);
   EXPECT_TRUE(SSL_in_early_data(server_.get()));
   EXPECT_TRUE(transport_->SecretsMatch(ssl_encryption_early_data));
-  // The transport should have keys for sending half-RTT data.
-  EXPECT_TRUE(
-      transport_->server()->HasSecrets(ssl_encryption_application));
+  // At this point, the server has half-RTT write keys, but it cannot access
+  // 1-RTT read keys until client Finished.
+  EXPECT_TRUE(transport_->server()->HasWriteSecret(ssl_encryption_application));
+  EXPECT_FALSE(transport_->server()->HasReadSecret(ssl_encryption_application));
 
   // Finish up the client and server handshakes.
   ASSERT_TRUE(CompleteHandshakesForQUIC());
@@ -5267,13 +5436,85 @@
   EXPECT_TRUE(SSL_early_data_accepted(server_.get()));
 }
 
+TEST_F(QUICMethodTest, ZeroRTTRejectMismatchedParameters) {
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_early_data_enabled(client_ctx_.get(), 1);
+  SSL_CTX_set_early_data_enabled(server_ctx_.get(), 1);
+  ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+
+
+  bssl::UniquePtr<SSL_SESSION> session = CreateClientSessionForQUIC();
+  ASSERT_TRUE(session);
+
+  ASSERT_TRUE(CreateClientAndServer());
+  static const uint8_t new_context[] = {4};
+  ASSERT_TRUE(SSL_set_quic_early_data_context(server_.get(), new_context,
+                                              sizeof(new_context)));
+  SSL_set_session(client_.get(), session.get());
+
+  // The client handshake should return immediately into the early data
+  // state.
+  ASSERT_EQ(SSL_do_handshake(client_.get()), 1);
+  EXPECT_TRUE(SSL_in_early_data(client_.get()));
+  // The transport should have keys for sending 0-RTT data.
+  EXPECT_TRUE(transport_->client()->HasWriteSecret(ssl_encryption_early_data));
+
+  // The server will consume the ClientHello, but it will not accept 0-RTT.
+  ASSERT_TRUE(ProvideHandshakeData(server_.get()));
+  ASSERT_EQ(SSL_do_handshake(server_.get()), -1);
+  EXPECT_EQ(SSL_ERROR_WANT_READ, SSL_get_error(server_.get(), -1));
+  EXPECT_FALSE(SSL_in_early_data(server_.get()));
+  EXPECT_FALSE(transport_->server()->HasReadSecret(ssl_encryption_early_data));
+
+  // The client consumes the server response and signals 0-RTT rejection.
+  for (;;) {
+    ASSERT_TRUE(ProvideHandshakeData(client_.get()));
+    ASSERT_EQ(-1, SSL_do_handshake(client_.get()));
+    int err = SSL_get_error(client_.get(), -1);
+    if (err == SSL_ERROR_EARLY_DATA_REJECTED) {
+      break;
+    }
+    ASSERT_EQ(SSL_ERROR_WANT_READ, err);
+  }
+
+  // As in TLS over TCP, 0-RTT rejection is sticky.
+  ASSERT_EQ(-1, SSL_do_handshake(client_.get()));
+  ASSERT_EQ(SSL_ERROR_EARLY_DATA_REJECTED, SSL_get_error(client_.get(), -1));
+
+  // Finish up the client and server handshakes.
+  SSL_reset_early_data_reject(client_.get());
+  ASSERT_TRUE(CompleteHandshakesForQUIC());
+
+  // Both sides can now exchange 1-RTT data.
+  ExpectHandshakeSuccess();
+  EXPECT_TRUE(SSL_session_reused(client_.get()));
+  EXPECT_TRUE(SSL_session_reused(server_.get()));
+  EXPECT_FALSE(SSL_in_early_data(client_.get()));
+  EXPECT_FALSE(SSL_in_early_data(server_.get()));
+  EXPECT_FALSE(SSL_early_data_accepted(client_.get()));
+  EXPECT_FALSE(SSL_early_data_accepted(server_.get()));
+}
+
+TEST_F(QUICMethodTest, NoZeroRTTTicketWithoutEarlyDataContext) {
+  server_quic_early_data_context_ = {};
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_early_data_enabled(client_ctx_.get(), 1);
+  SSL_CTX_set_early_data_enabled(server_ctx_.get(), 1);
+  ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+
+  bssl::UniquePtr<SSL_SESSION> session = CreateClientSessionForQUIC();
+  ASSERT_TRUE(session);
+  EXPECT_FALSE(SSL_SESSION_early_data_capable(session.get()));
+}
+
 TEST_F(QUICMethodTest, ZeroRTTReject) {
-  const SSL_QUIC_METHOD quic_method = {
-      SetEncryptionSecretsCallback,
-      AddHandshakeDataCallback,
-      FlushFlightCallback,
-      SendAlertCallback,
-  };
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
 
   SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
   SSL_CTX_set_early_data_enabled(client_ctx_.get(), 1);
@@ -5303,14 +5544,16 @@
     ASSERT_EQ(SSL_do_handshake(client_.get()), 1);
     EXPECT_TRUE(SSL_in_early_data(client_.get()));
     // The transport should have keys for sending 0-RTT data.
-    EXPECT_TRUE(transport_->client()->HasSecrets(ssl_encryption_early_data));
+    EXPECT_TRUE(
+        transport_->client()->HasWriteSecret(ssl_encryption_early_data));
 
     // The server will consume the ClientHello, but it will not accept 0-RTT.
     ASSERT_TRUE(ProvideHandshakeData(server_.get()));
     ASSERT_EQ(SSL_do_handshake(server_.get()), -1);
     EXPECT_EQ(SSL_ERROR_WANT_READ, SSL_get_error(server_.get(), -1));
     EXPECT_FALSE(SSL_in_early_data(server_.get()));
-    EXPECT_FALSE(transport_->server()->HasSecrets(ssl_encryption_early_data));
+    EXPECT_FALSE(
+        transport_->server()->HasReadSecret(ssl_encryption_early_data));
 
     // The client consumes the server response and signals 0-RTT rejection.
     for (;;) {
@@ -5343,12 +5586,7 @@
 }
 
 TEST_F(QUICMethodTest, NoZeroRTTKeysBeforeReverify) {
-  const SSL_QUIC_METHOD quic_method = {
-      SetEncryptionSecretsCallback,
-      AddHandshakeDataCallback,
-      FlushFlightCallback,
-      SendAlertCallback,
-  };
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
 
   SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
   SSL_CTX_set_early_data_enabled(client_ctx_.get(), 1);
@@ -5375,7 +5613,7 @@
             SSL_ERROR_WANT_CERTIFICATE_VERIFY);
 
   // The early data keys have not yet been released.
-  EXPECT_FALSE(transport_->client()->HasSecrets(ssl_encryption_early_data));
+  EXPECT_FALSE(transport_->client()->HasWriteSecret(ssl_encryption_early_data));
 
   // After the verification completes, the handshake progresses to the 0-RTT
   // point and releases keys.
@@ -5386,19 +5624,14 @@
       });
   ASSERT_EQ(SSL_do_handshake(client_.get()), 1);
   EXPECT_TRUE(SSL_in_early_data(client_.get()));
-  EXPECT_TRUE(transport_->client()->HasSecrets(ssl_encryption_early_data));
+  EXPECT_TRUE(transport_->client()->HasWriteSecret(ssl_encryption_early_data));
 }
 
 // Test only releasing data to QUIC one byte at a time on request, to maximize
 // state machine pauses. Additionally, test that existing asynchronous callbacks
 // still work.
 TEST_F(QUICMethodTest, Async) {
-  const SSL_QUIC_METHOD quic_method = {
-      SetEncryptionSecretsCallback,
-      AddHandshakeDataCallback,
-      FlushFlightCallback,
-      SendAlertCallback,
-  };
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
 
   ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
   ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
@@ -5447,6 +5680,8 @@
 
 // Test buffering write data until explicit flushes.
 TEST_F(QUICMethodTest, Buffered) {
+  AllowOutOfOrderWrites();
+
   struct BufferedFlight {
     std::vector<uint8_t> data[kNumQUICLevels];
   };
@@ -5474,12 +5709,9 @@
     return 1;
   };
 
-  const SSL_QUIC_METHOD quic_method = {
-    SetEncryptionSecretsCallback,
-    add_handshake_data,
-    flush_flight,
-    SendAlertCallback,
-  };
+  SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+  quic_method.add_handshake_data = add_handshake_data;
+  quic_method.flush_flight = flush_flight;
 
   ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
   ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
@@ -5499,6 +5731,8 @@
 // EncryptedExtensions in a single chunk, BoringSSL notices and rejects this on
 // key change.
 TEST_F(QUICMethodTest, ExcessProvidedData) {
+  AllowOutOfOrderWrites();
+
   auto add_handshake_data = [](SSL *ssl, enum ssl_encryption_level_t level,
                                const uint8_t *data, size_t len) -> int {
     // Switch everything to the initial level.
@@ -5506,12 +5740,8 @@
                                                      MakeConstSpan(data, len));
   };
 
-  const SSL_QUIC_METHOD quic_method = {
-      SetEncryptionSecretsCallback,
-      add_handshake_data,
-      FlushFlightCallback,
-      SendAlertCallback,
-  };
+  SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+  quic_method.add_handshake_data = add_handshake_data;
 
   ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
   ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
@@ -5540,24 +5770,23 @@
   EXPECT_EQ(ERR_GET_LIB(err), ERR_LIB_SSL);
   EXPECT_EQ(ERR_GET_REASON(err), SSL_R_EXCESS_HANDSHAKE_DATA);
 
-  // The client sends an alert in response to this.
+  // The client sends an alert in response to this. The alert is sent at
+  // handshake level because we install write secrets before read secrets and
+  // the error is discovered when installing the read secret. (How to send
+  // alerts on protocol syntax errors near key changes is ambiguous in general.)
   ASSERT_TRUE(transport_->client()->has_alert());
-  EXPECT_EQ(transport_->client()->alert_level(), ssl_encryption_initial);
+  EXPECT_EQ(transport_->client()->alert_level(), ssl_encryption_handshake);
   EXPECT_EQ(transport_->client()->alert(), SSL_AD_UNEXPECTED_MESSAGE);
 
-  // Sanity-check client did get far enough to process the ServerHello and
-  // install keys.
-  EXPECT_TRUE(transport_->client()->HasSecrets(ssl_encryption_handshake));
+  // Sanity-check handshake secrets. The error is discovered while setting the
+  // read secret, so only the write secret has been installed.
+  EXPECT_TRUE(transport_->client()->HasWriteSecret(ssl_encryption_handshake));
+  EXPECT_FALSE(transport_->client()->HasReadSecret(ssl_encryption_handshake));
 }
 
 // Test that |SSL_provide_quic_data| will reject data at the wrong level.
 TEST_F(QUICMethodTest, ProvideWrongLevel) {
-  const SSL_QUIC_METHOD quic_method = {
-      SetEncryptionSecretsCallback,
-      AddHandshakeDataCallback,
-      FlushFlightCallback,
-      SendAlertCallback,
-  };
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
 
   ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
   ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
@@ -5597,12 +5826,7 @@
 }
 
 TEST_F(QUICMethodTest, TooMuchData) {
-  const SSL_QUIC_METHOD quic_method = {
-      SetEncryptionSecretsCallback,
-      AddHandshakeDataCallback,
-      FlushFlightCallback,
-      SendAlertCallback,
-  };
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
 
   ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
   ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
@@ -5622,12 +5846,7 @@
 
 // Provide invalid post-handshake data.
 TEST_F(QUICMethodTest, BadPostHandshake) {
-  const SSL_QUIC_METHOD quic_method = {
-      SetEncryptionSecretsCallback,
-      AddHandshakeDataCallback,
-      FlushFlightCallback,
-      SendAlertCallback,
-  };
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
 
   g_last_session = nullptr;
 
@@ -5651,6 +5870,169 @@
   EXPECT_EQ(SSL_process_quic_post_handshake(client_.get()), 0);
 }
 
+static void ExpectReceivedTransportParamsEqual(const SSL *ssl,
+                                               Span<const uint8_t> expected) {
+  const uint8_t *received;
+  size_t received_len;
+  SSL_get_peer_quic_transport_params(ssl, &received, &received_len);
+  ASSERT_EQ(received_len, expected.size());
+  EXPECT_EQ(Bytes(received, received_len), Bytes(expected));
+}
+
+TEST_F(QUICMethodTest, SetTransportParameters) {
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+  ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+
+  ASSERT_TRUE(CreateClientAndServer());
+  uint8_t kClientParams[] = {1, 2, 3, 4};
+  uint8_t kServerParams[] = {5, 6, 7};
+  ASSERT_TRUE(SSL_set_quic_transport_params(client_.get(), kClientParams,
+                                            sizeof(kClientParams)));
+  ASSERT_TRUE(SSL_set_quic_transport_params(server_.get(), kServerParams,
+                                            sizeof(kServerParams)));
+
+  ASSERT_TRUE(CompleteHandshakesForQUIC());
+  ExpectReceivedTransportParamsEqual(client_.get(), kServerParams);
+  ExpectReceivedTransportParamsEqual(server_.get(), kClientParams);
+}
+
+TEST_F(QUICMethodTest, SetTransportParamsInCallback) {
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+  ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+
+  ASSERT_TRUE(CreateClientAndServer());
+  uint8_t kClientParams[] = {1, 2, 3, 4};
+  static uint8_t kServerParams[] = {5, 6, 7};
+  ASSERT_TRUE(SSL_set_quic_transport_params(client_.get(), kClientParams,
+                                            sizeof(kClientParams)));
+  SSL_CTX_set_tlsext_servername_callback(
+      server_ctx_.get(), [](SSL *ssl, int *out_alert, void *arg) -> int {
+        EXPECT_TRUE(SSL_set_quic_transport_params(ssl, kServerParams,
+                                                  sizeof(kServerParams)));
+        return SSL_TLSEXT_ERR_OK;
+      });
+
+  ASSERT_TRUE(CompleteHandshakesForQUIC());
+  ExpectReceivedTransportParamsEqual(client_.get(), kServerParams);
+  ExpectReceivedTransportParamsEqual(server_.get(), kClientParams);
+}
+
+TEST_F(QUICMethodTest, ForbidCrossProtocolResumptionClient) {
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+
+  g_last_session = nullptr;
+
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_sess_set_new_cb(client_ctx_.get(), SaveLastSession);
+  ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+
+  ASSERT_TRUE(CreateClientAndServer());
+  ASSERT_TRUE(CompleteHandshakesForQUIC());
+
+  ExpectHandshakeSuccess();
+  EXPECT_FALSE(SSL_session_reused(client_.get()));
+  EXPECT_FALSE(SSL_session_reused(server_.get()));
+
+  // The server sent NewSessionTicket messages in the handshake.
+  EXPECT_FALSE(g_last_session);
+  ASSERT_TRUE(ProvideHandshakeData(client_.get()));
+  EXPECT_EQ(SSL_process_quic_post_handshake(client_.get()), 1);
+  EXPECT_TRUE(g_last_session);
+
+  // Pretend that g_last_session came from a TLS-over-TCP connection.
+  g_last_session.get()->is_quic = false;
+
+  // Create a second connection and verify that resumption does not occur with
+  // a session from a non-QUIC connection. This tests that the client does not
+  // offer over QUIC a session believed to be received over TCP. The server
+  // believes this is a QUIC session, so if the client offered the session, the
+  // server would have resumed it.
+  ASSERT_TRUE(CreateClientAndServer());
+  bssl::UniquePtr<SSL_SESSION> session = std::move(g_last_session);
+  SSL_set_session(client_.get(), session.get());
+
+  ASSERT_TRUE(CompleteHandshakesForQUIC());
+  ExpectHandshakeSuccess();
+  EXPECT_FALSE(SSL_session_reused(client_.get()));
+  EXPECT_FALSE(SSL_session_reused(server_.get()));
+}
+
+TEST_F(QUICMethodTest, ForbidCrossProtocolResumptionServer) {
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+
+  g_last_session = nullptr;
+
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_sess_set_new_cb(client_ctx_.get(), SaveLastSession);
+  ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+
+  ASSERT_TRUE(CreateClientAndServer());
+  ASSERT_TRUE(CompleteHandshakesForQUIC());
+
+  ExpectHandshakeSuccess();
+  EXPECT_FALSE(SSL_session_reused(client_.get()));
+  EXPECT_FALSE(SSL_session_reused(server_.get()));
+
+  // The server sent NewSessionTicket messages in the handshake.
+  EXPECT_FALSE(g_last_session);
+  ASSERT_TRUE(ProvideHandshakeData(client_.get()));
+  EXPECT_EQ(SSL_process_quic_post_handshake(client_.get()), 1);
+  EXPECT_TRUE(g_last_session);
+
+  // Attempt a resumption with g_last_session using TLS_method.
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(client_ctx);
+
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), nullptr));
+
+  bssl::UniquePtr<SSL> client(SSL_new(client_ctx.get())),
+      server(SSL_new(server_ctx_.get()));
+  ASSERT_TRUE(client);
+  ASSERT_TRUE(server);
+  SSL_set_connect_state(client.get());
+  SSL_set_accept_state(server.get());
+
+  // The TLS-over-TCP client will refuse to resume with a quic session, so
+  // mark is_quic = false to bypass the client check to test the server check.
+  g_last_session.get()->is_quic = false;
+  SSL_set_session(client.get(), g_last_session.get());
+
+  BIO *bio1, *bio2;
+  ASSERT_TRUE(BIO_new_bio_pair(&bio1, 0, &bio2, 0));
+
+  // SSL_set_bio takes ownership.
+  SSL_set_bio(client.get(), bio1, bio1);
+  SSL_set_bio(server.get(), bio2, bio2);
+  ASSERT_TRUE(CompleteHandshakes(client.get(), server.get()));
+
+  EXPECT_FALSE(SSL_session_reused(client.get()));
+  EXPECT_FALSE(SSL_session_reused(server.get()));
+}
+
+TEST_F(QUICMethodTest, ClientRejectsMissingTransportParams) {
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+  ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+
+  ASSERT_TRUE(CreateClientAndServer());
+  ASSERT_TRUE(SSL_set_quic_transport_params(server_.get(), nullptr, 0));
+  ASSERT_TRUE(RunQUICHandshakesAndExpectError(ExpectedError::kServerError));
+}
+
+TEST_F(QUICMethodTest, ServerRejectsMissingTransportParams) {
+  const SSL_QUIC_METHOD quic_method = DefaultQUICMethod();
+  ASSERT_TRUE(SSL_CTX_set_quic_method(client_ctx_.get(), &quic_method));
+  ASSERT_TRUE(SSL_CTX_set_quic_method(server_ctx_.get(), &quic_method));
+
+  ASSERT_TRUE(CreateClientAndServer());
+  ASSERT_TRUE(SSL_set_quic_transport_params(client_.get(), nullptr, 0));
+  ASSERT_TRUE(RunQUICHandshakesAndExpectError(ExpectedError::kClientError));
+}
+
 extern "C" {
 int BORINGSSL_enum_c_type_test(void);
 }
@@ -5749,6 +6131,111 @@
   }
 }
 
+TEST_P(SSLVersionTest, SameKeyResume) {
+  uint8_t key[48];
+  RAND_bytes(key, sizeof(key));
+
+  bssl::UniquePtr<SSL_CTX> server_ctx2 = CreateContext();
+  ASSERT_TRUE(server_ctx2);
+  ASSERT_TRUE(UseCertAndKey(server_ctx2.get()));
+  ASSERT_TRUE(
+      SSL_CTX_set_tlsext_ticket_keys(server_ctx_.get(), key, sizeof(key)));
+  ASSERT_TRUE(
+      SSL_CTX_set_tlsext_ticket_keys(server_ctx2.get(), key, sizeof(key)));
+
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_session_cache_mode(server_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_session_cache_mode(server_ctx2.get(), SSL_SESS_CACHE_BOTH);
+
+  // Establish a session for |server_ctx_|.
+  bssl::UniquePtr<SSL_SESSION> session =
+      CreateClientSession(client_ctx_.get(), server_ctx_.get());
+  ASSERT_TRUE(session);
+  ClientConfig config;
+  config.session = session.get();
+
+  // Resuming with |server_ctx_| again works.
+  bssl::UniquePtr<SSL> client, server;
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx_.get(),
+                                     server_ctx_.get(), config));
+  EXPECT_TRUE(SSL_session_reused(client.get()));
+  EXPECT_TRUE(SSL_session_reused(server.get()));
+
+  // Resuming with |server_ctx2| also works.
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx_.get(),
+                                     server_ctx2.get(), config));
+  EXPECT_TRUE(SSL_session_reused(client.get()));
+  EXPECT_TRUE(SSL_session_reused(server.get()));
+}
+
+TEST_P(SSLVersionTest, DifferentKeyNoResume) {
+  uint8_t key1[48], key2[48];
+  RAND_bytes(key1, sizeof(key1));
+  RAND_bytes(key2, sizeof(key2));
+
+  bssl::UniquePtr<SSL_CTX> server_ctx2 = CreateContext();
+  ASSERT_TRUE(server_ctx2);
+  ASSERT_TRUE(UseCertAndKey(server_ctx2.get()));
+  ASSERT_TRUE(
+      SSL_CTX_set_tlsext_ticket_keys(server_ctx_.get(), key1, sizeof(key1)));
+  ASSERT_TRUE(
+      SSL_CTX_set_tlsext_ticket_keys(server_ctx2.get(), key2, sizeof(key2)));
+
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_session_cache_mode(server_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_session_cache_mode(server_ctx2.get(), SSL_SESS_CACHE_BOTH);
+
+  // Establish a session for |server_ctx_|.
+  bssl::UniquePtr<SSL_SESSION> session =
+      CreateClientSession(client_ctx_.get(), server_ctx_.get());
+  ASSERT_TRUE(session);
+  ClientConfig config;
+  config.session = session.get();
+
+  // Resuming with |server_ctx_| again works.
+  bssl::UniquePtr<SSL> client, server;
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx_.get(),
+                                     server_ctx_.get(), config));
+  EXPECT_TRUE(SSL_session_reused(client.get()));
+  EXPECT_TRUE(SSL_session_reused(server.get()));
+
+  // Resuming with |server_ctx2| does not work.
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx_.get(),
+                                     server_ctx2.get(), config));
+  EXPECT_FALSE(SSL_session_reused(client.get()));
+  EXPECT_FALSE(SSL_session_reused(server.get()));
+}
+
+TEST_P(SSLVersionTest, UnrelatedServerNoResume) {
+  bssl::UniquePtr<SSL_CTX> server_ctx2 = CreateContext();
+  ASSERT_TRUE(server_ctx2);
+  ASSERT_TRUE(UseCertAndKey(server_ctx2.get()));
+
+  SSL_CTX_set_session_cache_mode(client_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_session_cache_mode(server_ctx_.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_session_cache_mode(server_ctx2.get(), SSL_SESS_CACHE_BOTH);
+
+  // Establish a session for |server_ctx_|.
+  bssl::UniquePtr<SSL_SESSION> session =
+      CreateClientSession(client_ctx_.get(), server_ctx_.get());
+  ASSERT_TRUE(session);
+  ClientConfig config;
+  config.session = session.get();
+
+  // Resuming with |server_ctx_| again works.
+  bssl::UniquePtr<SSL> client, server;
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx_.get(),
+                                     server_ctx_.get(), config));
+  EXPECT_TRUE(SSL_session_reused(client.get()));
+  EXPECT_TRUE(SSL_session_reused(server.get()));
+
+  // Resuming with |server_ctx2| does not work.
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx_.get(),
+                                     server_ctx2.get(), config));
+  EXPECT_FALSE(SSL_session_reused(client.get()));
+  EXPECT_FALSE(SSL_session_reused(server.get()));
+}
+
 TEST(SSLTest, WriteWhileExplicitRenegotiate) {
   bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
   ASSERT_TRUE(ctx);
@@ -5883,5 +6370,124 @@
   EXPECT_EQ(SSL_R_NO_RENEGOTIATION, ERR_GET_REASON(err));
 }
 
+
+TEST(SSLTest, CopyWithoutEarlyData) {
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(client_ctx);
+  ASSERT_TRUE(server_ctx);
+
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  ASSERT_TRUE(cert);
+  ASSERT_TRUE(key);
+  ASSERT_TRUE(SSL_CTX_use_certificate(server_ctx.get(), cert.get()));
+  ASSERT_TRUE(SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()));
+
+  SSL_CTX_set_session_cache_mode(client_ctx.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_session_cache_mode(server_ctx.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_early_data_enabled(client_ctx.get(), 1);
+  SSL_CTX_set_early_data_enabled(server_ctx.get(), 1);
+
+  bssl::UniquePtr<SSL_SESSION> session =
+      CreateClientSession(client_ctx.get(), server_ctx.get());
+  ASSERT_TRUE(session);
+
+  // The client should attempt early data with |session|.
+  auto config = ClientConfig();
+  config.early_data = true;
+  config.session = session.get();
+  bssl::UniquePtr<SSL> client, server;
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+                                     server_ctx.get(), config,
+                                     /*do_handshake=*/false));
+  ASSERT_EQ(1, SSL_do_handshake(client.get()));
+  EXPECT_TRUE(SSL_in_early_data(client.get()));
+
+  // |SSL_SESSION_copy_without_early_data| should disable early data but
+  // still resume the session.
+  bssl::UniquePtr<SSL_SESSION> session2(
+      SSL_SESSION_copy_without_early_data(session.get()));
+  ASSERT_TRUE(session2);
+  EXPECT_NE(session.get(), session2.get());
+  config.session = session2.get();
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+                                     server_ctx.get(), config));
+  EXPECT_TRUE(SSL_session_reused(client.get()));
+  EXPECT_EQ(ssl_early_data_unsupported_for_session,
+            SSL_get_early_data_reason(client.get()));
+
+  // |SSL_SESSION_copy_without_early_data| should be a reference count increase
+  // when passed an early-data-incapable session.
+  bssl::UniquePtr<SSL_SESSION> session3(
+      SSL_SESSION_copy_without_early_data(session2.get()));
+  EXPECT_EQ(session2.get(), session3.get());
+}
+
+TEST(SSLTest, ProcessTLS13NewSessionTicket) {
+  // Configure client and server to negotiate TLS 1.3 only.
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(client_ctx);
+  ASSERT_TRUE(server_ctx);
+  ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), TLS1_3_VERSION));
+  ASSERT_TRUE(SSL_CTX_set_min_proto_version(server_ctx.get(), TLS1_3_VERSION));
+  ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION));
+  ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_3_VERSION));
+  ASSERT_TRUE(SSL_CTX_use_certificate(server_ctx.get(), cert.get()));
+  ASSERT_TRUE(SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()));
+
+  bssl::UniquePtr<SSL> client, server;
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+                                     server_ctx.get()));
+  EXPECT_EQ(TLS1_3_VERSION, SSL_version(client.get()));
+
+  // Process a TLS 1.3 NewSessionTicket.
+  static const uint8_t kTicket[] = {
+      0x04, 0x00, 0x00, 0xb2, 0x00, 0x02, 0xa3, 0x00, 0x04, 0x03, 0x02, 0x01,
+      0x01, 0x00, 0x00, 0xa0, 0x01, 0x06, 0x09, 0x11, 0x16, 0x19, 0x21, 0x26,
+      0x29, 0x31, 0x36, 0x39, 0x41, 0x46, 0x49, 0x51, 0x03, 0x06, 0x09, 0x13,
+      0x16, 0x19, 0x23, 0x26, 0x29, 0x33, 0x36, 0x39, 0x43, 0x46, 0x49, 0x53,
+      0xf7, 0x00, 0x29, 0xec, 0xf2, 0xc4, 0xa4, 0x41, 0xfc, 0x30, 0x17, 0x2e,
+      0x9f, 0x7c, 0xa8, 0xaf, 0x75, 0x70, 0xf0, 0x1f, 0xc7, 0x98, 0xf7, 0xcf,
+      0x5a, 0x5a, 0x6b, 0x5b, 0xfe, 0xf1, 0xe7, 0x3a, 0xe8, 0xf7, 0x6c, 0xd2,
+      0xa8, 0xa6, 0x92, 0x5b, 0x96, 0x8d, 0xde, 0xdb, 0xd3, 0x20, 0x6a, 0xcb,
+      0x69, 0x06, 0xf4, 0x91, 0x85, 0x2e, 0xe6, 0x5e, 0x0c, 0x59, 0xf2, 0x9e,
+      0x9b, 0x79, 0x91, 0x24, 0x7e, 0x4a, 0x32, 0x3d, 0xbe, 0x4b, 0x80, 0x70,
+      0xaf, 0xd0, 0x1d, 0xe2, 0xca, 0x05, 0x35, 0x09, 0x09, 0x05, 0x0f, 0xbb,
+      0xc4, 0xae, 0xd7, 0xc4, 0xed, 0xd7, 0xae, 0x35, 0xc8, 0x73, 0x63, 0x78,
+      0x64, 0xc9, 0x7a, 0x1f, 0xed, 0x7a, 0x9a, 0x47, 0x44, 0xfd, 0x50, 0xf7,
+      0xb7, 0xe0, 0x64, 0xa9, 0x02, 0xc1, 0x5c, 0x23, 0x18, 0x3f, 0xc4, 0xcf,
+      0x72, 0x02, 0x59, 0x2d, 0xe1, 0xaa, 0x61, 0x72, 0x00, 0x04, 0x5a, 0x5a,
+      0x00, 0x00,
+  };
+  bssl::UniquePtr<SSL_SESSION> session(SSL_process_tls13_new_session_ticket(
+      client.get(), kTicket, sizeof(kTicket)));
+  ASSERT_TRUE(session);
+  ASSERT_TRUE(SSL_SESSION_has_ticket(session.get()));
+
+  uint8_t *session_buf = nullptr;
+  size_t session_length = 0;
+  ASSERT_TRUE(
+      SSL_SESSION_to_bytes(session.get(), &session_buf, &session_length));
+  bssl::UniquePtr<uint8_t> session_buf_free(session_buf);
+  ASSERT_TRUE(session_buf);
+  ASSERT_GT(session_length, 0u);
+
+  // Servers cannot call |SSL_process_tls13_new_session_ticket|.
+  ASSERT_FALSE(SSL_process_tls13_new_session_ticket(server.get(), kTicket,
+                                                    sizeof(kTicket)));
+
+  // Clients cannot call |SSL_process_tls13_new_session_ticket| before the
+  // handshake completes.
+  bssl::UniquePtr<SSL> client2(SSL_new(client_ctx.get()));
+  ASSERT_TRUE(client2);
+  SSL_set_connect_state(client2.get());
+  ASSERT_FALSE(SSL_process_tls13_new_session_ticket(client2.get(), kTicket,
+                                                    sizeof(kTicket)));
+}
+
 }  // namespace
 BSSL_NAMESPACE_END
diff --git a/src/ssl/ssl_versions.cc b/src/ssl/ssl_versions.cc
index d95aeb3..3bbb4e3 100644
--- a/src/ssl/ssl_versions.cc
+++ b/src/ssl/ssl_versions.cc
@@ -193,11 +193,11 @@
     min_version = TLS1_3_VERSION;
   }
 
-  // OpenSSL's API for controlling versions entails blacklisting individual
-  // protocols. This has two problems. First, on the client, the protocol can
-  // only express a contiguous range of versions. Second, a library consumer
-  // trying to set a maximum version cannot disable protocol versions that get
-  // added in a future version of the library.
+  // The |SSL_OP_NO_*| flags disable individual protocols. This has two
+  // problems. First, prior to TLS 1.3, the protocol can only express a
+  // contiguous range of versions. Second, a library consumer trying to set a
+  // maximum version cannot disable protocol versions that get added in a future
+  // version of the library.
   //
   // To account for both of these, OpenSSL interprets the client-side bitmask
   // as a min/max range by picking the lowest contiguous non-empty range of
diff --git a/src/ssl/t1_enc.cc b/src/ssl/t1_enc.cc
index 8091021..d8b6ea2 100644
--- a/src/ssl/t1_enc.cc
+++ b/src/ssl/t1_enc.cc
@@ -189,21 +189,36 @@
   return true;
 }
 
-int tls1_configure_aead(SSL *ssl, evp_aead_direction_t direction,
-                        Array<uint8_t> *key_block_cache,
-                        const SSL_CIPHER *cipher,
-                        Span<const uint8_t> iv_override) {
+static bool generate_key_block(const SSL *ssl, Span<uint8_t> out,
+                               const SSL_SESSION *session) {
+  auto master_key =
+      MakeConstSpan(session->master_key, session->master_key_length);
+  static const char kLabel[] = "key expansion";
+  auto label = MakeConstSpan(kLabel, sizeof(kLabel) - 1);
+
+  const EVP_MD *digest = ssl_session_get_digest(session);
+  // Note this function assumes that |session|'s key material corresponds to
+  // |ssl->s3->client_random| and |ssl->s3->server_random|.
+  return tls1_prf(digest, out, master_key, label, ssl->s3->server_random,
+                  ssl->s3->client_random);
+}
+
+bool tls1_configure_aead(SSL *ssl, evp_aead_direction_t direction,
+                         Array<uint8_t> *key_block_cache,
+                         const SSL_SESSION *session,
+                         Span<const uint8_t> iv_override) {
   size_t mac_secret_len, key_len, iv_len;
-  if (!get_key_block_lengths(ssl, &mac_secret_len, &key_len, &iv_len, cipher)) {
-    return 0;
+  if (!get_key_block_lengths(ssl, &mac_secret_len, &key_len, &iv_len,
+                             session->cipher)) {
+    return false;
   }
 
   // Ensure that |key_block_cache| is set up.
   const size_t key_block_size = 2 * (mac_secret_len + key_len + iv_len);
   if (key_block_cache->empty()) {
     if (!key_block_cache->Init(key_block_size) ||
-        !SSL_generate_key_block(ssl, key_block_cache->data(), key_block_size)) {
-      return 0;
+        !generate_key_block(ssl, MakeSpan(*key_block_cache), session)) {
+      return false;
     }
   }
   assert(key_block_cache->size() == key_block_size);
@@ -224,30 +239,33 @@
 
   if (!iv_override.empty()) {
     if (iv_override.size() != iv_len) {
-      return 0;
+      return false;
     }
     iv = iv_override;
   }
 
-  UniquePtr<SSLAEADContext> aead_ctx = SSLAEADContext::Create(
-      direction, ssl->version, SSL_is_dtls(ssl), cipher, key, mac_secret, iv);
+  UniquePtr<SSLAEADContext> aead_ctx =
+      SSLAEADContext::Create(direction, ssl->version, SSL_is_dtls(ssl),
+                             session->cipher, key, mac_secret, iv);
   if (!aead_ctx) {
-    return 0;
+    return false;
   }
 
   if (direction == evp_aead_open) {
     return ssl->method->set_read_state(ssl, ssl_encryption_application,
-                                       std::move(aead_ctx));
+                                       std::move(aead_ctx),
+                                       /*secret_for_quic=*/{});
   }
 
   return ssl->method->set_write_state(ssl, ssl_encryption_application,
-                                      std::move(aead_ctx));
+                                      std::move(aead_ctx),
+                                      /*secret_for_quic=*/{});
 }
 
-int tls1_change_cipher_state(SSL_HANDSHAKE *hs,
-                             evp_aead_direction_t direction) {
+bool tls1_change_cipher_state(SSL_HANDSHAKE *hs,
+                              evp_aead_direction_t direction) {
   return tls1_configure_aead(hs->ssl, direction, &hs->key_block,
-                             hs->new_cipher, {});
+                             ssl_handshake_session(hs), {});
 }
 
 int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
@@ -284,6 +302,11 @@
 using namespace bssl;
 
 size_t SSL_get_key_block_len(const SSL *ssl) {
+  // See |SSL_generate_key_block|.
+  if (SSL_in_init(ssl)) {
+    return 0;
+  }
+
   size_t mac_secret_len, key_len, fixed_iv_len;
   if (!get_key_block_lengths(ssl, &mac_secret_len, &key_len, &fixed_iv_len,
                              SSL_get_current_cipher(ssl))) {
@@ -295,16 +318,16 @@
 }
 
 int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
-  const SSL_SESSION *session = SSL_get_session(ssl);
-  auto out_span = MakeSpan(out, out_len);
-  auto master_key =
-      MakeConstSpan(session->master_key, session->master_key_length);
-  static const char kLabel[] = "key expansion";
-  auto label = MakeConstSpan(kLabel, sizeof(kLabel) - 1);
+  // Which cipher state to use is ambiguous during a handshake. In particular,
+  // there are points where read and write states are from different epochs.
+  // During a handshake, before ChangeCipherSpec, the encryption states may not
+  // match |ssl->s3->client_random| and |ssl->s3->server_random|.
+  if (SSL_in_init(ssl)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
 
-  const EVP_MD *digest = ssl_session_get_digest(session);
-  return tls1_prf(digest, out_span, master_key, label, ssl->s3->server_random,
-                  ssl->s3->client_random);
+  return generate_key_block(ssl, MakeSpan(out, out_len), SSL_get_session(ssl));
 }
 
 int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 5fdfec2..4a2bbcf 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -1245,6 +1245,12 @@
 
 static bool ext_alpn_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
   SSL *const ssl = hs->ssl;
+  if (hs->config->alpn_client_proto_list.empty() && ssl->quic_method) {
+    // ALPN MUST be used with QUIC.
+    OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_ALPN);
+    return false;
+  }
+
   if (hs->config->alpn_client_proto_list.empty() ||
       ssl->s3->initial_handshake_complete) {
     return true;
@@ -1267,6 +1273,12 @@
                                        CBS *contents) {
   SSL *const ssl = hs->ssl;
   if (contents == NULL) {
+    if (ssl->quic_method) {
+      // ALPN is required when QUIC is used.
+      OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_ALPN);
+      *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
+      return false;
+    }
     return true;
   }
 
@@ -1342,6 +1354,12 @@
       !ssl_client_hello_get_extension(
           client_hello, &contents,
           TLSEXT_TYPE_application_layer_protocol_negotiation)) {
+    if (ssl->quic_method) {
+      // ALPN is required when QUIC is used.
+      OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_ALPN);
+      *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
+      return false;
+    }
     // Ignore ALPN if not configured or no extension was supplied.
     return true;
   }
@@ -1388,6 +1406,11 @@
       *out_alert = SSL_AD_INTERNAL_ERROR;
       return false;
     }
+  } else if (ssl->quic_method) {
+    // ALPN is required when QUIC is used.
+    OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_ALPN);
+    *out_alert = SSL_AD_NO_APPLICATION_PROTOCOL;
+    return false;
   }
 
   return true;
@@ -2547,10 +2570,17 @@
 
 static bool ext_quic_transport_params_add_clienthello(SSL_HANDSHAKE *hs,
                                                       CBB *out) {
-  if (hs->config->quic_transport_params.empty() ||
-      hs->max_version <= TLS1_2_VERSION) {
+  if (hs->config->quic_transport_params.empty() && !hs->ssl->quic_method) {
     return true;
   }
+  if (hs->config->quic_transport_params.empty() || !hs->ssl->quic_method) {
+    // QUIC Transport Parameters must be sent over QUIC, and they must not be
+    // sent over non-QUIC transports. If transport params are set, then
+    // SSL(_CTX)_set_quic_method must also be called.
+    OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
+    return false;
+  }
+  assert(hs->min_version > TLS1_2_VERSION);
 
   CBB contents;
   if (!CBB_add_u16(out, TLSEXT_TYPE_quic_transport_parameters) ||
@@ -2568,13 +2598,19 @@
                                                         CBS *contents) {
   SSL *const ssl = hs->ssl;
   if (contents == nullptr) {
-    return true;
+    if (!ssl->quic_method) {
+      return true;
+    }
+    assert(ssl->quic_method);
+    *out_alert = SSL_AD_MISSING_EXTENSION;
+    return false;
   }
-  // QUIC requires TLS 1.3.
-  if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
+  if (!ssl->quic_method) {
     *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
     return false;
   }
+  // QUIC requires TLS 1.3.
+  assert(ssl_protocol_version(ssl) == TLS1_3_VERSION);
 
   return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
 }
@@ -2583,21 +2619,34 @@
                                                         uint8_t *out_alert,
                                                         CBS *contents) {
   SSL *const ssl = hs->ssl;
-  if (!contents || hs->config->quic_transport_params.empty()) {
-    return true;
+  if (!contents) {
+    if (!ssl->quic_method) {
+      if (hs->config->quic_transport_params.empty()) {
+        return true;
+      }
+      // QUIC transport parameters must not be set if |ssl| is not configured
+      // for QUIC.
+      OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
+      *out_alert = SSL_AD_INTERNAL_ERROR;
+    }
+    *out_alert = SSL_AD_MISSING_EXTENSION;
+    return false;
   }
-  // Ignore the extension before TLS 1.3.
-  if (ssl_protocol_version(ssl) < TLS1_3_VERSION) {
-    return true;
+  if (!ssl->quic_method) {
+    *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+    return false;
   }
-
+  assert(ssl_protocol_version(ssl) == TLS1_3_VERSION);
   return ssl->s3->peer_quic_transport_params.CopyFrom(*contents);
 }
 
 static bool ext_quic_transport_params_add_serverhello(SSL_HANDSHAKE *hs,
                                                       CBB *out) {
+  assert(hs->ssl->quic_method != nullptr);
   if (hs->config->quic_transport_params.empty()) {
-    return true;
+    // Transport parameters must be set when using QUIC.
+    OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED);
+    return false;
   }
 
   CBB contents;
@@ -2624,20 +2673,22 @@
 static bool ext_delegated_credential_parse_clienthello(SSL_HANDSHAKE *hs,
                                                        uint8_t *out_alert,
                                                        CBS *contents) {
-  assert(TLSEXT_TYPE_delegated_credential == 0xff02);
-  // TODO: Check that the extension is empty.
-  //
-  // As of draft-03, the client sends an empty extension in order indicate
-  // support for delegated credentials. This could change, however, since the
-  // spec is not yet finalized. This assertion is here to remind us to enforce
-  // this check once the extension ID is assigned.
-
   if (contents == nullptr || ssl_protocol_version(hs->ssl) < TLS1_3_VERSION) {
     // Don't use delegated credentials unless we're negotiating TLS 1.3 or
     // higher.
     return true;
   }
 
+  // The contents of the extension are the signature algorithms the client will
+  // accept for a delegated credential.
+  CBS sigalg_list;
+  if (!CBS_get_u16_length_prefixed(contents, &sigalg_list) ||
+      CBS_len(&sigalg_list) == 0 ||
+      CBS_len(contents) != 0 ||
+      !parse_u16_array(&sigalg_list, &hs->peer_delegated_credential_sigalgs)) {
+    return false;
+  }
+
   hs->delegated_credential_requested = true;
   return true;
 }
@@ -3021,7 +3072,7 @@
     last_was_empty = false;
   }
 
-  if (!SSL_is_dtls(ssl)) {
+  if (!SSL_is_dtls(ssl) && !ssl->quic_method) {
     size_t psk_extension_len = ext_pre_shared_key_clienthello_length(hs);
     header_len += 2 + CBB_len(&extensions) + psk_extension_len;
     size_t padding_len = 0;
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index c9845f3..a91524a 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -424,6 +424,8 @@
       return "token_binding";
     case ssl_early_data_ticket_age_skew:
       return "ticket_age_skew";
+    case ssl_early_data_quic_parameter_mismatch:
+      return "quic_parameter_mismatch";
   }
 
   abort();
@@ -534,7 +536,7 @@
     }
   }
 
-  if (!config->expect_quic_transport_params.empty()) {
+  if (!config->expect_quic_transport_params.empty() && expect_handshake_done) {
     const uint8_t *peer_params;
     size_t peer_params_len;
     SSL_get_peer_quic_transport_params(ssl, &peer_params, &peer_params_len);
@@ -1196,6 +1198,16 @@
     return 0;
   }
 
+  if (initial_config.wait_for_debugger) {
+#if defined(OPENSSL_WINDOWS)
+    fprintf(stderr, "-wait-for-debugger is not supported on Windows.\n");
+    return 1;
+#else
+    // The debugger will resume the process.
+    raise(SIGSTOP);
+#endif
+  }
+
   bssl::UniquePtr<SSL_CTX> ssl_ctx;
 
   bssl::UniquePtr<SSL_SESSION> session;
diff --git a/src/ssl/test/mock_quic_transport.cc b/src/ssl/test/mock_quic_transport.cc
index e63ccbf..6a3f0e8 100644
--- a/src/ssl/test/mock_quic_transport.cc
+++ b/src/ssl/test/mock_quic_transport.cc
@@ -23,37 +23,33 @@
 
 const uint8_t kTagHandshake = 'H';
 const uint8_t kTagApplication = 'A';
-
-bool write_header(BIO *bio, uint8_t tag, size_t len) {
-  uint8_t header[5];
-  header[0] = tag;
-  header[1] = (len >> 24) & 0xff;
-  header[2] = (len >> 16) & 0xff;
-  header[3] = (len >> 8) & 0xff;
-  header[4] = len & 0xff;
-  return BIO_write_all(bio, header, sizeof(header));
-}
+const uint8_t kTagAlert = 'L';
 
 }  // namespace
 
 MockQuicTransport::MockQuicTransport(bssl::UniquePtr<BIO> bio, SSL *ssl)
     : bio_(std::move(bio)),
-      read_secrets_(ssl_encryption_application + 1),
-      write_secrets_(ssl_encryption_application + 1),
+      read_levels_(ssl_encryption_application + 1),
+      write_levels_(ssl_encryption_application + 1),
       ssl_(ssl) {}
 
-bool MockQuicTransport::SetSecrets(enum ssl_encryption_level_t level,
-                                   const uint8_t *read_secret,
-                                   const uint8_t *write_secret,
-                                   size_t secret_len) {
-  if (read_secret) {
-    read_secrets_[level].resize(secret_len);
-    memcpy(read_secrets_[level].data(), read_secret, secret_len);
-  }
-  if (write_secret) {
-    write_secrets_[level].resize(secret_len);
-    memcpy(write_secrets_[level].data(), write_secret, secret_len);
-  }
+bool MockQuicTransport::SetReadSecret(enum ssl_encryption_level_t level,
+                                      const SSL_CIPHER *cipher,
+                                      const uint8_t *secret,
+                                      size_t secret_len) {
+  // TODO(davidben): Assert the various encryption secret invariants.
+  read_levels_[level].cipher = SSL_CIPHER_get_protocol_id(cipher);
+  read_levels_[level].secret.assign(secret, secret + secret_len);
+  return true;
+}
+
+bool MockQuicTransport::SetWriteSecret(enum ssl_encryption_level_t level,
+                                       const SSL_CIPHER *cipher,
+                                       const uint8_t *secret,
+                                       size_t secret_len) {
+  // TODO(davidben): Assert the various encryption secret invariants.
+  write_levels_[level].cipher = SSL_CIPHER_get_protocol_id(cipher);
+  write_levels_[level].secret.assign(secret, secret + secret_len);
   return true;
 }
 
@@ -77,39 +73,53 @@
   return true;
 }
 
-bool ReadHeader(BIO *bio, uint8_t *out_tag, size_t *out_len) {
-  uint8_t header[5];
-  if (!ReadAll(bio, header)) {
+}  // namespace
+
+bool MockQuicTransport::ReadHeader(uint8_t *out_tag, size_t *out_len) {
+  uint8_t header[7];
+  if (!ReadAll(bio_.get(), header)) {
     return false;
   }
-
-  *out_len = header[1] << 24 | header[2] << 16 | header[3] << 8 | header[4];
   *out_tag = header[0];
+  uint16_t cipher_suite = header[1] << 8 | header[2];
+  size_t remaining_bytes =
+      header[3] << 24 | header[4] << 16 | header[5] << 8 | header[6];
+
+  enum ssl_encryption_level_t level = SSL_quic_read_level(ssl_);
+  if (*out_tag == kTagApplication) {
+    if (SSL_in_early_data(ssl_)) {
+      level = ssl_encryption_early_data;
+    } else {
+      level = ssl_encryption_application;
+    }
+  }
+  if (cipher_suite != read_levels_[level].cipher) {
+    return false;
+  }
+  const std::vector<uint8_t> &secret = read_levels_[level].secret;
+  std::vector<uint8_t> read_secret(secret.size());
+  if (remaining_bytes < secret.size()) {
+    return false;
+  }
+  remaining_bytes -= secret.size();
+  if (!ReadAll(bio_.get(), bssl::MakeSpan(read_secret)) ||
+      read_secret != secret) {
+    return false;
+  }
+  *out_len = remaining_bytes;
   return true;
 }
 
-}  // namespace
-
 bool MockQuicTransport::ReadHandshake() {
-  enum ssl_encryption_level_t level = SSL_quic_read_level(ssl_);
   uint8_t tag;
   size_t len;
-  if (!ReadHeader(bio_.get(), &tag, &len)) {
+  if (!ReadHeader(&tag, &len)) {
     return false;
   }
   if (tag != kTagHandshake) {
     return false;
   }
 
-  const std::vector<uint8_t> &secret = read_secrets_[level];
-  std::vector<uint8_t> read_secret(secret.size());
-  if (!ReadAll(bio_.get(), bssl::MakeSpan(read_secret))) {
-    return false;
-  }
-  if (read_secret != secret) {
-    return false;
-  }
-
   std::vector<uint8_t> buf(len);
   if (!ReadAll(bio_.get(), bssl::MakeSpan(buf))) {
     return false;
@@ -136,34 +146,36 @@
   uint8_t tag = 0;
   size_t len;
   while (true) {
-    if (!ReadHeader(bio_.get(), &tag, &len)) {
+    if (!ReadHeader(&tag, &len)) {
       // Assume that a failure to read the header means there's no more to read,
       // not an error reading.
       return 0;
     }
-    if (tag != kTagHandshake && tag != kTagApplication) {
-      return -1;
-    }
-    const std::vector<uint8_t> &secret =
-        read_secrets_[ssl_encryption_application];
-    std::vector<uint8_t> read_secret(secret.size());
-    if (!ReadAll(bio_.get(), bssl::MakeSpan(read_secret))) {
-      return -1;
-    }
-    if (read_secret != secret) {
-      return -1;
-    }
     if (tag == kTagApplication) {
       break;
     }
+    if (tag != kTagHandshake) {
+      return -1;
+    }
 
     std::vector<uint8_t> buf(len);
     if (!ReadAll(bio_.get(), bssl::MakeSpan(buf))) {
       return -1;
     }
     if (SSL_provide_quic_data(ssl_, SSL_quic_read_level(ssl_), buf.data(),
-                              buf.size()) != 1 ||
-        SSL_process_quic_post_handshake(ssl_) != 1) {
+                              buf.size()) != 1) {
+      return -1;
+    }
+    if (SSL_in_init(ssl_)) {
+      int ret = SSL_do_handshake(ssl_);
+      if (ret < 0) {
+        int ssl_err = SSL_get_error(ssl_, ret);
+        if (ssl_err == SSL_ERROR_WANT_READ) {
+          continue;
+        }
+        return -1;
+      }
+    } else if (SSL_process_quic_post_handshake(ssl_) != 1) {
       return -1;
     }
   }
@@ -185,26 +197,42 @@
   return len;
 }
 
+bool MockQuicTransport::WriteRecord(enum ssl_encryption_level_t level,
+                                    uint8_t tag, const uint8_t *data,
+                                    size_t len) {
+  uint16_t cipher_suite = write_levels_[level].cipher;
+  const std::vector<uint8_t> &secret = write_levels_[level].secret;
+  size_t tlv_len = secret.size() + len;
+  uint8_t header[7];
+  header[0] = tag;
+  header[1] = (cipher_suite >> 8) & 0xff;
+  header[2] = cipher_suite & 0xff;
+  header[3] = (tlv_len >> 24) & 0xff;
+  header[4] = (tlv_len >> 16) & 0xff;
+  header[5] = (tlv_len >> 8) & 0xff;
+  header[6] = tlv_len & 0xff;
+  return BIO_write_all(bio_.get(), header, sizeof(header)) &&
+         BIO_write_all(bio_.get(), secret.data(), secret.size()) &&
+         BIO_write_all(bio_.get(), data, len);
+}
+
 bool MockQuicTransport::WriteHandshakeData(enum ssl_encryption_level_t level,
                                            const uint8_t *data, size_t len) {
-  const std::vector<uint8_t> &secret = write_secrets_[level];
-  if (!write_header(bio_.get(), kTagHandshake, len) ||
-      BIO_write_all(bio_.get(), secret.data(), secret.size()) != 1 ||
-      BIO_write_all(bio_.get(), data, len) != 1) {
-    return false;
-  }
-  return true;
+  return WriteRecord(level, kTagHandshake, data, len);
 }
 
 bool MockQuicTransport::WriteApplicationData(const uint8_t *in, size_t len) {
-  const std::vector<uint8_t> &secret =
-      write_secrets_[ssl_encryption_application];
-  if (!write_header(bio_.get(), kTagApplication, len) ||
-      BIO_write_all(bio_.get(), secret.data(), secret.size()) != 1 ||
-      BIO_write_all(bio_.get(), in, len) != 1) {
-    return false;
+  enum ssl_encryption_level_t level = ssl_encryption_application;
+  if (SSL_in_early_data(ssl_) && !SSL_is_server(ssl_)) {
+    level = ssl_encryption_early_data;
   }
-  return true;
+  return WriteRecord(level, kTagApplication, in, len);
 }
 
 bool MockQuicTransport::Flush() { return BIO_flush(bio_.get()); }
+
+bool MockQuicTransport::SendAlert(enum ssl_encryption_level_t level,
+                                  uint8_t alert) {
+  uint8_t alert_msg[] = {2, alert};
+  return WriteRecord(level, kTagAlert, alert_msg, sizeof(alert_msg));
+}
diff --git a/src/ssl/test/mock_quic_transport.h b/src/ssl/test/mock_quic_transport.h
index 21f7dc6..a56652d 100644
--- a/src/ssl/test/mock_quic_transport.h
+++ b/src/ssl/test/mock_quic_transport.h
@@ -25,8 +25,12 @@
  public:
   explicit MockQuicTransport(bssl::UniquePtr<BIO> bio, SSL *ssl);
 
-  bool SetSecrets(enum ssl_encryption_level_t level, const uint8_t *read_secret,
-                  const uint8_t *write_secret, size_t secret_len);
+  bool SetReadSecret(enum ssl_encryption_level_t level,
+                     const SSL_CIPHER *cipher, const uint8_t *secret,
+                     size_t secret_len);
+  bool SetWriteSecret(enum ssl_encryption_level_t level,
+                      const SSL_CIPHER *cipher, const uint8_t *secret,
+                      size_t secret_len);
 
   bool ReadHandshake();
   bool WriteHandshakeData(enum ssl_encryption_level_t level,
@@ -35,15 +39,35 @@
   int ReadApplicationData(uint8_t *out, size_t max_out);
   bool WriteApplicationData(const uint8_t *in, size_t len);
   bool Flush();
+  bool SendAlert(enum ssl_encryption_level_t level, uint8_t alert);
 
  private:
+  // Reads a record header from |bio_| and returns whether the record was read
+  // successfully. As part of reading the header, this function checks that the
+  // cipher suite and secret in the header are correct. On success, the tag
+  // indicating the TLS record type is put in  |*out_tag|, the length of the TLS
+  // record is put in |*out_len|, and the next thing to be read from |bio_| is
+  // |*out_len| bytes of the TLS record.
+  bool ReadHeader(uint8_t *out_tag, size_t *out_len);
+
+  // Writes a MockQuicTransport record to |bio_| at encryption level |level|
+  // with record type |tag| and a TLS record payload of length |len| from
+  // |data|.
+  bool WriteRecord(enum ssl_encryption_level_t level, uint8_t tag,
+                   const uint8_t *data, size_t len);
+
   bssl::UniquePtr<BIO> bio_;
 
   std::vector<uint8_t> pending_app_data_;
   size_t app_data_offset_;
 
-  std::vector<std::vector<uint8_t>> read_secrets_;
-  std::vector<std::vector<uint8_t>> write_secrets_;
+  struct EncryptionLevel {
+    uint16_t cipher;
+    std::vector<uint8_t> secret;
+  };
+
+  std::vector<EncryptionLevel> read_levels_;
+  std::vector<EncryptionLevel> write_levels_;
 
   SSL *ssl_;  // Unowned.
 };
diff --git a/src/ssl/test/runner/alert.go b/src/ssl/test/runner/alert.go
index c1f7f27..a6f61e9 100644
--- a/src/ssl/test/runner/alert.go
+++ b/src/ssl/test/runner/alert.go
@@ -45,6 +45,7 @@
 	alertBadCertificateStatusResponse alert = 113
 	alertUnknownPSKIdentity           alert = 115
 	alertCertificateRequired          alert = 116
+	alertNoApplicationProtocol        alert = 120
 )
 
 var alertText = map[alert]string{
@@ -78,6 +79,7 @@
 	alertUnrecognizedName:             "unrecognized name",
 	alertUnknownPSKIdentity:           "unknown PSK identity",
 	alertCertificateRequired:          "certificate required",
+	alertNoApplicationProtocol:        "no application protocol",
 }
 
 func (e alert) String() string {
diff --git a/src/ssl/test/runner/chacha20_poly1305.go b/src/ssl/test/runner/chacha20_poly1305.go
deleted file mode 100644
index 446fb55..0000000
--- a/src/ssl/test/runner/chacha20_poly1305.go
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright (c) 2016, Google Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package runner
-
-import (
-	"crypto/cipher"
-	"crypto/subtle"
-	"encoding/binary"
-	"errors"
-
-	"boringssl.googlesource.com/boringssl/ssl/test/runner/poly1305"
-)
-
-// See RFC 7539.
-
-func leftRotate(a uint32, n uint) uint32 {
-	return (a << n) | (a >> (32 - n))
-}
-
-func chaChaQuarterRound(state *[16]uint32, a, b, c, d int) {
-	state[a] += state[b]
-	state[d] = leftRotate(state[d]^state[a], 16)
-
-	state[c] += state[d]
-	state[b] = leftRotate(state[b]^state[c], 12)
-
-	state[a] += state[b]
-	state[d] = leftRotate(state[d]^state[a], 8)
-
-	state[c] += state[d]
-	state[b] = leftRotate(state[b]^state[c], 7)
-}
-
-func chaCha20Block(state *[16]uint32, out []byte) {
-	var workingState [16]uint32
-	copy(workingState[:], state[:])
-	for i := 0; i < 10; i++ {
-		chaChaQuarterRound(&workingState, 0, 4, 8, 12)
-		chaChaQuarterRound(&workingState, 1, 5, 9, 13)
-		chaChaQuarterRound(&workingState, 2, 6, 10, 14)
-		chaChaQuarterRound(&workingState, 3, 7, 11, 15)
-		chaChaQuarterRound(&workingState, 0, 5, 10, 15)
-		chaChaQuarterRound(&workingState, 1, 6, 11, 12)
-		chaChaQuarterRound(&workingState, 2, 7, 8, 13)
-		chaChaQuarterRound(&workingState, 3, 4, 9, 14)
-	}
-	for i := 0; i < 16; i++ {
-		binary.LittleEndian.PutUint32(out[i*4:i*4+4], workingState[i]+state[i])
-	}
-}
-
-// sliceForAppend takes a slice and a requested number of bytes. It returns a
-// slice with the contents of the given slice followed by that many bytes and a
-// second slice that aliases into it and contains only the extra bytes. If the
-// original slice has sufficient capacity then no allocation is performed.
-func sliceForAppend(in []byte, n int) (head, tail []byte) {
-	if total := len(in) + n; cap(in) >= total {
-		head = in[:total]
-	} else {
-		head = make([]byte, total)
-		copy(head, in)
-	}
-	tail = head[len(in):]
-	return
-}
-
-func chaCha20(out, in, key, nonce []byte, counter uint64) {
-	var state [16]uint32
-	state[0] = 0x61707865
-	state[1] = 0x3320646e
-	state[2] = 0x79622d32
-	state[3] = 0x6b206574
-	for i := 0; i < 8; i++ {
-		state[4+i] = binary.LittleEndian.Uint32(key[i*4 : i*4+4])
-	}
-
-	switch len(nonce) {
-	case 8:
-		state[14] = binary.LittleEndian.Uint32(nonce[0:4])
-		state[15] = binary.LittleEndian.Uint32(nonce[4:8])
-	case 12:
-		state[13] = binary.LittleEndian.Uint32(nonce[0:4])
-		state[14] = binary.LittleEndian.Uint32(nonce[4:8])
-		state[15] = binary.LittleEndian.Uint32(nonce[8:12])
-	default:
-		panic("bad nonce length")
-	}
-
-	for i := 0; i < len(in); i += 64 {
-		state[12] = uint32(counter)
-
-		var tmp [64]byte
-		chaCha20Block(&state, tmp[:])
-		count := 64
-		if len(in)-i < count {
-			count = len(in) - i
-		}
-		for j := 0; j < count; j++ {
-			out[i+j] = in[i+j] ^ tmp[j]
-		}
-
-		counter++
-	}
-}
-
-// chaCha20Poly1305 implements the AEAD from
-// RFC 7539 and draft-agl-tls-chacha20poly1305-04.
-type chaCha20Poly1305 struct {
-	key [32]byte
-}
-
-func newChaCha20Poly1305(key []byte) (cipher.AEAD, error) {
-	if len(key) != 32 {
-		return nil, errors.New("bad key length")
-	}
-	aead := new(chaCha20Poly1305)
-	copy(aead.key[:], key)
-	return aead, nil
-}
-
-func (c *chaCha20Poly1305) NonceSize() int {
-	return 12
-}
-
-func (c *chaCha20Poly1305) Overhead() int { return 16 }
-
-func (c *chaCha20Poly1305) poly1305(tag *[16]byte, nonce, ciphertext, additionalData []byte) {
-	input := make([]byte, 0, len(additionalData)+15+len(ciphertext)+15+8+8)
-	input = append(input, additionalData...)
-	var zeros [15]byte
-	if pad := len(input) % 16; pad != 0 {
-		input = append(input, zeros[:16-pad]...)
-	}
-	input = append(input, ciphertext...)
-	if pad := len(input) % 16; pad != 0 {
-		input = append(input, zeros[:16-pad]...)
-	}
-	input, out := sliceForAppend(input, 8)
-	binary.LittleEndian.PutUint64(out, uint64(len(additionalData)))
-	input, out = sliceForAppend(input, 8)
-	binary.LittleEndian.PutUint64(out, uint64(len(ciphertext)))
-
-	var poly1305Key [32]byte
-	chaCha20(poly1305Key[:], poly1305Key[:], c.key[:], nonce, 0)
-
-	poly1305.Sum(tag, input, &poly1305Key)
-}
-
-func (c *chaCha20Poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
-	if len(nonce) != c.NonceSize() {
-		panic("Bad nonce length")
-	}
-
-	ret, out := sliceForAppend(dst, len(plaintext)+16)
-	chaCha20(out[:len(plaintext)], plaintext, c.key[:], nonce, 1)
-
-	var tag [16]byte
-	c.poly1305(&tag, nonce, out[:len(plaintext)], additionalData)
-	copy(out[len(plaintext):], tag[:])
-
-	return ret
-}
-
-func (c *chaCha20Poly1305) Open(dst, nonce, ciphertext, additionalData []byte) ([]byte, error) {
-	if len(nonce) != c.NonceSize() {
-		panic("Bad nonce length")
-	}
-	if len(ciphertext) < 16 {
-		return nil, errors.New("chacha20: message authentication failed")
-	}
-	plaintextLen := len(ciphertext) - 16
-
-	var tag [16]byte
-	c.poly1305(&tag, nonce, ciphertext[:plaintextLen], additionalData)
-	if subtle.ConstantTimeCompare(tag[:], ciphertext[plaintextLen:]) != 1 {
-		return nil, errors.New("chacha20: message authentication failed")
-	}
-
-	ret, out := sliceForAppend(dst, plaintextLen)
-	chaCha20(out, ciphertext[:plaintextLen], c.key[:], nonce, 1)
-	return ret, nil
-}
diff --git a/src/ssl/test/runner/chacha20_poly1305_test.go b/src/ssl/test/runner/chacha20_poly1305_test.go
deleted file mode 100644
index b59bb02..0000000
--- a/src/ssl/test/runner/chacha20_poly1305_test.go
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2016, Google Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package runner
-
-import (
-	"bytes"
-	"testing"
-)
-
-// See RFC 7539, section 2.1.1.
-func TestChaChaQuarterRound(t *testing.T) {
-	state := [16]uint32{0x11111111, 0x01020304, 0x9b8d6f43, 0x01234567}
-	chaChaQuarterRound(&state, 0, 1, 2, 3)
-
-	a, b, c, d := state[0], state[1], state[2], state[3]
-	if a != 0xea2a92f4 || b != 0xcb1cf8ce || c != 0x4581472e || d != 0x5881c4bb {
-		t.Errorf("Incorrect results: %x", state)
-	}
-}
-
-// See RFC 7539, section 2.2.1.
-func TestChaChaQuarterRoundState(t *testing.T) {
-	state := [16]uint32{
-		0x879531e0, 0xc5ecf37d, 0x516461b1, 0xc9a62f8a,
-		0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0x2a5f714c,
-		0x53372767, 0xb00a5631, 0x974c541a, 0x359e9963,
-		0x5c971061, 0x3d631689, 0x2098d9d6, 0x91dbd320,
-	}
-	chaChaQuarterRound(&state, 2, 7, 8, 13)
-
-	expected := [16]uint32{
-		0x879531e0, 0xc5ecf37d, 0xbdb886dc, 0xc9a62f8a,
-		0x44c20ef3, 0x3390af7f, 0xd9fc690b, 0xcfacafd2,
-		0xe46bea80, 0xb00a5631, 0x974c541a, 0x359e9963,
-		0x5c971061, 0xccc07c79, 0x2098d9d6, 0x91dbd320,
-	}
-	for i := range state {
-		if state[i] != expected[i] {
-			t.Errorf("Mismatch at %d: %x vs %x", i, state, expected)
-		}
-	}
-}
-
-// See RFC 7539, section 2.3.2.
-func TestChaCha20Block(t *testing.T) {
-	state := [16]uint32{
-		0x61707865, 0x3320646e, 0x79622d32, 0x6b206574,
-		0x03020100, 0x07060504, 0x0b0a0908, 0x0f0e0d0c,
-		0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c,
-		0x00000001, 0x09000000, 0x4a000000, 0x00000000,
-	}
-	out := make([]byte, 64)
-	chaCha20Block(&state, out)
-
-	expected := []byte{
-		0x10, 0xf1, 0xe7, 0xe4, 0xd1, 0x3b, 0x59, 0x15,
-		0x50, 0x0f, 0xdd, 0x1f, 0xa3, 0x20, 0x71, 0xc4,
-		0xc7, 0xd1, 0xf4, 0xc7, 0x33, 0xc0, 0x68, 0x03,
-		0x04, 0x22, 0xaa, 0x9a, 0xc3, 0xd4, 0x6c, 0x4e,
-		0xd2, 0x82, 0x64, 0x46, 0x07, 0x9f, 0xaa, 0x09,
-		0x14, 0xc2, 0xd7, 0x05, 0xd9, 0x8b, 0x02, 0xa2,
-		0xb5, 0x12, 0x9c, 0xd1, 0xde, 0x16, 0x4e, 0xb9,
-		0xcb, 0xd0, 0x83, 0xe8, 0xa2, 0x50, 0x3c, 0x4e,
-	}
-	if !bytes.Equal(out, expected) {
-		t.Errorf("Got %x, wanted %x", out, expected)
-	}
-}
-
-var chaCha20Poly1305TestVectors = []struct {
-	key, input, nonce, ad, output string
-}{
-	{
-		// See RFC 7539, section 2.8.2.
-		key:    "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f",
-		input:  "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e",
-		nonce:  "070000004041424344454647",
-		ad:     "50515253c0c1c2c3c4c5c6c7",
-		output: "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b61161ae10b594f09e26a7e902ecbd0600691",
-	},
-	{
-		// See RFC 7539, section A.5.
-		key:    "1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0",
-		input:  "496e7465726e65742d4472616674732061726520647261667420646f63756d656e74732076616c696420666f722061206d6178696d756d206f6620736978206d6f6e74687320616e64206d617920626520757064617465642c207265706c616365642c206f72206f62736f6c65746564206279206f7468657220646f63756d656e747320617420616e792074696d652e20497420697320696e617070726f70726961746520746f2075736520496e7465726e65742d447261667473206173207265666572656e6365206d6174657269616c206f7220746f2063697465207468656d206f74686572207468616e206173202fe2809c776f726b20696e2070726f67726573732e2fe2809d",
-		nonce:  "000000000102030405060708",
-		ad:     "f33388860000000000004e91",
-		output: "64a0861575861af460f062c79be643bd5e805cfd345cf389f108670ac76c8cb24c6cfc18755d43eea09ee94e382d26b0bdb7b73c321b0100d4f03b7f355894cf332f830e710b97ce98c8a84abd0b948114ad176e008d33bd60f982b1ff37c8559797a06ef4f0ef61c186324e2b3506383606907b6a7c02b0f9f6157b53c867e4b9166c767b804d46a59b5216cde7a4e99040c5a40433225ee282a1b0a06c523eaf4534d7f83fa1155b0047718cbc546a0d072b04b3564eea1b422273f548271a0bb2316053fa76991955ebd63159434ecebb4e466dae5a1073a6727627097a1049e617d91d361094fa68f0ff77987130305beaba2eda04df997b714d6c6f2c29a6ad5cb4022b02709beead9d67890cbb22392336fea1851f38",
-	},
-}
-
-// See draft-agl-tls-chacha20poly1305-04, section 7.
-func TestChaCha20Poly1305(t *testing.T) {
-	for i, tt := range chaCha20Poly1305TestVectors {
-		key := decodeHexOrPanic(tt.key)
-		input := decodeHexOrPanic(tt.input)
-		nonce := decodeHexOrPanic(tt.nonce)
-		ad := decodeHexOrPanic(tt.ad)
-		output := decodeHexOrPanic(tt.output)
-
-		aead, err := newChaCha20Poly1305(key)
-		if err != nil {
-			t.Fatal(err)
-		}
-
-		out, err := aead.Open(nil, nonce, output, ad)
-		if err != nil {
-			t.Errorf("%d. Open failed: %s", i, err)
-		} else if !bytes.Equal(out, input) {
-			t.Errorf("%d. Open gave %x, wanted %x", i, out, input)
-		}
-
-		out = aead.Seal(nil, nonce, input, ad)
-		if !bytes.Equal(out, output) {
-			t.Errorf("%d. Open gave %x, wanted %x", i, out, output)
-		}
-
-		out[0]++
-		_, err = aead.Open(nil, nonce, out, ad)
-		if err == nil {
-			t.Errorf("%d. Open on malformed data unexpectedly succeeded", i)
-		}
-	}
-}
diff --git a/src/ssl/test/runner/cipher_suites.go b/src/ssl/test/runner/cipher_suites.go
index e827c52..48dfa57 100644
--- a/src/ssl/test/runner/cipher_suites.go
+++ b/src/ssl/test/runner/cipher_suites.go
@@ -16,6 +16,8 @@
 	"crypto/sha512"
 	"crypto/x509"
 	"hash"
+
+	"golang.org/x/crypto/chacha20poly1305"
 )
 
 // a keyAgreement implements the client and server side of a TLS key agreement
@@ -305,7 +307,7 @@
 }
 
 func aeadCHACHA20POLY1305(version uint16, key, fixedNonce []byte) *tlsAead {
-	aead, err := newChaCha20Poly1305(key)
+	aead, err := chacha20poly1305.New(key)
 	if err != nil {
 		panic(err)
 	}
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 26f4885..6a744db 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -124,7 +124,7 @@
 	extensionRenegotiationInfo          uint16 = 0xff01
 	extensionQUICTransportParams        uint16 = 0xffa5 // draft-ietf-quic-tls-13
 	extensionChannelID                  uint16 = 30032  // not IANA assigned
-	extensionDelegatedCredentials       uint16 = 0xff02 // not IANA assigned
+	extensionDelegatedCredentials       uint16 = 0x22   // draft-ietf-tls-subcerts-06
 )
 
 // TLS signaling cipher suite values
@@ -1670,6 +1670,10 @@
 	// DisableDelegatedCredentials, if true, disables client support for delegated
 	// credentials.
 	DisableDelegatedCredentials bool
+
+	// CompatModeWithQUIC, if true, enables TLS 1.3 compatibility mode
+	// when running over QUIC.
+	CompatModeWithQUIC bool
 }
 
 func (c *Config) serverInit() {
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index 0142ff6..a449f2f 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -761,6 +761,7 @@
 	}
 	if c.config.Bugs.MockQUICTransport != nil {
 		c.config.Bugs.MockQUICTransport.readSecret = secret
+		c.config.Bugs.MockQUICTransport.readCipherSuite = suite.id
 	}
 	c.in.useTrafficSecret(version, suite, secret, side)
 	c.seenHandshakePackEnd = false
@@ -774,10 +775,26 @@
 	}
 	if c.config.Bugs.MockQUICTransport != nil {
 		c.config.Bugs.MockQUICTransport.writeSecret = secret
+		c.config.Bugs.MockQUICTransport.writeCipherSuite = suite.id
 	}
 	c.out.useTrafficSecret(version, suite, secret, side)
 }
 
+func (c *Conn) setSkipEarlyData() {
+	if c.config.Bugs.MockQUICTransport != nil {
+		c.config.Bugs.MockQUICTransport.skipEarlyData = true
+	} else {
+		c.skipEarlyData = true
+	}
+}
+
+func (c *Conn) shouldSkipEarlyData() bool {
+	if c.config.Bugs.MockQUICTransport != nil {
+		return c.config.Bugs.MockQUICTransport.skipEarlyData
+	}
+	return c.skipEarlyData
+}
+
 func (c *Conn) doReadRecord(want recordType) (recordType, *block, error) {
 RestartReadRecord:
 	if c.isDTLS {
@@ -904,6 +921,9 @@
 }
 
 func (c *Conn) readTLS13ChangeCipherSpec() error {
+	if c.config.Bugs.MockQUICTransport != nil {
+		return nil
+	}
 	if !c.expectTLS13ChangeCipherSpec {
 		panic("c.expectTLS13ChangeCipherSpec not set")
 	}
@@ -964,7 +984,7 @@
 		break
 	}
 
-	if c.expectTLS13ChangeCipherSpec && c.config.Bugs.MockQUICTransport == nil {
+	if c.expectTLS13ChangeCipherSpec {
 		if err := c.readTLS13ChangeCipherSpec(); err != nil {
 			return err
 		}
@@ -1986,6 +2006,9 @@
 		ticketNonce:                 nonce,
 		maxEarlyDataSize:            c.config.MaxEarlyDataSize,
 	}
+	if c.config.Bugs.MockQUICTransport != nil && m.maxEarlyDataSize > 0 {
+		m.maxEarlyDataSize = 0xffffffff
+	}
 
 	if c.config.Bugs.SendTicketLifetime != 0 {
 		m.ticketLifetime = uint32(c.config.Bugs.SendTicketLifetime / time.Second)
diff --git a/src/ssl/test/runner/curve25519/const_amd64.h b/src/ssl/test/runner/curve25519/const_amd64.h
deleted file mode 100644
index 80ad222..0000000
--- a/src/ssl/test/runner/curve25519/const_amd64.h
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
-
-#define REDMASK51     0x0007FFFFFFFFFFFF
diff --git a/src/ssl/test/runner/curve25519/const_amd64.s b/src/ssl/test/runner/curve25519/const_amd64.s
deleted file mode 100644
index 0ad5398..0000000
--- a/src/ssl/test/runner/curve25519/const_amd64.s
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
-
-// +build amd64,!gccgo,!appengine
-
-// These constants cannot be encoded in non-MOVQ immediates.
-// We access them directly from memory instead.
-
-DATA ·_121666_213(SB)/8, $996687872
-GLOBL ·_121666_213(SB), 8, $8
-
-DATA ·_2P0(SB)/8, $0xFFFFFFFFFFFDA
-GLOBL ·_2P0(SB), 8, $8
-
-DATA ·_2P1234(SB)/8, $0xFFFFFFFFFFFFE
-GLOBL ·_2P1234(SB), 8, $8
diff --git a/src/ssl/test/runner/curve25519/cswap_amd64.s b/src/ssl/test/runner/curve25519/cswap_amd64.s
deleted file mode 100644
index 45484d1..0000000
--- a/src/ssl/test/runner/curve25519/cswap_amd64.s
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
-
-// +build amd64,!gccgo,!appengine
-
-// func cswap(inout *[5]uint64, v uint64)
-TEXT ·cswap(SB),7,$0
-	MOVQ inout+0(FP),DI
-	MOVQ v+8(FP),SI
-
-	CMPQ SI,$1
-	MOVQ 0(DI),SI
-	MOVQ 80(DI),DX
-	MOVQ 8(DI),CX
-	MOVQ 88(DI),R8
-	MOVQ SI,R9
-	CMOVQEQ DX,SI
-	CMOVQEQ R9,DX
-	MOVQ CX,R9
-	CMOVQEQ R8,CX
-	CMOVQEQ R9,R8
-	MOVQ SI,0(DI)
-	MOVQ DX,80(DI)
-	MOVQ CX,8(DI)
-	MOVQ R8,88(DI)
-	MOVQ 16(DI),SI
-	MOVQ 96(DI),DX
-	MOVQ 24(DI),CX
-	MOVQ 104(DI),R8
-	MOVQ SI,R9
-	CMOVQEQ DX,SI
-	CMOVQEQ R9,DX
-	MOVQ CX,R9
-	CMOVQEQ R8,CX
-	CMOVQEQ R9,R8
-	MOVQ SI,16(DI)
-	MOVQ DX,96(DI)
-	MOVQ CX,24(DI)
-	MOVQ R8,104(DI)
-	MOVQ 32(DI),SI
-	MOVQ 112(DI),DX
-	MOVQ 40(DI),CX
-	MOVQ 120(DI),R8
-	MOVQ SI,R9
-	CMOVQEQ DX,SI
-	CMOVQEQ R9,DX
-	MOVQ CX,R9
-	CMOVQEQ R8,CX
-	CMOVQEQ R9,R8
-	MOVQ SI,32(DI)
-	MOVQ DX,112(DI)
-	MOVQ CX,40(DI)
-	MOVQ R8,120(DI)
-	MOVQ 48(DI),SI
-	MOVQ 128(DI),DX
-	MOVQ 56(DI),CX
-	MOVQ 136(DI),R8
-	MOVQ SI,R9
-	CMOVQEQ DX,SI
-	CMOVQEQ R9,DX
-	MOVQ CX,R9
-	CMOVQEQ R8,CX
-	CMOVQEQ R9,R8
-	MOVQ SI,48(DI)
-	MOVQ DX,128(DI)
-	MOVQ CX,56(DI)
-	MOVQ R8,136(DI)
-	MOVQ 64(DI),SI
-	MOVQ 144(DI),DX
-	MOVQ 72(DI),CX
-	MOVQ 152(DI),R8
-	MOVQ SI,R9
-	CMOVQEQ DX,SI
-	CMOVQEQ R9,DX
-	MOVQ CX,R9
-	CMOVQEQ R8,CX
-	CMOVQEQ R9,R8
-	MOVQ SI,64(DI)
-	MOVQ DX,144(DI)
-	MOVQ CX,72(DI)
-	MOVQ R8,152(DI)
-	MOVQ DI,AX
-	MOVQ SI,DX
-	RET
diff --git a/src/ssl/test/runner/curve25519/curve25519.go b/src/ssl/test/runner/curve25519/curve25519.go
deleted file mode 100644
index 6918c47..0000000
--- a/src/ssl/test/runner/curve25519/curve25519.go
+++ /dev/null
@@ -1,841 +0,0 @@
-// Copyright 2013 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// We have a implementation in amd64 assembly so this code is only run on
-// non-amd64 platforms. The amd64 assembly does not support gccgo.
-// +build !amd64 gccgo appengine
-
-package curve25519
-
-// This code is a port of the public domain, "ref10" implementation of
-// curve25519 from SUPERCOP 20130419 by D. J. Bernstein.
-
-// fieldElement represents an element of the field GF(2^255 - 19). An element
-// t, entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
-// t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
-// context.
-type fieldElement [10]int32
-
-func feZero(fe *fieldElement) {
-	for i := range fe {
-		fe[i] = 0
-	}
-}
-
-func feOne(fe *fieldElement) {
-	feZero(fe)
-	fe[0] = 1
-}
-
-func feAdd(dst, a, b *fieldElement) {
-	for i := range dst {
-		dst[i] = a[i] + b[i]
-	}
-}
-
-func feSub(dst, a, b *fieldElement) {
-	for i := range dst {
-		dst[i] = a[i] - b[i]
-	}
-}
-
-func feCopy(dst, src *fieldElement) {
-	for i := range dst {
-		dst[i] = src[i]
-	}
-}
-
-// feCSwap replaces (f,g) with (g,f) if b == 1; replaces (f,g) with (f,g) if b == 0.
-//
-// Preconditions: b in {0,1}.
-func feCSwap(f, g *fieldElement, b int32) {
-	var x fieldElement
-	b = -b
-	for i := range x {
-		x[i] = b & (f[i] ^ g[i])
-	}
-
-	for i := range f {
-		f[i] ^= x[i]
-	}
-	for i := range g {
-		g[i] ^= x[i]
-	}
-}
-
-// load3 reads a 24-bit, little-endian value from in.
-func load3(in []byte) int64 {
-	var r int64
-	r = int64(in[0])
-	r |= int64(in[1]) << 8
-	r |= int64(in[2]) << 16
-	return r
-}
-
-// load4 reads a 32-bit, little-endian value from in.
-func load4(in []byte) int64 {
-	var r int64
-	r = int64(in[0])
-	r |= int64(in[1]) << 8
-	r |= int64(in[2]) << 16
-	r |= int64(in[3]) << 24
-	return r
-}
-
-func feFromBytes(dst *fieldElement, src *[32]byte) {
-	h0 := load4(src[:])
-	h1 := load3(src[4:]) << 6
-	h2 := load3(src[7:]) << 5
-	h3 := load3(src[10:]) << 3
-	h4 := load3(src[13:]) << 2
-	h5 := load4(src[16:])
-	h6 := load3(src[20:]) << 7
-	h7 := load3(src[23:]) << 5
-	h8 := load3(src[26:]) << 4
-	h9 := load3(src[29:]) << 2
-
-	var carry [10]int64
-	carry[9] = (h9 + 1<<24) >> 25
-	h0 += carry[9] * 19
-	h9 -= carry[9] << 25
-	carry[1] = (h1 + 1<<24) >> 25
-	h2 += carry[1]
-	h1 -= carry[1] << 25
-	carry[3] = (h3 + 1<<24) >> 25
-	h4 += carry[3]
-	h3 -= carry[3] << 25
-	carry[5] = (h5 + 1<<24) >> 25
-	h6 += carry[5]
-	h5 -= carry[5] << 25
-	carry[7] = (h7 + 1<<24) >> 25
-	h8 += carry[7]
-	h7 -= carry[7] << 25
-
-	carry[0] = (h0 + 1<<25) >> 26
-	h1 += carry[0]
-	h0 -= carry[0] << 26
-	carry[2] = (h2 + 1<<25) >> 26
-	h3 += carry[2]
-	h2 -= carry[2] << 26
-	carry[4] = (h4 + 1<<25) >> 26
-	h5 += carry[4]
-	h4 -= carry[4] << 26
-	carry[6] = (h6 + 1<<25) >> 26
-	h7 += carry[6]
-	h6 -= carry[6] << 26
-	carry[8] = (h8 + 1<<25) >> 26
-	h9 += carry[8]
-	h8 -= carry[8] << 26
-
-	dst[0] = int32(h0)
-	dst[1] = int32(h1)
-	dst[2] = int32(h2)
-	dst[3] = int32(h3)
-	dst[4] = int32(h4)
-	dst[5] = int32(h5)
-	dst[6] = int32(h6)
-	dst[7] = int32(h7)
-	dst[8] = int32(h8)
-	dst[9] = int32(h9)
-}
-
-// feToBytes marshals h to s.
-// Preconditions:
-//   |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-//
-// Write p=2^255-19; q=floor(h/p).
-// Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
-//
-// Proof:
-//   Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
-//   Also have |h-2^230 h9|<2^230 so |19 2^(-255)(h-2^230 h9)|<1/4.
-//
-//   Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
-//   Then 0<y<1.
-//
-//   Write r=h-pq.
-//   Have 0<=r<=p-1=2^255-20.
-//   Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
-//
-//   Write x=r+19(2^-255)r+y.
-//   Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
-//
-//   Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
-//   so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
-func feToBytes(s *[32]byte, h *fieldElement) {
-	var carry [10]int32
-
-	q := (19*h[9] + (1 << 24)) >> 25
-	q = (h[0] + q) >> 26
-	q = (h[1] + q) >> 25
-	q = (h[2] + q) >> 26
-	q = (h[3] + q) >> 25
-	q = (h[4] + q) >> 26
-	q = (h[5] + q) >> 25
-	q = (h[6] + q) >> 26
-	q = (h[7] + q) >> 25
-	q = (h[8] + q) >> 26
-	q = (h[9] + q) >> 25
-
-	// Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20.
-	h[0] += 19 * q
-	// Goal: Output h-2^255 q, which is between 0 and 2^255-20.
-
-	carry[0] = h[0] >> 26
-	h[1] += carry[0]
-	h[0] -= carry[0] << 26
-	carry[1] = h[1] >> 25
-	h[2] += carry[1]
-	h[1] -= carry[1] << 25
-	carry[2] = h[2] >> 26
-	h[3] += carry[2]
-	h[2] -= carry[2] << 26
-	carry[3] = h[3] >> 25
-	h[4] += carry[3]
-	h[3] -= carry[3] << 25
-	carry[4] = h[4] >> 26
-	h[5] += carry[4]
-	h[4] -= carry[4] << 26
-	carry[5] = h[5] >> 25
-	h[6] += carry[5]
-	h[5] -= carry[5] << 25
-	carry[6] = h[6] >> 26
-	h[7] += carry[6]
-	h[6] -= carry[6] << 26
-	carry[7] = h[7] >> 25
-	h[8] += carry[7]
-	h[7] -= carry[7] << 25
-	carry[8] = h[8] >> 26
-	h[9] += carry[8]
-	h[8] -= carry[8] << 26
-	carry[9] = h[9] >> 25
-	h[9] -= carry[9] << 25
-	// h10 = carry9
-
-	// Goal: Output h[0]+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
-	// Have h[0]+...+2^230 h[9] between 0 and 2^255-1;
-	// evidently 2^255 h10-2^255 q = 0.
-	// Goal: Output h[0]+...+2^230 h[9].
-
-	s[0] = byte(h[0] >> 0)
-	s[1] = byte(h[0] >> 8)
-	s[2] = byte(h[0] >> 16)
-	s[3] = byte((h[0] >> 24) | (h[1] << 2))
-	s[4] = byte(h[1] >> 6)
-	s[5] = byte(h[1] >> 14)
-	s[6] = byte((h[1] >> 22) | (h[2] << 3))
-	s[7] = byte(h[2] >> 5)
-	s[8] = byte(h[2] >> 13)
-	s[9] = byte((h[2] >> 21) | (h[3] << 5))
-	s[10] = byte(h[3] >> 3)
-	s[11] = byte(h[3] >> 11)
-	s[12] = byte((h[3] >> 19) | (h[4] << 6))
-	s[13] = byte(h[4] >> 2)
-	s[14] = byte(h[4] >> 10)
-	s[15] = byte(h[4] >> 18)
-	s[16] = byte(h[5] >> 0)
-	s[17] = byte(h[5] >> 8)
-	s[18] = byte(h[5] >> 16)
-	s[19] = byte((h[5] >> 24) | (h[6] << 1))
-	s[20] = byte(h[6] >> 7)
-	s[21] = byte(h[6] >> 15)
-	s[22] = byte((h[6] >> 23) | (h[7] << 3))
-	s[23] = byte(h[7] >> 5)
-	s[24] = byte(h[7] >> 13)
-	s[25] = byte((h[7] >> 21) | (h[8] << 4))
-	s[26] = byte(h[8] >> 4)
-	s[27] = byte(h[8] >> 12)
-	s[28] = byte((h[8] >> 20) | (h[9] << 6))
-	s[29] = byte(h[9] >> 2)
-	s[30] = byte(h[9] >> 10)
-	s[31] = byte(h[9] >> 18)
-}
-
-// feMul calculates h = f * g
-// Can overlap h with f or g.
-//
-// Preconditions:
-//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-//    |g| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-//
-// Postconditions:
-//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-//
-// Notes on implementation strategy:
-//
-// Using schoolbook multiplication.
-// Karatsuba would save a little in some cost models.
-//
-// Most multiplications by 2 and 19 are 32-bit precomputations;
-// cheaper than 64-bit postcomputations.
-//
-// There is one remaining multiplication by 19 in the carry chain;
-// one *19 precomputation can be merged into this,
-// but the resulting data flow is considerably less clean.
-//
-// There are 12 carries below.
-// 10 of them are 2-way parallelizable and vectorizable.
-// Can get away with 11 carries, but then data flow is much deeper.
-//
-// With tighter constraints on inputs can squeeze carries into int32.
-func feMul(h, f, g *fieldElement) {
-	f0 := f[0]
-	f1 := f[1]
-	f2 := f[2]
-	f3 := f[3]
-	f4 := f[4]
-	f5 := f[5]
-	f6 := f[6]
-	f7 := f[7]
-	f8 := f[8]
-	f9 := f[9]
-	g0 := g[0]
-	g1 := g[1]
-	g2 := g[2]
-	g3 := g[3]
-	g4 := g[4]
-	g5 := g[5]
-	g6 := g[6]
-	g7 := g[7]
-	g8 := g[8]
-	g9 := g[9]
-	g1_19 := 19 * g1 // 1.4*2^29
-	g2_19 := 19 * g2 // 1.4*2^30; still ok
-	g3_19 := 19 * g3
-	g4_19 := 19 * g4
-	g5_19 := 19 * g5
-	g6_19 := 19 * g6
-	g7_19 := 19 * g7
-	g8_19 := 19 * g8
-	g9_19 := 19 * g9
-	f1_2 := 2 * f1
-	f3_2 := 2 * f3
-	f5_2 := 2 * f5
-	f7_2 := 2 * f7
-	f9_2 := 2 * f9
-	f0g0 := int64(f0) * int64(g0)
-	f0g1 := int64(f0) * int64(g1)
-	f0g2 := int64(f0) * int64(g2)
-	f0g3 := int64(f0) * int64(g3)
-	f0g4 := int64(f0) * int64(g4)
-	f0g5 := int64(f0) * int64(g5)
-	f0g6 := int64(f0) * int64(g6)
-	f0g7 := int64(f0) * int64(g7)
-	f0g8 := int64(f0) * int64(g8)
-	f0g9 := int64(f0) * int64(g9)
-	f1g0 := int64(f1) * int64(g0)
-	f1g1_2 := int64(f1_2) * int64(g1)
-	f1g2 := int64(f1) * int64(g2)
-	f1g3_2 := int64(f1_2) * int64(g3)
-	f1g4 := int64(f1) * int64(g4)
-	f1g5_2 := int64(f1_2) * int64(g5)
-	f1g6 := int64(f1) * int64(g6)
-	f1g7_2 := int64(f1_2) * int64(g7)
-	f1g8 := int64(f1) * int64(g8)
-	f1g9_38 := int64(f1_2) * int64(g9_19)
-	f2g0 := int64(f2) * int64(g0)
-	f2g1 := int64(f2) * int64(g1)
-	f2g2 := int64(f2) * int64(g2)
-	f2g3 := int64(f2) * int64(g3)
-	f2g4 := int64(f2) * int64(g4)
-	f2g5 := int64(f2) * int64(g5)
-	f2g6 := int64(f2) * int64(g6)
-	f2g7 := int64(f2) * int64(g7)
-	f2g8_19 := int64(f2) * int64(g8_19)
-	f2g9_19 := int64(f2) * int64(g9_19)
-	f3g0 := int64(f3) * int64(g0)
-	f3g1_2 := int64(f3_2) * int64(g1)
-	f3g2 := int64(f3) * int64(g2)
-	f3g3_2 := int64(f3_2) * int64(g3)
-	f3g4 := int64(f3) * int64(g4)
-	f3g5_2 := int64(f3_2) * int64(g5)
-	f3g6 := int64(f3) * int64(g6)
-	f3g7_38 := int64(f3_2) * int64(g7_19)
-	f3g8_19 := int64(f3) * int64(g8_19)
-	f3g9_38 := int64(f3_2) * int64(g9_19)
-	f4g0 := int64(f4) * int64(g0)
-	f4g1 := int64(f4) * int64(g1)
-	f4g2 := int64(f4) * int64(g2)
-	f4g3 := int64(f4) * int64(g3)
-	f4g4 := int64(f4) * int64(g4)
-	f4g5 := int64(f4) * int64(g5)
-	f4g6_19 := int64(f4) * int64(g6_19)
-	f4g7_19 := int64(f4) * int64(g7_19)
-	f4g8_19 := int64(f4) * int64(g8_19)
-	f4g9_19 := int64(f4) * int64(g9_19)
-	f5g0 := int64(f5) * int64(g0)
-	f5g1_2 := int64(f5_2) * int64(g1)
-	f5g2 := int64(f5) * int64(g2)
-	f5g3_2 := int64(f5_2) * int64(g3)
-	f5g4 := int64(f5) * int64(g4)
-	f5g5_38 := int64(f5_2) * int64(g5_19)
-	f5g6_19 := int64(f5) * int64(g6_19)
-	f5g7_38 := int64(f5_2) * int64(g7_19)
-	f5g8_19 := int64(f5) * int64(g8_19)
-	f5g9_38 := int64(f5_2) * int64(g9_19)
-	f6g0 := int64(f6) * int64(g0)
-	f6g1 := int64(f6) * int64(g1)
-	f6g2 := int64(f6) * int64(g2)
-	f6g3 := int64(f6) * int64(g3)
-	f6g4_19 := int64(f6) * int64(g4_19)
-	f6g5_19 := int64(f6) * int64(g5_19)
-	f6g6_19 := int64(f6) * int64(g6_19)
-	f6g7_19 := int64(f6) * int64(g7_19)
-	f6g8_19 := int64(f6) * int64(g8_19)
-	f6g9_19 := int64(f6) * int64(g9_19)
-	f7g0 := int64(f7) * int64(g0)
-	f7g1_2 := int64(f7_2) * int64(g1)
-	f7g2 := int64(f7) * int64(g2)
-	f7g3_38 := int64(f7_2) * int64(g3_19)
-	f7g4_19 := int64(f7) * int64(g4_19)
-	f7g5_38 := int64(f7_2) * int64(g5_19)
-	f7g6_19 := int64(f7) * int64(g6_19)
-	f7g7_38 := int64(f7_2) * int64(g7_19)
-	f7g8_19 := int64(f7) * int64(g8_19)
-	f7g9_38 := int64(f7_2) * int64(g9_19)
-	f8g0 := int64(f8) * int64(g0)
-	f8g1 := int64(f8) * int64(g1)
-	f8g2_19 := int64(f8) * int64(g2_19)
-	f8g3_19 := int64(f8) * int64(g3_19)
-	f8g4_19 := int64(f8) * int64(g4_19)
-	f8g5_19 := int64(f8) * int64(g5_19)
-	f8g6_19 := int64(f8) * int64(g6_19)
-	f8g7_19 := int64(f8) * int64(g7_19)
-	f8g8_19 := int64(f8) * int64(g8_19)
-	f8g9_19 := int64(f8) * int64(g9_19)
-	f9g0 := int64(f9) * int64(g0)
-	f9g1_38 := int64(f9_2) * int64(g1_19)
-	f9g2_19 := int64(f9) * int64(g2_19)
-	f9g3_38 := int64(f9_2) * int64(g3_19)
-	f9g4_19 := int64(f9) * int64(g4_19)
-	f9g5_38 := int64(f9_2) * int64(g5_19)
-	f9g6_19 := int64(f9) * int64(g6_19)
-	f9g7_38 := int64(f9_2) * int64(g7_19)
-	f9g8_19 := int64(f9) * int64(g8_19)
-	f9g9_38 := int64(f9_2) * int64(g9_19)
-	h0 := f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38
-	h1 := f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19
-	h2 := f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38
-	h3 := f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19
-	h4 := f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38
-	h5 := f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19
-	h6 := f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38
-	h7 := f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19
-	h8 := f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38
-	h9 := f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0
-	var carry [10]int64
-
-	// |h0| <= (1.1*1.1*2^52*(1+19+19+19+19)+1.1*1.1*2^50*(38+38+38+38+38))
-	//   i.e. |h0| <= 1.2*2^59; narrower ranges for h2, h4, h6, h8
-	// |h1| <= (1.1*1.1*2^51*(1+1+19+19+19+19+19+19+19+19))
-	//   i.e. |h1| <= 1.5*2^58; narrower ranges for h3, h5, h7, h9
-
-	carry[0] = (h0 + (1 << 25)) >> 26
-	h1 += carry[0]
-	h0 -= carry[0] << 26
-	carry[4] = (h4 + (1 << 25)) >> 26
-	h5 += carry[4]
-	h4 -= carry[4] << 26
-	// |h0| <= 2^25
-	// |h4| <= 2^25
-	// |h1| <= 1.51*2^58
-	// |h5| <= 1.51*2^58
-
-	carry[1] = (h1 + (1 << 24)) >> 25
-	h2 += carry[1]
-	h1 -= carry[1] << 25
-	carry[5] = (h5 + (1 << 24)) >> 25
-	h6 += carry[5]
-	h5 -= carry[5] << 25
-	// |h1| <= 2^24; from now on fits into int32
-	// |h5| <= 2^24; from now on fits into int32
-	// |h2| <= 1.21*2^59
-	// |h6| <= 1.21*2^59
-
-	carry[2] = (h2 + (1 << 25)) >> 26
-	h3 += carry[2]
-	h2 -= carry[2] << 26
-	carry[6] = (h6 + (1 << 25)) >> 26
-	h7 += carry[6]
-	h6 -= carry[6] << 26
-	// |h2| <= 2^25; from now on fits into int32 unchanged
-	// |h6| <= 2^25; from now on fits into int32 unchanged
-	// |h3| <= 1.51*2^58
-	// |h7| <= 1.51*2^58
-
-	carry[3] = (h3 + (1 << 24)) >> 25
-	h4 += carry[3]
-	h3 -= carry[3] << 25
-	carry[7] = (h7 + (1 << 24)) >> 25
-	h8 += carry[7]
-	h7 -= carry[7] << 25
-	// |h3| <= 2^24; from now on fits into int32 unchanged
-	// |h7| <= 2^24; from now on fits into int32 unchanged
-	// |h4| <= 1.52*2^33
-	// |h8| <= 1.52*2^33
-
-	carry[4] = (h4 + (1 << 25)) >> 26
-	h5 += carry[4]
-	h4 -= carry[4] << 26
-	carry[8] = (h8 + (1 << 25)) >> 26
-	h9 += carry[8]
-	h8 -= carry[8] << 26
-	// |h4| <= 2^25; from now on fits into int32 unchanged
-	// |h8| <= 2^25; from now on fits into int32 unchanged
-	// |h5| <= 1.01*2^24
-	// |h9| <= 1.51*2^58
-
-	carry[9] = (h9 + (1 << 24)) >> 25
-	h0 += carry[9] * 19
-	h9 -= carry[9] << 25
-	// |h9| <= 2^24; from now on fits into int32 unchanged
-	// |h0| <= 1.8*2^37
-
-	carry[0] = (h0 + (1 << 25)) >> 26
-	h1 += carry[0]
-	h0 -= carry[0] << 26
-	// |h0| <= 2^25; from now on fits into int32 unchanged
-	// |h1| <= 1.01*2^24
-
-	h[0] = int32(h0)
-	h[1] = int32(h1)
-	h[2] = int32(h2)
-	h[3] = int32(h3)
-	h[4] = int32(h4)
-	h[5] = int32(h5)
-	h[6] = int32(h6)
-	h[7] = int32(h7)
-	h[8] = int32(h8)
-	h[9] = int32(h9)
-}
-
-// feSquare calculates h = f*f. Can overlap h with f.
-//
-// Preconditions:
-//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-//
-// Postconditions:
-//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-func feSquare(h, f *fieldElement) {
-	f0 := f[0]
-	f1 := f[1]
-	f2 := f[2]
-	f3 := f[3]
-	f4 := f[4]
-	f5 := f[5]
-	f6 := f[6]
-	f7 := f[7]
-	f8 := f[8]
-	f9 := f[9]
-	f0_2 := 2 * f0
-	f1_2 := 2 * f1
-	f2_2 := 2 * f2
-	f3_2 := 2 * f3
-	f4_2 := 2 * f4
-	f5_2 := 2 * f5
-	f6_2 := 2 * f6
-	f7_2 := 2 * f7
-	f5_38 := 38 * f5 // 1.31*2^30
-	f6_19 := 19 * f6 // 1.31*2^30
-	f7_38 := 38 * f7 // 1.31*2^30
-	f8_19 := 19 * f8 // 1.31*2^30
-	f9_38 := 38 * f9 // 1.31*2^30
-	f0f0 := int64(f0) * int64(f0)
-	f0f1_2 := int64(f0_2) * int64(f1)
-	f0f2_2 := int64(f0_2) * int64(f2)
-	f0f3_2 := int64(f0_2) * int64(f3)
-	f0f4_2 := int64(f0_2) * int64(f4)
-	f0f5_2 := int64(f0_2) * int64(f5)
-	f0f6_2 := int64(f0_2) * int64(f6)
-	f0f7_2 := int64(f0_2) * int64(f7)
-	f0f8_2 := int64(f0_2) * int64(f8)
-	f0f9_2 := int64(f0_2) * int64(f9)
-	f1f1_2 := int64(f1_2) * int64(f1)
-	f1f2_2 := int64(f1_2) * int64(f2)
-	f1f3_4 := int64(f1_2) * int64(f3_2)
-	f1f4_2 := int64(f1_2) * int64(f4)
-	f1f5_4 := int64(f1_2) * int64(f5_2)
-	f1f6_2 := int64(f1_2) * int64(f6)
-	f1f7_4 := int64(f1_2) * int64(f7_2)
-	f1f8_2 := int64(f1_2) * int64(f8)
-	f1f9_76 := int64(f1_2) * int64(f9_38)
-	f2f2 := int64(f2) * int64(f2)
-	f2f3_2 := int64(f2_2) * int64(f3)
-	f2f4_2 := int64(f2_2) * int64(f4)
-	f2f5_2 := int64(f2_2) * int64(f5)
-	f2f6_2 := int64(f2_2) * int64(f6)
-	f2f7_2 := int64(f2_2) * int64(f7)
-	f2f8_38 := int64(f2_2) * int64(f8_19)
-	f2f9_38 := int64(f2) * int64(f9_38)
-	f3f3_2 := int64(f3_2) * int64(f3)
-	f3f4_2 := int64(f3_2) * int64(f4)
-	f3f5_4 := int64(f3_2) * int64(f5_2)
-	f3f6_2 := int64(f3_2) * int64(f6)
-	f3f7_76 := int64(f3_2) * int64(f7_38)
-	f3f8_38 := int64(f3_2) * int64(f8_19)
-	f3f9_76 := int64(f3_2) * int64(f9_38)
-	f4f4 := int64(f4) * int64(f4)
-	f4f5_2 := int64(f4_2) * int64(f5)
-	f4f6_38 := int64(f4_2) * int64(f6_19)
-	f4f7_38 := int64(f4) * int64(f7_38)
-	f4f8_38 := int64(f4_2) * int64(f8_19)
-	f4f9_38 := int64(f4) * int64(f9_38)
-	f5f5_38 := int64(f5) * int64(f5_38)
-	f5f6_38 := int64(f5_2) * int64(f6_19)
-	f5f7_76 := int64(f5_2) * int64(f7_38)
-	f5f8_38 := int64(f5_2) * int64(f8_19)
-	f5f9_76 := int64(f5_2) * int64(f9_38)
-	f6f6_19 := int64(f6) * int64(f6_19)
-	f6f7_38 := int64(f6) * int64(f7_38)
-	f6f8_38 := int64(f6_2) * int64(f8_19)
-	f6f9_38 := int64(f6) * int64(f9_38)
-	f7f7_38 := int64(f7) * int64(f7_38)
-	f7f8_38 := int64(f7_2) * int64(f8_19)
-	f7f9_76 := int64(f7_2) * int64(f9_38)
-	f8f8_19 := int64(f8) * int64(f8_19)
-	f8f9_38 := int64(f8) * int64(f9_38)
-	f9f9_38 := int64(f9) * int64(f9_38)
-	h0 := f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38
-	h1 := f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38
-	h2 := f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19
-	h3 := f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38
-	h4 := f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38
-	h5 := f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38
-	h6 := f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19
-	h7 := f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38
-	h8 := f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38
-	h9 := f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2
-	var carry [10]int64
-
-	carry[0] = (h0 + (1 << 25)) >> 26
-	h1 += carry[0]
-	h0 -= carry[0] << 26
-	carry[4] = (h4 + (1 << 25)) >> 26
-	h5 += carry[4]
-	h4 -= carry[4] << 26
-
-	carry[1] = (h1 + (1 << 24)) >> 25
-	h2 += carry[1]
-	h1 -= carry[1] << 25
-	carry[5] = (h5 + (1 << 24)) >> 25
-	h6 += carry[5]
-	h5 -= carry[5] << 25
-
-	carry[2] = (h2 + (1 << 25)) >> 26
-	h3 += carry[2]
-	h2 -= carry[2] << 26
-	carry[6] = (h6 + (1 << 25)) >> 26
-	h7 += carry[6]
-	h6 -= carry[6] << 26
-
-	carry[3] = (h3 + (1 << 24)) >> 25
-	h4 += carry[3]
-	h3 -= carry[3] << 25
-	carry[7] = (h7 + (1 << 24)) >> 25
-	h8 += carry[7]
-	h7 -= carry[7] << 25
-
-	carry[4] = (h4 + (1 << 25)) >> 26
-	h5 += carry[4]
-	h4 -= carry[4] << 26
-	carry[8] = (h8 + (1 << 25)) >> 26
-	h9 += carry[8]
-	h8 -= carry[8] << 26
-
-	carry[9] = (h9 + (1 << 24)) >> 25
-	h0 += carry[9] * 19
-	h9 -= carry[9] << 25
-
-	carry[0] = (h0 + (1 << 25)) >> 26
-	h1 += carry[0]
-	h0 -= carry[0] << 26
-
-	h[0] = int32(h0)
-	h[1] = int32(h1)
-	h[2] = int32(h2)
-	h[3] = int32(h3)
-	h[4] = int32(h4)
-	h[5] = int32(h5)
-	h[6] = int32(h6)
-	h[7] = int32(h7)
-	h[8] = int32(h8)
-	h[9] = int32(h9)
-}
-
-// feMul121666 calculates h = f * 121666. Can overlap h with f.
-//
-// Preconditions:
-//    |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
-//
-// Postconditions:
-//    |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
-func feMul121666(h, f *fieldElement) {
-	h0 := int64(f[0]) * 121666
-	h1 := int64(f[1]) * 121666
-	h2 := int64(f[2]) * 121666
-	h3 := int64(f[3]) * 121666
-	h4 := int64(f[4]) * 121666
-	h5 := int64(f[5]) * 121666
-	h6 := int64(f[6]) * 121666
-	h7 := int64(f[7]) * 121666
-	h8 := int64(f[8]) * 121666
-	h9 := int64(f[9]) * 121666
-	var carry [10]int64
-
-	carry[9] = (h9 + (1 << 24)) >> 25
-	h0 += carry[9] * 19
-	h9 -= carry[9] << 25
-	carry[1] = (h1 + (1 << 24)) >> 25
-	h2 += carry[1]
-	h1 -= carry[1] << 25
-	carry[3] = (h3 + (1 << 24)) >> 25
-	h4 += carry[3]
-	h3 -= carry[3] << 25
-	carry[5] = (h5 + (1 << 24)) >> 25
-	h6 += carry[5]
-	h5 -= carry[5] << 25
-	carry[7] = (h7 + (1 << 24)) >> 25
-	h8 += carry[7]
-	h7 -= carry[7] << 25
-
-	carry[0] = (h0 + (1 << 25)) >> 26
-	h1 += carry[0]
-	h0 -= carry[0] << 26
-	carry[2] = (h2 + (1 << 25)) >> 26
-	h3 += carry[2]
-	h2 -= carry[2] << 26
-	carry[4] = (h4 + (1 << 25)) >> 26
-	h5 += carry[4]
-	h4 -= carry[4] << 26
-	carry[6] = (h6 + (1 << 25)) >> 26
-	h7 += carry[6]
-	h6 -= carry[6] << 26
-	carry[8] = (h8 + (1 << 25)) >> 26
-	h9 += carry[8]
-	h8 -= carry[8] << 26
-
-	h[0] = int32(h0)
-	h[1] = int32(h1)
-	h[2] = int32(h2)
-	h[3] = int32(h3)
-	h[4] = int32(h4)
-	h[5] = int32(h5)
-	h[6] = int32(h6)
-	h[7] = int32(h7)
-	h[8] = int32(h8)
-	h[9] = int32(h9)
-}
-
-// feInvert sets out = z^-1.
-func feInvert(out, z *fieldElement) {
-	var t0, t1, t2, t3 fieldElement
-	var i int
-
-	feSquare(&t0, z)
-	for i = 1; i < 1; i++ {
-		feSquare(&t0, &t0)
-	}
-	feSquare(&t1, &t0)
-	for i = 1; i < 2; i++ {
-		feSquare(&t1, &t1)
-	}
-	feMul(&t1, z, &t1)
-	feMul(&t0, &t0, &t1)
-	feSquare(&t2, &t0)
-	for i = 1; i < 1; i++ {
-		feSquare(&t2, &t2)
-	}
-	feMul(&t1, &t1, &t2)
-	feSquare(&t2, &t1)
-	for i = 1; i < 5; i++ {
-		feSquare(&t2, &t2)
-	}
-	feMul(&t1, &t2, &t1)
-	feSquare(&t2, &t1)
-	for i = 1; i < 10; i++ {
-		feSquare(&t2, &t2)
-	}
-	feMul(&t2, &t2, &t1)
-	feSquare(&t3, &t2)
-	for i = 1; i < 20; i++ {
-		feSquare(&t3, &t3)
-	}
-	feMul(&t2, &t3, &t2)
-	feSquare(&t2, &t2)
-	for i = 1; i < 10; i++ {
-		feSquare(&t2, &t2)
-	}
-	feMul(&t1, &t2, &t1)
-	feSquare(&t2, &t1)
-	for i = 1; i < 50; i++ {
-		feSquare(&t2, &t2)
-	}
-	feMul(&t2, &t2, &t1)
-	feSquare(&t3, &t2)
-	for i = 1; i < 100; i++ {
-		feSquare(&t3, &t3)
-	}
-	feMul(&t2, &t3, &t2)
-	feSquare(&t2, &t2)
-	for i = 1; i < 50; i++ {
-		feSquare(&t2, &t2)
-	}
-	feMul(&t1, &t2, &t1)
-	feSquare(&t1, &t1)
-	for i = 1; i < 5; i++ {
-		feSquare(&t1, &t1)
-	}
-	feMul(out, &t1, &t0)
-}
-
-func scalarMult(out, in, base *[32]byte) {
-	var e [32]byte
-
-	copy(e[:], in[:])
-	e[0] &= 248
-	e[31] &= 127
-	e[31] |= 64
-
-	var x1, x2, z2, x3, z3, tmp0, tmp1 fieldElement
-	feFromBytes(&x1, base)
-	feOne(&x2)
-	feCopy(&x3, &x1)
-	feOne(&z3)
-
-	swap := int32(0)
-	for pos := 254; pos >= 0; pos-- {
-		b := e[pos/8] >> uint(pos&7)
-		b &= 1
-		swap ^= int32(b)
-		feCSwap(&x2, &x3, swap)
-		feCSwap(&z2, &z3, swap)
-		swap = int32(b)
-
-		feSub(&tmp0, &x3, &z3)
-		feSub(&tmp1, &x2, &z2)
-		feAdd(&x2, &x2, &z2)
-		feAdd(&z2, &x3, &z3)
-		feMul(&z3, &tmp0, &x2)
-		feMul(&z2, &z2, &tmp1)
-		feSquare(&tmp0, &tmp1)
-		feSquare(&tmp1, &x2)
-		feAdd(&x3, &z3, &z2)
-		feSub(&z2, &z3, &z2)
-		feMul(&x2, &tmp1, &tmp0)
-		feSub(&tmp1, &tmp1, &tmp0)
-		feSquare(&z2, &z2)
-		feMul121666(&z3, &tmp1)
-		feSquare(&x3, &x3)
-		feAdd(&tmp0, &tmp0, &z3)
-		feMul(&z3, &x1, &z2)
-		feMul(&z2, &tmp1, &tmp0)
-	}
-
-	feCSwap(&x2, &x3, swap)
-	feCSwap(&z2, &z3, swap)
-
-	feInvert(&z2, &z2)
-	feMul(&x2, &x2, &z2)
-	feToBytes(out, &x2)
-}
diff --git a/src/ssl/test/runner/curve25519/curve25519_test.go b/src/ssl/test/runner/curve25519/curve25519_test.go
deleted file mode 100644
index 14b0ee8..0000000
--- a/src/ssl/test/runner/curve25519/curve25519_test.go
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package curve25519
-
-import (
-	"fmt"
-	"testing"
-)
-
-const expectedHex = "89161fde887b2b53de549af483940106ecc114d6982daa98256de23bdf77661a"
-
-func TestBaseScalarMult(t *testing.T) {
-	var a, b [32]byte
-	in := &a
-	out := &b
-	a[0] = 1
-
-	for i := 0; i < 200; i++ {
-		ScalarBaseMult(out, in)
-		in, out = out, in
-	}
-
-	result := fmt.Sprintf("%x", in[:])
-	if result != expectedHex {
-		t.Errorf("incorrect result: got %s, want %s", result, expectedHex)
-	}
-}
diff --git a/src/ssl/test/runner/curve25519/doc.go b/src/ssl/test/runner/curve25519/doc.go
deleted file mode 100644
index ebeea3c..0000000
--- a/src/ssl/test/runner/curve25519/doc.go
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// Package curve25519 provides an implementation of scalar multiplication on
-// the elliptic curve known as curve25519. See http://cr.yp.to/ecdh.html
-package curve25519 // import "golang.org/x/crypto/curve25519"
-
-// basePoint is the x coordinate of the generator of the curve.
-var basePoint = [32]byte{9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
-
-// ScalarMult sets dst to the product in*base where dst and base are the x
-// coordinates of group points and all values are in little-endian form.
-func ScalarMult(dst, in, base *[32]byte) {
-	scalarMult(dst, in, base)
-}
-
-// ScalarBaseMult sets dst to the product in*base where dst and base are the x
-// coordinates of group points, base is the standard generator and all values
-// are in little-endian form.
-func ScalarBaseMult(dst, in *[32]byte) {
-	ScalarMult(dst, in, &basePoint)
-}
diff --git a/src/ssl/test/runner/curve25519/freeze_amd64.s b/src/ssl/test/runner/curve25519/freeze_amd64.s
deleted file mode 100644
index 536479b..0000000
--- a/src/ssl/test/runner/curve25519/freeze_amd64.s
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
-
-// +build amd64,!gccgo,!appengine
-
-#include "const_amd64.h"
-
-// func freeze(inout *[5]uint64)
-TEXT ·freeze(SB),7,$0-8
-	MOVQ inout+0(FP), DI
-
-	MOVQ 0(DI),SI
-	MOVQ 8(DI),DX
-	MOVQ 16(DI),CX
-	MOVQ 24(DI),R8
-	MOVQ 32(DI),R9
-	MOVQ $REDMASK51,AX
-	MOVQ AX,R10
-	SUBQ $18,R10
-	MOVQ $3,R11
-REDUCELOOP:
-	MOVQ SI,R12
-	SHRQ $51,R12
-	ANDQ AX,SI
-	ADDQ R12,DX
-	MOVQ DX,R12
-	SHRQ $51,R12
-	ANDQ AX,DX
-	ADDQ R12,CX
-	MOVQ CX,R12
-	SHRQ $51,R12
-	ANDQ AX,CX
-	ADDQ R12,R8
-	MOVQ R8,R12
-	SHRQ $51,R12
-	ANDQ AX,R8
-	ADDQ R12,R9
-	MOVQ R9,R12
-	SHRQ $51,R12
-	ANDQ AX,R9
-	IMUL3Q $19,R12,R12
-	ADDQ R12,SI
-	SUBQ $1,R11
-	JA REDUCELOOP
-	MOVQ $1,R12
-	CMPQ R10,SI
-	CMOVQLT R11,R12
-	CMPQ AX,DX
-	CMOVQNE R11,R12
-	CMPQ AX,CX
-	CMOVQNE R11,R12
-	CMPQ AX,R8
-	CMOVQNE R11,R12
-	CMPQ AX,R9
-	CMOVQNE R11,R12
-	NEGQ R12
-	ANDQ R12,AX
-	ANDQ R12,R10
-	SUBQ R10,SI
-	SUBQ AX,DX
-	SUBQ AX,CX
-	SUBQ AX,R8
-	SUBQ AX,R9
-	MOVQ SI,0(DI)
-	MOVQ DX,8(DI)
-	MOVQ CX,16(DI)
-	MOVQ R8,24(DI)
-	MOVQ R9,32(DI)
-	RET
diff --git a/src/ssl/test/runner/curve25519/ladderstep_amd64.s b/src/ssl/test/runner/curve25519/ladderstep_amd64.s
deleted file mode 100644
index 7074e5c..0000000
--- a/src/ssl/test/runner/curve25519/ladderstep_amd64.s
+++ /dev/null
@@ -1,1377 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
-
-// +build amd64,!gccgo,!appengine
-
-#include "const_amd64.h"
-
-// func ladderstep(inout *[5][5]uint64)
-TEXT ·ladderstep(SB),0,$296-8
-	MOVQ inout+0(FP),DI
-
-	MOVQ 40(DI),SI
-	MOVQ 48(DI),DX
-	MOVQ 56(DI),CX
-	MOVQ 64(DI),R8
-	MOVQ 72(DI),R9
-	MOVQ SI,AX
-	MOVQ DX,R10
-	MOVQ CX,R11
-	MOVQ R8,R12
-	MOVQ R9,R13
-	ADDQ ·_2P0(SB),AX
-	ADDQ ·_2P1234(SB),R10
-	ADDQ ·_2P1234(SB),R11
-	ADDQ ·_2P1234(SB),R12
-	ADDQ ·_2P1234(SB),R13
-	ADDQ 80(DI),SI
-	ADDQ 88(DI),DX
-	ADDQ 96(DI),CX
-	ADDQ 104(DI),R8
-	ADDQ 112(DI),R9
-	SUBQ 80(DI),AX
-	SUBQ 88(DI),R10
-	SUBQ 96(DI),R11
-	SUBQ 104(DI),R12
-	SUBQ 112(DI),R13
-	MOVQ SI,0(SP)
-	MOVQ DX,8(SP)
-	MOVQ CX,16(SP)
-	MOVQ R8,24(SP)
-	MOVQ R9,32(SP)
-	MOVQ AX,40(SP)
-	MOVQ R10,48(SP)
-	MOVQ R11,56(SP)
-	MOVQ R12,64(SP)
-	MOVQ R13,72(SP)
-	MOVQ 40(SP),AX
-	MULQ 40(SP)
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 40(SP),AX
-	SHLQ $1,AX
-	MULQ 48(SP)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 40(SP),AX
-	SHLQ $1,AX
-	MULQ 56(SP)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 40(SP),AX
-	SHLQ $1,AX
-	MULQ 64(SP)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 40(SP),AX
-	SHLQ $1,AX
-	MULQ 72(SP)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 48(SP),AX
-	MULQ 48(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 48(SP),AX
-	SHLQ $1,AX
-	MULQ 56(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 48(SP),AX
-	SHLQ $1,AX
-	MULQ 64(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 48(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 72(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 56(SP),AX
-	MULQ 56(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 56(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 64(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 56(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 72(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 64(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 64(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 64(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 72(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 72(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 72(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ $REDMASK51,DX
-	SHLQ $13,CX:SI
-	ANDQ DX,SI
-	SHLQ $13,R9:R8
-	ANDQ DX,R8
-	ADDQ CX,R8
-	SHLQ $13,R11:R10
-	ANDQ DX,R10
-	ADDQ R9,R10
-	SHLQ $13,R13:R12
-	ANDQ DX,R12
-	ADDQ R11,R12
-	SHLQ $13,R15:R14
-	ANDQ DX,R14
-	ADDQ R13,R14
-	IMUL3Q $19,R15,CX
-	ADDQ CX,SI
-	MOVQ SI,CX
-	SHRQ $51,CX
-	ADDQ R8,CX
-	ANDQ DX,SI
-	MOVQ CX,R8
-	SHRQ $51,CX
-	ADDQ R10,CX
-	ANDQ DX,R8
-	MOVQ CX,R9
-	SHRQ $51,CX
-	ADDQ R12,CX
-	ANDQ DX,R9
-	MOVQ CX,AX
-	SHRQ $51,CX
-	ADDQ R14,CX
-	ANDQ DX,AX
-	MOVQ CX,R10
-	SHRQ $51,CX
-	IMUL3Q $19,CX,CX
-	ADDQ CX,SI
-	ANDQ DX,R10
-	MOVQ SI,80(SP)
-	MOVQ R8,88(SP)
-	MOVQ R9,96(SP)
-	MOVQ AX,104(SP)
-	MOVQ R10,112(SP)
-	MOVQ 0(SP),AX
-	MULQ 0(SP)
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 0(SP),AX
-	SHLQ $1,AX
-	MULQ 8(SP)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 0(SP),AX
-	SHLQ $1,AX
-	MULQ 16(SP)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 0(SP),AX
-	SHLQ $1,AX
-	MULQ 24(SP)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 0(SP),AX
-	SHLQ $1,AX
-	MULQ 32(SP)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 8(SP),AX
-	MULQ 8(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 8(SP),AX
-	SHLQ $1,AX
-	MULQ 16(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 8(SP),AX
-	SHLQ $1,AX
-	MULQ 24(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 8(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 32(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 16(SP),AX
-	MULQ 16(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 16(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 24(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 16(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 32(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 24(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 24(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 24(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 32(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 32(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 32(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ $REDMASK51,DX
-	SHLQ $13,CX:SI
-	ANDQ DX,SI
-	SHLQ $13,R9:R8
-	ANDQ DX,R8
-	ADDQ CX,R8
-	SHLQ $13,R11:R10
-	ANDQ DX,R10
-	ADDQ R9,R10
-	SHLQ $13,R13:R12
-	ANDQ DX,R12
-	ADDQ R11,R12
-	SHLQ $13,R15:R14
-	ANDQ DX,R14
-	ADDQ R13,R14
-	IMUL3Q $19,R15,CX
-	ADDQ CX,SI
-	MOVQ SI,CX
-	SHRQ $51,CX
-	ADDQ R8,CX
-	ANDQ DX,SI
-	MOVQ CX,R8
-	SHRQ $51,CX
-	ADDQ R10,CX
-	ANDQ DX,R8
-	MOVQ CX,R9
-	SHRQ $51,CX
-	ADDQ R12,CX
-	ANDQ DX,R9
-	MOVQ CX,AX
-	SHRQ $51,CX
-	ADDQ R14,CX
-	ANDQ DX,AX
-	MOVQ CX,R10
-	SHRQ $51,CX
-	IMUL3Q $19,CX,CX
-	ADDQ CX,SI
-	ANDQ DX,R10
-	MOVQ SI,120(SP)
-	MOVQ R8,128(SP)
-	MOVQ R9,136(SP)
-	MOVQ AX,144(SP)
-	MOVQ R10,152(SP)
-	MOVQ SI,SI
-	MOVQ R8,DX
-	MOVQ R9,CX
-	MOVQ AX,R8
-	MOVQ R10,R9
-	ADDQ ·_2P0(SB),SI
-	ADDQ ·_2P1234(SB),DX
-	ADDQ ·_2P1234(SB),CX
-	ADDQ ·_2P1234(SB),R8
-	ADDQ ·_2P1234(SB),R9
-	SUBQ 80(SP),SI
-	SUBQ 88(SP),DX
-	SUBQ 96(SP),CX
-	SUBQ 104(SP),R8
-	SUBQ 112(SP),R9
-	MOVQ SI,160(SP)
-	MOVQ DX,168(SP)
-	MOVQ CX,176(SP)
-	MOVQ R8,184(SP)
-	MOVQ R9,192(SP)
-	MOVQ 120(DI),SI
-	MOVQ 128(DI),DX
-	MOVQ 136(DI),CX
-	MOVQ 144(DI),R8
-	MOVQ 152(DI),R9
-	MOVQ SI,AX
-	MOVQ DX,R10
-	MOVQ CX,R11
-	MOVQ R8,R12
-	MOVQ R9,R13
-	ADDQ ·_2P0(SB),AX
-	ADDQ ·_2P1234(SB),R10
-	ADDQ ·_2P1234(SB),R11
-	ADDQ ·_2P1234(SB),R12
-	ADDQ ·_2P1234(SB),R13
-	ADDQ 160(DI),SI
-	ADDQ 168(DI),DX
-	ADDQ 176(DI),CX
-	ADDQ 184(DI),R8
-	ADDQ 192(DI),R9
-	SUBQ 160(DI),AX
-	SUBQ 168(DI),R10
-	SUBQ 176(DI),R11
-	SUBQ 184(DI),R12
-	SUBQ 192(DI),R13
-	MOVQ SI,200(SP)
-	MOVQ DX,208(SP)
-	MOVQ CX,216(SP)
-	MOVQ R8,224(SP)
-	MOVQ R9,232(SP)
-	MOVQ AX,240(SP)
-	MOVQ R10,248(SP)
-	MOVQ R11,256(SP)
-	MOVQ R12,264(SP)
-	MOVQ R13,272(SP)
-	MOVQ 224(SP),SI
-	IMUL3Q $19,SI,AX
-	MOVQ AX,280(SP)
-	MULQ 56(SP)
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 232(SP),DX
-	IMUL3Q $19,DX,AX
-	MOVQ AX,288(SP)
-	MULQ 48(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 200(SP),AX
-	MULQ 40(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 200(SP),AX
-	MULQ 48(SP)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 200(SP),AX
-	MULQ 56(SP)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 200(SP),AX
-	MULQ 64(SP)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 200(SP),AX
-	MULQ 72(SP)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 208(SP),AX
-	MULQ 40(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 208(SP),AX
-	MULQ 48(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 208(SP),AX
-	MULQ 56(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 208(SP),AX
-	MULQ 64(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 208(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 72(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 216(SP),AX
-	MULQ 40(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 216(SP),AX
-	MULQ 48(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 216(SP),AX
-	MULQ 56(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 216(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 64(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 216(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 72(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 224(SP),AX
-	MULQ 40(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 224(SP),AX
-	MULQ 48(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 280(SP),AX
-	MULQ 64(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 280(SP),AX
-	MULQ 72(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 232(SP),AX
-	MULQ 40(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 288(SP),AX
-	MULQ 56(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 288(SP),AX
-	MULQ 64(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 288(SP),AX
-	MULQ 72(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ $REDMASK51,DX
-	SHLQ $13,CX:SI
-	ANDQ DX,SI
-	SHLQ $13,R9:R8
-	ANDQ DX,R8
-	ADDQ CX,R8
-	SHLQ $13,R11:R10
-	ANDQ DX,R10
-	ADDQ R9,R10
-	SHLQ $13,R13:R12
-	ANDQ DX,R12
-	ADDQ R11,R12
-	SHLQ $13,R15:R14
-	ANDQ DX,R14
-	ADDQ R13,R14
-	IMUL3Q $19,R15,CX
-	ADDQ CX,SI
-	MOVQ SI,CX
-	SHRQ $51,CX
-	ADDQ R8,CX
-	MOVQ CX,R8
-	SHRQ $51,CX
-	ANDQ DX,SI
-	ADDQ R10,CX
-	MOVQ CX,R9
-	SHRQ $51,CX
-	ANDQ DX,R8
-	ADDQ R12,CX
-	MOVQ CX,AX
-	SHRQ $51,CX
-	ANDQ DX,R9
-	ADDQ R14,CX
-	MOVQ CX,R10
-	SHRQ $51,CX
-	ANDQ DX,AX
-	IMUL3Q $19,CX,CX
-	ADDQ CX,SI
-	ANDQ DX,R10
-	MOVQ SI,40(SP)
-	MOVQ R8,48(SP)
-	MOVQ R9,56(SP)
-	MOVQ AX,64(SP)
-	MOVQ R10,72(SP)
-	MOVQ 264(SP),SI
-	IMUL3Q $19,SI,AX
-	MOVQ AX,200(SP)
-	MULQ 16(SP)
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 272(SP),DX
-	IMUL3Q $19,DX,AX
-	MOVQ AX,208(SP)
-	MULQ 8(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 240(SP),AX
-	MULQ 0(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 240(SP),AX
-	MULQ 8(SP)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 240(SP),AX
-	MULQ 16(SP)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 240(SP),AX
-	MULQ 24(SP)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 240(SP),AX
-	MULQ 32(SP)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 248(SP),AX
-	MULQ 0(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 248(SP),AX
-	MULQ 8(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 248(SP),AX
-	MULQ 16(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 248(SP),AX
-	MULQ 24(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 248(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 32(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 256(SP),AX
-	MULQ 0(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 256(SP),AX
-	MULQ 8(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 256(SP),AX
-	MULQ 16(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 256(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 24(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 256(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 32(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 264(SP),AX
-	MULQ 0(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 264(SP),AX
-	MULQ 8(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 200(SP),AX
-	MULQ 24(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 200(SP),AX
-	MULQ 32(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 272(SP),AX
-	MULQ 0(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 208(SP),AX
-	MULQ 16(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 208(SP),AX
-	MULQ 24(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 208(SP),AX
-	MULQ 32(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ $REDMASK51,DX
-	SHLQ $13,CX:SI
-	ANDQ DX,SI
-	SHLQ $13,R9:R8
-	ANDQ DX,R8
-	ADDQ CX,R8
-	SHLQ $13,R11:R10
-	ANDQ DX,R10
-	ADDQ R9,R10
-	SHLQ $13,R13:R12
-	ANDQ DX,R12
-	ADDQ R11,R12
-	SHLQ $13,R15:R14
-	ANDQ DX,R14
-	ADDQ R13,R14
-	IMUL3Q $19,R15,CX
-	ADDQ CX,SI
-	MOVQ SI,CX
-	SHRQ $51,CX
-	ADDQ R8,CX
-	MOVQ CX,R8
-	SHRQ $51,CX
-	ANDQ DX,SI
-	ADDQ R10,CX
-	MOVQ CX,R9
-	SHRQ $51,CX
-	ANDQ DX,R8
-	ADDQ R12,CX
-	MOVQ CX,AX
-	SHRQ $51,CX
-	ANDQ DX,R9
-	ADDQ R14,CX
-	MOVQ CX,R10
-	SHRQ $51,CX
-	ANDQ DX,AX
-	IMUL3Q $19,CX,CX
-	ADDQ CX,SI
-	ANDQ DX,R10
-	MOVQ SI,DX
-	MOVQ R8,CX
-	MOVQ R9,R11
-	MOVQ AX,R12
-	MOVQ R10,R13
-	ADDQ ·_2P0(SB),DX
-	ADDQ ·_2P1234(SB),CX
-	ADDQ ·_2P1234(SB),R11
-	ADDQ ·_2P1234(SB),R12
-	ADDQ ·_2P1234(SB),R13
-	ADDQ 40(SP),SI
-	ADDQ 48(SP),R8
-	ADDQ 56(SP),R9
-	ADDQ 64(SP),AX
-	ADDQ 72(SP),R10
-	SUBQ 40(SP),DX
-	SUBQ 48(SP),CX
-	SUBQ 56(SP),R11
-	SUBQ 64(SP),R12
-	SUBQ 72(SP),R13
-	MOVQ SI,120(DI)
-	MOVQ R8,128(DI)
-	MOVQ R9,136(DI)
-	MOVQ AX,144(DI)
-	MOVQ R10,152(DI)
-	MOVQ DX,160(DI)
-	MOVQ CX,168(DI)
-	MOVQ R11,176(DI)
-	MOVQ R12,184(DI)
-	MOVQ R13,192(DI)
-	MOVQ 120(DI),AX
-	MULQ 120(DI)
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 120(DI),AX
-	SHLQ $1,AX
-	MULQ 128(DI)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 120(DI),AX
-	SHLQ $1,AX
-	MULQ 136(DI)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 120(DI),AX
-	SHLQ $1,AX
-	MULQ 144(DI)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 120(DI),AX
-	SHLQ $1,AX
-	MULQ 152(DI)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 128(DI),AX
-	MULQ 128(DI)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 128(DI),AX
-	SHLQ $1,AX
-	MULQ 136(DI)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 128(DI),AX
-	SHLQ $1,AX
-	MULQ 144(DI)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 128(DI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 152(DI)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 136(DI),AX
-	MULQ 136(DI)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 136(DI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 144(DI)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 136(DI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 152(DI)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 144(DI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 144(DI)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 144(DI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 152(DI)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 152(DI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 152(DI)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ $REDMASK51,DX
-	SHLQ $13,CX:SI
-	ANDQ DX,SI
-	SHLQ $13,R9:R8
-	ANDQ DX,R8
-	ADDQ CX,R8
-	SHLQ $13,R11:R10
-	ANDQ DX,R10
-	ADDQ R9,R10
-	SHLQ $13,R13:R12
-	ANDQ DX,R12
-	ADDQ R11,R12
-	SHLQ $13,R15:R14
-	ANDQ DX,R14
-	ADDQ R13,R14
-	IMUL3Q $19,R15,CX
-	ADDQ CX,SI
-	MOVQ SI,CX
-	SHRQ $51,CX
-	ADDQ R8,CX
-	ANDQ DX,SI
-	MOVQ CX,R8
-	SHRQ $51,CX
-	ADDQ R10,CX
-	ANDQ DX,R8
-	MOVQ CX,R9
-	SHRQ $51,CX
-	ADDQ R12,CX
-	ANDQ DX,R9
-	MOVQ CX,AX
-	SHRQ $51,CX
-	ADDQ R14,CX
-	ANDQ DX,AX
-	MOVQ CX,R10
-	SHRQ $51,CX
-	IMUL3Q $19,CX,CX
-	ADDQ CX,SI
-	ANDQ DX,R10
-	MOVQ SI,120(DI)
-	MOVQ R8,128(DI)
-	MOVQ R9,136(DI)
-	MOVQ AX,144(DI)
-	MOVQ R10,152(DI)
-	MOVQ 160(DI),AX
-	MULQ 160(DI)
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 160(DI),AX
-	SHLQ $1,AX
-	MULQ 168(DI)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 160(DI),AX
-	SHLQ $1,AX
-	MULQ 176(DI)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 160(DI),AX
-	SHLQ $1,AX
-	MULQ 184(DI)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 160(DI),AX
-	SHLQ $1,AX
-	MULQ 192(DI)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 168(DI),AX
-	MULQ 168(DI)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 168(DI),AX
-	SHLQ $1,AX
-	MULQ 176(DI)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 168(DI),AX
-	SHLQ $1,AX
-	MULQ 184(DI)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 168(DI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 192(DI)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 176(DI),AX
-	MULQ 176(DI)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 176(DI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 184(DI)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 176(DI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 192(DI)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 184(DI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 184(DI)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 184(DI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 192(DI)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 192(DI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 192(DI)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ $REDMASK51,DX
-	SHLQ $13,CX:SI
-	ANDQ DX,SI
-	SHLQ $13,R9:R8
-	ANDQ DX,R8
-	ADDQ CX,R8
-	SHLQ $13,R11:R10
-	ANDQ DX,R10
-	ADDQ R9,R10
-	SHLQ $13,R13:R12
-	ANDQ DX,R12
-	ADDQ R11,R12
-	SHLQ $13,R15:R14
-	ANDQ DX,R14
-	ADDQ R13,R14
-	IMUL3Q $19,R15,CX
-	ADDQ CX,SI
-	MOVQ SI,CX
-	SHRQ $51,CX
-	ADDQ R8,CX
-	ANDQ DX,SI
-	MOVQ CX,R8
-	SHRQ $51,CX
-	ADDQ R10,CX
-	ANDQ DX,R8
-	MOVQ CX,R9
-	SHRQ $51,CX
-	ADDQ R12,CX
-	ANDQ DX,R9
-	MOVQ CX,AX
-	SHRQ $51,CX
-	ADDQ R14,CX
-	ANDQ DX,AX
-	MOVQ CX,R10
-	SHRQ $51,CX
-	IMUL3Q $19,CX,CX
-	ADDQ CX,SI
-	ANDQ DX,R10
-	MOVQ SI,160(DI)
-	MOVQ R8,168(DI)
-	MOVQ R9,176(DI)
-	MOVQ AX,184(DI)
-	MOVQ R10,192(DI)
-	MOVQ 184(DI),SI
-	IMUL3Q $19,SI,AX
-	MOVQ AX,0(SP)
-	MULQ 16(DI)
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 192(DI),DX
-	IMUL3Q $19,DX,AX
-	MOVQ AX,8(SP)
-	MULQ 8(DI)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 160(DI),AX
-	MULQ 0(DI)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 160(DI),AX
-	MULQ 8(DI)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 160(DI),AX
-	MULQ 16(DI)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 160(DI),AX
-	MULQ 24(DI)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 160(DI),AX
-	MULQ 32(DI)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 168(DI),AX
-	MULQ 0(DI)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 168(DI),AX
-	MULQ 8(DI)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 168(DI),AX
-	MULQ 16(DI)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 168(DI),AX
-	MULQ 24(DI)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 168(DI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 32(DI)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 176(DI),AX
-	MULQ 0(DI)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 176(DI),AX
-	MULQ 8(DI)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 176(DI),AX
-	MULQ 16(DI)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 176(DI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 24(DI)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 176(DI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 32(DI)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 184(DI),AX
-	MULQ 0(DI)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 184(DI),AX
-	MULQ 8(DI)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 0(SP),AX
-	MULQ 24(DI)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 0(SP),AX
-	MULQ 32(DI)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 192(DI),AX
-	MULQ 0(DI)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 8(SP),AX
-	MULQ 16(DI)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 8(SP),AX
-	MULQ 24(DI)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 8(SP),AX
-	MULQ 32(DI)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ $REDMASK51,DX
-	SHLQ $13,CX:SI
-	ANDQ DX,SI
-	SHLQ $13,R9:R8
-	ANDQ DX,R8
-	ADDQ CX,R8
-	SHLQ $13,R11:R10
-	ANDQ DX,R10
-	ADDQ R9,R10
-	SHLQ $13,R13:R12
-	ANDQ DX,R12
-	ADDQ R11,R12
-	SHLQ $13,R15:R14
-	ANDQ DX,R14
-	ADDQ R13,R14
-	IMUL3Q $19,R15,CX
-	ADDQ CX,SI
-	MOVQ SI,CX
-	SHRQ $51,CX
-	ADDQ R8,CX
-	MOVQ CX,R8
-	SHRQ $51,CX
-	ANDQ DX,SI
-	ADDQ R10,CX
-	MOVQ CX,R9
-	SHRQ $51,CX
-	ANDQ DX,R8
-	ADDQ R12,CX
-	MOVQ CX,AX
-	SHRQ $51,CX
-	ANDQ DX,R9
-	ADDQ R14,CX
-	MOVQ CX,R10
-	SHRQ $51,CX
-	ANDQ DX,AX
-	IMUL3Q $19,CX,CX
-	ADDQ CX,SI
-	ANDQ DX,R10
-	MOVQ SI,160(DI)
-	MOVQ R8,168(DI)
-	MOVQ R9,176(DI)
-	MOVQ AX,184(DI)
-	MOVQ R10,192(DI)
-	MOVQ 144(SP),SI
-	IMUL3Q $19,SI,AX
-	MOVQ AX,0(SP)
-	MULQ 96(SP)
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 152(SP),DX
-	IMUL3Q $19,DX,AX
-	MOVQ AX,8(SP)
-	MULQ 88(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 120(SP),AX
-	MULQ 80(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 120(SP),AX
-	MULQ 88(SP)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 120(SP),AX
-	MULQ 96(SP)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 120(SP),AX
-	MULQ 104(SP)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 120(SP),AX
-	MULQ 112(SP)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 128(SP),AX
-	MULQ 80(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 128(SP),AX
-	MULQ 88(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 128(SP),AX
-	MULQ 96(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 128(SP),AX
-	MULQ 104(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 128(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 112(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 136(SP),AX
-	MULQ 80(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 136(SP),AX
-	MULQ 88(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 136(SP),AX
-	MULQ 96(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 136(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 104(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 136(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 112(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 144(SP),AX
-	MULQ 80(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 144(SP),AX
-	MULQ 88(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 0(SP),AX
-	MULQ 104(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 0(SP),AX
-	MULQ 112(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 152(SP),AX
-	MULQ 80(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 8(SP),AX
-	MULQ 96(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 8(SP),AX
-	MULQ 104(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 8(SP),AX
-	MULQ 112(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ $REDMASK51,DX
-	SHLQ $13,CX:SI
-	ANDQ DX,SI
-	SHLQ $13,R9:R8
-	ANDQ DX,R8
-	ADDQ CX,R8
-	SHLQ $13,R11:R10
-	ANDQ DX,R10
-	ADDQ R9,R10
-	SHLQ $13,R13:R12
-	ANDQ DX,R12
-	ADDQ R11,R12
-	SHLQ $13,R15:R14
-	ANDQ DX,R14
-	ADDQ R13,R14
-	IMUL3Q $19,R15,CX
-	ADDQ CX,SI
-	MOVQ SI,CX
-	SHRQ $51,CX
-	ADDQ R8,CX
-	MOVQ CX,R8
-	SHRQ $51,CX
-	ANDQ DX,SI
-	ADDQ R10,CX
-	MOVQ CX,R9
-	SHRQ $51,CX
-	ANDQ DX,R8
-	ADDQ R12,CX
-	MOVQ CX,AX
-	SHRQ $51,CX
-	ANDQ DX,R9
-	ADDQ R14,CX
-	MOVQ CX,R10
-	SHRQ $51,CX
-	ANDQ DX,AX
-	IMUL3Q $19,CX,CX
-	ADDQ CX,SI
-	ANDQ DX,R10
-	MOVQ SI,40(DI)
-	MOVQ R8,48(DI)
-	MOVQ R9,56(DI)
-	MOVQ AX,64(DI)
-	MOVQ R10,72(DI)
-	MOVQ 160(SP),AX
-	MULQ ·_121666_213(SB)
-	SHRQ $13,AX
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 168(SP),AX
-	MULQ ·_121666_213(SB)
-	SHRQ $13,AX
-	ADDQ AX,CX
-	MOVQ DX,R8
-	MOVQ 176(SP),AX
-	MULQ ·_121666_213(SB)
-	SHRQ $13,AX
-	ADDQ AX,R8
-	MOVQ DX,R9
-	MOVQ 184(SP),AX
-	MULQ ·_121666_213(SB)
-	SHRQ $13,AX
-	ADDQ AX,R9
-	MOVQ DX,R10
-	MOVQ 192(SP),AX
-	MULQ ·_121666_213(SB)
-	SHRQ $13,AX
-	ADDQ AX,R10
-	IMUL3Q $19,DX,DX
-	ADDQ DX,SI
-	ADDQ 80(SP),SI
-	ADDQ 88(SP),CX
-	ADDQ 96(SP),R8
-	ADDQ 104(SP),R9
-	ADDQ 112(SP),R10
-	MOVQ SI,80(DI)
-	MOVQ CX,88(DI)
-	MOVQ R8,96(DI)
-	MOVQ R9,104(DI)
-	MOVQ R10,112(DI)
-	MOVQ 104(DI),SI
-	IMUL3Q $19,SI,AX
-	MOVQ AX,0(SP)
-	MULQ 176(SP)
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 112(DI),DX
-	IMUL3Q $19,DX,AX
-	MOVQ AX,8(SP)
-	MULQ 168(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 80(DI),AX
-	MULQ 160(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 80(DI),AX
-	MULQ 168(SP)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 80(DI),AX
-	MULQ 176(SP)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 80(DI),AX
-	MULQ 184(SP)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 80(DI),AX
-	MULQ 192(SP)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 88(DI),AX
-	MULQ 160(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 88(DI),AX
-	MULQ 168(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 88(DI),AX
-	MULQ 176(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 88(DI),AX
-	MULQ 184(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 88(DI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 192(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 96(DI),AX
-	MULQ 160(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 96(DI),AX
-	MULQ 168(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 96(DI),AX
-	MULQ 176(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 96(DI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 184(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 96(DI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 192(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 104(DI),AX
-	MULQ 160(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 104(DI),AX
-	MULQ 168(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 0(SP),AX
-	MULQ 184(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 0(SP),AX
-	MULQ 192(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 112(DI),AX
-	MULQ 160(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 8(SP),AX
-	MULQ 176(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 8(SP),AX
-	MULQ 184(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 8(SP),AX
-	MULQ 192(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ $REDMASK51,DX
-	SHLQ $13,CX:SI
-	ANDQ DX,SI
-	SHLQ $13,R9:R8
-	ANDQ DX,R8
-	ADDQ CX,R8
-	SHLQ $13,R11:R10
-	ANDQ DX,R10
-	ADDQ R9,R10
-	SHLQ $13,R13:R12
-	ANDQ DX,R12
-	ADDQ R11,R12
-	SHLQ $13,R15:R14
-	ANDQ DX,R14
-	ADDQ R13,R14
-	IMUL3Q $19,R15,CX
-	ADDQ CX,SI
-	MOVQ SI,CX
-	SHRQ $51,CX
-	ADDQ R8,CX
-	MOVQ CX,R8
-	SHRQ $51,CX
-	ANDQ DX,SI
-	ADDQ R10,CX
-	MOVQ CX,R9
-	SHRQ $51,CX
-	ANDQ DX,R8
-	ADDQ R12,CX
-	MOVQ CX,AX
-	SHRQ $51,CX
-	ANDQ DX,R9
-	ADDQ R14,CX
-	MOVQ CX,R10
-	SHRQ $51,CX
-	ANDQ DX,AX
-	IMUL3Q $19,CX,CX
-	ADDQ CX,SI
-	ANDQ DX,R10
-	MOVQ SI,80(DI)
-	MOVQ R8,88(DI)
-	MOVQ R9,96(DI)
-	MOVQ AX,104(DI)
-	MOVQ R10,112(DI)
-	RET
diff --git a/src/ssl/test/runner/curve25519/mont25519_amd64.go b/src/ssl/test/runner/curve25519/mont25519_amd64.go
deleted file mode 100644
index 5822bd5..0000000
--- a/src/ssl/test/runner/curve25519/mont25519_amd64.go
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build amd64,!gccgo,!appengine
-
-package curve25519
-
-// These functions are implemented in the .s files. The names of the functions
-// in the rest of the file are also taken from the SUPERCOP sources to help
-// people following along.
-
-//go:noescape
-
-func cswap(inout *[5]uint64, v uint64)
-
-//go:noescape
-
-func ladderstep(inout *[5][5]uint64)
-
-//go:noescape
-
-func freeze(inout *[5]uint64)
-
-//go:noescape
-
-func mul(dest, a, b *[5]uint64)
-
-//go:noescape
-
-func square(out, in *[5]uint64)
-
-// mladder uses a Montgomery ladder to calculate (xr/zr) *= s.
-func mladder(xr, zr *[5]uint64, s *[32]byte) {
-	var work [5][5]uint64
-
-	work[0] = *xr
-	setint(&work[1], 1)
-	setint(&work[2], 0)
-	work[3] = *xr
-	setint(&work[4], 1)
-
-	j := uint(6)
-	var prevbit byte
-
-	for i := 31; i >= 0; i-- {
-		for j < 8 {
-			bit := ((*s)[i] >> j) & 1
-			swap := bit ^ prevbit
-			prevbit = bit
-			cswap(&work[1], uint64(swap))
-			ladderstep(&work)
-			j--
-		}
-		j = 7
-	}
-
-	*xr = work[1]
-	*zr = work[2]
-}
-
-func scalarMult(out, in, base *[32]byte) {
-	var e [32]byte
-	copy(e[:], (*in)[:])
-	e[0] &= 248
-	e[31] &= 127
-	e[31] |= 64
-
-	var t, z [5]uint64
-	unpack(&t, base)
-	mladder(&t, &z, &e)
-	invert(&z, &z)
-	mul(&t, &t, &z)
-	pack(out, &t)
-}
-
-func setint(r *[5]uint64, v uint64) {
-	r[0] = v
-	r[1] = 0
-	r[2] = 0
-	r[3] = 0
-	r[4] = 0
-}
-
-// unpack sets r = x where r consists of 5, 51-bit limbs in little-endian
-// order.
-func unpack(r *[5]uint64, x *[32]byte) {
-	r[0] = uint64(x[0]) |
-		uint64(x[1])<<8 |
-		uint64(x[2])<<16 |
-		uint64(x[3])<<24 |
-		uint64(x[4])<<32 |
-		uint64(x[5])<<40 |
-		uint64(x[6]&7)<<48
-
-	r[1] = uint64(x[6])>>3 |
-		uint64(x[7])<<5 |
-		uint64(x[8])<<13 |
-		uint64(x[9])<<21 |
-		uint64(x[10])<<29 |
-		uint64(x[11])<<37 |
-		uint64(x[12]&63)<<45
-
-	r[2] = uint64(x[12])>>6 |
-		uint64(x[13])<<2 |
-		uint64(x[14])<<10 |
-		uint64(x[15])<<18 |
-		uint64(x[16])<<26 |
-		uint64(x[17])<<34 |
-		uint64(x[18])<<42 |
-		uint64(x[19]&1)<<50
-
-	r[3] = uint64(x[19])>>1 |
-		uint64(x[20])<<7 |
-		uint64(x[21])<<15 |
-		uint64(x[22])<<23 |
-		uint64(x[23])<<31 |
-		uint64(x[24])<<39 |
-		uint64(x[25]&15)<<47
-
-	r[4] = uint64(x[25])>>4 |
-		uint64(x[26])<<4 |
-		uint64(x[27])<<12 |
-		uint64(x[28])<<20 |
-		uint64(x[29])<<28 |
-		uint64(x[30])<<36 |
-		uint64(x[31]&127)<<44
-}
-
-// pack sets out = x where out is the usual, little-endian form of the 5,
-// 51-bit limbs in x.
-func pack(out *[32]byte, x *[5]uint64) {
-	t := *x
-	freeze(&t)
-
-	out[0] = byte(t[0])
-	out[1] = byte(t[0] >> 8)
-	out[2] = byte(t[0] >> 16)
-	out[3] = byte(t[0] >> 24)
-	out[4] = byte(t[0] >> 32)
-	out[5] = byte(t[0] >> 40)
-	out[6] = byte(t[0] >> 48)
-
-	out[6] ^= byte(t[1]<<3) & 0xf8
-	out[7] = byte(t[1] >> 5)
-	out[8] = byte(t[1] >> 13)
-	out[9] = byte(t[1] >> 21)
-	out[10] = byte(t[1] >> 29)
-	out[11] = byte(t[1] >> 37)
-	out[12] = byte(t[1] >> 45)
-
-	out[12] ^= byte(t[2]<<6) & 0xc0
-	out[13] = byte(t[2] >> 2)
-	out[14] = byte(t[2] >> 10)
-	out[15] = byte(t[2] >> 18)
-	out[16] = byte(t[2] >> 26)
-	out[17] = byte(t[2] >> 34)
-	out[18] = byte(t[2] >> 42)
-	out[19] = byte(t[2] >> 50)
-
-	out[19] ^= byte(t[3]<<1) & 0xfe
-	out[20] = byte(t[3] >> 7)
-	out[21] = byte(t[3] >> 15)
-	out[22] = byte(t[3] >> 23)
-	out[23] = byte(t[3] >> 31)
-	out[24] = byte(t[3] >> 39)
-	out[25] = byte(t[3] >> 47)
-
-	out[25] ^= byte(t[4]<<4) & 0xf0
-	out[26] = byte(t[4] >> 4)
-	out[27] = byte(t[4] >> 12)
-	out[28] = byte(t[4] >> 20)
-	out[29] = byte(t[4] >> 28)
-	out[30] = byte(t[4] >> 36)
-	out[31] = byte(t[4] >> 44)
-}
-
-// invert calculates r = x^-1 mod p using Fermat's little theorem.
-func invert(r *[5]uint64, x *[5]uint64) {
-	var z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t [5]uint64
-
-	square(&z2, x)        /* 2 */
-	square(&t, &z2)       /* 4 */
-	square(&t, &t)        /* 8 */
-	mul(&z9, &t, x)       /* 9 */
-	mul(&z11, &z9, &z2)   /* 11 */
-	square(&t, &z11)      /* 22 */
-	mul(&z2_5_0, &t, &z9) /* 2^5 - 2^0 = 31 */
-
-	square(&t, &z2_5_0)      /* 2^6 - 2^1 */
-	for i := 1; i < 5; i++ { /* 2^20 - 2^10 */
-		square(&t, &t)
-	}
-	mul(&z2_10_0, &t, &z2_5_0) /* 2^10 - 2^0 */
-
-	square(&t, &z2_10_0)      /* 2^11 - 2^1 */
-	for i := 1; i < 10; i++ { /* 2^20 - 2^10 */
-		square(&t, &t)
-	}
-	mul(&z2_20_0, &t, &z2_10_0) /* 2^20 - 2^0 */
-
-	square(&t, &z2_20_0)      /* 2^21 - 2^1 */
-	for i := 1; i < 20; i++ { /* 2^40 - 2^20 */
-		square(&t, &t)
-	}
-	mul(&t, &t, &z2_20_0) /* 2^40 - 2^0 */
-
-	square(&t, &t)            /* 2^41 - 2^1 */
-	for i := 1; i < 10; i++ { /* 2^50 - 2^10 */
-		square(&t, &t)
-	}
-	mul(&z2_50_0, &t, &z2_10_0) /* 2^50 - 2^0 */
-
-	square(&t, &z2_50_0)      /* 2^51 - 2^1 */
-	for i := 1; i < 50; i++ { /* 2^100 - 2^50 */
-		square(&t, &t)
-	}
-	mul(&z2_100_0, &t, &z2_50_0) /* 2^100 - 2^0 */
-
-	square(&t, &z2_100_0)      /* 2^101 - 2^1 */
-	for i := 1; i < 100; i++ { /* 2^200 - 2^100 */
-		square(&t, &t)
-	}
-	mul(&t, &t, &z2_100_0) /* 2^200 - 2^0 */
-
-	square(&t, &t)            /* 2^201 - 2^1 */
-	for i := 1; i < 50; i++ { /* 2^250 - 2^50 */
-		square(&t, &t)
-	}
-	mul(&t, &t, &z2_50_0) /* 2^250 - 2^0 */
-
-	square(&t, &t) /* 2^251 - 2^1 */
-	square(&t, &t) /* 2^252 - 2^2 */
-	square(&t, &t) /* 2^253 - 2^3 */
-
-	square(&t, &t) /* 2^254 - 2^4 */
-
-	square(&t, &t)   /* 2^255 - 2^5 */
-	mul(r, &t, &z11) /* 2^255 - 21 */
-}
diff --git a/src/ssl/test/runner/curve25519/mul_amd64.s b/src/ssl/test/runner/curve25519/mul_amd64.s
deleted file mode 100644
index b162e65..0000000
--- a/src/ssl/test/runner/curve25519/mul_amd64.s
+++ /dev/null
@@ -1,169 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
-
-// +build amd64,!gccgo,!appengine
-
-#include "const_amd64.h"
-
-// func mul(dest, a, b *[5]uint64)
-TEXT ·mul(SB),0,$16-24
-	MOVQ dest+0(FP), DI
-	MOVQ a+8(FP), SI
-	MOVQ b+16(FP), DX
-
-	MOVQ DX,CX
-	MOVQ 24(SI),DX
-	IMUL3Q $19,DX,AX
-	MOVQ AX,0(SP)
-	MULQ 16(CX)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 32(SI),DX
-	IMUL3Q $19,DX,AX
-	MOVQ AX,8(SP)
-	MULQ 8(CX)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 0(SI),AX
-	MULQ 0(CX)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 0(SI),AX
-	MULQ 8(CX)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 0(SI),AX
-	MULQ 16(CX)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 0(SI),AX
-	MULQ 24(CX)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 0(SI),AX
-	MULQ 32(CX)
-	MOVQ AX,BX
-	MOVQ DX,BP
-	MOVQ 8(SI),AX
-	MULQ 0(CX)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 8(SI),AX
-	MULQ 8(CX)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 8(SI),AX
-	MULQ 16(CX)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 8(SI),AX
-	MULQ 24(CX)
-	ADDQ AX,BX
-	ADCQ DX,BP
-	MOVQ 8(SI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 32(CX)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 16(SI),AX
-	MULQ 0(CX)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 16(SI),AX
-	MULQ 8(CX)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 16(SI),AX
-	MULQ 16(CX)
-	ADDQ AX,BX
-	ADCQ DX,BP
-	MOVQ 16(SI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 24(CX)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 16(SI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 32(CX)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 24(SI),AX
-	MULQ 0(CX)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 24(SI),AX
-	MULQ 8(CX)
-	ADDQ AX,BX
-	ADCQ DX,BP
-	MOVQ 0(SP),AX
-	MULQ 24(CX)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 0(SP),AX
-	MULQ 32(CX)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 32(SI),AX
-	MULQ 0(CX)
-	ADDQ AX,BX
-	ADCQ DX,BP
-	MOVQ 8(SP),AX
-	MULQ 16(CX)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 8(SP),AX
-	MULQ 24(CX)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 8(SP),AX
-	MULQ 32(CX)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ $REDMASK51,SI
-	SHLQ $13,R9:R8
-	ANDQ SI,R8
-	SHLQ $13,R11:R10
-	ANDQ SI,R10
-	ADDQ R9,R10
-	SHLQ $13,R13:R12
-	ANDQ SI,R12
-	ADDQ R11,R12
-	SHLQ $13,R15:R14
-	ANDQ SI,R14
-	ADDQ R13,R14
-	SHLQ $13,BP:BX
-	ANDQ SI,BX
-	ADDQ R15,BX
-	IMUL3Q $19,BP,DX
-	ADDQ DX,R8
-	MOVQ R8,DX
-	SHRQ $51,DX
-	ADDQ R10,DX
-	MOVQ DX,CX
-	SHRQ $51,DX
-	ANDQ SI,R8
-	ADDQ R12,DX
-	MOVQ DX,R9
-	SHRQ $51,DX
-	ANDQ SI,CX
-	ADDQ R14,DX
-	MOVQ DX,AX
-	SHRQ $51,DX
-	ANDQ SI,R9
-	ADDQ BX,DX
-	MOVQ DX,R10
-	SHRQ $51,DX
-	ANDQ SI,AX
-	IMUL3Q $19,DX,DX
-	ADDQ DX,R8
-	ANDQ SI,R10
-	MOVQ R8,0(DI)
-	MOVQ CX,8(DI)
-	MOVQ R9,16(DI)
-	MOVQ AX,24(DI)
-	MOVQ R10,32(DI)
-	RET
diff --git a/src/ssl/test/runner/curve25519/square_amd64.s b/src/ssl/test/runner/curve25519/square_amd64.s
deleted file mode 100644
index 4e864a8..0000000
--- a/src/ssl/test/runner/curve25519/square_amd64.s
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// This code was translated into a form compatible with 6a from the public
-// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
-
-// +build amd64,!gccgo,!appengine
-
-#include "const_amd64.h"
-
-// func square(out, in *[5]uint64)
-TEXT ·square(SB),7,$0-16
-	MOVQ out+0(FP), DI
-	MOVQ in+8(FP), SI
-
-	MOVQ 0(SI),AX
-	MULQ 0(SI)
-	MOVQ AX,CX
-	MOVQ DX,R8
-	MOVQ 0(SI),AX
-	SHLQ $1,AX
-	MULQ 8(SI)
-	MOVQ AX,R9
-	MOVQ DX,R10
-	MOVQ 0(SI),AX
-	SHLQ $1,AX
-	MULQ 16(SI)
-	MOVQ AX,R11
-	MOVQ DX,R12
-	MOVQ 0(SI),AX
-	SHLQ $1,AX
-	MULQ 24(SI)
-	MOVQ AX,R13
-	MOVQ DX,R14
-	MOVQ 0(SI),AX
-	SHLQ $1,AX
-	MULQ 32(SI)
-	MOVQ AX,R15
-	MOVQ DX,BX
-	MOVQ 8(SI),AX
-	MULQ 8(SI)
-	ADDQ AX,R11
-	ADCQ DX,R12
-	MOVQ 8(SI),AX
-	SHLQ $1,AX
-	MULQ 16(SI)
-	ADDQ AX,R13
-	ADCQ DX,R14
-	MOVQ 8(SI),AX
-	SHLQ $1,AX
-	MULQ 24(SI)
-	ADDQ AX,R15
-	ADCQ DX,BX
-	MOVQ 8(SI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 32(SI)
-	ADDQ AX,CX
-	ADCQ DX,R8
-	MOVQ 16(SI),AX
-	MULQ 16(SI)
-	ADDQ AX,R15
-	ADCQ DX,BX
-	MOVQ 16(SI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 24(SI)
-	ADDQ AX,CX
-	ADCQ DX,R8
-	MOVQ 16(SI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 32(SI)
-	ADDQ AX,R9
-	ADCQ DX,R10
-	MOVQ 24(SI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 24(SI)
-	ADDQ AX,R9
-	ADCQ DX,R10
-	MOVQ 24(SI),DX
-	IMUL3Q $38,DX,AX
-	MULQ 32(SI)
-	ADDQ AX,R11
-	ADCQ DX,R12
-	MOVQ 32(SI),DX
-	IMUL3Q $19,DX,AX
-	MULQ 32(SI)
-	ADDQ AX,R13
-	ADCQ DX,R14
-	MOVQ $REDMASK51,SI
-	SHLQ $13,R8:CX
-	ANDQ SI,CX
-	SHLQ $13,R10:R9
-	ANDQ SI,R9
-	ADDQ R8,R9
-	SHLQ $13,R12:R11
-	ANDQ SI,R11
-	ADDQ R10,R11
-	SHLQ $13,R14:R13
-	ANDQ SI,R13
-	ADDQ R12,R13
-	SHLQ $13,BX:R15
-	ANDQ SI,R15
-	ADDQ R14,R15
-	IMUL3Q $19,BX,DX
-	ADDQ DX,CX
-	MOVQ CX,DX
-	SHRQ $51,DX
-	ADDQ R9,DX
-	ANDQ SI,CX
-	MOVQ DX,R8
-	SHRQ $51,DX
-	ADDQ R11,DX
-	ANDQ SI,R8
-	MOVQ DX,R9
-	SHRQ $51,DX
-	ADDQ R13,DX
-	ANDQ SI,R9
-	MOVQ DX,AX
-	SHRQ $51,DX
-	ADDQ R15,DX
-	ANDQ SI,AX
-	MOVQ DX,R10
-	SHRQ $51,DX
-	IMUL3Q $19,DX,DX
-	ADDQ DX,CX
-	ANDQ SI,R10
-	MOVQ CX,0(DI)
-	MOVQ R8,8(DI)
-	MOVQ R9,16(DI)
-	MOVQ AX,24(DI)
-	MOVQ R10,32(DI)
-	RET
diff --git a/src/ssl/test/runner/deterministic.go b/src/ssl/test/runner/deterministic.go
index 2b71076..50ae47f 100644
--- a/src/ssl/test/runner/deterministic.go
+++ b/src/ssl/test/runner/deterministic.go
@@ -16,6 +16,8 @@
 
 import (
 	"encoding/binary"
+
+	"golang.org/x/crypto/chacha20"
 )
 
 // Use a different key from crypto/rand/deterministic.c.
@@ -31,7 +33,11 @@
 	}
 	var nonce [12]byte
 	binary.LittleEndian.PutUint64(nonce[:8], d.numCalls)
-	chaCha20(buf, buf, deterministicRandKey, nonce[:], 0)
+	cipher, err := chacha20.NewUnauthenticatedCipher(deterministicRandKey, nonce[:])
+	if err != nil {
+		return 0, err
+	}
+	cipher.XORKeyStream(buf, buf)
 	d.numCalls++
 	return len(buf), nil
 }
diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json
index 940415d..384b1db 100644
--- a/src/ssl/test/runner/fuzzer_mode.json
+++ b/src/ssl/test/runner/fuzzer_mode.json
@@ -11,10 +11,10 @@
 
     "BadRSAClientKeyExchange*": "Fuzzer mode does not notice a bad premaster secret.",
 
-    "TrailingMessageData-TLS13-ServerHello": "Fuzzer mode will not read the peer's alert as a MAC error",
+    "TrailingMessageData-TLS13-ServerHello-*": "Fuzzer mode will not read the peer's alert as a MAC error",
     "UnexpectedUnencryptedExtension-Client-TLS13": "Fuzzer mode will not read the peer's alert as a MAC error",
     "UnknownUnencryptedExtension-Client-TLS13": "Fuzzer mode will not read the peer's alert as a MAC error",
-    "WrongMessageType-TLS13-ServerHello": "Fuzzer mode will not read the peer's alert as a MAC error",
+    "WrongMessageType-TLS13-ServerHello-*": "Fuzzer mode will not read the peer's alert as a MAC error",
 
     "BadECDSA-*": "Fuzzer mode always accepts a signature.",
     "*-InvalidSignature-*": "Fuzzer mode always accepts a signature.",
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index 27e9a95..8548b78 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -389,6 +389,9 @@
 			return errors.New("tls: short read from Rand: " + err.Error())
 		}
 	}
+	if c.config.Bugs.MockQUICTransport != nil && !c.config.Bugs.CompatModeWithQUIC {
+		hello.sessionId = []byte{}
+	}
 
 	if c.config.Bugs.SendCipherSuites != nil {
 		hello.cipherSuites = c.config.Bugs.SendCipherSuites
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index a1ce421..9d3b6bc 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -596,7 +596,11 @@
 	}
 	if m.delegatedCredentials {
 		extensions.addU16(extensionDelegatedCredentials)
-		extensions.addU16(0) // Length is always 0
+		body := extensions.addU16LengthPrefixed()
+		signatureSchemeList := body.addU16LengthPrefixed()
+		for _, sigAlg := range m.signatureAlgorithms {
+			signatureSchemeList.addU16(uint16(sigAlg))
+		}
 	}
 
 	// The PSK extension must be last. See https://tools.ietf.org/html/rfc8446#section-4.2.11
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 28523f0..931ecca 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -299,6 +299,9 @@
 		}
 	}
 
+	if config.Bugs.MockQUICTransport != nil && len(hs.clientHello.sessionId) > 0 {
+		return fmt.Errorf("tls: QUIC client did not disable compatibility mode")
+	}
 	if config.Bugs.ExpectNoTLS12Session {
 		if len(hs.clientHello.sessionId) > 0 && c.vers >= VersionTLS13 {
 			return fmt.Errorf("tls: client offered an unexpected session ID")
@@ -621,7 +624,7 @@
 		}
 
 		if hs.clientHello.hasEarlyData {
-			c.skipEarlyData = true
+			c.setSkipEarlyData()
 		}
 
 		// Read new ClientHello.
@@ -737,7 +740,7 @@
 				c.input = nil
 			}
 		} else {
-			c.skipEarlyData = true
+			c.setSkipEarlyData()
 		}
 	}
 
@@ -988,7 +991,7 @@
 	}
 	c.flushHandshake()
 
-	if encryptedExtensions.extensions.hasEarlyData && !c.skipEarlyData {
+	if encryptedExtensions.extensions.hasEarlyData && !c.shouldSkipEarlyData() {
 		for _, expectedMsg := range config.Bugs.ExpectLateEarlyData {
 			if err := c.readRecord(recordTypeApplicationData); err != nil {
 				return err
@@ -1022,7 +1025,7 @@
 	}
 
 	// Read end_of_early_data.
-	if encryptedExtensions.extensions.hasEarlyData {
+	if encryptedExtensions.extensions.hasEarlyData && config.Bugs.MockQUICTransport == nil {
 		msg, err := c.readHandshake()
 		if err != nil {
 			return err
diff --git a/src/ssl/test/runner/hkdf.go b/src/ssl/test/runner/hkdf.go
deleted file mode 100644
index c60e4cc..0000000
--- a/src/ssl/test/runner/hkdf.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2016, Google Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package runner
-
-import (
-	"crypto/hmac"
-	"hash"
-)
-
-// hkdfExtract implements HKDF-Extract from RFC 5869.
-func hkdfExtract(hash func() hash.Hash, salt, ikm []byte) []byte {
-	if salt == nil {
-		salt = make([]byte, hash().Size())
-	}
-	hmac := hmac.New(hash, salt)
-	hmac.Write(ikm)
-	return hmac.Sum(nil)
-}
-
-// hkdfExpand implements HKDF-Expand from RFC 5869.
-func hkdfExpand(hash func() hash.Hash, prk, info []byte, length int) []byte {
-	hashSize := hash().Size()
-	if length > 255*hashSize {
-		panic("hkdfExpand: length too long")
-	}
-	if len(prk) < hashSize {
-		panic("hkdfExpand: prk too short")
-	}
-	var lastBlock []byte
-	counter := byte(0)
-	okm := make([]byte, length)
-	hmac := hmac.New(hash, prk)
-	for length > 0 {
-		hmac.Reset()
-		counter++
-		hmac.Write(lastBlock)
-		hmac.Write(info)
-		hmac.Write([]byte{counter})
-		block := hmac.Sum(nil)
-		lastBlock = block
-		copy(okm[(int(counter)-1)*hashSize:], block)
-		length -= hashSize
-	}
-	return okm
-}
diff --git a/src/ssl/test/runner/hkdf_test.go b/src/ssl/test/runner/hkdf_test.go
deleted file mode 100644
index 4e6958e..0000000
--- a/src/ssl/test/runner/hkdf_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2016, Google Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-package runner
-
-import (
-	"bytes"
-	"crypto"
-	_ "crypto/sha1"
-	_ "crypto/sha256"
-	"testing"
-)
-
-var hkdfTests = []struct {
-	hash                      crypto.Hash
-	ikm, salt, info, prk, okm []byte
-}{
-	{
-		crypto.SHA256,
-		[]byte{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b},
-		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c},
-		[]byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9},
-		[]byte{0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5},
-		[]byte{0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65},
-	},
-	{
-		crypto.SHA256,
-		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f},
-		[]byte{0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf},
-		[]byte{0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff},
-		[]byte{0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44},
-		[]byte{0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87},
-	},
-	{
-		crypto.SHA256,
-		[]byte{
-			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
-			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b},
-		[]byte{},
-		[]byte{},
-		[]byte{0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04},
-		[]byte{0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8},
-	},
-	{
-		crypto.SHA1,
-		[]byte{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b},
-		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c},
-		[]byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9},
-		[]byte{0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b, 0xaa, 0x2b, 0xa2, 0x43},
-		[]byte{0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, 0xf8, 0x96},
-	},
-	{
-		crypto.SHA1,
-		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f},
-		[]byte{0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf},
-		[]byte{0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff},
-		[]byte{0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a, 0x22, 0x4c, 0xfa, 0xf6},
-		[]byte{0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, 0xd3, 0xb4},
-	},
-	{
-		crypto.SHA1,
-		[]byte{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b},
-		[]byte{},
-		[]byte{},
-		[]byte{0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a, 0xa0, 0xd3, 0x2d, 0x01},
-		[]byte{0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, 0x49, 0x18},
-	},
-	{
-		crypto.SHA1,
-		[]byte{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
-		[]byte{},
-		[]byte{},
-		[]byte{0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e, 0x73, 0x13, 0x85, 0xdd},
-		[]byte{0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, 0xfc, 0x48},
-	},
-}
-
-func TestHKDF(t *testing.T) {
-	for i, tt := range hkdfTests {
-		prk := hkdfExtract(tt.hash.New, tt.salt, tt.ikm)
-		if !bytes.Equal(prk, tt.prk) {
-			t.Errorf("%d. got hkdfExtract(%x, %x) = %x; wanted %x", i+1, tt.salt, tt.ikm, prk, tt.prk)
-		}
-
-		okm := hkdfExpand(tt.hash.New, tt.prk, tt.info, len(tt.okm))
-		if !bytes.Equal(okm, tt.okm) {
-			t.Errorf("%d. got hkdfExpand(%x, %x, %d) = %x; wanted %x", i+1, tt.prk, tt.info, len(tt.okm), okm, tt.okm)
-		}
-	}
-}
diff --git a/src/ssl/test/runner/key_agreement.go b/src/ssl/test/runner/key_agreement.go
index 266163e..b435f18 100644
--- a/src/ssl/test/runner/key_agreement.go
+++ b/src/ssl/test/runner/key_agreement.go
@@ -17,8 +17,8 @@
 	"io"
 	"math/big"
 
-	"boringssl.googlesource.com/boringssl/ssl/test/runner/curve25519"
 	"boringssl.googlesource.com/boringssl/ssl/test/runner/hrss"
+	"golang.org/x/crypto/curve25519"
 )
 
 type keyType int
diff --git a/src/ssl/test/runner/mock_quic_transport.go b/src/ssl/test/runner/mock_quic_transport.go
index 4d971c4..27a8bc3 100644
--- a/src/ssl/test/runner/mock_quic_transport.go
+++ b/src/ssl/test/runner/mock_quic_transport.go
@@ -24,10 +24,28 @@
 
 const tagHandshake = byte('H')
 const tagApplication = byte('A')
+const tagAlert = byte('L')
 
+// mockQUICTransport provides a record layer for sending/receiving messages
+// when testing TLS over QUIC. It is only intended for testing, as it runs over
+// an in-order reliable transport, looks nothing like the QUIC wire image, and
+// provides no confidentiality guarantees. (In fact, it leaks keys in the
+// clear.)
+//
+// Messages from TLS that are sent over a mockQUICTransport are wrapped in a
+// TLV-like format. The first byte of a mockQUICTransport message is a tag
+// indicating the TLS record type. This is followed by the 2 byte cipher suite
+// ID of the cipher suite that would have been used to encrypt the record. Next
+// is a 4-byte big-endian length indicating the length of the remaining payload.
+// The payload starts with the key that would be used to encrypt the record, and
+// the remainder of the payload is the plaintext of the TLS record. Note that
+// the 4-byte length covers the length of the key and plaintext, but not the
+// cipher suite ID or tag.
 type mockQUICTransport struct {
 	net.Conn
-	readSecret, writeSecret []byte
+	readSecret, writeSecret           []byte
+	readCipherSuite, writeCipherSuite uint16
+	skipEarlyData                     bool
 }
 
 func newMockQUICTransport(conn net.Conn) *mockQUICTransport {
@@ -35,24 +53,39 @@
 }
 
 func (m *mockQUICTransport) read() (byte, []byte, error) {
-	header := make([]byte, 5)
-	if _, err := io.ReadFull(m.Conn, header); err != nil {
-		return 0, nil, err
+	for {
+		header := make([]byte, 7)
+		if _, err := io.ReadFull(m.Conn, header); err != nil {
+			return 0, nil, err
+		}
+		cipherSuite := binary.BigEndian.Uint16(header[1:3])
+		length := binary.BigEndian.Uint32(header[3:])
+		value := make([]byte, length)
+		if _, err := io.ReadFull(m.Conn, value); err != nil {
+			return 0, nil, fmt.Errorf("Error reading record")
+		}
+		if cipherSuite != m.readCipherSuite {
+			if m.skipEarlyData {
+				continue
+			}
+			return 0, nil, fmt.Errorf("Received cipher suite %d does not match expected %d", cipherSuite, m.readCipherSuite)
+		}
+		if len(m.readSecret) > len(value) {
+			return 0, nil, fmt.Errorf("Input length too short")
+		}
+		secret := value[:len(m.readSecret)]
+		out := value[len(m.readSecret):]
+		if !bytes.Equal(secret, m.readSecret) {
+			if m.skipEarlyData {
+				continue
+			}
+			return 0, nil, fmt.Errorf("secrets don't match: got %x but expected %x", secret, m.readSecret)
+		}
+		if m.skipEarlyData && header[0] == tagHandshake {
+			m.skipEarlyData = false
+		}
+		return header[0], out, nil
 	}
-	var length uint32
-	binary.Read(bytes.NewBuffer(header[1:]), binary.BigEndian, &length)
-	secret := make([]byte, len(m.readSecret))
-	if _, err := io.ReadFull(m.Conn, secret); err != nil {
-		return 0, nil, err
-	}
-	if !bytes.Equal(secret, m.readSecret) {
-		return 0, nil, fmt.Errorf("secrets don't match")
-	}
-	out := make([]byte, int(length))
-	if _, err := io.ReadFull(m.Conn, out); err != nil {
-		return 0, nil, err
-	}
-	return header[0], out, nil
 }
 
 func (m *mockQUICTransport) readRecord(want recordType) (recordType, *block, error) {
@@ -65,6 +98,8 @@
 		returnType = recordTypeHandshake
 	} else if typ == tagApplication {
 		returnType = recordTypeApplicationData
+	} else if typ == tagAlert {
+		returnType = recordTypeAlert
 	} else {
 		return 0, nil, fmt.Errorf("unknown type %d\n", typ)
 	}
@@ -78,11 +113,13 @@
 	} else if typ != recordTypeHandshake {
 		return 0, fmt.Errorf("unsupported record type %d\n", typ)
 	}
-	payload := make([]byte, 1+4+len(m.writeSecret)+len(data))
+	length := len(m.writeSecret) + len(data)
+	payload := make([]byte, 1+2+4+length)
 	payload[0] = tag
-	binary.BigEndian.PutUint32(payload[1:5], uint32(len(data)))
-	copy(payload[5:], m.writeSecret)
-	copy(payload[5+len(m.writeSecret):], data)
+	binary.BigEndian.PutUint16(payload[1:3], m.writeCipherSuite)
+	binary.BigEndian.PutUint32(payload[3:7], uint32(length))
+	copy(payload[7:], m.writeSecret)
+	copy(payload[7+len(m.writeSecret):], data)
 	if _, err := m.Conn.Write(payload); err != nil {
 		return 0, err
 	}
diff --git a/src/ssl/test/runner/poly1305/poly1305.go b/src/ssl/test/runner/poly1305/poly1305.go
deleted file mode 100644
index f562fa5..0000000
--- a/src/ssl/test/runner/poly1305/poly1305.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-/*
-Package poly1305 implements Poly1305 one-time message authentication code as
-specified in https://cr.yp.to/mac/poly1305-20050329.pdf.
-
-Poly1305 is a fast, one-time authentication function. It is infeasible for an
-attacker to generate an authenticator for a message without the key. However, a
-key must only be used for a single message. Authenticating two different
-messages with the same key allows an attacker to forge authenticators for other
-messages with the same key.
-
-Poly1305 was originally coupled with AES in order to make Poly1305-AES. AES was
-used with a fixed key in order to generate one-time keys from an nonce.
-However, in this package AES isn't used and the one-time key is specified
-directly.
-*/
-package poly1305 // import "golang.org/x/crypto/poly1305"
-
-import "crypto/subtle"
-
-// TagSize is the size, in bytes, of a poly1305 authenticator.
-const TagSize = 16
-
-// Verify returns true if mac is a valid authenticator for m with the given
-// key.
-func Verify(mac *[16]byte, m []byte, key *[32]byte) bool {
-	var tmp [16]byte
-	Sum(&tmp, m, key)
-	return subtle.ConstantTimeCompare(tmp[:], mac[:]) == 1
-}
diff --git a/src/ssl/test/runner/poly1305/poly1305_test.go b/src/ssl/test/runner/poly1305/poly1305_test.go
deleted file mode 100644
index 256bdbb..0000000
--- a/src/ssl/test/runner/poly1305/poly1305_test.go
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package poly1305
-
-import (
-	"encoding/hex"
-	"flag"
-	"testing"
-	"unsafe"
-)
-
-var stressFlag = flag.Bool("stress", false, "run slow stress tests")
-
-type test struct {
-	in  string
-	key string
-	tag string
-}
-
-func (t *test) Input() []byte {
-	in, err := hex.DecodeString(t.in)
-	if err != nil {
-		panic(err)
-	}
-	return in
-}
-
-func (t *test) Key() [32]byte {
-	buf, err := hex.DecodeString(t.key)
-	if err != nil {
-		panic(err)
-	}
-	var key [32]byte
-	copy(key[:], buf[:32])
-	return key
-}
-
-func (t *test) Tag() [16]byte {
-	buf, err := hex.DecodeString(t.tag)
-	if err != nil {
-		panic(err)
-	}
-	var tag [16]byte
-	copy(tag[:], buf[:16])
-	return tag
-}
-
-func testSum(t *testing.T, unaligned bool, sumImpl func(tag *[TagSize]byte, msg []byte, key *[32]byte)) {
-	var tag [16]byte
-	for i, v := range testData {
-		in := v.Input()
-		if unaligned {
-			in = unalignBytes(in)
-		}
-		key := v.Key()
-		sumImpl(&tag, in, &key)
-		if tag != v.Tag() {
-			t.Errorf("%d: expected %x, got %x", i, v.Tag(), tag[:])
-		}
-	}
-}
-
-func TestBurnin(t *testing.T) {
-	// This test can be used to sanity-check significant changes. It can
-	// take about many minutes to run, even on fast machines. It's disabled
-	// by default.
-	if !*stressFlag {
-		t.Skip("skipping without -stress")
-	}
-
-	var key [32]byte
-	var input [25]byte
-	var output [16]byte
-
-	for i := range key {
-		key[i] = 1
-	}
-	for i := range input {
-		input[i] = 2
-	}
-
-	for i := uint64(0); i < 1e10; i++ {
-		Sum(&output, input[:], &key)
-		copy(key[0:], output[:])
-		copy(key[16:], output[:])
-		copy(input[:], output[:])
-		copy(input[16:], output[:])
-	}
-
-	const expected = "5e3b866aea0b636d240c83c428f84bfa"
-	if got := hex.EncodeToString(output[:]); got != expected {
-		t.Errorf("expected %s, got %s", expected, got)
-	}
-}
-
-func TestSum(t *testing.T)                 { testSum(t, false, Sum) }
-func TestSumUnaligned(t *testing.T)        { testSum(t, true, Sum) }
-func TestSumGeneric(t *testing.T)          { testSum(t, false, sumGeneric) }
-func TestSumGenericUnaligned(t *testing.T) { testSum(t, true, sumGeneric) }
-
-func benchmark(b *testing.B, size int, unaligned bool) {
-	var out [16]byte
-	var key [32]byte
-	in := make([]byte, size)
-	if unaligned {
-		in = unalignBytes(in)
-	}
-	b.SetBytes(int64(len(in)))
-	b.ResetTimer()
-	for i := 0; i < b.N; i++ {
-		Sum(&out, in, &key)
-	}
-}
-
-func Benchmark64(b *testing.B)          { benchmark(b, 64, false) }
-func Benchmark1K(b *testing.B)          { benchmark(b, 1024, false) }
-func Benchmark64Unaligned(b *testing.B) { benchmark(b, 64, true) }
-func Benchmark1KUnaligned(b *testing.B) { benchmark(b, 1024, true) }
-func Benchmark2M(b *testing.B)          { benchmark(b, 2097152, true) }
-
-func unalignBytes(in []byte) []byte {
-	out := make([]byte, len(in)+1)
-	if uintptr(unsafe.Pointer(&out[0]))&(unsafe.Alignof(uint32(0))-1) == 0 {
-		out = out[1:]
-	} else {
-		out = out[:len(in)]
-	}
-	copy(out, in)
-	return out
-}
diff --git a/src/ssl/test/runner/poly1305/sum_amd64.go b/src/ssl/test/runner/poly1305/sum_amd64.go
deleted file mode 100644
index 4dd72fe..0000000
--- a/src/ssl/test/runner/poly1305/sum_amd64.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build amd64,!gccgo,!appengine
-
-package poly1305
-
-// This function is implemented in sum_amd64.s
-//go:noescape
-func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
-
-// Sum generates an authenticator for m using a one-time key and puts the
-// 16-byte result into out. Authenticating two different messages with the same
-// key allows an attacker to forge messages at will.
-func Sum(out *[16]byte, m []byte, key *[32]byte) {
-	var mPtr *byte
-	if len(m) > 0 {
-		mPtr = &m[0]
-	}
-	poly1305(out, mPtr, uint64(len(m)), key)
-}
diff --git a/src/ssl/test/runner/poly1305/sum_amd64.s b/src/ssl/test/runner/poly1305/sum_amd64.s
deleted file mode 100644
index 2edae63..0000000
--- a/src/ssl/test/runner/poly1305/sum_amd64.s
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build amd64,!gccgo,!appengine
-
-#include "textflag.h"
-
-#define POLY1305_ADD(msg, h0, h1, h2) \
-	ADDQ 0(msg), h0;  \
-	ADCQ 8(msg), h1;  \
-	ADCQ $1, h2;      \
-	LEAQ 16(msg), msg
-
-#define POLY1305_MUL(h0, h1, h2, r0, r1, t0, t1, t2, t3) \
-	MOVQ  r0, AX;                  \
-	MULQ  h0;                      \
-	MOVQ  AX, t0;                  \
-	MOVQ  DX, t1;                  \
-	MOVQ  r0, AX;                  \
-	MULQ  h1;                      \
-	ADDQ  AX, t1;                  \
-	ADCQ  $0, DX;                  \
-	MOVQ  r0, t2;                  \
-	IMULQ h2, t2;                  \
-	ADDQ  DX, t2;                  \
-	                               \
-	MOVQ  r1, AX;                  \
-	MULQ  h0;                      \
-	ADDQ  AX, t1;                  \
-	ADCQ  $0, DX;                  \
-	MOVQ  DX, h0;                  \
-	MOVQ  r1, t3;                  \
-	IMULQ h2, t3;                  \
-	MOVQ  r1, AX;                  \
-	MULQ  h1;                      \
-	ADDQ  AX, t2;                  \
-	ADCQ  DX, t3;                  \
-	ADDQ  h0, t2;                  \
-	ADCQ  $0, t3;                  \
-	                               \
-	MOVQ  t0, h0;                  \
-	MOVQ  t1, h1;                  \
-	MOVQ  t2, h2;                  \
-	ANDQ  $3, h2;                  \
-	MOVQ  t2, t0;                  \
-	ANDQ  $0xFFFFFFFFFFFFFFFC, t0; \
-	ADDQ  t0, h0;                  \
-	ADCQ  t3, h1;                  \
-	ADCQ  $0, h2;                  \
-	SHRQ  $2, t3, t2;              \
-	SHRQ  $2, t3;                  \
-	ADDQ  t2, h0;                  \
-	ADCQ  t3, h1;                  \
-	ADCQ  $0, h2
-
-DATA ·poly1305Mask<>+0x00(SB)/8, $0x0FFFFFFC0FFFFFFF
-DATA ·poly1305Mask<>+0x08(SB)/8, $0x0FFFFFFC0FFFFFFC
-GLOBL ·poly1305Mask<>(SB), RODATA, $16
-
-// func poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
-TEXT ·poly1305(SB), $0-32
-	MOVQ out+0(FP), DI
-	MOVQ m+8(FP), SI
-	MOVQ mlen+16(FP), R15
-	MOVQ key+24(FP), AX
-
-	MOVQ 0(AX), R11
-	MOVQ 8(AX), R12
-	ANDQ ·poly1305Mask<>(SB), R11   // r0
-	ANDQ ·poly1305Mask<>+8(SB), R12 // r1
-	XORQ R8, R8                    // h0
-	XORQ R9, R9                    // h1
-	XORQ R10, R10                  // h2
-
-	CMPQ R15, $16
-	JB   bytes_between_0_and_15
-
-loop:
-	POLY1305_ADD(SI, R8, R9, R10)
-
-multiply:
-	POLY1305_MUL(R8, R9, R10, R11, R12, BX, CX, R13, R14)
-	SUBQ $16, R15
-	CMPQ R15, $16
-	JAE  loop
-
-bytes_between_0_and_15:
-	TESTQ R15, R15
-	JZ    done
-	MOVQ  $1, BX
-	XORQ  CX, CX
-	XORQ  R13, R13
-	ADDQ  R15, SI
-
-flush_buffer:
-	SHLQ $8, BX, CX
-	SHLQ $8, BX
-	MOVB -1(SI), R13
-	XORQ R13, BX
-	DECQ SI
-	DECQ R15
-	JNZ  flush_buffer
-
-	ADDQ BX, R8
-	ADCQ CX, R9
-	ADCQ $0, R10
-	MOVQ $16, R15
-	JMP  multiply
-
-done:
-	MOVQ    R8, AX
-	MOVQ    R9, BX
-	SUBQ    $0xFFFFFFFFFFFFFFFB, AX
-	SBBQ    $0xFFFFFFFFFFFFFFFF, BX
-	SBBQ    $3, R10
-	CMOVQCS R8, AX
-	CMOVQCS R9, BX
-	MOVQ    key+24(FP), R8
-	ADDQ    16(R8), AX
-	ADCQ    24(R8), BX
-
-	MOVQ AX, 0(DI)
-	MOVQ BX, 8(DI)
-	RET
diff --git a/src/ssl/test/runner/poly1305/sum_arm.go b/src/ssl/test/runner/poly1305/sum_arm.go
deleted file mode 100644
index 5dc321c..0000000
--- a/src/ssl/test/runner/poly1305/sum_arm.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build arm,!gccgo,!appengine,!nacl
-
-package poly1305
-
-// This function is implemented in sum_arm.s
-//go:noescape
-func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]byte)
-
-// Sum generates an authenticator for m using a one-time key and puts the
-// 16-byte result into out. Authenticating two different messages with the same
-// key allows an attacker to forge messages at will.
-func Sum(out *[16]byte, m []byte, key *[32]byte) {
-	var mPtr *byte
-	if len(m) > 0 {
-		mPtr = &m[0]
-	}
-	poly1305_auth_armv6(out, mPtr, uint32(len(m)), key)
-}
diff --git a/src/ssl/test/runner/poly1305/sum_arm.s b/src/ssl/test/runner/poly1305/sum_arm.s
deleted file mode 100644
index f70b4ac..0000000
--- a/src/ssl/test/runner/poly1305/sum_arm.s
+++ /dev/null
@@ -1,427 +0,0 @@
-// Copyright 2015 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build arm,!gccgo,!appengine,!nacl
-
-#include "textflag.h"
-
-// This code was translated into a form compatible with 5a from the public
-// domain source by Andrew Moon: github.com/floodyberry/poly1305-opt/blob/master/app/extensions/poly1305.
-
-DATA ·poly1305_init_constants_armv6<>+0x00(SB)/4, $0x3ffffff
-DATA ·poly1305_init_constants_armv6<>+0x04(SB)/4, $0x3ffff03
-DATA ·poly1305_init_constants_armv6<>+0x08(SB)/4, $0x3ffc0ff
-DATA ·poly1305_init_constants_armv6<>+0x0c(SB)/4, $0x3f03fff
-DATA ·poly1305_init_constants_armv6<>+0x10(SB)/4, $0x00fffff
-GLOBL ·poly1305_init_constants_armv6<>(SB), 8, $20
-
-// Warning: the linker may use R11 to synthesize certain instructions. Please
-// take care and verify that no synthetic instructions use it.
-
-TEXT poly1305_init_ext_armv6<>(SB), NOSPLIT, $0
-	// Needs 16 bytes of stack and 64 bytes of space pointed to by R0.  (It
-	// might look like it's only 60 bytes of space but the final four bytes
-	// will be written by another function.) We need to skip over four
-	// bytes of stack because that's saving the value of 'g'.
-	ADD       $4, R13, R8
-	MOVM.IB   [R4-R7], (R8)
-	MOVM.IA.W (R1), [R2-R5]
-	MOVW      $·poly1305_init_constants_armv6<>(SB), R7
-	MOVW      R2, R8
-	MOVW      R2>>26, R9
-	MOVW      R3>>20, g
-	MOVW      R4>>14, R11
-	MOVW      R5>>8, R12
-	ORR       R3<<6, R9, R9
-	ORR       R4<<12, g, g
-	ORR       R5<<18, R11, R11
-	MOVM.IA   (R7), [R2-R6]
-	AND       R8, R2, R2
-	AND       R9, R3, R3
-	AND       g, R4, R4
-	AND       R11, R5, R5
-	AND       R12, R6, R6
-	MOVM.IA.W [R2-R6], (R0)
-	EOR       R2, R2, R2
-	EOR       R3, R3, R3
-	EOR       R4, R4, R4
-	EOR       R5, R5, R5
-	EOR       R6, R6, R6
-	MOVM.IA.W [R2-R6], (R0)
-	MOVM.IA.W (R1), [R2-R5]
-	MOVM.IA   [R2-R6], (R0)
-	ADD       $20, R13, R0
-	MOVM.DA   (R0), [R4-R7]
-	RET
-
-#define MOVW_UNALIGNED(Rsrc, Rdst, Rtmp, offset) \
-	MOVBU (offset+0)(Rsrc), Rtmp; \
-	MOVBU Rtmp, (offset+0)(Rdst); \
-	MOVBU (offset+1)(Rsrc), Rtmp; \
-	MOVBU Rtmp, (offset+1)(Rdst); \
-	MOVBU (offset+2)(Rsrc), Rtmp; \
-	MOVBU Rtmp, (offset+2)(Rdst); \
-	MOVBU (offset+3)(Rsrc), Rtmp; \
-	MOVBU Rtmp, (offset+3)(Rdst)
-
-TEXT poly1305_blocks_armv6<>(SB), NOSPLIT, $0
-	// Needs 24 bytes of stack for saved registers and then 88 bytes of
-	// scratch space after that. We assume that 24 bytes at (R13) have
-	// already been used: four bytes for the link register saved in the
-	// prelude of poly1305_auth_armv6, four bytes for saving the value of g
-	// in that function and 16 bytes of scratch space used around
-	// poly1305_finish_ext_armv6_skip1.
-	ADD     $24, R13, R12
-	MOVM.IB [R4-R8, R14], (R12)
-	MOVW    R0, 88(R13)
-	MOVW    R1, 92(R13)
-	MOVW    R2, 96(R13)
-	MOVW    R1, R14
-	MOVW    R2, R12
-	MOVW    56(R0), R8
-	WORD    $0xe1180008                // TST R8, R8 not working see issue 5921
-	EOR     R6, R6, R6
-	MOVW.EQ $(1<<24), R6
-	MOVW    R6, 84(R13)
-	ADD     $116, R13, g
-	MOVM.IA (R0), [R0-R9]
-	MOVM.IA [R0-R4], (g)
-	CMP     $16, R12
-	BLO     poly1305_blocks_armv6_done
-
-poly1305_blocks_armv6_mainloop:
-	WORD    $0xe31e0003                            // TST R14, #3 not working see issue 5921
-	BEQ     poly1305_blocks_armv6_mainloop_aligned
-	ADD     $100, R13, g
-	MOVW_UNALIGNED(R14, g, R0, 0)
-	MOVW_UNALIGNED(R14, g, R0, 4)
-	MOVW_UNALIGNED(R14, g, R0, 8)
-	MOVW_UNALIGNED(R14, g, R0, 12)
-	MOVM.IA (g), [R0-R3]
-	ADD     $16, R14
-	B       poly1305_blocks_armv6_mainloop_loaded
-
-poly1305_blocks_armv6_mainloop_aligned:
-	MOVM.IA.W (R14), [R0-R3]
-
-poly1305_blocks_armv6_mainloop_loaded:
-	MOVW    R0>>26, g
-	MOVW    R1>>20, R11
-	MOVW    R2>>14, R12
-	MOVW    R14, 92(R13)
-	MOVW    R3>>8, R4
-	ORR     R1<<6, g, g
-	ORR     R2<<12, R11, R11
-	ORR     R3<<18, R12, R12
-	BIC     $0xfc000000, R0, R0
-	BIC     $0xfc000000, g, g
-	MOVW    84(R13), R3
-	BIC     $0xfc000000, R11, R11
-	BIC     $0xfc000000, R12, R12
-	ADD     R0, R5, R5
-	ADD     g, R6, R6
-	ORR     R3, R4, R4
-	ADD     R11, R7, R7
-	ADD     $116, R13, R14
-	ADD     R12, R8, R8
-	ADD     R4, R9, R9
-	MOVM.IA (R14), [R0-R4]
-	MULLU   R4, R5, (R11, g)
-	MULLU   R3, R5, (R14, R12)
-	MULALU  R3, R6, (R11, g)
-	MULALU  R2, R6, (R14, R12)
-	MULALU  R2, R7, (R11, g)
-	MULALU  R1, R7, (R14, R12)
-	ADD     R4<<2, R4, R4
-	ADD     R3<<2, R3, R3
-	MULALU  R1, R8, (R11, g)
-	MULALU  R0, R8, (R14, R12)
-	MULALU  R0, R9, (R11, g)
-	MULALU  R4, R9, (R14, R12)
-	MOVW    g, 76(R13)
-	MOVW    R11, 80(R13)
-	MOVW    R12, 68(R13)
-	MOVW    R14, 72(R13)
-	MULLU   R2, R5, (R11, g)
-	MULLU   R1, R5, (R14, R12)
-	MULALU  R1, R6, (R11, g)
-	MULALU  R0, R6, (R14, R12)
-	MULALU  R0, R7, (R11, g)
-	MULALU  R4, R7, (R14, R12)
-	ADD     R2<<2, R2, R2
-	ADD     R1<<2, R1, R1
-	MULALU  R4, R8, (R11, g)
-	MULALU  R3, R8, (R14, R12)
-	MULALU  R3, R9, (R11, g)
-	MULALU  R2, R9, (R14, R12)
-	MOVW    g, 60(R13)
-	MOVW    R11, 64(R13)
-	MOVW    R12, 52(R13)
-	MOVW    R14, 56(R13)
-	MULLU   R0, R5, (R11, g)
-	MULALU  R4, R6, (R11, g)
-	MULALU  R3, R7, (R11, g)
-	MULALU  R2, R8, (R11, g)
-	MULALU  R1, R9, (R11, g)
-	ADD     $52, R13, R0
-	MOVM.IA (R0), [R0-R7]
-	MOVW    g>>26, R12
-	MOVW    R4>>26, R14
-	ORR     R11<<6, R12, R12
-	ORR     R5<<6, R14, R14
-	BIC     $0xfc000000, g, g
-	BIC     $0xfc000000, R4, R4
-	ADD.S   R12, R0, R0
-	ADC     $0, R1, R1
-	ADD.S   R14, R6, R6
-	ADC     $0, R7, R7
-	MOVW    R0>>26, R12
-	MOVW    R6>>26, R14
-	ORR     R1<<6, R12, R12
-	ORR     R7<<6, R14, R14
-	BIC     $0xfc000000, R0, R0
-	BIC     $0xfc000000, R6, R6
-	ADD     R14<<2, R14, R14
-	ADD.S   R12, R2, R2
-	ADC     $0, R3, R3
-	ADD     R14, g, g
-	MOVW    R2>>26, R12
-	MOVW    g>>26, R14
-	ORR     R3<<6, R12, R12
-	BIC     $0xfc000000, g, R5
-	BIC     $0xfc000000, R2, R7
-	ADD     R12, R4, R4
-	ADD     R14, R0, R0
-	MOVW    R4>>26, R12
-	BIC     $0xfc000000, R4, R8
-	ADD     R12, R6, R9
-	MOVW    96(R13), R12
-	MOVW    92(R13), R14
-	MOVW    R0, R6
-	CMP     $32, R12
-	SUB     $16, R12, R12
-	MOVW    R12, 96(R13)
-	BHS     poly1305_blocks_armv6_mainloop
-
-poly1305_blocks_armv6_done:
-	MOVW    88(R13), R12
-	MOVW    R5, 20(R12)
-	MOVW    R6, 24(R12)
-	MOVW    R7, 28(R12)
-	MOVW    R8, 32(R12)
-	MOVW    R9, 36(R12)
-	ADD     $48, R13, R0
-	MOVM.DA (R0), [R4-R8, R14]
-	RET
-
-#define MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp) \
-	MOVBU.P 1(Rsrc), Rtmp; \
-	MOVBU.P Rtmp, 1(Rdst); \
-	MOVBU.P 1(Rsrc), Rtmp; \
-	MOVBU.P Rtmp, 1(Rdst)
-
-#define MOVWP_UNALIGNED(Rsrc, Rdst, Rtmp) \
-	MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp); \
-	MOVHUP_UNALIGNED(Rsrc, Rdst, Rtmp)
-
-// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
-TEXT ·poly1305_auth_armv6(SB), $196-16
-	// The value 196, just above, is the sum of 64 (the size of the context
-	// structure) and 132 (the amount of stack needed).
-	//
-	// At this point, the stack pointer (R13) has been moved down. It
-	// points to the saved link register and there's 196 bytes of free
-	// space above it.
-	//
-	// The stack for this function looks like:
-	//
-	// +---------------------
-	// |
-	// | 64 bytes of context structure
-	// |
-	// +---------------------
-	// |
-	// | 112 bytes for poly1305_blocks_armv6
-	// |
-	// +---------------------
-	// | 16 bytes of final block, constructed at
-	// | poly1305_finish_ext_armv6_skip8
-	// +---------------------
-	// | four bytes of saved 'g'
-	// +---------------------
-	// | lr, saved by prelude    <- R13 points here
-	// +---------------------
-	MOVW g, 4(R13)
-
-	MOVW out+0(FP), R4
-	MOVW m+4(FP), R5
-	MOVW mlen+8(FP), R6
-	MOVW key+12(FP), R7
-
-	ADD  $136, R13, R0 // 136 = 4 + 4 + 16 + 112
-	MOVW R7, R1
-
-	// poly1305_init_ext_armv6 will write to the stack from R13+4, but
-	// that's ok because none of the other values have been written yet.
-	BL    poly1305_init_ext_armv6<>(SB)
-	BIC.S $15, R6, R2
-	BEQ   poly1305_auth_armv6_noblocks
-	ADD   $136, R13, R0
-	MOVW  R5, R1
-	ADD   R2, R5, R5
-	SUB   R2, R6, R6
-	BL    poly1305_blocks_armv6<>(SB)
-
-poly1305_auth_armv6_noblocks:
-	ADD  $136, R13, R0
-	MOVW R5, R1
-	MOVW R6, R2
-	MOVW R4, R3
-
-	MOVW  R0, R5
-	MOVW  R1, R6
-	MOVW  R2, R7
-	MOVW  R3, R8
-	AND.S R2, R2, R2
-	BEQ   poly1305_finish_ext_armv6_noremaining
-	EOR   R0, R0
-	ADD   $8, R13, R9                           // 8 = offset to 16 byte scratch space
-	MOVW  R0, (R9)
-	MOVW  R0, 4(R9)
-	MOVW  R0, 8(R9)
-	MOVW  R0, 12(R9)
-	WORD  $0xe3110003                           // TST R1, #3 not working see issue 5921
-	BEQ   poly1305_finish_ext_armv6_aligned
-	WORD  $0xe3120008                           // TST R2, #8 not working see issue 5921
-	BEQ   poly1305_finish_ext_armv6_skip8
-	MOVWP_UNALIGNED(R1, R9, g)
-	MOVWP_UNALIGNED(R1, R9, g)
-
-poly1305_finish_ext_armv6_skip8:
-	WORD $0xe3120004                     // TST $4, R2 not working see issue 5921
-	BEQ  poly1305_finish_ext_armv6_skip4
-	MOVWP_UNALIGNED(R1, R9, g)
-
-poly1305_finish_ext_armv6_skip4:
-	WORD $0xe3120002                     // TST $2, R2 not working see issue 5921
-	BEQ  poly1305_finish_ext_armv6_skip2
-	MOVHUP_UNALIGNED(R1, R9, g)
-	B    poly1305_finish_ext_armv6_skip2
-
-poly1305_finish_ext_armv6_aligned:
-	WORD      $0xe3120008                             // TST R2, #8 not working see issue 5921
-	BEQ       poly1305_finish_ext_armv6_skip8_aligned
-	MOVM.IA.W (R1), [g-R11]
-	MOVM.IA.W [g-R11], (R9)
-
-poly1305_finish_ext_armv6_skip8_aligned:
-	WORD   $0xe3120004                             // TST $4, R2 not working see issue 5921
-	BEQ    poly1305_finish_ext_armv6_skip4_aligned
-	MOVW.P 4(R1), g
-	MOVW.P g, 4(R9)
-
-poly1305_finish_ext_armv6_skip4_aligned:
-	WORD    $0xe3120002                     // TST $2, R2 not working see issue 5921
-	BEQ     poly1305_finish_ext_armv6_skip2
-	MOVHU.P 2(R1), g
-	MOVH.P  g, 2(R9)
-
-poly1305_finish_ext_armv6_skip2:
-	WORD    $0xe3120001                     // TST $1, R2 not working see issue 5921
-	BEQ     poly1305_finish_ext_armv6_skip1
-	MOVBU.P 1(R1), g
-	MOVBU.P g, 1(R9)
-
-poly1305_finish_ext_armv6_skip1:
-	MOVW  $1, R11
-	MOVBU R11, 0(R9)
-	MOVW  R11, 56(R5)
-	MOVW  R5, R0
-	ADD   $8, R13, R1
-	MOVW  $16, R2
-	BL    poly1305_blocks_armv6<>(SB)
-
-poly1305_finish_ext_armv6_noremaining:
-	MOVW      20(R5), R0
-	MOVW      24(R5), R1
-	MOVW      28(R5), R2
-	MOVW      32(R5), R3
-	MOVW      36(R5), R4
-	MOVW      R4>>26, R12
-	BIC       $0xfc000000, R4, R4
-	ADD       R12<<2, R12, R12
-	ADD       R12, R0, R0
-	MOVW      R0>>26, R12
-	BIC       $0xfc000000, R0, R0
-	ADD       R12, R1, R1
-	MOVW      R1>>26, R12
-	BIC       $0xfc000000, R1, R1
-	ADD       R12, R2, R2
-	MOVW      R2>>26, R12
-	BIC       $0xfc000000, R2, R2
-	ADD       R12, R3, R3
-	MOVW      R3>>26, R12
-	BIC       $0xfc000000, R3, R3
-	ADD       R12, R4, R4
-	ADD       $5, R0, R6
-	MOVW      R6>>26, R12
-	BIC       $0xfc000000, R6, R6
-	ADD       R12, R1, R7
-	MOVW      R7>>26, R12
-	BIC       $0xfc000000, R7, R7
-	ADD       R12, R2, g
-	MOVW      g>>26, R12
-	BIC       $0xfc000000, g, g
-	ADD       R12, R3, R11
-	MOVW      $-(1<<26), R12
-	ADD       R11>>26, R12, R12
-	BIC       $0xfc000000, R11, R11
-	ADD       R12, R4, R9
-	MOVW      R9>>31, R12
-	SUB       $1, R12
-	AND       R12, R6, R6
-	AND       R12, R7, R7
-	AND       R12, g, g
-	AND       R12, R11, R11
-	AND       R12, R9, R9
-	MVN       R12, R12
-	AND       R12, R0, R0
-	AND       R12, R1, R1
-	AND       R12, R2, R2
-	AND       R12, R3, R3
-	AND       R12, R4, R4
-	ORR       R6, R0, R0
-	ORR       R7, R1, R1
-	ORR       g, R2, R2
-	ORR       R11, R3, R3
-	ORR       R9, R4, R4
-	ORR       R1<<26, R0, R0
-	MOVW      R1>>6, R1
-	ORR       R2<<20, R1, R1
-	MOVW      R2>>12, R2
-	ORR       R3<<14, R2, R2
-	MOVW      R3>>18, R3
-	ORR       R4<<8, R3, R3
-	MOVW      40(R5), R6
-	MOVW      44(R5), R7
-	MOVW      48(R5), g
-	MOVW      52(R5), R11
-	ADD.S     R6, R0, R0
-	ADC.S     R7, R1, R1
-	ADC.S     g, R2, R2
-	ADC.S     R11, R3, R3
-	MOVM.IA   [R0-R3], (R8)
-	MOVW      R5, R12
-	EOR       R0, R0, R0
-	EOR       R1, R1, R1
-	EOR       R2, R2, R2
-	EOR       R3, R3, R3
-	EOR       R4, R4, R4
-	EOR       R5, R5, R5
-	EOR       R6, R6, R6
-	EOR       R7, R7, R7
-	MOVM.IA.W [R0-R7], (R12)
-	MOVM.IA   [R0-R7], (R12)
-	MOVW      4(R13), g
-	RET
diff --git a/src/ssl/test/runner/poly1305/sum_noasm.go b/src/ssl/test/runner/poly1305/sum_noasm.go
deleted file mode 100644
index 751eec5..0000000
--- a/src/ssl/test/runner/poly1305/sum_noasm.go
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build s390x,!go1.11 !arm,!amd64,!s390x gccgo appengine nacl
-
-package poly1305
-
-// Sum generates an authenticator for msg using a one-time key and puts the
-// 16-byte result into out. Authenticating two different messages with the same
-// key allows an attacker to forge messages at will.
-func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
-	sumGeneric(out, msg, key)
-}
diff --git a/src/ssl/test/runner/poly1305/sum_ref.go b/src/ssl/test/runner/poly1305/sum_ref.go
deleted file mode 100644
index c4d59bd..0000000
--- a/src/ssl/test/runner/poly1305/sum_ref.go
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2012 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package poly1305
-
-import "encoding/binary"
-
-// sumGeneric generates an authenticator for msg using a one-time key and
-// puts the 16-byte result into out. This is the generic implementation of
-// Sum and should be called if no assembly implementation is available.
-func sumGeneric(out *[TagSize]byte, msg []byte, key *[32]byte) {
-	var (
-		h0, h1, h2, h3, h4 uint32 // the hash accumulators
-		r0, r1, r2, r3, r4 uint64 // the r part of the key
-	)
-
-	r0 = uint64(binary.LittleEndian.Uint32(key[0:]) & 0x3ffffff)
-	r1 = uint64((binary.LittleEndian.Uint32(key[3:]) >> 2) & 0x3ffff03)
-	r2 = uint64((binary.LittleEndian.Uint32(key[6:]) >> 4) & 0x3ffc0ff)
-	r3 = uint64((binary.LittleEndian.Uint32(key[9:]) >> 6) & 0x3f03fff)
-	r4 = uint64((binary.LittleEndian.Uint32(key[12:]) >> 8) & 0x00fffff)
-
-	R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5
-
-	for len(msg) >= TagSize {
-		// h += msg
-		h0 += binary.LittleEndian.Uint32(msg[0:]) & 0x3ffffff
-		h1 += (binary.LittleEndian.Uint32(msg[3:]) >> 2) & 0x3ffffff
-		h2 += (binary.LittleEndian.Uint32(msg[6:]) >> 4) & 0x3ffffff
-		h3 += (binary.LittleEndian.Uint32(msg[9:]) >> 6) & 0x3ffffff
-		h4 += (binary.LittleEndian.Uint32(msg[12:]) >> 8) | (1 << 24)
-
-		// h *= r
-		d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
-		d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
-		d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
-		d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
-		d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
-
-		// h %= p
-		h0 = uint32(d0) & 0x3ffffff
-		h1 = uint32(d1) & 0x3ffffff
-		h2 = uint32(d2) & 0x3ffffff
-		h3 = uint32(d3) & 0x3ffffff
-		h4 = uint32(d4) & 0x3ffffff
-
-		h0 += uint32(d4>>26) * 5
-		h1 += h0 >> 26
-		h0 = h0 & 0x3ffffff
-
-		msg = msg[TagSize:]
-	}
-
-	if len(msg) > 0 {
-		var block [TagSize]byte
-		off := copy(block[:], msg)
-		block[off] = 0x01
-
-		// h += msg
-		h0 += binary.LittleEndian.Uint32(block[0:]) & 0x3ffffff
-		h1 += (binary.LittleEndian.Uint32(block[3:]) >> 2) & 0x3ffffff
-		h2 += (binary.LittleEndian.Uint32(block[6:]) >> 4) & 0x3ffffff
-		h3 += (binary.LittleEndian.Uint32(block[9:]) >> 6) & 0x3ffffff
-		h4 += (binary.LittleEndian.Uint32(block[12:]) >> 8)
-
-		// h *= r
-		d0 := (uint64(h0) * r0) + (uint64(h1) * R4) + (uint64(h2) * R3) + (uint64(h3) * R2) + (uint64(h4) * R1)
-		d1 := (d0 >> 26) + (uint64(h0) * r1) + (uint64(h1) * r0) + (uint64(h2) * R4) + (uint64(h3) * R3) + (uint64(h4) * R2)
-		d2 := (d1 >> 26) + (uint64(h0) * r2) + (uint64(h1) * r1) + (uint64(h2) * r0) + (uint64(h3) * R4) + (uint64(h4) * R3)
-		d3 := (d2 >> 26) + (uint64(h0) * r3) + (uint64(h1) * r2) + (uint64(h2) * r1) + (uint64(h3) * r0) + (uint64(h4) * R4)
-		d4 := (d3 >> 26) + (uint64(h0) * r4) + (uint64(h1) * r3) + (uint64(h2) * r2) + (uint64(h3) * r1) + (uint64(h4) * r0)
-
-		// h %= p
-		h0 = uint32(d0) & 0x3ffffff
-		h1 = uint32(d1) & 0x3ffffff
-		h2 = uint32(d2) & 0x3ffffff
-		h3 = uint32(d3) & 0x3ffffff
-		h4 = uint32(d4) & 0x3ffffff
-
-		h0 += uint32(d4>>26) * 5
-		h1 += h0 >> 26
-		h0 = h0 & 0x3ffffff
-	}
-
-	// h %= p reduction
-	h2 += h1 >> 26
-	h1 &= 0x3ffffff
-	h3 += h2 >> 26
-	h2 &= 0x3ffffff
-	h4 += h3 >> 26
-	h3 &= 0x3ffffff
-	h0 += 5 * (h4 >> 26)
-	h4 &= 0x3ffffff
-	h1 += h0 >> 26
-	h0 &= 0x3ffffff
-
-	// h - p
-	t0 := h0 + 5
-	t1 := h1 + (t0 >> 26)
-	t2 := h2 + (t1 >> 26)
-	t3 := h3 + (t2 >> 26)
-	t4 := h4 + (t3 >> 26) - (1 << 26)
-	t0 &= 0x3ffffff
-	t1 &= 0x3ffffff
-	t2 &= 0x3ffffff
-	t3 &= 0x3ffffff
-
-	// select h if h < p else h - p
-	t_mask := (t4 >> 31) - 1
-	h_mask := ^t_mask
-	h0 = (h0 & h_mask) | (t0 & t_mask)
-	h1 = (h1 & h_mask) | (t1 & t_mask)
-	h2 = (h2 & h_mask) | (t2 & t_mask)
-	h3 = (h3 & h_mask) | (t3 & t_mask)
-	h4 = (h4 & h_mask) | (t4 & t_mask)
-
-	// h %= 2^128
-	h0 |= h1 << 26
-	h1 = ((h1 >> 6) | (h2 << 20))
-	h2 = ((h2 >> 12) | (h3 << 14))
-	h3 = ((h3 >> 18) | (h4 << 8))
-
-	// s: the s part of the key
-	// tag = (h + s) % (2^128)
-	t := uint64(h0) + uint64(binary.LittleEndian.Uint32(key[16:]))
-	h0 = uint32(t)
-	t = uint64(h1) + uint64(binary.LittleEndian.Uint32(key[20:])) + (t >> 32)
-	h1 = uint32(t)
-	t = uint64(h2) + uint64(binary.LittleEndian.Uint32(key[24:])) + (t >> 32)
-	h2 = uint32(t)
-	t = uint64(h3) + uint64(binary.LittleEndian.Uint32(key[28:])) + (t >> 32)
-	h3 = uint32(t)
-
-	binary.LittleEndian.PutUint32(out[0:], h0)
-	binary.LittleEndian.PutUint32(out[4:], h1)
-	binary.LittleEndian.PutUint32(out[8:], h2)
-	binary.LittleEndian.PutUint32(out[12:], h3)
-}
diff --git a/src/ssl/test/runner/poly1305/sum_s390x.go b/src/ssl/test/runner/poly1305/sum_s390x.go
deleted file mode 100644
index 7a266ce..0000000
--- a/src/ssl/test/runner/poly1305/sum_s390x.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build s390x,go1.11,!gccgo,!appengine
-
-package poly1305
-
-// hasVectorFacility reports whether the machine supports
-// the vector facility (vx).
-func hasVectorFacility() bool
-
-// hasVMSLFacility reports whether the machine supports
-// Vector Multiply Sum Logical (VMSL).
-func hasVMSLFacility() bool
-
-var hasVX = hasVectorFacility()
-var hasVMSL = hasVMSLFacility()
-
-// poly1305vx is an assembly implementation of Poly1305 that uses vector
-// instructions. It must only be called if the vector facility (vx) is
-// available.
-//go:noescape
-func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
-
-// poly1305vmsl is an assembly implementation of Poly1305 that uses vector
-// instructions, including VMSL. It must only be called if the vector facility (vx) is
-// available and if VMSL is supported.
-//go:noescape
-func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]byte)
-
-// Sum generates an authenticator for m using a one-time key and puts the
-// 16-byte result into out. Authenticating two different messages with the same
-// key allows an attacker to forge messages at will.
-func Sum(out *[16]byte, m []byte, key *[32]byte) {
-	if hasVX {
-		var mPtr *byte
-		if len(m) > 0 {
-			mPtr = &m[0]
-		}
-		if hasVMSL && len(m) > 256 {
-			poly1305vmsl(out, mPtr, uint64(len(m)), key)
-		} else {
-			poly1305vx(out, mPtr, uint64(len(m)), key)
-		}
-	} else {
-		sumGeneric(out, m, key)
-	}
-}
diff --git a/src/ssl/test/runner/poly1305/sum_s390x.s b/src/ssl/test/runner/poly1305/sum_s390x.s
deleted file mode 100644
index 356c07a..0000000
--- a/src/ssl/test/runner/poly1305/sum_s390x.s
+++ /dev/null
@@ -1,400 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build s390x,go1.11,!gccgo,!appengine
-
-#include "textflag.h"
-
-// Implementation of Poly1305 using the vector facility (vx).
-
-// constants
-#define MOD26 V0
-#define EX0   V1
-#define EX1   V2
-#define EX2   V3
-
-// temporaries
-#define T_0 V4
-#define T_1 V5
-#define T_2 V6
-#define T_3 V7
-#define T_4 V8
-
-// key (r)
-#define R_0  V9
-#define R_1  V10
-#define R_2  V11
-#define R_3  V12
-#define R_4  V13
-#define R5_1 V14
-#define R5_2 V15
-#define R5_3 V16
-#define R5_4 V17
-#define RSAVE_0 R5
-#define RSAVE_1 R6
-#define RSAVE_2 R7
-#define RSAVE_3 R8
-#define RSAVE_4 R9
-#define R5SAVE_1 V28
-#define R5SAVE_2 V29
-#define R5SAVE_3 V30
-#define R5SAVE_4 V31
-
-// message block
-#define F_0 V18
-#define F_1 V19
-#define F_2 V20
-#define F_3 V21
-#define F_4 V22
-
-// accumulator
-#define H_0 V23
-#define H_1 V24
-#define H_2 V25
-#define H_3 V26
-#define H_4 V27
-
-GLOBL ·keyMask<>(SB), RODATA, $16
-DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f
-DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f
-
-GLOBL ·bswapMask<>(SB), RODATA, $16
-DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908
-DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100
-
-GLOBL ·constants<>(SB), RODATA, $64
-// MOD26
-DATA ·constants<>+0(SB)/8, $0x3ffffff
-DATA ·constants<>+8(SB)/8, $0x3ffffff
-// EX0
-DATA ·constants<>+16(SB)/8, $0x0006050403020100
-DATA ·constants<>+24(SB)/8, $0x1016151413121110
-// EX1
-DATA ·constants<>+32(SB)/8, $0x060c0b0a09080706
-DATA ·constants<>+40(SB)/8, $0x161c1b1a19181716
-// EX2
-DATA ·constants<>+48(SB)/8, $0x0d0d0d0d0d0f0e0d
-DATA ·constants<>+56(SB)/8, $0x1d1d1d1d1d1f1e1d
-
-// h = (f*g) % (2**130-5) [partial reduction]
-#define MULTIPLY(f0, f1, f2, f3, f4, g0, g1, g2, g3, g4, g51, g52, g53, g54, h0, h1, h2, h3, h4) \
-	VMLOF  f0, g0, h0        \
-	VMLOF  f0, g1, h1        \
-	VMLOF  f0, g2, h2        \
-	VMLOF  f0, g3, h3        \
-	VMLOF  f0, g4, h4        \
-	VMLOF  f1, g54, T_0      \
-	VMLOF  f1, g0, T_1       \
-	VMLOF  f1, g1, T_2       \
-	VMLOF  f1, g2, T_3       \
-	VMLOF  f1, g3, T_4       \
-	VMALOF f2, g53, h0, h0   \
-	VMALOF f2, g54, h1, h1   \
-	VMALOF f2, g0, h2, h2    \
-	VMALOF f2, g1, h3, h3    \
-	VMALOF f2, g2, h4, h4    \
-	VMALOF f3, g52, T_0, T_0 \
-	VMALOF f3, g53, T_1, T_1 \
-	VMALOF f3, g54, T_2, T_2 \
-	VMALOF f3, g0, T_3, T_3  \
-	VMALOF f3, g1, T_4, T_4  \
-	VMALOF f4, g51, h0, h0   \
-	VMALOF f4, g52, h1, h1   \
-	VMALOF f4, g53, h2, h2   \
-	VMALOF f4, g54, h3, h3   \
-	VMALOF f4, g0, h4, h4    \
-	VAG    T_0, h0, h0       \
-	VAG    T_1, h1, h1       \
-	VAG    T_2, h2, h2       \
-	VAG    T_3, h3, h3       \
-	VAG    T_4, h4, h4
-
-// carry h0->h1 h3->h4, h1->h2 h4->h0, h0->h1 h2->h3, h3->h4
-#define REDUCE(h0, h1, h2, h3, h4) \
-	VESRLG $26, h0, T_0  \
-	VESRLG $26, h3, T_1  \
-	VN     MOD26, h0, h0 \
-	VN     MOD26, h3, h3 \
-	VAG    T_0, h1, h1   \
-	VAG    T_1, h4, h4   \
-	VESRLG $26, h1, T_2  \
-	VESRLG $26, h4, T_3  \
-	VN     MOD26, h1, h1 \
-	VN     MOD26, h4, h4 \
-	VESLG  $2, T_3, T_4  \
-	VAG    T_3, T_4, T_4 \
-	VAG    T_2, h2, h2   \
-	VAG    T_4, h0, h0   \
-	VESRLG $26, h2, T_0  \
-	VESRLG $26, h0, T_1  \
-	VN     MOD26, h2, h2 \
-	VN     MOD26, h0, h0 \
-	VAG    T_0, h3, h3   \
-	VAG    T_1, h1, h1   \
-	VESRLG $26, h3, T_2  \
-	VN     MOD26, h3, h3 \
-	VAG    T_2, h4, h4
-
-// expand in0 into d[0] and in1 into d[1]
-#define EXPAND(in0, in1, d0, d1, d2, d3, d4) \
-	VGBM   $0x0707, d1       \ // d1=tmp
-	VPERM  in0, in1, EX2, d4 \
-	VPERM  in0, in1, EX0, d0 \
-	VPERM  in0, in1, EX1, d2 \
-	VN     d1, d4, d4        \
-	VESRLG $26, d0, d1       \
-	VESRLG $30, d2, d3       \
-	VESRLG $4, d2, d2        \
-	VN     MOD26, d0, d0     \
-	VN     MOD26, d1, d1     \
-	VN     MOD26, d2, d2     \
-	VN     MOD26, d3, d3
-
-// pack h4:h0 into h1:h0 (no carry)
-#define PACK(h0, h1, h2, h3, h4) \
-	VESLG $26, h1, h1  \
-	VESLG $26, h3, h3  \
-	VO    h0, h1, h0   \
-	VO    h2, h3, h2   \
-	VESLG $4, h2, h2   \
-	VLEIB $7, $48, h1  \
-	VSLB  h1, h2, h2   \
-	VO    h0, h2, h0   \
-	VLEIB $7, $104, h1 \
-	VSLB  h1, h4, h3   \
-	VO    h3, h0, h0   \
-	VLEIB $7, $24, h1  \
-	VSRLB h1, h4, h1
-
-// if h > 2**130-5 then h -= 2**130-5
-#define MOD(h0, h1, t0, t1, t2) \
-	VZERO t0          \
-	VLEIG $1, $5, t0  \
-	VACCQ h0, t0, t1  \
-	VAQ   h0, t0, t0  \
-	VONE  t2          \
-	VLEIG $1, $-4, t2 \
-	VAQ   t2, t1, t1  \
-	VACCQ h1, t1, t1  \
-	VONE  t2          \
-	VAQ   t2, t1, t1  \
-	VN    h0, t1, t2  \
-	VNC   t0, t1, t1  \
-	VO    t1, t2, h0
-
-// func poly1305vx(out *[16]byte, m *byte, mlen uint64, key *[32]key)
-TEXT ·poly1305vx(SB), $0-32
-	// This code processes up to 2 blocks (32 bytes) per iteration
-	// using the algorithm described in:
-	// NEON crypto, Daniel J. Bernstein & Peter Schwabe
-	// https://cryptojedi.org/papers/neoncrypto-20120320.pdf
-	LMG out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key
-
-	// load MOD26, EX0, EX1 and EX2
-	MOVD $·constants<>(SB), R5
-	VLM  (R5), MOD26, EX2
-
-	// setup r
-	VL   (R4), T_0
-	MOVD $·keyMask<>(SB), R6
-	VL   (R6), T_1
-	VN   T_0, T_1, T_0
-	EXPAND(T_0, T_0, R_0, R_1, R_2, R_3, R_4)
-
-	// setup r*5
-	VLEIG $0, $5, T_0
-	VLEIG $1, $5, T_0
-
-	// store r (for final block)
-	VMLOF T_0, R_1, R5SAVE_1
-	VMLOF T_0, R_2, R5SAVE_2
-	VMLOF T_0, R_3, R5SAVE_3
-	VMLOF T_0, R_4, R5SAVE_4
-	VLGVG $0, R_0, RSAVE_0
-	VLGVG $0, R_1, RSAVE_1
-	VLGVG $0, R_2, RSAVE_2
-	VLGVG $0, R_3, RSAVE_3
-	VLGVG $0, R_4, RSAVE_4
-
-	// skip r**2 calculation
-	CMPBLE R3, $16, skip
-
-	// calculate r**2
-	MULTIPLY(R_0, R_1, R_2, R_3, R_4, R_0, R_1, R_2, R_3, R_4, R5SAVE_1, R5SAVE_2, R5SAVE_3, R5SAVE_4, H_0, H_1, H_2, H_3, H_4)
-	REDUCE(H_0, H_1, H_2, H_3, H_4)
-	VLEIG $0, $5, T_0
-	VLEIG $1, $5, T_0
-	VMLOF T_0, H_1, R5_1
-	VMLOF T_0, H_2, R5_2
-	VMLOF T_0, H_3, R5_3
-	VMLOF T_0, H_4, R5_4
-	VLR   H_0, R_0
-	VLR   H_1, R_1
-	VLR   H_2, R_2
-	VLR   H_3, R_3
-	VLR   H_4, R_4
-
-	// initialize h
-	VZERO H_0
-	VZERO H_1
-	VZERO H_2
-	VZERO H_3
-	VZERO H_4
-
-loop:
-	CMPBLE R3, $32, b2
-	VLM    (R2), T_0, T_1
-	SUB    $32, R3
-	MOVD   $32(R2), R2
-	EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4)
-	VLEIB  $4, $1, F_4
-	VLEIB  $12, $1, F_4
-
-multiply:
-	VAG    H_0, F_0, F_0
-	VAG    H_1, F_1, F_1
-	VAG    H_2, F_2, F_2
-	VAG    H_3, F_3, F_3
-	VAG    H_4, F_4, F_4
-	MULTIPLY(F_0, F_1, F_2, F_3, F_4, R_0, R_1, R_2, R_3, R_4, R5_1, R5_2, R5_3, R5_4, H_0, H_1, H_2, H_3, H_4)
-	REDUCE(H_0, H_1, H_2, H_3, H_4)
-	CMPBNE R3, $0, loop
-
-finish:
-	// sum vectors
-	VZERO  T_0
-	VSUMQG H_0, T_0, H_0
-	VSUMQG H_1, T_0, H_1
-	VSUMQG H_2, T_0, H_2
-	VSUMQG H_3, T_0, H_3
-	VSUMQG H_4, T_0, H_4
-
-	// h may be >= 2*(2**130-5) so we need to reduce it again
-	REDUCE(H_0, H_1, H_2, H_3, H_4)
-
-	// carry h1->h4
-	VESRLG $26, H_1, T_1
-	VN     MOD26, H_1, H_1
-	VAQ    T_1, H_2, H_2
-	VESRLG $26, H_2, T_2
-	VN     MOD26, H_2, H_2
-	VAQ    T_2, H_3, H_3
-	VESRLG $26, H_3, T_3
-	VN     MOD26, H_3, H_3
-	VAQ    T_3, H_4, H_4
-
-	// h is now < 2*(2**130-5)
-	// pack h into h1 (hi) and h0 (lo)
-	PACK(H_0, H_1, H_2, H_3, H_4)
-
-	// if h > 2**130-5 then h -= 2**130-5
-	MOD(H_0, H_1, T_0, T_1, T_2)
-
-	// h += s
-	MOVD  $·bswapMask<>(SB), R5
-	VL    (R5), T_1
-	VL    16(R4), T_0
-	VPERM T_0, T_0, T_1, T_0    // reverse bytes (to big)
-	VAQ   T_0, H_0, H_0
-	VPERM H_0, H_0, T_1, H_0    // reverse bytes (to little)
-	VST   H_0, (R1)
-
-	RET
-
-b2:
-	CMPBLE R3, $16, b1
-
-	// 2 blocks remaining
-	SUB    $17, R3
-	VL     (R2), T_0
-	VLL    R3, 16(R2), T_1
-	ADD    $1, R3
-	MOVBZ  $1, R0
-	CMPBEQ R3, $16, 2(PC)
-	VLVGB  R3, R0, T_1
-	EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4)
-	CMPBNE R3, $16, 2(PC)
-	VLEIB  $12, $1, F_4
-	VLEIB  $4, $1, F_4
-
-	// setup [r²,r]
-	VLVGG $1, RSAVE_0, R_0
-	VLVGG $1, RSAVE_1, R_1
-	VLVGG $1, RSAVE_2, R_2
-	VLVGG $1, RSAVE_3, R_3
-	VLVGG $1, RSAVE_4, R_4
-	VPDI  $0, R5_1, R5SAVE_1, R5_1
-	VPDI  $0, R5_2, R5SAVE_2, R5_2
-	VPDI  $0, R5_3, R5SAVE_3, R5_3
-	VPDI  $0, R5_4, R5SAVE_4, R5_4
-
-	MOVD $0, R3
-	BR   multiply
-
-skip:
-	VZERO H_0
-	VZERO H_1
-	VZERO H_2
-	VZERO H_3
-	VZERO H_4
-
-	CMPBEQ R3, $0, finish
-
-b1:
-	// 1 block remaining
-	SUB    $1, R3
-	VLL    R3, (R2), T_0
-	ADD    $1, R3
-	MOVBZ  $1, R0
-	CMPBEQ R3, $16, 2(PC)
-	VLVGB  R3, R0, T_0
-	VZERO  T_1
-	EXPAND(T_0, T_1, F_0, F_1, F_2, F_3, F_4)
-	CMPBNE R3, $16, 2(PC)
-	VLEIB  $4, $1, F_4
-	VLEIG  $1, $1, R_0
-	VZERO  R_1
-	VZERO  R_2
-	VZERO  R_3
-	VZERO  R_4
-	VZERO  R5_1
-	VZERO  R5_2
-	VZERO  R5_3
-	VZERO  R5_4
-
-	// setup [r, 1]
-	VLVGG $0, RSAVE_0, R_0
-	VLVGG $0, RSAVE_1, R_1
-	VLVGG $0, RSAVE_2, R_2
-	VLVGG $0, RSAVE_3, R_3
-	VLVGG $0, RSAVE_4, R_4
-	VPDI  $0, R5SAVE_1, R5_1, R5_1
-	VPDI  $0, R5SAVE_2, R5_2, R5_2
-	VPDI  $0, R5SAVE_3, R5_3, R5_3
-	VPDI  $0, R5SAVE_4, R5_4, R5_4
-
-	MOVD $0, R3
-	BR   multiply
-
-TEXT ·hasVectorFacility(SB), NOSPLIT, $24-1
-	MOVD  $x-24(SP), R1
-	XC    $24, 0(R1), 0(R1) // clear the storage
-	MOVD  $2, R0            // R0 is the number of double words stored -1
-	WORD  $0xB2B01000       // STFLE 0(R1)
-	XOR   R0, R0            // reset the value of R0
-	MOVBZ z-8(SP), R1
-	AND   $0x40, R1
-	BEQ   novector
-
-vectorinstalled:
-	// check if the vector instruction has been enabled
-	VLEIB  $0, $0xF, V16
-	VLGVB  $0, V16, R1
-	CMPBNE R1, $0xF, novector
-	MOVB   $1, ret+0(FP)      // have vx
-	RET
-
-novector:
-	MOVB $0, ret+0(FP) // no vx
-	RET
diff --git a/src/ssl/test/runner/poly1305/sum_vmsl_s390x.s b/src/ssl/test/runner/poly1305/sum_vmsl_s390x.s
deleted file mode 100644
index e548020..0000000
--- a/src/ssl/test/runner/poly1305/sum_vmsl_s390x.s
+++ /dev/null
@@ -1,931 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build s390x,go1.11,!gccgo,!appengine
-
-#include "textflag.h"
-
-// Implementation of Poly1305 using the vector facility (vx) and the VMSL instruction.
-
-// constants
-#define EX0   V1
-#define EX1   V2
-#define EX2   V3
-
-// temporaries
-#define T_0 V4
-#define T_1 V5
-#define T_2 V6
-#define T_3 V7
-#define T_4 V8
-#define T_5 V9
-#define T_6 V10
-#define T_7 V11
-#define T_8 V12
-#define T_9 V13
-#define T_10 V14
-
-// r**2 & r**4
-#define R_0  V15
-#define R_1  V16
-#define R_2  V17
-#define R5_1 V18
-#define R5_2 V19
-// key (r)
-#define RSAVE_0 R7
-#define RSAVE_1 R8
-#define RSAVE_2 R9
-#define R5SAVE_1 R10
-#define R5SAVE_2 R11
-
-// message block
-#define M0 V20
-#define M1 V21
-#define M2 V22
-#define M3 V23
-#define M4 V24
-#define M5 V25
-
-// accumulator
-#define H0_0 V26
-#define H1_0 V27
-#define H2_0 V28
-#define H0_1 V29
-#define H1_1 V30
-#define H2_1 V31
-
-GLOBL ·keyMask<>(SB), RODATA, $16
-DATA ·keyMask<>+0(SB)/8, $0xffffff0ffcffff0f
-DATA ·keyMask<>+8(SB)/8, $0xfcffff0ffcffff0f
-
-GLOBL ·bswapMask<>(SB), RODATA, $16
-DATA ·bswapMask<>+0(SB)/8, $0x0f0e0d0c0b0a0908
-DATA ·bswapMask<>+8(SB)/8, $0x0706050403020100
-
-GLOBL ·constants<>(SB), RODATA, $48
-// EX0
-DATA ·constants<>+0(SB)/8, $0x18191a1b1c1d1e1f
-DATA ·constants<>+8(SB)/8, $0x0000050403020100
-// EX1
-DATA ·constants<>+16(SB)/8, $0x18191a1b1c1d1e1f
-DATA ·constants<>+24(SB)/8, $0x00000a0908070605
-// EX2
-DATA ·constants<>+32(SB)/8, $0x18191a1b1c1d1e1f
-DATA ·constants<>+40(SB)/8, $0x0000000f0e0d0c0b
-
-GLOBL ·c<>(SB), RODATA, $48
-// EX0
-DATA ·c<>+0(SB)/8, $0x0000050403020100
-DATA ·c<>+8(SB)/8, $0x0000151413121110
-// EX1
-DATA ·c<>+16(SB)/8, $0x00000a0908070605
-DATA ·c<>+24(SB)/8, $0x00001a1918171615
-// EX2
-DATA ·c<>+32(SB)/8, $0x0000000f0e0d0c0b
-DATA ·c<>+40(SB)/8, $0x0000001f1e1d1c1b
-
-GLOBL ·reduce<>(SB), RODATA, $32
-// 44 bit
-DATA ·reduce<>+0(SB)/8, $0x0
-DATA ·reduce<>+8(SB)/8, $0xfffffffffff
-// 42 bit
-DATA ·reduce<>+16(SB)/8, $0x0
-DATA ·reduce<>+24(SB)/8, $0x3ffffffffff
-
-// h = (f*g) % (2**130-5) [partial reduction]
-// uses T_0...T_9 temporary registers
-// input: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2
-// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9
-// output: m02_0, m02_1, m02_2, m13_0, m13_1, m13_2
-#define MULTIPLY(m02_0, m02_1, m02_2, m13_0, m13_1, m13_2, r_0, r_1, r_2, r5_1, r5_2, m4_0, m4_1, m4_2, m5_0, m5_1, m5_2, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) \
-	\ // Eliminate the dependency for the last 2 VMSLs
-	VMSLG m02_0, r_2, m4_2, m4_2                       \
-	VMSLG m13_0, r_2, m5_2, m5_2                       \ // 8 VMSLs pipelined
-	VMSLG m02_0, r_0, m4_0, m4_0                       \
-	VMSLG m02_1, r5_2, V0, T_0                         \
-	VMSLG m02_0, r_1, m4_1, m4_1                       \
-	VMSLG m02_1, r_0, V0, T_1                          \
-	VMSLG m02_1, r_1, V0, T_2                          \
-	VMSLG m02_2, r5_1, V0, T_3                         \
-	VMSLG m02_2, r5_2, V0, T_4                         \
-	VMSLG m13_0, r_0, m5_0, m5_0                       \
-	VMSLG m13_1, r5_2, V0, T_5                         \
-	VMSLG m13_0, r_1, m5_1, m5_1                       \
-	VMSLG m13_1, r_0, V0, T_6                          \
-	VMSLG m13_1, r_1, V0, T_7                          \
-	VMSLG m13_2, r5_1, V0, T_8                         \
-	VMSLG m13_2, r5_2, V0, T_9                         \
-	VMSLG m02_2, r_0, m4_2, m4_2                       \
-	VMSLG m13_2, r_0, m5_2, m5_2                       \
-	VAQ   m4_0, T_0, m02_0                             \
-	VAQ   m4_1, T_1, m02_1                             \
-	VAQ   m5_0, T_5, m13_0                             \
-	VAQ   m5_1, T_6, m13_1                             \
-	VAQ   m02_0, T_3, m02_0                            \
-	VAQ   m02_1, T_4, m02_1                            \
-	VAQ   m13_0, T_8, m13_0                            \
-	VAQ   m13_1, T_9, m13_1                            \
-	VAQ   m4_2, T_2, m02_2                             \
-	VAQ   m5_2, T_7, m13_2                             \
-
-// SQUARE uses three limbs of r and r_2*5 to output square of r
-// uses T_1, T_5 and T_7 temporary registers
-// input: r_0, r_1, r_2, r5_2
-// temp: TEMP0, TEMP1, TEMP2
-// output: p0, p1, p2
-#define SQUARE(r_0, r_1, r_2, r5_2, p0, p1, p2, TEMP0, TEMP1, TEMP2) \
-	VMSLG r_0, r_0, p0, p0     \
-	VMSLG r_1, r5_2, V0, TEMP0 \
-	VMSLG r_2, r5_2, p1, p1    \
-	VMSLG r_0, r_1, V0, TEMP1  \
-	VMSLG r_1, r_1, p2, p2     \
-	VMSLG r_0, r_2, V0, TEMP2  \
-	VAQ   TEMP0, p0, p0        \
-	VAQ   TEMP1, p1, p1        \
-	VAQ   TEMP2, p2, p2        \
-	VAQ   TEMP0, p0, p0        \
-	VAQ   TEMP1, p1, p1        \
-	VAQ   TEMP2, p2, p2        \
-
-// carry h0->h1->h2->h0 || h3->h4->h5->h3
-// uses T_2, T_4, T_5, T_7, T_8, T_9
-//       t6,  t7,  t8,  t9, t10, t11
-// input: h0, h1, h2, h3, h4, h5
-// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11
-// output: h0, h1, h2, h3, h4, h5
-#define REDUCE(h0, h1, h2, h3, h4, h5, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) \
-	VLM    (R12), t6, t7  \ // 44 and 42 bit clear mask
-	VLEIB  $7, $0x28, t10 \ // 5 byte shift mask
-	VREPIB $4, t8         \ // 4 bit shift mask
-	VREPIB $2, t11        \ // 2 bit shift mask
-	VSRLB  t10, h0, t0    \ // h0 byte shift
-	VSRLB  t10, h1, t1    \ // h1 byte shift
-	VSRLB  t10, h2, t2    \ // h2 byte shift
-	VSRLB  t10, h3, t3    \ // h3 byte shift
-	VSRLB  t10, h4, t4    \ // h4 byte shift
-	VSRLB  t10, h5, t5    \ // h5 byte shift
-	VSRL   t8, t0, t0     \ // h0 bit shift
-	VSRL   t8, t1, t1     \ // h2 bit shift
-	VSRL   t11, t2, t2    \ // h2 bit shift
-	VSRL   t8, t3, t3     \ // h3 bit shift
-	VSRL   t8, t4, t4     \ // h4 bit shift
-	VESLG  $2, t2, t9     \ // h2 carry x5
-	VSRL   t11, t5, t5    \ // h5 bit shift
-	VN     t6, h0, h0     \ // h0 clear carry
-	VAQ    t2, t9, t2     \ // h2 carry x5
-	VESLG  $2, t5, t9     \ // h5 carry x5
-	VN     t6, h1, h1     \ // h1 clear carry
-	VN     t7, h2, h2     \ // h2 clear carry
-	VAQ    t5, t9, t5     \ // h5 carry x5
-	VN     t6, h3, h3     \ // h3 clear carry
-	VN     t6, h4, h4     \ // h4 clear carry
-	VN     t7, h5, h5     \ // h5 clear carry
-	VAQ    t0, h1, h1     \ // h0->h1
-	VAQ    t3, h4, h4     \ // h3->h4
-	VAQ    t1, h2, h2     \ // h1->h2
-	VAQ    t4, h5, h5     \ // h4->h5
-	VAQ    t2, h0, h0     \ // h2->h0
-	VAQ    t5, h3, h3     \ // h5->h3
-	VREPG  $1, t6, t6     \ // 44 and 42 bit masks across both halves
-	VREPG  $1, t7, t7     \
-	VSLDB  $8, h0, h0, h0 \ // set up [h0/1/2, h3/4/5]
-	VSLDB  $8, h1, h1, h1 \
-	VSLDB  $8, h2, h2, h2 \
-	VO     h0, h3, h3     \
-	VO     h1, h4, h4     \
-	VO     h2, h5, h5     \
-	VESRLG $44, h3, t0    \ // 44 bit shift right
-	VESRLG $44, h4, t1    \
-	VESRLG $42, h5, t2    \
-	VN     t6, h3, h3     \ // clear carry bits
-	VN     t6, h4, h4     \
-	VN     t7, h5, h5     \
-	VESLG  $2, t2, t9     \ // multiply carry by 5
-	VAQ    t9, t2, t2     \
-	VAQ    t0, h4, h4     \
-	VAQ    t1, h5, h5     \
-	VAQ    t2, h3, h3     \
-
-// carry h0->h1->h2->h0
-// input: h0, h1, h2
-// temp: t0, t1, t2, t3, t4, t5, t6, t7, t8
-// output: h0, h1, h2
-#define REDUCE2(h0, h1, h2, t0, t1, t2, t3, t4, t5, t6, t7, t8) \
-	VLEIB  $7, $0x28, t3 \ // 5 byte shift mask
-	VREPIB $4, t4        \ // 4 bit shift mask
-	VREPIB $2, t7        \ // 2 bit shift mask
-	VGBM   $0x003F, t5   \ // mask to clear carry bits
-	VSRLB  t3, h0, t0    \
-	VSRLB  t3, h1, t1    \
-	VSRLB  t3, h2, t2    \
-	VESRLG $4, t5, t5    \ // 44 bit clear mask
-	VSRL   t4, t0, t0    \
-	VSRL   t4, t1, t1    \
-	VSRL   t7, t2, t2    \
-	VESRLG $2, t5, t6    \ // 42 bit clear mask
-	VESLG  $2, t2, t8    \
-	VAQ    t8, t2, t2    \
-	VN     t5, h0, h0    \
-	VN     t5, h1, h1    \
-	VN     t6, h2, h2    \
-	VAQ    t0, h1, h1    \
-	VAQ    t1, h2, h2    \
-	VAQ    t2, h0, h0    \
-	VSRLB  t3, h0, t0    \
-	VSRLB  t3, h1, t1    \
-	VSRLB  t3, h2, t2    \
-	VSRL   t4, t0, t0    \
-	VSRL   t4, t1, t1    \
-	VSRL   t7, t2, t2    \
-	VN     t5, h0, h0    \
-	VN     t5, h1, h1    \
-	VESLG  $2, t2, t8    \
-	VN     t6, h2, h2    \
-	VAQ    t0, h1, h1    \
-	VAQ    t8, t2, t2    \
-	VAQ    t1, h2, h2    \
-	VAQ    t2, h0, h0    \
-
-// expands two message blocks into the lower halfs of the d registers
-// moves the contents of the d registers into upper halfs
-// input: in1, in2, d0, d1, d2, d3, d4, d5
-// temp: TEMP0, TEMP1, TEMP2, TEMP3
-// output: d0, d1, d2, d3, d4, d5
-#define EXPACC(in1, in2, d0, d1, d2, d3, d4, d5, TEMP0, TEMP1, TEMP2, TEMP3) \
-	VGBM   $0xff3f, TEMP0      \
-	VGBM   $0xff1f, TEMP1      \
-	VESLG  $4, d1, TEMP2       \
-	VESLG  $4, d4, TEMP3       \
-	VESRLG $4, TEMP0, TEMP0    \
-	VPERM  in1, d0, EX0, d0    \
-	VPERM  in2, d3, EX0, d3    \
-	VPERM  in1, d2, EX2, d2    \
-	VPERM  in2, d5, EX2, d5    \
-	VPERM  in1, TEMP2, EX1, d1 \
-	VPERM  in2, TEMP3, EX1, d4 \
-	VN     TEMP0, d0, d0       \
-	VN     TEMP0, d3, d3       \
-	VESRLG $4, d1, d1          \
-	VESRLG $4, d4, d4          \
-	VN     TEMP1, d2, d2       \
-	VN     TEMP1, d5, d5       \
-	VN     TEMP0, d1, d1       \
-	VN     TEMP0, d4, d4       \
-
-// expands one message block into the lower halfs of the d registers
-// moves the contents of the d registers into upper halfs
-// input: in, d0, d1, d2
-// temp: TEMP0, TEMP1, TEMP2
-// output: d0, d1, d2
-#define EXPACC2(in, d0, d1, d2, TEMP0, TEMP1, TEMP2) \
-	VGBM   $0xff3f, TEMP0     \
-	VESLG  $4, d1, TEMP2      \
-	VGBM   $0xff1f, TEMP1     \
-	VPERM  in, d0, EX0, d0    \
-	VESRLG $4, TEMP0, TEMP0   \
-	VPERM  in, d2, EX2, d2    \
-	VPERM  in, TEMP2, EX1, d1 \
-	VN     TEMP0, d0, d0      \
-	VN     TEMP1, d2, d2      \
-	VESRLG $4, d1, d1         \
-	VN     TEMP0, d1, d1      \
-
-// pack h2:h0 into h1:h0 (no carry)
-// input: h0, h1, h2
-// output: h0, h1, h2
-#define PACK(h0, h1, h2) \
-	VMRLG  h1, h2, h2  \ // copy h1 to upper half h2
-	VESLG  $44, h1, h1 \ // shift limb 1 44 bits, leaving 20
-	VO     h0, h1, h0  \ // combine h0 with 20 bits from limb 1
-	VESRLG $20, h2, h1 \ // put top 24 bits of limb 1 into h1
-	VLEIG  $1, $0, h1  \ // clear h2 stuff from lower half of h1
-	VO     h0, h1, h0  \ // h0 now has 88 bits (limb 0 and 1)
-	VLEIG  $0, $0, h2  \ // clear upper half of h2
-	VESRLG $40, h2, h1 \ // h1 now has upper two bits of result
-	VLEIB  $7, $88, h1 \ // for byte shift (11 bytes)
-	VSLB   h1, h2, h2  \ // shift h2 11 bytes to the left
-	VO     h0, h2, h0  \ // combine h0 with 20 bits from limb 1
-	VLEIG  $0, $0, h1  \ // clear upper half of h1
-
-// if h > 2**130-5 then h -= 2**130-5
-// input: h0, h1
-// temp: t0, t1, t2
-// output: h0
-#define MOD(h0, h1, t0, t1, t2) \
-	VZERO t0          \
-	VLEIG $1, $5, t0  \
-	VACCQ h0, t0, t1  \
-	VAQ   h0, t0, t0  \
-	VONE  t2          \
-	VLEIG $1, $-4, t2 \
-	VAQ   t2, t1, t1  \
-	VACCQ h1, t1, t1  \
-	VONE  t2          \
-	VAQ   t2, t1, t1  \
-	VN    h0, t1, t2  \
-	VNC   t0, t1, t1  \
-	VO    t1, t2, h0  \
-
-// func poly1305vmsl(out *[16]byte, m *byte, mlen uint64, key *[32]key)
-TEXT ·poly1305vmsl(SB), $0-32
-	// This code processes 6 + up to 4 blocks (32 bytes) per iteration
-	// using the algorithm described in:
-	// NEON crypto, Daniel J. Bernstein & Peter Schwabe
-	// https://cryptojedi.org/papers/neoncrypto-20120320.pdf
-	// And as moddified for VMSL as described in
-	// Accelerating Poly1305 Cryptographic Message Authentication on the z14
-	// O'Farrell et al, CASCON 2017, p48-55
-	// https://ibm.ent.box.com/s/jf9gedj0e9d2vjctfyh186shaztavnht
-
-	LMG   out+0(FP), R1, R4 // R1=out, R2=m, R3=mlen, R4=key
-	VZERO V0                // c
-
-	// load EX0, EX1 and EX2
-	MOVD $·constants<>(SB), R5
-	VLM  (R5), EX0, EX2        // c
-
-	// setup r
-	VL    (R4), T_0
-	MOVD  $·keyMask<>(SB), R6
-	VL    (R6), T_1
-	VN    T_0, T_1, T_0
-	VZERO T_2                 // limbs for r
-	VZERO T_3
-	VZERO T_4
-	EXPACC2(T_0, T_2, T_3, T_4, T_1, T_5, T_7)
-
-	// T_2, T_3, T_4: [0, r]
-
-	// setup r*20
-	VLEIG $0, $0, T_0
-	VLEIG $1, $20, T_0       // T_0: [0, 20]
-	VZERO T_5
-	VZERO T_6
-	VMSLG T_0, T_3, T_5, T_5
-	VMSLG T_0, T_4, T_6, T_6
-
-	// store r for final block in GR
-	VLGVG $1, T_2, RSAVE_0  // c
-	VLGVG $1, T_3, RSAVE_1  // c
-	VLGVG $1, T_4, RSAVE_2  // c
-	VLGVG $1, T_5, R5SAVE_1 // c
-	VLGVG $1, T_6, R5SAVE_2 // c
-
-	// initialize h
-	VZERO H0_0
-	VZERO H1_0
-	VZERO H2_0
-	VZERO H0_1
-	VZERO H1_1
-	VZERO H2_1
-
-	// initialize pointer for reduce constants
-	MOVD $·reduce<>(SB), R12
-
-	// calculate r**2 and 20*(r**2)
-	VZERO R_0
-	VZERO R_1
-	VZERO R_2
-	SQUARE(T_2, T_3, T_4, T_6, R_0, R_1, R_2, T_1, T_5, T_7)
-	REDUCE2(R_0, R_1, R_2, M0, M1, M2, M3, M4, R5_1, R5_2, M5, T_1)
-	VZERO R5_1
-	VZERO R5_2
-	VMSLG T_0, R_1, R5_1, R5_1
-	VMSLG T_0, R_2, R5_2, R5_2
-
-	// skip r**4 calculation if 3 blocks or less
-	CMPBLE R3, $48, b4
-
-	// calculate r**4 and 20*(r**4)
-	VZERO T_8
-	VZERO T_9
-	VZERO T_10
-	SQUARE(R_0, R_1, R_2, R5_2, T_8, T_9, T_10, T_1, T_5, T_7)
-	REDUCE2(T_8, T_9, T_10, M0, M1, M2, M3, M4, T_2, T_3, M5, T_1)
-	VZERO T_2
-	VZERO T_3
-	VMSLG T_0, T_9, T_2, T_2
-	VMSLG T_0, T_10, T_3, T_3
-
-	// put r**2 to the right and r**4 to the left of R_0, R_1, R_2
-	VSLDB $8, T_8, T_8, T_8
-	VSLDB $8, T_9, T_9, T_9
-	VSLDB $8, T_10, T_10, T_10
-	VSLDB $8, T_2, T_2, T_2
-	VSLDB $8, T_3, T_3, T_3
-
-	VO T_8, R_0, R_0
-	VO T_9, R_1, R_1
-	VO T_10, R_2, R_2
-	VO T_2, R5_1, R5_1
-	VO T_3, R5_2, R5_2
-
-	CMPBLE R3, $80, load // less than or equal to 5 blocks in message
-
-	// 6(or 5+1) blocks
-	SUB    $81, R3
-	VLM    (R2), M0, M4
-	VLL    R3, 80(R2), M5
-	ADD    $1, R3
-	MOVBZ  $1, R0
-	CMPBGE R3, $16, 2(PC)
-	VLVGB  R3, R0, M5
-	MOVD   $96(R2), R2
-	EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
-	EXPACC(M2, M3, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
-	VLEIB  $2, $1, H2_0
-	VLEIB  $2, $1, H2_1
-	VLEIB  $10, $1, H2_0
-	VLEIB  $10, $1, H2_1
-
-	VZERO  M0
-	VZERO  M1
-	VZERO  M2
-	VZERO  M3
-	VZERO  T_4
-	VZERO  T_10
-	EXPACC(M4, M5, M0, M1, M2, M3, T_4, T_10, T_0, T_1, T_2, T_3)
-	VLR    T_4, M4
-	VLEIB  $10, $1, M2
-	CMPBLT R3, $16, 2(PC)
-	VLEIB  $10, $1, T_10
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9)
-	VMRHG  V0, H0_1, H0_0
-	VMRHG  V0, H1_1, H1_0
-	VMRHG  V0, H2_1, H2_0
-	VMRLG  V0, H0_1, H0_1
-	VMRLG  V0, H1_1, H1_1
-	VMRLG  V0, H2_1, H2_1
-
-	SUB    $16, R3
-	CMPBLE R3, $0, square
-
-load:
-	// load EX0, EX1 and EX2
-	MOVD $·c<>(SB), R5
-	VLM  (R5), EX0, EX2
-
-loop:
-	CMPBLE R3, $64, add // b4	// last 4 or less blocks left
-
-	// next 4 full blocks
-	VLM  (R2), M2, M5
-	SUB  $64, R3
-	MOVD $64(R2), R2
-	REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, T_0, T_1, T_3, T_4, T_5, T_2, T_7, T_8, T_9)
-
-	// expacc in-lined to create [m2, m3] limbs
-	VGBM   $0x3f3f, T_0     // 44 bit clear mask
-	VGBM   $0x1f1f, T_1     // 40 bit clear mask
-	VPERM  M2, M3, EX0, T_3
-	VESRLG $4, T_0, T_0     // 44 bit clear mask ready
-	VPERM  M2, M3, EX1, T_4
-	VPERM  M2, M3, EX2, T_5
-	VN     T_0, T_3, T_3
-	VESRLG $4, T_4, T_4
-	VN     T_1, T_5, T_5
-	VN     T_0, T_4, T_4
-	VMRHG  H0_1, T_3, H0_0
-	VMRHG  H1_1, T_4, H1_0
-	VMRHG  H2_1, T_5, H2_0
-	VMRLG  H0_1, T_3, H0_1
-	VMRLG  H1_1, T_4, H1_1
-	VMRLG  H2_1, T_5, H2_1
-	VLEIB  $10, $1, H2_0
-	VLEIB  $10, $1, H2_1
-	VPERM  M4, M5, EX0, T_3
-	VPERM  M4, M5, EX1, T_4
-	VPERM  M4, M5, EX2, T_5
-	VN     T_0, T_3, T_3
-	VESRLG $4, T_4, T_4
-	VN     T_1, T_5, T_5
-	VN     T_0, T_4, T_4
-	VMRHG  V0, T_3, M0
-	VMRHG  V0, T_4, M1
-	VMRHG  V0, T_5, M2
-	VMRLG  V0, T_3, M3
-	VMRLG  V0, T_4, M4
-	VMRLG  V0, T_5, M5
-	VLEIB  $10, $1, M2
-	VLEIB  $10, $1, M5
-
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	CMPBNE R3, $0, loop
-	REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
-	VMRHG  V0, H0_1, H0_0
-	VMRHG  V0, H1_1, H1_0
-	VMRHG  V0, H2_1, H2_0
-	VMRLG  V0, H0_1, H0_1
-	VMRLG  V0, H1_1, H1_1
-	VMRLG  V0, H2_1, H2_1
-
-	// load EX0, EX1, EX2
-	MOVD $·constants<>(SB), R5
-	VLM  (R5), EX0, EX2
-
-	// sum vectors
-	VAQ H0_0, H0_1, H0_0
-	VAQ H1_0, H1_1, H1_0
-	VAQ H2_0, H2_1, H2_0
-
-	// h may be >= 2*(2**130-5) so we need to reduce it again
-	// M0...M4 are used as temps here
-	REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
-
-next:  // carry h1->h2
-	VLEIB  $7, $0x28, T_1
-	VREPIB $4, T_2
-	VGBM   $0x003F, T_3
-	VESRLG $4, T_3
-
-	// byte shift
-	VSRLB T_1, H1_0, T_4
-
-	// bit shift
-	VSRL T_2, T_4, T_4
-
-	// clear h1 carry bits
-	VN T_3, H1_0, H1_0
-
-	// add carry
-	VAQ T_4, H2_0, H2_0
-
-	// h is now < 2*(2**130-5)
-	// pack h into h1 (hi) and h0 (lo)
-	PACK(H0_0, H1_0, H2_0)
-
-	// if h > 2**130-5 then h -= 2**130-5
-	MOD(H0_0, H1_0, T_0, T_1, T_2)
-
-	// h += s
-	MOVD  $·bswapMask<>(SB), R5
-	VL    (R5), T_1
-	VL    16(R4), T_0
-	VPERM T_0, T_0, T_1, T_0    // reverse bytes (to big)
-	VAQ   T_0, H0_0, H0_0
-	VPERM H0_0, H0_0, T_1, H0_0 // reverse bytes (to little)
-	VST   H0_0, (R1)
-	RET
-
-add:
-	// load EX0, EX1, EX2
-	MOVD $·constants<>(SB), R5
-	VLM  (R5), EX0, EX2
-
-	REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
-	VMRHG  V0, H0_1, H0_0
-	VMRHG  V0, H1_1, H1_0
-	VMRHG  V0, H2_1, H2_0
-	VMRLG  V0, H0_1, H0_1
-	VMRLG  V0, H1_1, H1_1
-	VMRLG  V0, H2_1, H2_1
-	CMPBLE R3, $64, b4
-
-b4:
-	CMPBLE R3, $48, b3 // 3 blocks or less
-
-	// 4(3+1) blocks remaining
-	SUB    $49, R3
-	VLM    (R2), M0, M2
-	VLL    R3, 48(R2), M3
-	ADD    $1, R3
-	MOVBZ  $1, R0
-	CMPBEQ R3, $16, 2(PC)
-	VLVGB  R3, R0, M3
-	MOVD   $64(R2), R2
-	EXPACC(M0, M1, H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_0, T_1, T_2, T_3)
-	VLEIB  $10, $1, H2_0
-	VLEIB  $10, $1, H2_1
-	VZERO  M0
-	VZERO  M1
-	VZERO  M4
-	VZERO  M5
-	VZERO  T_4
-	VZERO  T_10
-	EXPACC(M2, M3, M0, M1, M4, M5, T_4, T_10, T_0, T_1, T_2, T_3)
-	VLR    T_4, M2
-	VLEIB  $10, $1, M4
-	CMPBNE R3, $16, 2(PC)
-	VLEIB  $10, $1, T_10
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M4, M5, M2, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M3, M4, M5, T_4, T_5, T_2, T_7, T_8, T_9)
-	VMRHG  V0, H0_1, H0_0
-	VMRHG  V0, H1_1, H1_0
-	VMRHG  V0, H2_1, H2_0
-	VMRLG  V0, H0_1, H0_1
-	VMRLG  V0, H1_1, H1_1
-	VMRLG  V0, H2_1, H2_1
-	SUB    $16, R3
-	CMPBLE R3, $0, square // this condition must always hold true!
-
-b3:
-	CMPBLE R3, $32, b2
-
-	// 3 blocks remaining
-
-	// setup [r²,r]
-	VSLDB $8, R_0, R_0, R_0
-	VSLDB $8, R_1, R_1, R_1
-	VSLDB $8, R_2, R_2, R_2
-	VSLDB $8, R5_1, R5_1, R5_1
-	VSLDB $8, R5_2, R5_2, R5_2
-
-	VLVGG $1, RSAVE_0, R_0
-	VLVGG $1, RSAVE_1, R_1
-	VLVGG $1, RSAVE_2, R_2
-	VLVGG $1, R5SAVE_1, R5_1
-	VLVGG $1, R5SAVE_2, R5_2
-
-	// setup [h0, h1]
-	VSLDB $8, H0_0, H0_0, H0_0
-	VSLDB $8, H1_0, H1_0, H1_0
-	VSLDB $8, H2_0, H2_0, H2_0
-	VO    H0_1, H0_0, H0_0
-	VO    H1_1, H1_0, H1_0
-	VO    H2_1, H2_0, H2_0
-	VZERO H0_1
-	VZERO H1_1
-	VZERO H2_1
-
-	VZERO M0
-	VZERO M1
-	VZERO M2
-	VZERO M3
-	VZERO M4
-	VZERO M5
-
-	// H*[r**2, r]
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, T_10, M5)
-
-	SUB    $33, R3
-	VLM    (R2), M0, M1
-	VLL    R3, 32(R2), M2
-	ADD    $1, R3
-	MOVBZ  $1, R0
-	CMPBEQ R3, $16, 2(PC)
-	VLVGB  R3, R0, M2
-
-	// H += m0
-	VZERO T_1
-	VZERO T_2
-	VZERO T_3
-	EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)
-	VLEIB $10, $1, T_3
-	VAG   H0_0, T_1, H0_0
-	VAG   H1_0, T_2, H1_0
-	VAG   H2_0, T_3, H2_0
-
-	VZERO M0
-	VZERO M3
-	VZERO M4
-	VZERO M5
-	VZERO T_10
-
-	// (H+m0)*r
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M3, M4, M5, V0, T_10, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_10, H0_1, H1_1, H2_1, T_9)
-
-	// H += m1
-	VZERO V0
-	VZERO T_1
-	VZERO T_2
-	VZERO T_3
-	EXPACC2(M1, T_1, T_2, T_3, T_4, T_5, T_6)
-	VLEIB $10, $1, T_3
-	VAQ   H0_0, T_1, H0_0
-	VAQ   H1_0, T_2, H1_0
-	VAQ   H2_0, T_3, H2_0
-	REDUCE2(H0_0, H1_0, H2_0, M0, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10)
-
-	// [H, m2] * [r**2, r]
-	EXPACC2(M2, H0_0, H1_0, H2_0, T_1, T_2, T_3)
-	CMPBNE R3, $16, 2(PC)
-	VLEIB  $10, $1, H2_0
-	VZERO  M0
-	VZERO  M1
-	VZERO  M2
-	VZERO  M3
-	VZERO  M4
-	VZERO  M5
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, H0_1, H1_1, M5, T_10)
-	SUB    $16, R3
-	CMPBLE R3, $0, next   // this condition must always hold true!
-
-b2:
-	CMPBLE R3, $16, b1
-
-	// 2 blocks remaining
-
-	// setup [r²,r]
-	VSLDB $8, R_0, R_0, R_0
-	VSLDB $8, R_1, R_1, R_1
-	VSLDB $8, R_2, R_2, R_2
-	VSLDB $8, R5_1, R5_1, R5_1
-	VSLDB $8, R5_2, R5_2, R5_2
-
-	VLVGG $1, RSAVE_0, R_0
-	VLVGG $1, RSAVE_1, R_1
-	VLVGG $1, RSAVE_2, R_2
-	VLVGG $1, R5SAVE_1, R5_1
-	VLVGG $1, R5SAVE_2, R5_2
-
-	// setup [h0, h1]
-	VSLDB $8, H0_0, H0_0, H0_0
-	VSLDB $8, H1_0, H1_0, H1_0
-	VSLDB $8, H2_0, H2_0, H2_0
-	VO    H0_1, H0_0, H0_0
-	VO    H1_1, H1_0, H1_0
-	VO    H2_1, H2_0, H2_0
-	VZERO H0_1
-	VZERO H1_1
-	VZERO H2_1
-
-	VZERO M0
-	VZERO M1
-	VZERO M2
-	VZERO M3
-	VZERO M4
-	VZERO M5
-
-	// H*[r**2, r]
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	REDUCE(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, T_10, M0, M1, M2, M3, M4, T_4, T_5, T_2, T_7, T_8, T_9)
-	VMRHG V0, H0_1, H0_0
-	VMRHG V0, H1_1, H1_0
-	VMRHG V0, H2_1, H2_0
-	VMRLG V0, H0_1, H0_1
-	VMRLG V0, H1_1, H1_1
-	VMRLG V0, H2_1, H2_1
-
-	// move h to the left and 0s at the right
-	VSLDB $8, H0_0, H0_0, H0_0
-	VSLDB $8, H1_0, H1_0, H1_0
-	VSLDB $8, H2_0, H2_0, H2_0
-
-	// get message blocks and append 1 to start
-	SUB    $17, R3
-	VL     (R2), M0
-	VLL    R3, 16(R2), M1
-	ADD    $1, R3
-	MOVBZ  $1, R0
-	CMPBEQ R3, $16, 2(PC)
-	VLVGB  R3, R0, M1
-	VZERO  T_6
-	VZERO  T_7
-	VZERO  T_8
-	EXPACC2(M0, T_6, T_7, T_8, T_1, T_2, T_3)
-	EXPACC2(M1, T_6, T_7, T_8, T_1, T_2, T_3)
-	VLEIB  $2, $1, T_8
-	CMPBNE R3, $16, 2(PC)
-	VLEIB  $10, $1, T_8
-
-	// add [m0, m1] to h
-	VAG H0_0, T_6, H0_0
-	VAG H1_0, T_7, H1_0
-	VAG H2_0, T_8, H2_0
-
-	VZERO M2
-	VZERO M3
-	VZERO M4
-	VZERO M5
-	VZERO T_10
-	VZERO M0
-
-	// at this point R_0 .. R5_2 look like [r**2, r]
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M2, M3, M4, M5, T_10, M0, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	REDUCE2(H0_0, H1_0, H2_0, M2, M3, M4, M5, T_9, H0_1, H1_1, H2_1, T_10)
-	SUB    $16, R3, R3
-	CMPBLE R3, $0, next
-
-b1:
-	CMPBLE R3, $0, next
-
-	// 1 block remaining
-
-	// setup [r²,r]
-	VSLDB $8, R_0, R_0, R_0
-	VSLDB $8, R_1, R_1, R_1
-	VSLDB $8, R_2, R_2, R_2
-	VSLDB $8, R5_1, R5_1, R5_1
-	VSLDB $8, R5_2, R5_2, R5_2
-
-	VLVGG $1, RSAVE_0, R_0
-	VLVGG $1, RSAVE_1, R_1
-	VLVGG $1, RSAVE_2, R_2
-	VLVGG $1, R5SAVE_1, R5_1
-	VLVGG $1, R5SAVE_2, R5_2
-
-	// setup [h0, h1]
-	VSLDB $8, H0_0, H0_0, H0_0
-	VSLDB $8, H1_0, H1_0, H1_0
-	VSLDB $8, H2_0, H2_0, H2_0
-	VO    H0_1, H0_0, H0_0
-	VO    H1_1, H1_0, H1_0
-	VO    H2_1, H2_0, H2_0
-	VZERO H0_1
-	VZERO H1_1
-	VZERO H2_1
-
-	VZERO M0
-	VZERO M1
-	VZERO M2
-	VZERO M3
-	VZERO M4
-	VZERO M5
-
-	// H*[r**2, r]
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
-
-	// set up [0, m0] limbs
-	SUB    $1, R3
-	VLL    R3, (R2), M0
-	ADD    $1, R3
-	MOVBZ  $1, R0
-	CMPBEQ R3, $16, 2(PC)
-	VLVGB  R3, R0, M0
-	VZERO  T_1
-	VZERO  T_2
-	VZERO  T_3
-	EXPACC2(M0, T_1, T_2, T_3, T_4, T_5, T_6)// limbs: [0, m]
-	CMPBNE R3, $16, 2(PC)
-	VLEIB  $10, $1, T_3
-
-	// h+m0
-	VAQ H0_0, T_1, H0_0
-	VAQ H1_0, T_2, H1_0
-	VAQ H2_0, T_3, H2_0
-
-	VZERO M0
-	VZERO M1
-	VZERO M2
-	VZERO M3
-	VZERO M4
-	VZERO M5
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
-
-	BR next
-
-square:
-	// setup [r²,r]
-	VSLDB $8, R_0, R_0, R_0
-	VSLDB $8, R_1, R_1, R_1
-	VSLDB $8, R_2, R_2, R_2
-	VSLDB $8, R5_1, R5_1, R5_1
-	VSLDB $8, R5_2, R5_2, R5_2
-
-	VLVGG $1, RSAVE_0, R_0
-	VLVGG $1, RSAVE_1, R_1
-	VLVGG $1, RSAVE_2, R_2
-	VLVGG $1, R5SAVE_1, R5_1
-	VLVGG $1, R5SAVE_2, R5_2
-
-	// setup [h0, h1]
-	VSLDB $8, H0_0, H0_0, H0_0
-	VSLDB $8, H1_0, H1_0, H1_0
-	VSLDB $8, H2_0, H2_0, H2_0
-	VO    H0_1, H0_0, H0_0
-	VO    H1_1, H1_0, H1_0
-	VO    H2_1, H2_0, H2_0
-	VZERO H0_1
-	VZERO H1_1
-	VZERO H2_1
-
-	VZERO M0
-	VZERO M1
-	VZERO M2
-	VZERO M3
-	VZERO M4
-	VZERO M5
-
-	// (h0*r**2) + (h1*r)
-	MULTIPLY(H0_0, H1_0, H2_0, H0_1, H1_1, H2_1, R_0, R_1, R_2, R5_1, R5_2, M0, M1, M2, M3, M4, M5, T_0, T_1, T_2, T_3, T_4, T_5, T_6, T_7, T_8, T_9)
-	REDUCE2(H0_0, H1_0, H2_0, M0, M1, M2, M3, M4, T_9, T_10, H0_1, M5)
-	BR next
-
-TEXT ·hasVMSLFacility(SB), NOSPLIT, $24-1
-	MOVD  $x-24(SP), R1
-	XC    $24, 0(R1), 0(R1) // clear the storage
-	MOVD  $2, R0            // R0 is the number of double words stored -1
-	WORD  $0xB2B01000       // STFLE 0(R1)
-	XOR   R0, R0            // reset the value of R0
-	MOVBZ z-8(SP), R1
-	AND   $0x01, R1
-	BEQ   novmsl
-
-vectorinstalled:
-	// check if the vector instruction has been enabled
-	VLEIB  $0, $0xF, V16
-	VLGVB  $0, V16, R1
-	CMPBNE R1, $0xF, novmsl
-	MOVB   $1, ret+0(FP)    // have vx
-	RET
-
-novmsl:
-	MOVB $0, ret+0(FP) // no vx
-	RET
diff --git a/src/ssl/test/runner/poly1305/vectors_test.go b/src/ssl/test/runner/poly1305/vectors_test.go
deleted file mode 100644
index 18d7ff8..0000000
--- a/src/ssl/test/runner/poly1305/vectors_test.go
+++ /dev/null
@@ -1,2943 +0,0 @@
-// Copyright 2018 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package poly1305
-
-var testData = [...]test{
-	// edge cases
-	{
-		// see https://go-review.googlesource.com/#/c/30101/
-		key: "3b3a29e93b213a5c5c3b3b053a3a8c0d00000000000000000000000000000000",
-		tag: "6dc18b8c344cd79927118bbe84b7f314",
-		in:  "81d8b2e46a25213b58fee4213a2a28e921c12a9632516d3b73272727becf2129",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "04000000000000000000000000000000", // (2¹³⁰-1) % (2¹³⁰-5)
-		in: "ffffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "faffffffffffffffffffffffffffffff", // (2¹³⁰-6) % (2¹³⁰-5)
-		in: "faffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "00000000000000000000000000000000", // (2¹³⁰-5) % (2¹³⁰-5)
-		in: "fbffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "f9ffffffffffffffffffffffffffffff", // (2*(2¹³⁰-6)) % (2¹³⁰-5)
-		in: "faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "00000000000000000000000000000000", // (2*(2¹³⁰-5)) % (2¹³⁰-5)
-		in: "fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "f8ffffffffffffffffffffffffffffff", // (3*(2¹³⁰-6)) % (2¹³⁰-5)
-		in: "faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "00000000000000000000000000000000", // (3*(2¹³⁰-5)) % (2¹³⁰-5)
-		in: "fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "f7ffffffffffffffffffffffffffffff", // (4*(2¹³⁰-6)) % (2¹³⁰-5)
-		in: "faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "00000000000000000000000000000000", // (4*(2¹³⁰-5)) % (2¹³⁰-5)
-		in: "fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "f3ffffffffffffffffffffffffffffff", // (8*(2¹³⁰-6)) % (2¹³⁰-5)
-		in: "faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "00000000000000000000000000000000", // (8*(2¹³⁰-5)) % (2¹³⁰-5)
-		in: "fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "ebffffffffffffffffffffffffffffff", // (16*(2¹³⁰-6)) % (2¹³⁰-5)
-		in: "faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"faffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	{
-		key: "0100000000000000000000000000000000000000000000000000000000000000",
-		tag: "00000000000000000000000000000000", // (16*(2¹³⁰-5)) % (2¹³⁰-5)
-		in: "fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"fbffffffffffffffffffffffffffffff" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000" +
-			"00000000000000000000000000000000",
-	},
-	// original smoke tests
-	{
-		key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
-		tag: "a6f745008f81c916a20dcc74eef2b2f0",
-		in:  "48656c6c6f20776f726c6421",
-	},
-	{
-		key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
-		tag: "49ec78090e481ec6c26b33b91ccc0307",
-		in:  "0000000000000000000000000000000000000000000000000000000000000000",
-	},
-	{
-		key: "746869732069732033322d62797465206b657920666f7220506f6c7931333035",
-		tag: "da84bcab02676c38cdb015604274c2aa",
-		in: "000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000",
-	},
-	{
-		key: "0000000000000000000000000000000000000000000000000000000000000000",
-		tag: "00000000000000000000000000000000",
-		in: "000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000000000" +
-			"000000000000000000000000000000000000000000000000000000",
-	},
-	// randomly generated
-	{
-		key: "52fdfc072182654f163f5f0f9a621d729566c74d10037c4d7bbb0407d1e2c649",
-		tag: "9566c74d10037c4d7bbb0407d1e2c649",
-		in:  "",
-	},
-	{
-		key: "81855ad8681d0d86d1e91e00167939cb6694d2c422acd208a0072939487f6999",
-		tag: "eaa270caaa12faa39b797374a4b8a420",
-		in:  "eb",
-	},
-	{
-		key: "9d18a44784045d87f3c67cf22746e995af5a25367951baa2ff6cd471c483f15f",
-		tag: "dbea66e1da48a8f822887c6162c2acf1",
-		in:  "b90b",
-	},
-	{
-		key: "adb37c5821b6d95526a41a9504680b4e7c8b763a1b1d49d4955c848621632525",
-		tag: "6ac09aaa88c32ee95a7198376f16abdb",
-		in:  "3fec73",
-	},
-	{
-		key: "8dd7a9e28bf921119c160f0702448615bbda08313f6a8eb668d20bf505987592",
-		tag: "b1443487f97fe340b04a74719ed4de68",
-		in:  "1e668a5b",
-	},
-	{
-		key: "df2c7fc4844592d2572bcd0668d2d6c52f5054e2d0836bf84c7174cb7476364c",
-		tag: "7463be0f9d99a5348039e4afcbf4019c",
-		in:  "c3dbd968b0",
-	},
-	{
-		key: "f7172ed85794bb358b0c3b525da1786f9fff094279db1944ebd7a19d0f7bbacb",
-		tag: "2edaee3bcf303fd05609e131716f8157",
-		in:  "e0255aa5b7d4",
-	},
-	{
-		key: "4bec40f84c892b9bffd43629b0223beea5f4f74391f445d15afd4294040374f6",
-		tag: "965f18767420c1d94a4ef657e8d15e1e",
-		in:  "924b98cbf8713f",
-	},
-	{
-		key: "8d962d7c8d019192c24224e2cafccae3a61fb586b14323a6bc8f9e7df1d92933",
-		tag: "2bf4a33287dd6d87e1ed4282f7342b6a",
-		in:  "3ff993933bea6f5b",
-	},
-	{
-		key: "3af6de0374366c4719e43a1b067d89bc7f01f1f573981659a44ff17a4c7215a3",
-		tag: "c5e987b60373a48893c5af30acf2471f",
-		in:  "b539eb1e5849c6077d",
-	},
-	{
-		key: "bb5722f5717a289a266f97647981998ebea89c0b4b373970115e82ed6f4125c8",
-		tag: "19f0f640b309d168ea1b480e6a4faee5",
-		in:  "fa7311e4d7defa922daa",
-	},
-	{
-		key: "e7786667f7e936cd4f24abf7df866baa56038367ad6145de1ee8f4a8b0993ebd",
-		tag: "de75e5565d97834b9fa84ad568d31359",
-		in:  "f8883a0ad8be9c3978b048",
-	},
-	{
-		key: "83e56a156a8de563afa467d49dec6a40e9a1d007f033c2823061bdd0eaa59f8e",
-		tag: "de184a5a9b826aa203c5c017986d6690",
-		in:  "4da6430105220d0b29688b73",
-	},
-	{
-		key: "4b8ea0f3ca9936e8461f10d77c96ea80a7a665f606f6a63b7f3dfd2567c18979",
-		tag: "7478f18d9684905aa5d1a34ee67e4c84",
-		in:  "e4d60f26686d9bf2fb26c901ff",
-	},
-	{
-		key: "354cde1607ee294b39f32b7c7822ba64f84ab43ca0c6e6b91c1fd3be89904341",
-		tag: "3b2008a9c52b5308f5538b789ab5506f",
-		in:  "79d3af4491a369012db92d184fc3",
-	},
-	{
-		key: "9d1734ff5716428953bb6865fcf92b0c3a17c9028be9914eb7649c6c93478009",
-		tag: "71c8e76a67a505b7370b562ba15ba032",
-		in:  "79d1830356f2a54c3deab2a4b4475d",
-	},
-	{
-		key: "63afbe8fb56987c77f5818526f1814be823350eab13935f31d84484517e924ae",
-		tag: "1dc895f74f866bdb3edf6c4430829c1c",
-		in:  "f78ae151c00755925836b7075885650c",
-	},
-	{
-		key: "30ec29a3703934bf50a28da102975deda77e758579ea3dfe4136abf752b3b827",
-		tag: "afca2b3ba7b0e1a928001966883e9b16",
-		in: "1d03e944b3c9db366b75045f8efd69d22ae5411947cb553d7694267aef4e" +
-			"bcea406b32d6108bd68584f57e37caac6e33feaa3263a399437024ba9c9b" +
-			"14678a274f01a910ae295f6efbfe5f5abf44ccde263b5606633e2bf0006f" +
-			"28295d7d39069f01a239c4365854c3af7f6b41d631f92b9a8d12f4125732" +
-			"5fff332f7576b0620556304a3e3eae14c28d0cea39d2901a52720da85ca1" +
-			"e4b38eaf3f",
-	},
-	{
-		key: "44c6c6ef8362f2f54fc00e09d6fc25640854c15dfcacaa8a2cecce5a3aba53ab",
-		tag: "6f2a09aa76c9b76774e31ec02dcf7991",
-		in: "705b18db94b4d338a5143e63408d8724b0cf3fae17a3f79be1072fb63c35" +
-			"d6042c4160f38ee9e2a9f3fb4ffb0019b454d522b5ffa17604193fb89667" +
-			"10a7960732ca52cf53c3f520c889b79bf504cfb57c7601232d589baccea9" +
-			"d6e263e25c27741d3f6c62cbbb15d9afbcbf7f7da41ab0408e3969c2e2cd" +
-			"cf233438bf1774ace7709a4f091e9a83fdeae0ec55eb233a9b5394cb3c78" +
-			"56b546d313c8a3b4c1c0e05447f4ba370eb36dbcfdec90b302dcdc3b9ef5" +
-			"22e2a6f1ed0afec1f8e20faabedf6b162e717d3a748a58677a0c56348f89" +
-			"21a266b11d0f334c62fe52ba53af19779cb2948b6570ffa0b773963c130a" +
-			"d797ddea",
-	},
-	{
-		key: "fe4e3ad29b5125210f0ef1c314090f07c79a6f571c246f3e9ac0b7413ef110bd",
-		tag: "27381e3fc2a356103fb796f107d826e7",
-		in: "58b00ce73bff706f7ff4b6f44090a32711f3208e4e4b89cb5165ce64002c" +
-			"bd9c2887aa113df2468928d5a23b9ca740f80c9382d9c6034ad2960c7965" +
-			"03e1ce221725f50caf1fbfe831b10b7bf5b15c47a53dbf8e7dcafc9e1386" +
-			"47a4b44ed4bce964ed47f74aa594468ced323cb76f0d3fac476c9fb03fc9" +
-			"228fbae88fd580663a0454b68312207f0a3b584c62316492b49753b5d502" +
-			"7ce15a4f0a58250d8fb50e77f2bf4f0152e5d49435807f9d4b97be6fb779" +
-			"70466a5626fe33408cf9e88e2c797408a32d29416baf206a329cfffd4a75" +
-			"e498320982c85aad70384859c05a4b13a1d5b2f5bfef5a6ed92da482caa9" +
-			"568e5b6fe9d8a9ddd9eb09277b92cef9046efa18500944cbe800a0b1527e" +
-			"a6",
-	},
-	{
-		key: "4729a861d2f6497a3235c37f4192779ec1d96b3b1c5424fce0b727b03072e641",
-		tag: "0173965669fb9de88d38a827a0271271",
-		in: "5a761f03abaa40abc9448fddeb2191d945c04767af847afd0edb5d8857b7" +
-			"99acb18e4affabe3037ffe7fa68aa8af5e39cc416e734d373c5ebebc9cdc" +
-			"c595bcce3c7bd3d8df93fab7e125ddebafe65a31bd5d41e2d2ce9c2b1789" +
-			"2f0fea1931a290220777a93143dfdcbfa68406e877073ff08834e197a403" +
-			"4aa48afa3f85b8a62708caebbac880b5b89b93da53810164402104e648b6" +
-			"226a1b78021851f5d9ac0f313a89ddfc454c5f8f72ac89b38b19f53784c1" +
-			"9e9beac03c875a27db029de37ae37a42318813487685929359ca8c5eb94e" +
-			"152dc1af42ea3d1676c1bdd19ab8e2925c6daee4de5ef9f9dcf08dfcbd02" +
-			"b80809398585928a0f7de50be1a6dc1d5768e8537988fddce562e9b948c9" +
-			"18bba3e933e5c400cde5e60c5ead6fc7ae77ba1d259b188a4b21c86fbc23" +
-			"d728b45347eada650af24c56d0800a8691332088a805bd55c446e25eb075" +
-			"90bafcccbec6177536401d9a2b7f512b54bfc9d00532adf5aaa7c3a96bc5" +
-			"9b489f77d9042c5bce26b163defde5ee6a0fbb3e9346cef81f0ae9515ef3" +
-			"0fa47a364e75aea9e111d596e685a591121966e031650d510354aa845580" +
-			"ff560760fd36514ca197c875f1d02d9216eba7627e2398322eb5cf43d72b" +
-			"d2e5b887d4630fb8d4747ead6eb82acd1c5b078143ee26a586ad23139d50" +
-			"41723470bf24a865837c",
-	},
-	{
-		key: "9123461c41f5ff99aa99ce24eb4d788576e3336e65491622558fdf297b9fa007",
-		tag: "1eb0cdad9237905250d30a24fe172a34",
-		in: "864bafd7cd4ca1b2fb5766ab431a032b72b9a7e937ed648d0801f29055d3" +
-			"090d2463718254f9442483c7b98b938045da519843854b0ed3f7ba951a49" +
-			"3f321f0966603022c1dfc579b99ed9d20d573ad53171c8fef7f1f4e4613b" +
-			"b365b2ebb44f0ffb6907136385cdc838f0bdd4c812f042577410aca008c2" +
-			"afbc4c79c62572e20f8ed94ee62b4de7aa1cc84c887e1f7c31e927dfe52a" +
-			"5f8f46627eb5d3a4fe16fafce23623e196c9dfff7fbaff4ffe94f4589733" +
-			"e563e19d3045aad3e226488ac02cca4291aed169dce5039d6ab00e40f67a" +
-			"ab29332de1448b35507c7c8a09c4db07105dc31003620405da3b2169f5a9" +
-			"10c9d0096e5e3ef1b570680746acd0cc7760331b663138d6d342b051b5df" +
-			"410637cf7aee9b0c8c10a8f9980630f34ce001c0ab7ac65e502d39b216cb" +
-			"c50e73a32eaf936401e2506bd8b82c30d346bc4b2fa319f245a8657ec122" +
-			"eaf4ad5425c249ee160e17b95541c2aee5df820ac85de3f8e784870fd87a" +
-			"36cc0d163833df636613a9cc947437b6592835b9f6f4f8c0e70dbeebae7b" +
-			"14cdb9bc41033aa5baf40d45e24d72eac4a28e3ca030c9937ab8409a7cbf" +
-			"05ae21f97425254543d94d115900b90ae703b97d9856d2441d14ba49a677" +
-			"de8b18cb454b99ddd9daa7ccbb7500dae4e2e5df8cf3859ebddada6745fb" +
-			"a6a04c5c37c7ca35036f11732ce8bc27b48868611fc73c82a491bfabd7a1" +
-			"9df50fdc78a55dbbc2fd37f9296566557fab885b039f30e706f0cd5961e1" +
-			"9b642221db44a69497b8ad99408fe1e037c68bf7c5e5de1d2c68192348ec" +
-			"1189fb2e36973cef09ff14be23922801f6eaee41409158b45f2dec82d17c" +
-			"aaba160cd6",
-	},
-	{
-		key: "40ff73495fe4a05ce1202ca7287ed3235b95e69f571fa5e656aaa51fae1ebdd7",
-		tag: "2e619d8ea81b77484e4fddeb29844e4b",
-		in: "aa6269c2ec7f4057b33593bc84888c970fd528d4a99a1eab9d2420134537" +
-			"cd6d02282e0981e140232a4a87383a21d1845c408ad757043813032a0bd5" +
-			"a30dcca6e3aa2df04715d879279a96879a4f3690ac2025a60c7db15e0501" +
-			"ebc34b734355fe4a059bd3899d920e95f1c46d432f9b08e64d7f9b38965d" +
-			"5a77a7ac183c3833e1a3425ead69d4f975012fd1a49ed832f69e6e9c63b4" +
-			"53ec049c9e7a5cf944232d10353f64434abae060f6506ad3fdb1f4415b0a" +
-			"f9ce8c208bc20ee526741539fa3203c77ecba410fd6718f227e0b430f9bc" +
-			"b049a3d38540dc222969120ce80f2007cd42a708a721aa29987b45d4e428" +
-			"811984ecad349cc35dd93515cefe0b002cee5e71c47935e281ebfc4b8b65" +
-			"2b69ccb092e55a20f1b9f97d046296124621928739a86671cc180152b953" +
-			"e3bf9d19f825c3dd54ae1688e49efb5efe65dcdad34bc860010e7c8c997c" +
-			"d5f9e320ca7d39d4ba801a175b1c76f057832f3f36d7d893e216e4c7bbdb" +
-			"548d0ba48449330027368b34f9c69776b4591532da1c5be68ef4eebe8cb8" +
-			"fa7dc5483fb70c2c896334cb1f9cb5dfe044fa086197ff5dfd02f2ba3884" +
-			"c53dd718c8560da743a8e9d4aeae20ccef002d82ca352592b8d8f2a8df3b" +
-			"0c35f15b9b370dca80d4ca8e9a133eb52094f2dd5c08731f52315d828846" +
-			"e37df68fd10658b480f2ac84233633957e688e924ffe3713b52c76fd8a56" +
-			"da8bb07daa8eb4eb8f7334f99256e2766a4109150eed424f0f743543cdea" +
-			"66e5baaa03edc918e8305bb19fc0c6b4ddb4aa3886cb5090940fc6d4cabe" +
-			"2153809e4ed60a0e2af07f1b2a6bb5a6017a578a27cbdc20a1759f76b088" +
-			"9a83ce25ce3ca91a4eb5c2f8580819da04d02c41770c01746de44f3db6e3" +
-			"402e7873db7635516e87b33e4b412ba3df68544920f5ea27ec097710954f" +
-			"42158bdba66d4814c064b4112538676095467c89ba98e6a543758d7093a4" +
-			"94df",
-	},
-	{
-		key: "5cc36d09c7a6472a41f29c380a987b1ecdcf84765f4e5d3ceefc1c02181f570f",
-		tag: "0d57b8cbea8090df0541354673dcb4e0",
-		in: "44fcd629f08dc1ef53c9ae0d8869fe67fdc7a2c67b425f13c5be8d9f630c" +
-			"1d063c02fd75cf64c1aec9d2e2ef6e6431d5f5ad0489078dc61f46494dcc" +
-			"f403dad7f094170d2c3e29c198b0f341e284c4be8fa60c1a478d6bd55dd2" +
-			"c04dad86d2053d5d25b014e3d8b64322cdcb5004faa46cfa2d6ad2ff933b" +
-			"c3bd9a5a74660af3d048a9a43634c0250427d9a6219197a3f3633f841753" +
-			"ba7c27f3619f387b6b1a6cb9c1dc227674aa020724d137da2cb87b1615d5" +
-			"12974fa4747dd1e17d02c9462a44fec150ca3a8f99cc1e4953365e429956" +
-			"5e108535b1f62e1d4ba18e17a52164418bfd1a933f7fb3a126c860830a87" +
-			"293d9271da736e4398c1e37fb75c4bf02786e1faf4b610cd1377fbb9ae18" +
-			"0655a0abefbad700c09473469f1eca5a66d53fa3dc7cd3e7c3b0411d7e14" +
-			"5f96eb9654ab94913dda503a50f9e773842f4d2a5faa60869bf365830511" +
-			"f2ededd03e0a73000edb60c9a29a5f5e194cf3b5667a694690384599d116" +
-			"f8d2fd93b2aed55b7d44b5b054f3f38e788e4fdf36e591568c41d1052cad" +
-			"0fcb68ca4c4bf5090d57df9db6f0d91dd8b11b804f331adb7efb087a5604" +
-			"e9e22b4d54db40bcbc6e272ff5eaddfc1471459e59f0554c58251342134a" +
-			"8daaef1498069ba581ef1da2510be92843487a4eb8111c79a6f0195fc38a" +
-			"d6aee93c1df2b5897eaa38ad8f47ab2fe0e3aa3e6accbfd4c16d46843318" +
-			"5fc61c861b96ca65e34d31f24d6f56ee85092314a4d7656205c15322f1c9" +
-			"7613c079eae292ba966e10d1e700164e518b243f424c46f9ea63db1c2c34" +
-			"b512c403c128ee19030a6226517b805a072512a5e4cd274b7fd1fa23f830" +
-			"058208ff1a063b41039c74036b5b3da8b1a0b93135a710352da0f6c31203" +
-			"a09d1f2329651bb3ab3984ab591f2247e71cd44835e7a1a1b66d8595f7ae" +
-			"f9bf39d1417d2d31ea3599d405ff4b5999a86f52f3259b452909b57937d8" +
-			"5364d6c23deb4f14e0d9fcee9184df5994fdc11f045c025c8d561adb0e7d" +
-			"fd4748fd4b20f84e53322471a410cdb3fd88e48b2e7eb7ae5dae994cb5ea" +
-			"e3eaf21cf9005db560d6d22e4d9b97d7e9e488751afcd72aa176c0fcde93" +
-			"16f676fd527d9c42105b851639f09ea70533d26fc60cbeb4b76ed554fc99" +
-			"177620b28ca6f56a716f8cb384",
-	},
-	{
-		key: "811c3e356e7c793acf114c624dc86ace38e67bff2a60e5b2a6c20723c1b9f003",
-		tag: "c6e59044cefc43ee681c3eed872d02b3",
-		in: "e115b304c023792448794546a2474f04294d7a616215e5dd6c40a65bb6ed" +
-			"b508c3680b14c176c327fdfb1ee21962c0006b7deb4e5de87db21989d13c" +
-			"3ab0462d5d2a52ef4ca0d366ae06a314f50e3a21d9247f814037798cc5e1" +
-			"0a63de027477decdeb8a8e0c279299272490106ddf8683126f60d35772c6" +
-			"dfc744b0adbfd5dcf118c4f2b06cfaf077881d733a5e643b7c46976647d1" +
-			"c1d3f8f6237c6218fa86fb47080b1f7966137667bd6661660c43b75b6339" +
-			"0b514bbe491aa46b524bde1c5b7456255fb214c3f74907b7ce1cba94210b" +
-			"78b5e68f049fcb002b96a5d38d59df6e977d587abb42d0972d5f3ffc898b" +
-			"3cbec26f104255761aee1b8a232d703585dd276ee1f43c8cd7e92a993eb1" +
-			"5107d02f59ba75f8dd1442ee37786ddb902deb88dd0ebdbf229fb25a9dca" +
-			"86d0ce46a278a45f5517bff2c049cc959a227dcdd3aca677e96ce84390e9" +
-			"b9a28e0988777331847a59f1225b027a66c1421422683dd6081af95e16f2" +
-			"48ab03da494112449ce7bdace6c988292f95699bb5e4d9c8d250aa28a6df" +
-			"44c0c265156deb27e9476a0a4af44f34bdf631b4af1146afe34ea988fc95" +
-			"3e71fc21ce60b3962313000fe46d757109281f6e55bc950200d0834ceb5c" +
-			"41553afd12576f3fbb9a8e05883ccc51c9a1269b6d8e9d27123dce5d0bd6" +
-			"db649c6fea06b4e4e9dea8d2d17709dc50ae8aa38231fd409e9580e255fe" +
-			"2bf59e6e1b6e310610ea4881206262be76120d6c97db969e003947f08bad" +
-			"8fa731f149397c47d2c964e84f090e77e19046277e18cd8917c48a776c9d" +
-			"e627b6656203b522c60e97cc61914621c564243913ae643f1c9c9e0ad00a" +
-			"14f66eaa45844229ecc35abb2637317ae5d5e338c68691bea8fa1fd469b7" +
-			"b54d0fccd730c1284ec7e6fccdec800b8fa67e6e55ac574f1e53a65ab976" +
-			"4c218a404184793cc9892308e296b334c85f7097edc16927c2451c4cd7e5" +
-			"3f239aa4f4c83241bde178f692898b1ece2dbcb19a97e64c4710326528f2" +
-			"4b099d0b674bd614fad307d9b9440adab32117f0f15b1450277b00eb366e" +
-			"0260fca84c1d27e50a1116d2ce16c8f5eb212c77c1a84425744ea3195edb" +
-			"b54c970b77e090b644942d43fe8c4546a158bad7620217a40e34b9bb84d1" +
-			"89eff32b20ef3f015714dbb1f150015d6eeb84cbccbd3fffa63bde89",
-	},
-	{
-		key: "f33691f5db2dea41e1e608af3ff39f3a6988dba204ce1b09214475ae0ea864b8",
-		tag: "6e50e70411201378c8d67857d7b631d2",
-		in: "439bc9ea10db4d2b08c7fcf2e8bd89fa9844f8061d462e28f174489e7514" +
-			"0f84e842040141cc59ce38f9551850cfbdfac2d75337d155090d70d0d930" +
-			"04340bdfe60062f17c53f3c9005b9995a0feb49f6bef8eaff80f4feb7ef3" +
-			"f2181733a4b43b6ac43a5130a73a9b3c2cbc93bd296cd5f48c9df022b6c8" +
-			"2bb752bc21e3d8379be31328aa32edc11efc8a4b4b3f370ee8c870cd281d" +
-			"614e6bc2c0a5ca303bc48696a3bd574ee34738de4c4c29910f8feb7557bf" +
-			"ffcfe7428b4703144bd6d7fe5b3f5de748918553df5453b3c6001696f3de" +
-			"0137e454aadf30cedfb6be36b0b908a38409f1a2dc202fc285610765e4c8" +
-			"6414692bf4bde20ed899e97727b7ea1d95d7c621717c560f1d260ab3624e" +
-			"d6168d77c483dd5ce0d234049017795f2e5a7569d7ad323c50a5b1170337" +
-			"4174a9977026c20cd52c10b72f14e0569a684a3dcf2ccbc148fd3db506e2" +
-			"8d24f6c55544cb3980a36e86747adc89ebad78d1630618d113fa445f8625" +
-			"b583cd7be33913c30c419d047cf3baf40fd05219a1fcec717b87a65fa022" +
-			"1a3aa8143062d77588168019454240ae3d37640996f2967810459bc658df" +
-			"e556de4d07263dc3d9158ec242008226d1c6aea7f0846e12ce2d316e80da" +
-			"522343264ec9451ec23aaaa367d640faad4af3d44d6d86544ade34c93518" +
-			"2843f6b4d1c934996778affa9ee962e7dfef5e70d933d4309f0f343e9606" +
-			"1b91b11ac380a9675e17a96099fe411bedc28a298cd78d5496e28fbbd4f5" +
-			"b0a27735d1144348e22be5b75724d8f125e99c4cb4e9c3a1f0b4e9da5146" +
-			"e6afaa33d02fda74bf58a8badee2b634b989c01755afa6ab20ee494c6ae4" +
-			"c2c6f17af6b53b61d2947d83a18eb3b8a1612aad5d3ea7e8e35f325c9168" +
-			"ac490f22cb713ddb61fbd96011c5849ac8e2fcd42db820349bdf9157dcc0" +
-			"0d9f9ed9c099b10c7194d48b623b0df43759734b2a2e5f8a35e7192bf9a0" +
-			"03dcb9d16a54bd84d922f85b6021b28aacc5264fe9e83deb48f18f864cbd" +
-			"367eb163d39c45b0eb907311a2a4b09fb26109088df782ce031b02f3caff" +
-			"d2dbe25b1cbde9f35ba7c47292a4fd49e7def7a28824f3dfda259a86c3de" +
-			"59257c255c712686ee47d128a55c7b9e8c546035eab7e2da420f32ed5c94" +
-			"bc12a34dc68eb99257a7ea03b69d6c760b0681fa24e4ca97b7c377182ab5" +
-			"fee30a278b08c44c988a8f925af2997883111c750d176b432735868208f4" +
-			"0de7137331b544f2d28040a3581d195e82811c945c3f9fde68fc21b36a44" +
-			"e1cfa2d8eb625f3102461539b3f13c660936a5ddb29a0ae791fbf52c2f69" +
-			"7bd334653f3605b362d91cd78569b41dbd09b2a5892440b5097fa08d0b4b" +
-			"291fc5b934585dd8d5adc80d573fdd194b2eae26dfc49f5e51c1f1607d7e" +
-			"87740702f244bf39ca1d52423e0ae84891dfdf4f43ef984c7a5f293a2007" +
-			"a1e00e39c757f064518953f55621f955986f63",
-	},
-	{
-		key: "d115b6ac998a65b48b3dae5977abaf985258d3d1cfe1616cec3d6a77f7a75785",
-		tag: "b431c9318ec2769fc8ee8f5fc3c079c3",
-		in: "7e7eb43839a6d7616b8a7b1fb7144817904342a9bd34167051162941a6b1" +
-			"b85db5e587f76e4a53211755d5ab29c11822d7711a97b3f1ff5b21f2485d" +
-			"9c86241fb56cdd6796245d3112df11ad9a7344db44d09934c4efb280ed65" +
-			"80cfcafb5c97a32993cbbf4917183e0b7bb38f2ce2479c28e1d39f673962" +
-			"17a7010448dfd39a4e7f406c8bd2d804f993bb410fffa4eb57518a531ecf" +
-			"259a8af068230acb826d9ffc20ee0fc43885221a321e3928971bb28615f0" +
-			"d9f099f5b68a80503a910fdba0bc643c60b64837900be38770b6b30c362c" +
-			"4580722b5dbb1b9c8cd02a18fd7b5661d2c4d28aa941c50af6655c826690" +
-			"37312fbf9f1cf4adb0b9400532755011b40e8252bd0e3c7a22efb0ef9122" +
-			"1e04b4aa8316d4a4ffeaa11909d38cc264650e7ca416835ded0953f39e29" +
-			"b01d3a33bba454760fb0a96d9fe50b3e42c95271e57840380d1fd39a375b" +
-			"3e5513a31a4b80a2dad8731d4fd1ced5ff61e1fbe8ff3ff90a277e6b5631" +
-			"f99f046c4c3c66158554f61af2ede73aede97e94b1d1f129aaadf9b53548" +
-			"553cc2304103e245b77701f134d94d2a3658f2b41108c5a519c2c8f450db" +
-			"027824f1c0ab94010589a4139ff521938b4f0c7bf0986585f535b6e292e5" +
-			"b3ded23bf81cec17c8420fe67a449e508864e4cbb7eaf335975668f013e9" +
-			"da70b33bd52a72094a8f03762ea7440ce9fcd10e251837cfc9ccc1a8cc47" +
-			"0c67379f6a32f16cf70ea8c19d1a67779a9b2d2b379665e0e908a88b26e7" +
-			"8c9f94f17acefa6d5feb70a7095e0297c53e091cf98df132a23a5ce5aa72" +
-			"59f1154b92e079f0b6f95d2a38aa5d62a2fd97c12ee7b085e57cc4652863" +
-			"8defacc1e70c3aceab82a9fa04e6aa70f5fbfd19de075bee4e3aac4a87d0" +
-			"ad0226a463a554816f1ebac08f30f4c3a93fa85d79b92f0da06348b4f008" +
-			"880fac2df0f768d8f9d082f5a747afb0f62eb29c89d926de9fc491921474" +
-			"1d8647c67d57ac55f94751389ee466bbd44dbe186f2f38abbc61a0425613" +
-			"e9b6a64e6bcb45a2e2bb783b9103483643d5610a7e2dcdb10b5d78423285" +
-			"506b42a99b00a4fb7b619b4526bb4ec78299dd01ad894fde2f053e18c55b" +
-			"6047f86333f2690c2cb8e87d9834ab8a5e339aa346e4d9952ed62dc083e3" +
-			"b11a823a67f23fec099a033f127ebe8626a89fa1a5a6b3520aa0d215a8e7" +
-			"dea3af37907686c16521739a95d6c532cc259c497bf397fceaea49cd46b9" +
-			"ad5c1b39a36fdd2f0d2225fef1b6ca2bb73fe604646c10ba4c572ab13a26" +
-			"559ededc98f5a34c874cc25621e65ba4852529b5a4e9c1b2bf8e1a8f8ff0" +
-			"5a31095b84696c6381eb9ad37ac0db184fe5fccf3554e514946a33cabe6f" +
-			"4d617b549d28ad1cc4642dac96e0215ee1596481600d3619e8f45e2c9ae1" +
-			"da834d44aca216bba0efef6254503ca90339f2d7ca508b2722d50c08def8" +
-			"a736590fa44855cd9eb9979c743783aa26e633696739f2ae25ff7b72ceb2" +
-			"4dff4455b85bbd675c8cb71ad18386dc58c371bdf37b4b3875b98a9423ff" +
-			"3becfc0d0ba2aacab3ee7683cb3b345095fefcaca5751ca793da63c89428",
-	},
-	{
-		key: "f3717306b9729be998cdb2c9d856306c5ae3d89da2cdcef12f86f6110c98d873",
-		tag: "907dba0f4849c7cf4570b5128b5f31d5",
-		in: "079572187d4559f24d8e48dc366441acf226a4db79e214ec3ee288acc349" +
-			"887e2e377419bcafa377d0151497b52e4d9cf2a02b0fc91ad9516482bdf6" +
-			"eccd1497954b53241bfb0bc5c04cc45045c6251f23a510060fee32721872" +
-			"bbc95cd8d400dff00bcac2ecce6229c7d73d8f85ed5a87afdccf6dedd299" +
-			"2d5c7b5b8090c47c737ded036ff0e9aedf02a2242fd9820be618b9601e73" +
-			"d3ba5d8f1ae9805cfd2306251704bc74e3546997f109f1dfae20c03ff31f" +
-			"17564769aa49f01233c9c4b79f90fa3d1433d18cdc497914046ad77d2792" +
-			"2588a7d0e61d4258d7d80cdab8503e3111ddca22cf7f39c1f80f1e16a68d" +
-			"9e21db8b53dd316dfa4233cb453a39a90101c60efc08514a3057db007e96" +
-			"507745bd4a0764ed8717a250bffb5fd1ea58474bdfb5b869681939693926" +
-			"40d832a3387ed4ac9cdab0d2af8fcb51b86e4d927097f1e79b5af96574ec" +
-			"d59d0dd150a0208978c41de28ad6cadf72a49279cffd6dc281c640f2e294" +
-			"4cde49a13ed390da1dd92e3011ce0f4a0863375a9db3f67fca1e3b8288a0" +
-			"78611161d7cb668ecdb932e1ff3733982c8c460eeeff2bca46c96e8a02cf" +
-			"b55d770940de556373a4dd676e3a0dd66f1280c8cb77a85136b3f003fab4" +
-			"887dad548de7bfe6488ae55e7a71da4097db03900d4b94e776a939530328" +
-			"83492da900b2a6c3e73d7a6f12ee30c9dd06cc34e5a3893976eb1de5864d" +
-			"32e792ac02e68d052d9d0cfc7cfb40b77728422f6c26cf68987c6b40fcfe" +
-			"9d660abc657360eb129de11bd70af5eb8fe350af2c27a6ece2cdf81b94c8" +
-			"0e68e8c51106497cfa5171236efe2d71d76b5dff3352af9b407dc5aab60f" +
-			"46b5683646f5b28732b7c750d351a08a507243d8e437cc4bef13a3edaa20" +
-			"5fc4e9968b4e563fa0dc965ba20b8e48bc188a321b16d3213bed69647512" +
-			"7a20afc1a3680ef261df6d37b017dee05cfc3a42e4130216e5540cf715c4" +
-			"e638d7d615c50bef576eeb19b3b15b2c2b454dfcef2b18161a143ddf52fc" +
-			"8e88fa71cbe34c92cd4b5a0adc81e5c33e11d2721bc1b95a9e693ac3cabc" +
-			"490889a8a42bf7e22375b679e8598c8faef22a006ed2da8ab1c08aaed2f5" +
-			"6d6f26649036335c0881bfec1e3a5346335c3b3707ee92173f1a7a3305c2" +
-			"933f78e995da8f1df64daf12b81ce23c8813c27fd4551103dc33561c2e80" +
-			"45b6b6770fa03498fd359a104884699d628020173edbcc4398b977e456e4" +
-			"885964840466176a490e7c513ba5d66090277c1ab1632a995a54f555a452" +
-			"1170a000507865b6650730aa6d6050a55959102836fff3d37e4773340e59" +
-			"2e56951ff9652519de4421d9c5b63edbeb30a3852a1ea110a9a29721aee3" +
-			"23d5a306de1624cecc87badc47aa87f489635d2fb60bff62ba67f5257999" +
-			"6af0a1f1a6fbcd8704e119196fcc289a6db6a4170a2cae31a1d30744b702" +
-			"2536d1526d41659c2dcc8b39c26aecfc0f8a707136d81b2827a158fd7386" +
-			"a537514471c213a8c859016748e0264cf3fbde10f40c620840ec4df99432" +
-			"e2b9e1e368e33f126ec40c572e841c2618d49d4eb098b9533b1f4ae00b46" +
-			"8d15de8c8ab6d0b650e599576f2bd90a124c9c6a0f911fd1bd8253bac272" +
-			"942cbdf8864f3747ff7f09d8a5a9d8599be7ee1744e5f1faf3e526cd2a06" +
-			"b157527272af9d38565957c9ce663c295766c0e0e464971c6282b70d4c0c" +
-			"1fb3b69856b34c089ad2b2c745f5a033cee1429c5b855581ee285278893c" +
-			"43a5968d9c28384b7abe8d072ba69089c938685cb1eab461f05314ad6d06" +
-			"eaa58512f8738bde35b7b15ef359dd2e8753cb1ed6",
-	},
-	{
-		key: "9772c1a4b74cbf53586e5df04369b35f1fdca390565872251bc6844bc81bda88",
-		tag: "68eb7fc459ecc3be819485001ab438dc",
-		in: "e115cc2f33e367cb85c01a914b3a512404ad6a98b5b0c3a211d4bffd5802" +
-			"ee43b3fb07451c74524ec8b4eddbb41ca33dd6e49791875d716a44bec97b" +
-			"7c2d4546616939ffa3b1ab9b8ba1d1a637e7c985cc922606caa0453085e3" +
-			"5f2fe0bd2de129d1d1856ade975a3281a62965927d8bb695e54514e69558" +
-			"89361a2a00a1b24e62bda78d0b71a0d40147016fcdaf1a702331dda8e678" +
-			"d8f476dcc91698da1688c610ec0cb1d9b8fbcd45dfde6d1503ba60a01337" +
-			"ae5b2f5c854a82c3087779babd2e522dd92f4718cd9f8c649ac226745ca2" +
-			"fa1696442764758f67cd926369578ae87612790dc56ed9cda935281a490e" +
-			"5c984950ec7a4e930520d273a69da4ed3a330e532508e26f942961fed0e3" +
-			"efeed52a7b96250d723155aa39a8ae85131c255c32bf406b647de1a37fba" +
-			"dc61e302bb5b70adec4505ee66b3a1d1b7bfe9c58b11e53ad556d56e5807" +
-			"017bb30b71be94e8f86aaf1496e8b8d6db75ec0afbe1cd336c23963c745d" +
-			"7b4ba1787ceb30728f1762b46f6eaad5064c8029d29b86266b87f93142a2" +
-			"74f519f3281d8c1cb43c23eb184ae41f3f625cf624b05a48d73cd7783fdf" +
-			"14954a03ec1a930e9a954424eff030e3f15357de4c19983f484619a0e9e2" +
-			"b67221cf965e9aa8d8926595c793adfe0181050df8b845ce648a66df532f" +
-			"78b10c83ecc86374a4f8abf8edcc303654bafd3dcc7de9c77a0a9d1d98fb" +
-			"121534b47d16f75b55fdc2a5e2e6799f8a2f8000d4292282e56863ae422a" +
-			"5779900ad6881b78946e750d7777f33f2f013a75c19615632c0e40b98338" +
-			"1e9b8d35a26abe30242c45662eebb157e6d7a8a5519de60268ac289b8295" +
-			"5d4feb47b9eef6da65031c6f52c2c4f5baa36fce3618b6a331f1e8bdd621" +
-			"48954fcf0846afeeb0a6cadb495c909a7fe671b021d5b0b4669961052187" +
-			"d01b67d44218471bfb04c1a3d82bf7b776208013fc8adabaefb11719f7a7" +
-			"e6cb0b92d4cc39b403ceb56bd806cbdcc9ee75362ab4aaeb760e170fdc6a" +
-			"23c038d45f465d8ec8519af8b0aad2eb5fae2972c603ed35ff8e46644803" +
-			"fc042ff8044540280766e35d8aaddcaa81e7c0c7eba28674f710492924c6" +
-			"1743da4d241e12b0c519910d4e31de332c2672ea77c9a3d5c60cd78a35d7" +
-			"924fda105b6f0a7cc11523157982418405be0bacf554b6398aeb9a1a3b12" +
-			"fe411c09e9bfb66416a47dd51cbd29abf8fbbd264dd57ba21a388c7e19e8" +
-			"12e66768b2584ad8471bef36245881fc04a22d9900a246668592ca35cfc3" +
-			"a8faf77da494df65f7d5c3daa129b7c98cef57e0826dee394eb927b3d6b3" +
-			"a3c42fa2576dcc6efd1259b6819da9544c82728276b324a36121a519aee5" +
-			"ae850738a44349cdec1220a6a933808aee44ba48ce46ec8fb7d897bd9e6b" +
-			"c4c325a27d1b457eb6be5c1806cd301c5d874d2e863fb0a01cbd3e1f5b0f" +
-			"8e0c771fca0c0b14042a7b0f3ae6264294a82212119b73821dcfbbfd85bb" +
-			"625b6f75e4dc0ee0292ab4f17daf1d507e6c97364260480d406bd43b7d8e" +
-			"8c2f26672a916321b482d5fa7166e282bfeed9b3598c8f8c19d2f8c8b98d" +
-			"f24c2500c8ad41cd6ed3f2835737916d846f1a6406cda1125ed7740fe301" +
-			"d1144559b7c95fa407599ae40a795226513153f86c9b8abe7d8aa6963c99" +
-			"5646ec586cbf20a03a698cc0681b7bd333402d00fa8e15cb32300b5a24ea" +
-			"316c5e1df67de78891846cb9183a4b112c3bcc17bcaa5fecd6c1dbbf6ef8" +
-			"272d9269e7f0ba9f17050a6aa5f11cb28874360396ab647941f2c9a85cb0" +
-			"6a969919b16997b0827af8f909c614545f1ad638ebb23109f6bab6b49b22" +
-			"b2285cabbb998b3e1bf42771b4d4e52330b224e5a1d63169ec85fe1c7dd2" +
-			"46dbafa6138448420f463d547a41c2b26026d4621b854bc7786ab3a0a93a" +
-			"e5390dd840f2454028b7c3bb87680f04f084089bbc8786ee42cf06904d01" +
-			"7e405144d2fae141599e2babe71abfbe7644fb25ec8a8a44a8928ff77a59" +
-			"a3e235de6bd7c7b803cf3cf60435e473e3315f02d7292b1c3f5a19c93646" +
-			"3cc4ccd6b24961083756f86ffa107322c5c7dd8d2e4ca0466f6725e8a35b" +
-			"574f0439f34ca52a393b2f017d2503ba2018fb4a0991fddc1949832d370a" +
-			"27c42e",
-	},
-	{
-		key: "d18a328b63a1d0f34e987682fe6ca3d48b4834b4312a17e99b3d88827b8d2238",
-		tag: "938b43b80cb3935e39b21dd8ba133cf8",
-		in: "bc2b0baf92580ee6c5efe640f2a029a791a3c77bec459be74cbc30931508" +
-			"d9f312c3a0944212831cbe4fc92e8f107f2f750c91bcc09f7624fa9a09b4" +
-			"9b7712cf5d619ea9da100fc23068ae2f4e353047e3956b215884bdb12235" +
-			"3f06b8ee98f36c3212493d61ae9ce151cd0453f3075b18a12d7d73da3de7" +
-			"dc2d98376cfb420069ca8148c511ca6bbae57572394a3c615a6fefb30c5f" +
-			"d727f964b4065ac9ee252bdd2bcae3e70162fe0e8069974e073f0a093d45" +
-			"be52d7de16a8f5f65c548aa6525822ffb00dc642530fedf355f7188ef017" +
-			"56384760c80afb61ad903d10119a7d615ec4fbdc79c490160bdeaf200915" +
-			"e405f2a921a2380c0ab9d2ac1e4fdc8ec4b907368c004458598efac13dc7" +
-			"2751e7faded538e3dc8b16590cac9b7ec294da0ad53e22cb9c05d8ef494f" +
-			"a04f6ab7c843c867fbe3cf1b4eb146d65339b0b03392259f12627a8e98e8" +
-			"0f4896c30b8ecd210acb2365539a872541921dcd8e1e54caf4936dfc7e1f" +
-			"68f3bbce61d325b447a8cce7f0fcad28494f2e47dae46b136594b5dfca7a" +
-			"bdafd6856f91496c05b21079aa55aa8c41628220a2cf0cdd755893375b7b" +
-			"b13d914c9a1d1db4a18f8fa36c55e52d0342352052032fb62d32fcd51cb1" +
-			"ac46f44b06e682db5d96d583cda03b966c650c03ae53542e8da1066b6884" +
-			"4a7e2280c664415e413f270b1fdcfbb40b9daa6131d071ee7eb1553dc5b1" +
-			"a50677971223dc316d2d326d57cbd529c88698facdca425e2d5c6b10d7ae" +
-			"cae28b8890aa44ede9b9193dbe8d1d8aa1fa580ca384b57eadcbefc96dd8" +
-			"bfccbe3b855a96f1fd4913035f817b75954ef1827c7718aab24d353e41cb" +
-			"a73748e14e0c2750d5b6a9752125708cc7ee7a498c7fbadf4186e7f8fa93" +
-			"bfdf281a49400f877621651b8ba87edda5231e80b758564e75139b61b1a9" +
-			"9fb9ec694f928ab1f47c6c4287bd4182d1b2be053380616e98da06f3ef57" +
-			"b570ade17c51da1d602b6ebc5a638ebde30d99bf4f91d0e01557c7dcd8f7" +
-			"9e5120143c935fc699eb5616ccd3cac56b5f8a53ed9e6c47ba896bfefe71" +
-			"2004ad908c12cf6d954b83bec8fb0e641cc261ff8f542b86e62d90e227f2" +
-			"a5bd59c9d390c0dd857f6da2b7624787a0bb31908bae84896890b283da61" +
-			"d8ec4f56eea38b22b438d6374b42243f9c1d94288874e53ab90c554cc1f1" +
-			"d736acde67aff55007fd4b3becc4d0f3ddd96f10dc75255cb0327aa47076" +
-			"2b3a3a656e33c87b02a682658b6cd2a75d9c0462803c9bbffa51441501a0" +
-			"3a2fbb2344aa13d27ffb9e98704ea6720b6a9992e53449688cd74d0648fa" +
-			"e8e776b0ea6bf048b2ec05341e5948cab0af015328b284ae7bd89a5f763c" +
-			"eaf5ca3e647a9f5bff7197e4d357e4359fa5fe30709545453149be510e3b" +
-			"ff86beeba5110c79c0215fbe9ac9339a8ac7d41f7488588ab14ac657aaf7" +
-			"d5c03a353932bbb2b261f0e83f3526c5e8e0c2348a10ab4eed6ecdcf9014" +
-			"7550abcb0a722f257e01d38bad47cdd5a64eef43ef4e741bf50da275720a" +
-			"0aee47adfc5cd2534b911dc269197c3c396820b303f6941e3fd85b5ed21d" +
-			"6d8136745c3eeb9f36b1f226434e334dc94be8a5606079cb7643136aacd2" +
-			"da9c38b2eb7e2b898bd8632003767bf0c87d00a3c2fcee48bbbcdd949af3" +
-			"3455128216709df25879b0ce894ac4f121dfca6b8c7865002b828696641d" +
-			"14ffc59924fbda50866fded0afaea545c8008c564a3a0b023f519a9980ea" +
-			"d541d91d1c07a739fd02286ea5660e473f80494236a68e84ea31aad71348" +
-			"e45055ded69c39941e31d51df257a4d0b0d8f025dbedee093f2b91795bc1" +
-			"533dc472020769a157a187abd6d8d52e1693e2ef56b2212759d0c0120e54" +
-			"c425d0084fdb3925e296dd6cdd8e677043a90674904057d88ebdea5998aa" +
-			"03562a790adecc4399352df43e5179cf8c584d95ef8e4b37295946b1d37f" +
-			"faf4b3b7b98869184e42ea8b304fe1059f180ff83d14a0861ca7c0682c34" +
-			"b48a70df8653bd8d9a26f9489e1271fa44e41b392e648d0e619ecdad2c53" +
-			"952094802eeb70ade4ffe096e3049867de93a824217e31364b18204e9681" +
-			"dd8e84ae2678aad155b238f59dd9bf9ce07e97183a690b2a46a8f3624843" +
-			"5b2f713e7d8dcda4dea1e3c4cf9692dda082322c51f7bb1f63d92aa987ec" +
-			"cf1355a043e21a7b8d60a2b97f18487f6fff4c77df92dbfdc9837540c518" +
-			"9fd9585731bc6e726a34ca21154b0499522c9d1016953dd0fa2eb6a92b6d" +
-			"14d6e3da5c12fabe92bd639e253983fc91041091791643",
-	},
-	{
-		key: "46e8eb27acfdc8f4be622d8741c7bc414464c149e21da97ab4afbf3e07b98b0e",
-		tag: "56b5f49be824c7a19b19faabf0787a87",
-		in: "ced52b76c057872a60107194b432cf04b7be05e65209045d2952ea0284d8" +
-			"3e2ed5a15cfdc58071204573c18ab03765b4d5e63a601419e039c42075b2" +
-			"7ebb2827de9c6233d6632e6d3db9140bdb4a9291d53f33734c2dc8e24df9" +
-			"0764dc10e0d321d20fdf659bfa2a81bc9e04fd0f83448143276647c08bfa" +
-			"dcfe3bc23898eda655c9353693ed7b022f43eefa23c21db7660c5029ca64" +
-			"a6085d93029ea6c43197356f56b7624d4819f5008d053357d981ffbe7f40" +
-			"96d6c55d8417002d36189b04bbb2c637339d90f4910a400833a8d422d88d" +
-			"c816c1636e8d9f7f926c244a28d9e0a956cec11e81d0fd81d4b2b5d4904a" +
-			"d1a5f55b5ec078dcb5c2bc1112bbfd5efc8c2577fe6d9872a985ee129e5b" +
-			"953e9cebf28cf23c6f9c6a5e09cb09ab586c6a50e4389cd3110777591d7f" +
-			"0608a3fd95b99f6ba03984fb0e13c6bbbde3668c59f2f2b69d7caadffa94" +
-			"6f67e725d56280e59e66dca025a18d4616e81abd9801835bd94485bb2025" +
-			"dee81fba440005b181ee81dc1d7796cbec92e4ec1c9016c8e8073cf281ce" +
-			"f749993f09a618a4671d58b476feffa454600f82955c591882715148a826" +
-			"586f68bb50059914dce1c1c85e5e3951647c9964ec9316005209a58baeb5" +
-			"2c6d01e6b4c275c0050a7e2bdc52133e433b050a700b556d4314e5c041d1" +
-			"93ee47f47adc971aed1b63259dd5cd4f95854a71a947eae3d3d12d0d7b52" +
-			"c6cd2fef2d2e892607a9681d73ac3236fad21ee30a4f857010bc95c00d5f" +
-			"6f0c6b3fe50cd6452be6eec4f5f01542dc2cb5e2db1f52224f11348fe2a0" +
-			"5d1e5885f1317f2d06ce2813dc4c723008e836a2ee95d0aac66855fe4c3b" +
-			"1b2e02ba0700be759b1ef1c2a3123ee4ccf9200d8d4de5e0d503f04c2053" +
-			"66393d1e91b648392ca28389d976aa618b4796acbfe8aa356ecdce1f7786" +
-			"bf09af226bb9402317b6fa319bbb9248d8ce00b1f49f066c69d4df93266b" +
-			"938342cd7fd4b07c320c2409ef72d8a57c21d0c6d6d493f7ca94d01b9852" +
-			"e4fca6a9291e9060154bc38af6c86932645f53914709fc90e11db56ec471" +
-			"6d600ee6452041248ea8244f79534f793bfc1f2020855d817cb4ca3c48ea" +
-			"7f6441ce9af9bda61936c226d810086c04a35e8654fdc30d4b35701adccc" +
-			"016d5895b2121ba4066e44d694f6371d97911786edb73dc3020ba186a01f" +
-			"ee3dd6036c0e205a8d05979bad228fd12c0fd2fded6c7f1e4c11354d266e" +
-			"d9c2f706269c43cd90504997d93a17b39b10dab0ff083ab3bd06540ce612" +
-			"d08f46ce75a16ef330525737410a0d98fb3d484968f9c12edcaf50103fdc" +
-			"c14128ea4ad6c30b56247eab28197fe617e5f88afa5cbe003c63d423647a" +
-			"d3042626fafd2084a0582ff1b1efdb5baa162662048019546234e2f6b6a1" +
-			"d8bb971114aae41df7795b4f3598f2af9e8921a9aadc7fab6c780aaa32a3" +
-			"84865a4ccb02351dbc55ec92a3152d1e66ec9d478be5dca17b4a131b4a0d" +
-			"3d4420fc6123fef80fd56ca266407d58a7880d6b7e5ce2b6bdc9a3721071" +
-			"7feec573d83c83a2e3f7d4023f2f68e785cde728fdbf5054060e4c89faa6" +
-			"1c9dd10524a08811d15c627b3b4ada549a3fa1d8dd77c005daaf2addeb10" +
-			"0abf694da8dd692f113965cd6366a5a7b0c17e1f2a320243e2c90b01418e" +
-			"22426d0401a2c8fd02cb3129a14fdfa6cbcaa1f1c2f17706e9ac374a3458" +
-			"777761e986ee4c358d26f8e420d33230d198fd86704e77298dd4c40c5205" +
-			"7566ac0cd92993b21937c3a3b4a8b89110a97cf38c781ad758bdc28f3565" +
-			"60cf3acbedfa8e05b396d226ef619746e8e4fa84c8e00a7f0e6d652808c8" +
-			"9c9b123d9bd802624cfa949eb68af85ca459b9aa85b81dbc0b630856cb9d" +
-			"7e18cdc96b3c069a006dd5b716e218a5ed1f580be3e3ccf0083017607902" +
-			"a7967a02d0a439e7c54b3b7ca4cc9d94a7754efba0bb5e192e8d1a6e7c79" +
-			"4aa59e410869b21009d9443204213f7bceb880ccf1f61edb6a67c395a361" +
-			"ff14144262b4d90c0e715dbefce92339ff704cc4065d56118624a7e429e4" +
-			"cadf0b9d2e7ffc4eb31c6078474a5265beba0774209c79bf81a930b302bd" +
-			"0f142534a6ae402da6d355a010d8c82dc379ea16d49b9d859a7de4db6e62" +
-			"40f6976ae0f47bc583b327df7ec88f5bd68f713b5d53796e72e28c29e843" +
-			"6c64cd411d335623ff4f5d167f3c7b8cba411e82f03714662425c8e1bc1e" +
-			"fbf435d28df541a914a55317de0ded8c744a1c3a6e047590244b207bcdcb" +
-			"f4bd1f9f81210deddd629192c58e6fd73e83812f084ef52f21c67bea98ee" +
-			"17554437d9642e2e",
-	},
-	{
-		key: "b41210e5ef845bd5a8128455c4e67b533e3e2b19dffc1fb754caa528c234d6a0",
-		tag: "72c9534aec8c1d883eef899f04e1c65e",
-		in: "7eeca180bb20d99635e36b9208221b2b8ef073fbf5a57f5190e19cb86c49" +
-			"89b0e8150d22ec3aaf56f6ed9cb6720284d13a4b0a34cd3d7f7fc7089326" +
-			"6d1893fa4185269fb806677ff490aec8f889896fca50d6c80d295875b1d5" +
-			"4a779b6d49305360b31011b48537157d0f323ff4e865d46fba6bd23a06c1" +
-			"46878cf9404360d325432312ff08ce495edca63a3c93c44d79c050e3f1de" +
-			"4b6ca5fedbbd43dbdef9ceb26d440a59c7e0be3a8e461c4f15b6b1e1dc36" +
-			"a71fc723ad593fb903e83d0804ce497fc49bfc6b6a602b9dc6e9891010b1" +
-			"4ca066cb1c68044c1ad837c638076dd3708078509cba49fdc54922cdf5d7" +
-			"715fb43e9b5a5942cb8950eade143577bc9dcedde58d51deddc70075e452" +
-			"bbceab1e95b5d003eb96bea69687faa6d50d9c605769cb4287b5d9924dd6" +
-			"8881c699abaa6f93e41dac7639cdbbbd0259099a3ed096f482a1fa322b15" +
-			"ffc379812c74e09e95f1bd3706347eac421fe56895e738a47fcd3e118773" +
-			"c3a7e7e264cc7ff5a53a80e436df058265dab9756fdf6913786a47e98bbc" +
-			"411052d58ffec9ee948e28cbaadaae471c5d828eaf3b3c87d3bfd495477b" +
-			"403da54f1418a15ace0d4d0df68f6a8f2b0457b127d5eae1f45ae055afa1" +
-			"8f058d5dd7eea559de3ae9378ca53f7d6dc9a9465ea1f945295f16ee0404" +
-			"7fc9dd3deda8ee32631d7af70c20edc1e12c5f8abd2e78f43dbd4cd6407f" +
-			"038efab144a24ea8a090a7ba3e6499345a60106220c2959a388e1a73d070" +
-			"1d854bfaaa86165a5aee934b615ac7f45da7c43a1e8f74613917ed10dcd2" +
-			"27e4b070414412e77851db5bc053e5f502bb4e2b2645bca074c18643e814" +
-			"4caeccb58be49ea9a552913c0616382c899635eea79a166988c206b9aaa0" +
-			"977c7ced89c4c7aaeaa8fb89b38030c44530a97187fda592b088198b63a5" +
-			"2dfad59a0a4c1aadf812bdf1881924e8b51b8fd4dbca8e73b2986b3ab484" +
-			"171e9d0cbb08be40ae60de8818bd7f400191b42c7b3200c27643f06720a7" +
-			"e0a17441f34131629388ac43955b78c31ea6602a70dd665f872e7669e865" +
-			"f6f40e634e8772d747608cd3a570e1726eb1ddca64f08582b022bb026eda" +
-			"6a913dc83f174ce3c18b9fc0503d3ac74e2fe45691d6dfb4af8c86d752a1" +
-			"6d6664fab4de08afe8858392fcc35cb9ea82fc42c42d48c0c0556267ea0d" +
-			"cc19b10f05e0318c4488ffe704b5036908f5cb938eebd3163503acaa874f" +
-			"592d945448fbeb93a877a26a72306a36e181745ba300afdc30cb7986919f" +
-			"3dbdc5c47ef1fa052a9e4aeeda3955f61ce2f30a0593a81dbaffebac5a49" +
-			"e5a8d1308352701d1ca9e620a67a89abdf5f0f8b1a0acfde5819981d4b77" +
-			"58799c0fe41030b86754837712af821c315301aa8dd50d1387b9fb92ee63" +
-			"10777e08229edd54e5e86b086ac281bd321082ef46ce298a6211aaa3aa4f" +
-			"6e55b5a4641220ec94cca73087760da1b1ac3e0da3f438214e691aa184b0" +
-			"535950b715a64d11485940dcaa3f72e0aa521002b1443f5e7880e2a85b83" +
-			"40d32db0fc4c4702e10f0fa24a35da9307850e945f608ad34d6cfdf6f2b9" +
-			"ff4f6b8e9eb5a883546578e2ff3cc5787322e4384640f42dc5bd05f432d9" +
-			"610dcf7c06cdf34762dd2a5e805e24aee8cebb3b4db9e4d1471da995bba9" +
-			"a72cf59ea8a040671b1d8ce24a3dce4fc86d2df85c8ab5e1eb2b0567c186" +
-			"4fb464f48c3ca72c7df2749542ed4d4be51b63769012ce3d06356856b2a4" +
-			"24995a2429a156ad93bc79c705e7b163149ce53a42c34a19680dfe4fd0f7" +
-			"fce38c30dffe9da9bc941d131f435c1398f8284a230e9d6e3992710074c3" +
-			"881d03aa309a9edd0fde7a39c33f6455dfcc5ae3fa20ea0e0d6549a43536" +
-			"b4cd8a2991a135b7d7a4265fb840318813091274414108f13fe191db7774" +
-			"6a5f4270f6d51a29ff523954f84cb76131d4abee79161dcbd97dc1ef24cf" +
-			"db1fade057dddee00a1e0de0db1afaeed1b535f7bb402afa3b297551fd14" +
-			"8c8f3e05f1351d3a8ee2948daaf14e7fc448c4670c906ae076eac5a7c656" +
-			"fd5f9cd937b91e26c9e5adb43c138f8d65e447b0022a524e059f879c6e27" +
-			"4ff7e671f75717233aae70853d5bd7bbb41b43c47bb08d6dc2f54f9ec606" +
-			"9487d1267add72403d01552a3d138abab9ca8a0d2dc32439759aa5695f70" +
-			"1a17d28dfb85850fdb55fddadcdde4d220e4b05821e5736d346e7dc9c945" +
-			"72743366488b1de8975184771361894b6520e3407c5c2e38473430969e35" +
-			"b106024da8618665d58c9d084824a28991a33658d6ec702139e01b65b7d0" +
-			"cc537a644caeee880657803d95f5f67816948d5ab362922f8ffbd531473e" +
-			"b0ff8fde2afc37a4abfa28dbed0be1b3d4ed48a1d02358e8403905d33b12" +
-			"3066e7a9fe2491ee9eb24fc9de7dbd322c8ddbc5ebcd0d92cd102ebac96b" +
-			"90e2fd784fd6d4b699304df23b17d963080a013794322690456be525c071" +
-			"b78fcd2d1148026e44ff14c4d0f942cd44d2b3263f4a93b79ec7a618b4b0" +
-			"d77ae7a1f6e6c7c7e2f498b825bf1954df348bae45ae1d7c87b6787f1212" +
-			"60c9a724429a4a2491ef989f65acfdc72fa717486dcf1984905218e11cc3" +
-			"970a09d71061e6df751f100abfbf",
-	},
-	{
-		key: "d9b0dc303188756312c12d08488c29f43a72e78714560fe476703c1d9d3e20c1",
-		tag: "6b9782f2a09b59653aa448348a49291b",
-		in: "dbde1820035997dc8a8ff3015b4e0674e7ce7bf0c2d994b7977f2d91b49b" +
-			"f200995040daeb1218a0f4307b6b8211913992b070d321bdb947b4ba5017" +
-			"a0885e7e5502710a75cbbcb56d49e1bdc2bc2afa5a0e83851162dec41340" +
-			"bafc41c5e11fcbf4ea2ac45bc57def4742281bbf734777f83c9ae1ea3d5e" +
-			"d42380230570f59c40d5dd9a2d89b75fa3c92664f12a274d965ed8de79a8" +
-			"b37f3763939ad21d1703ad794f617c8b32b20cc4dd7c1b7f969a65e1bafa" +
-			"f6c43f30c9eba256f10201910e2cc31a9b13a46ad29257024ef8f2ee29b2" +
-			"ee63cc5b6230ab9f87cd5cb534f4b0bb08a790466e0d57b849fffa1ed21b" +
-			"fb0b27804e3ff9df7bebf14e100cf91691a493e53870abfad6321f6711c5" +
-			"0fbcf1f0b2c1e5231d6c0a08e710525176355f6f82bedc1f787f0d3cb41f" +
-			"a11e91ebf9f4cbae46035a371232d63ef0d8bda0355af8cd0a2f7d1327d8" +
-			"0ab769ea0f1da0f76ec99cc737b5ce84675fa8a9ac0c98342bb82b5848bf" +
-			"656d35327ea01a1b09d84ab974c307511af68a30cd6978b529a8f58c68a5" +
-			"9d476062ace8897ec0d1a90d5d167e29ebaa6f46d93d697760c8771417ce" +
-			"94c0f3698985a98702833d1b68641b811840ca3d935386dbd4600fbc81c8" +
-			"728c4fd0e4588be739a048f03bd4ac651ceecd7e2fb120fe7190011f957f" +
-			"cbbfdc025f1ca0b356208db8cad87fcd53c5d3a30a7c2a48140ccd4cdb49" +
-			"f3961cef742caedd1e848bf3cacafb0da030416bf3177877aa0bc5f9d1cc" +
-			"41fafcb829d5e3ace9394028683d712552579e024084a6b855830ad9f567" +
-			"ff58f05d3ec263eddd6f56adec378f167e8dabbeaf7d0a9e65c71660314d" +
-			"6c8d54beeca2711113fbc32a2ff8c0daa8373278d10085d2a0660ad53f4e" +
-			"1ade74a483be180180acf9e9ad3ea5bdd9162ccd69599163a451c6837d5e" +
-			"a5e115bd9a560f395128ea002ee739009a44fa46078b18959933fb6e866f" +
-			"eb4612a56ce93b1affcb95fccaa18d71a148582ba1412a5daa07404fcb39" +
-			"c3cb4a2519cc506c1172c6c326016ae2e5410f6a438569f35a50d45cbf3c" +
-			"c46188651aa22c257858f60649cee8c05c75953ce49358dfe5980445fce9" +
-			"614ccd16d333ad236e29d204691ca0bf46f29da954bcaae52e41016556d2" +
-			"f4cae1d37565bcbe84de1b49f344d0200478a38187da29c155cc98184d9d" +
-			"33dca088d70054e0fce321f7a90c48a14963d0ace2b4e7a24b21c14a5e67" +
-			"1994fe1f7d22d1135d4df9268dd18d323fde3603288735626a5449582d35" +
-			"30e2c2225414e05a8c7b987c873a82e272a5d83e59b90f3d7264631d6ad0" +
-			"4a0cf3b5e96596a66ed5bfbc24ab6e4870aeec0acbad2cc5affaee06de32" +
-			"dca06f175bf763cf8e7fdf95941a177e934f0078be7dbaa4c9b6f5c16b4a" +
-			"5607bab5d56144a6ba3c7d9a084b8d1f4b24b6f9754ed207b230d3a2cc26" +
-			"259ccc725e1f8a44c4df8143e13edb5ebf073e2c9d2da5f1562df4feece2" +
-			"f6480987f093f642eb7afa3aa92dce2a8b60bb925cd2d11cf6c2ae7d2153" +
-			"1a9c8f068d71d0e682023932fe64e956a49347aed22b21084c4a84480491" +
-			"244ac6b337b6d12d5551ad5684766c68bacca62bdcafab6603c81bdbd8e6" +
-			"80d9d8b3825eaea4df023142e840f98ee251466a0422d810a54726a9f03a" +
-			"7e0afeb0043e60e2ba4908f951d2e87fcbc372096f2a9f4f2a95ad5faede" +
-			"3796b11ecf4401c3ee3d268bd8c46476c61e0ffc5c43c0f3c58c79e20f75" +
-			"520c102aa3c260972a870fc50f8841fa0553a9e30bf37ad282fb51b34adc" +
-			"7a933ca1691a8a706605ce0b906fdccbe954f8e5f2f63c42599a483c4be7" +
-			"3a041ef90ad930fe60e7e6d44bab29eebde5abb111e433447825c8a46ef7" +
-			"070d1f65862b30418efd93bfea9c2b601a994354a2ff1fc11c383e7bc555" +
-			"9e7546b8bf8d44358b1ce8cb63978dd194260e00a88a8fd17df06373aa80" +
-			"04a89172a6051bd5b8cea41bdaf3f23fc0612197f5573f3f72bce39c9f89" +
-			"faf3fb48d8ca918586d4feaea7e0f2a0d7a6afca096a081af462ea5318cc" +
-			"898a9cc09e8258a837559570cbd5eb901e8c0e04ee88ba31c81a76b000b8" +
-			"0e544feba576b3eb5272b53e46e96a0b35b9c759caadcec61444f8ec47c3" +
-			"45a1d2304e2708eeddfbfa75a98eab3493889047d690e84431d445407fdd" +
-			"99560c0bdd287e0944116f8ac62ab992ed3f1e2b415aea784b03c6904795" +
-			"f4326ff60bc839615f2894570dc9c27cf928ef192047528a1a19ec990978" +
-			"3b0d1a13dd4baf4a19e49bf798975abe2ad167dd574b32b3d0c22aa4d9b5" +
-			"2761e8f56cf2100fe5a39fceae3d865f3724d4f299d07ff899fed6baf7fc" +
-			"eb7189357bf56cf94a6493e61301b43e3ed158cb9c7a0e615fd9888c2db0" +
-			"7f7689762f62ef6b3ad4125e06b07a422f5040c3aa8b8f205d68356c9225" +
-			"56fc4c976165fed9599daeb297498ecf744bf6c7dc5e30604c461ad99402" +
-			"2eea0fb6fe33f82a97b5c272fd24162a94b761ec7e52173e7bb42e88b343" +
-			"64f5fa2c141ed04a86b8d00fd9c25bf77a8dc3e63f5543331405be6bf421" +
-			"6a891089b316aa4f887cb4aff0dfb4e80c2ccd65ddd9daa74b17b4411c0f" +
-			"c849dc748d9b138279dcd9ebfc6e6759a53f5c28a41bb82107d71cc161fa" +
-			"81291a8290",
-	},
-	{
-		key: "fb70ae7ec12264ff9f51124da188e5b11dbf53cae2671363f6054b575b1ddcc1",
-		tag: "d9ab81fab28b3be96fa3331714e78c9a",
-		in: "c62edf20b1d53962b42386eb570b10378f9764421ecbd7c4802853332747" +
-			"19ff4c89c06005050fa9ba6579a844060eb7ece6c43bab520e683e0f36ba" +
-			"49cba259edc6ae35d41e0d7812a7d5edbe4d90cd5e0504d16f4c3f70d01f" +
-			"5a0313de55934b661ce1ec317968c2c4de60f45c66cded8c10565a1ca6d2" +
-			"3a84bf182df2fcb05956ed4d46b49fc0fe3bd23961d9466fde070341ce41" +
-			"bc6e148449360a31634fe10e91082d82def90d9da2c250ea72c58add2058" +
-			"d046b4392b78bc3af5b3936ed568733e8ad5672dabbfa3130a6a535ec73b" +
-			"da8e7223535f49f96cd35d56ed4792c5cb7076720d5461d96a2692b2ada5" +
-			"2be08fb7bad15d15a0108143790024f0f15f5adc275e783aa56b70844061" +
-			"e30952a040e4cb9650f2a010417812790105d8f58bd25d99b0db3cb16229" +
-			"3f6322e86cd5b0bb1505a7b998fb0f81d1e1915faca3c2c8ddea39115507" +
-			"80339430a7955521839deff5b301f3fad54edd5ebd2ac4ec9b1795cb4dc0" +
-			"e2eb62ebca8e886c3f1e507d10a0228c3027b472a7104b815f5ec8dae55e" +
-			"0783ff7ae9a3e6b99e381ad788206b135520cb870ba0cdbe876feea843b8" +
-			"5a82adc95a6d71c555f798da92b82daf0abfcdbc82ec30b1f12d78490b06" +
-			"7315735017a94ac150b44dfaace151896f873923310ffcd41e91bac04de6" +
-			"d70ea71565948c907ab21c4a23703fbbd2a8de6d3095f3d8f901538968e3" +
-			"60e7bfddb9d22036b1c23f4f5f1b2ee22623426a2d5de68c1e1a38e38e08" +
-			"e2b5670aac1edff69e9c73c2ca56cb69c709009ef1d541aff1fdb2b40c92" +
-			"9b87f162f394b76cdbba1f5605993e4dd9c312321d59b0aa5c6e33be1b10" +
-			"bfd00b92d4c02db064d0e4a98f2913c89051b0f0ead163deb5087b6466d9" +
-			"84f57553b0fa53850eaa142e072fd91802eb9f0d2eb7318dd620555e6ce1" +
-			"86706b866d41cf6ba81f100342faa14d801dc6f3d522db38fab17a879fcb" +
-			"b6acfe922163505bd23a6842f6ef6397ae5fb6e6016421998bd43b0142b0" +
-			"3ca3b16d6ccb7a47891c75c687d791a930b26aaa2e3412e7aa16e2cf1501" +
-			"7bf6df6d2e1c289af0d7ce03954a60c1dfcee5e4b3da51eb43ddd14faf59" +
-			"082005d0c8b104561f66c002ff426be60be769282fc5685cfd1968df1941" +
-			"73667e48e9ad681d35757f1199f1d93377bbad093c8cc3efa2bcb6ecb703" +
-			"694422772d15aaa58cab9e9ab277ed510f684114cc4a44ccadb3eb1c9a76" +
-			"d8619a9b7743106df6fb6f927ac49b22ae5bb9a9a4d231e340a2cd0e3282" +
-			"53f6d75df694826f60e4b3e758398793eaf73ef5d4b56cd1471e16400f40" +
-			"4a947e9737f4f874fe09a29ad799f4525156e3abbf0585c3c3c0a3744c86" +
-			"5d56db3d2ecba6bcbb1adcc8bf5f3b2a2d46d3eba18cda55201598a8112f" +
-			"d8f14e205f0e615f081b8ff6c5aa6669da776bfc7c34d5af4d0b26d0d819" +
-			"f6aacc53cf3c6653138b9a962acee9d6ea01d280c35bb1f05d1509238ccf" +
-			"004c5013167f804d1780d9f4ef9d45742fccac346b0472bde24ff5db9ae0" +
-			"16455a3c02256358fcd8e6a9aae94f8a37a1a3da58a889bbe3d295e16544" +
-			"2e580f59bdd31c92ffcab40c49c1cdbb4db1dd4882b66edc10fcb1704203" +
-			"c518c1d8d4c268588ce13fc38e0210aeb47d11d2603d4b3de5c6ff5e969b" +
-			"9d5904abb282b699bd04a6e9f1cb323679e30400d725aab128a032745dc0" +
-			"be05a46b02b34b93bff02523cd8498c021fc35a488f164a70ef1ceb873d9" +
-			"14a681d3a3a34cc76bfd5a547e2630d7741a284511bae5897d9f7a197fc2" +
-			"456af5c6cd7e1a93d3388c7a990b5feacd7749cf39fdecdc20adfdd540c6" +
-			"9d330195db7cc0d4555ea5f5356a3647e2265399f153c34ed1e217c5dafd" +
-			"c2c5dd3d566c332c7ddacb0d76ecd3a0ad505a4165443aa81b0f43cabfb4" +
-			"62942fe74a77c22b8f68a8b1a6d712d1e9b86e6a750005a3796ba1545396" +
-			"13170906d228dabf572ab969c762f8b296054f23d5d4a37bff64bf9cc46f" +
-			"43b491b41101256018376d487fe8097f1653a7a9e99e1ef2492600598fb0" +
-			"bbb7df8270be8b9106126d6f491f8b342a96ab95df6133e883d3db4c6a99" +
-			"402aeb58d371263a32dcf76d33c8904395b9cf0016fdfc15608eb43e20b0" +
-			"99cbe7455f7a76f69bba058ef96f83ae752587485657f89c7f26fde7fbeb" +
-			"a82ede581ee92821dc13b8202930aa58bd4f1c86f68926baca0d06fee642" +
-			"ea8c652d226af91a9638a0244f1a03c7ce56969b87cd5c1f86110d192e0b" +
-			"98dd979d74acca6c1956b1127d9a1f456053d17974081ed8ced0faa4293a" +
-			"319e5b25ba285c1151214f52c283e39c35af51c4572c8e395b7856697bfe" +
-			"dfc4145ab4ed0bdbe43ba509c06a196ae6bf30d7582550cb546c63b51833" +
-			"cb0dfff7196d83f6a1c6d6d712cce2ec1989fd9ff5a0a22ac5022b49d566" +
-			"58f196703e4809e7624fe7cfa6c13b378f5aac7e66e657ed7eaa942d1a00" +
-			"544a947199f24d736b8976ec2cfb563433c49ba131bd08b63636854219d4" +
-			"c45100c98e3092773ef492dd9210bfd8f54cfe2cddafcf5c05468d90e620" +
-			"0c2ef99d17fa6992cc45eff3072b7cfd51cabb07ea3019582c245b3ff758" +
-			"0302e88edc2c13fc43646ba34de37338568baa66ecff3accfebad88d143a" +
-			"fd1c3b09ae39c501e3f116af33b0b720d6c2baf5acd7f31220788b2f9017" +
-			"3ed7a51f400054e174d3b692273fcab263eb87bc38b1f486e707d399fe8d" +
-			"5a3f0a7ed4f5e443d477d1ab30bc0b312b7d85754cb886e9",
-	},
-	{
-		key: "f7e7affceb80a0127d9ce2f27693f447be80efc695d2e3ee9ca37c3f1b4120f4",
-		tag: "41c32ced08a16bb35ac8c23868f58ac9",
-		in: "5a3607fb98eaea52e4d642e98aa35719bfce5b7d7902950995f4a87c3dc6" +
-			"ad6238aadc71b7884318c2b93cd24139eed13d68773f901307a90189e272" +
-			"6471e4bf9e786b2e4cf144764f33c3ac3e66521f845f6f0688f09eaa227f" +
-			"e71033b0f74295f6ddb91fe741323f2b54f420cb9b774d4291b06219f1fb" +
-			"4410b55900425c5e6fcabec76a5c2424d637a1641db6f0f6cad564a36a91" +
-			"0f49894bfd598e91f38ceea65e8253c1284f210cf7b50a96e664e562f3cc" +
-			"01c4fc490fa6d4679fd63fbb3ed8995a8a05166b573e92d22ef4370c6aac" +
-			"74ae94c94177e5f71143c6f340efceefda679ae76f6ed7f26eaa4848a8de" +
-			"8c40894316efbb06400f9695b18ba279e8947c032a84a40ca647d9ace457" +
-			"6dd0082494d6bd7be4e7928e749c78110af8774a5d43e9c9479964e2fddc" +
-			"ee51146460eac734311225d08c60706e40f298a7cb97f369ef599be097ac" +
-			"3bf1c275497bbd68968a235fdf8a61bc7cfeef0fe451bb04e662ca39f34e" +
-			"a8e3acdd0befe9762f9eeb275c0cdd43c80fc91131d1e0e790020975ab65" +
-			"afbea81f303ebd86760821efb4cad7cc01fd6d6fd194ac5ffe7703d890d0" +
-			"169e21b444cdbaf691fc741a5d99bd47357c37785755fa72582ca4754a03" +
-			"b4def86ded39aa6d9eb3f38801077e6d17e3cee3fb57ae83f30c79c3cf29" +
-			"0e2739c6b7323612cec3a561ebeadb4faa642f150323aaa9d270658c907c" +
-			"4c1610a5e1834730c08be3379cf1abc50c30e2bf01ce903927c27d85e135" +
-			"3db9e216dda8860c45925e2bb791abe5c8281ee6d16607bdca87f60662dc" +
-			"bd6e20224e7f009a86db66fadd8e37e0a59559328385090c6953cd20bb61" +
-			"f28a734fb056714f5159977f18e5c5f11de75f7a00ba807e47a29e4da32d" +
-			"5c67ec76ce4d7b669b5e6ee17e1df7c673dd8a7c87fce665cda8adb9547d" +
-			"1dccbdbe7be44846b4b121b0bfa65e4ed530789510d79bc4477e50178060" +
-			"f2668ac8956f39ef422ecb0e4cf90b8ce508552eedeeefa6c7d1bccc077e" +
-			"8088bd7e0e6aaf0bda9f11c412c270ee2ad6912f9808f9344a4bb137bdac" +
-			"b5b9372b00b0de026a8f5d1fb13972e1290b5005689f7636c43aee2fd443" +
-			"93d390371ae573f0e064b2d7df552b9adf04bf173d71c621795b9fb503dc" +
-			"5e918536c6ad25ce4a76f70e6b752b6d44be321187269a19bcf33ec899ca" +
-			"40e88b4eb23217095a85057bf95d8a54812cae4a7d32e0c2966a21376110" +
-			"74c6c8c3dd45a553c43c675d23308709f91be0b235d0222aa5e1e1ce08f9" +
-			"c6b45ceb5b47bcd7d7b2d4380bcdbd6eced452d93e6d8cbe18123277889c" +
-			"7f86b15fb991364a501fbf5d8244f2e3332ea0ab49e833c6f765017a4006" +
-			"cc7cd1a0365945a8d8873cb21832b210c83e451c01ac949de2fb0f7a420e" +
-			"405bf64eb251c6f022181595d68174b91e503187d3b3f49b60c23e44ea40" +
-			"ca20311305b413047bb22e89672758b74d6bd1a06decf09e9556421087a4" +
-			"0c1d2c44c5fb13d4d9625581ac4ccef1a1b5eeb5689aac5c0291aebda276" +
-			"50daf9d4396a64d02c6d58bcbd609d9a0017880ae0cbaf02ad0f1fc8d1b3" +
-			"ec987ffe13102d77352690c9b761bf13ea0b3a8ebad4a0823817fcaab4d0" +
-			"9b0bf03486620761dc77a6ba007ba07153b17425c4026597473e78863cbf" +
-			"430c0e5e9b04a83ad11506b61b8d9be3aeb06b5114e0d53d4724863eba12" +
-			"4f3b974bdb0d02743520409910621cd730c97ca984fe2921c38055f83ee8" +
-			"c4611db92e52d8ea51d89203e89df7586c574df15f3a96ed5a10bf04cb27" +
-			"f9656b5b11cf35fd21360b029ab26e9a741c6b3e6357aa1a41de2cac6e85" +
-			"f9a49e3441e60a60e74f434e1b8cd4454b11962e5507ebf904e9d6c52a7d" +
-			"9722300517c434758fbd6191f4550108b143eb16c0b60094fdc29327492c" +
-			"18a3f36737e506fda2ae48cd48691533f525acfffb619d356bf8347a8bbb" +
-			"4babdc2ac866e497f192e65a694d620687cfb4f631fbd6ae5d20ac2e3a12" +
-			"4d85f9391a240b616d829ac2adceedf8f3451ee77e4835639b13c622ef8c" +
-			"48a181fc7598eacb419fa438d4046aa971942c86b36eb8e16eab67105783" +
-			"d27fc56f5b66f35451b2a407d4648a87ae70807e45bccf14983b3abcb198" +
-			"d661d562dfcb00ffc569ca967171746e4e36f839946bc7d2ea9a0eda85b5" +
-			"a5594f6a9c1b179f7230eaa7797a6aaf8628d67fd538050cf47aa654778c" +
-			"11dbdc149458c1ec2233c7ca5cb172356424eb79479b6a3eed1deb9f3278" +
-			"5282a1034ba165032b0d30733912e7cd775cdb7e0f2616b05d521dc407a2" +
-			"ae7dfcf46fbae30547b56f14dbb0ead11b3666666c45d345cd5dbfa200ae" +
-			"24d5d0b747cdc29dfe7d9029a3e8c94d205c0b78b56d5e18613b3169bd44" +
-			"1b3c31513528fe102f9bac588c400f29c515d59bbcb0725a62c2e5bfb32b" +
-			"5cf291d737e67f923080f52d8a79f2324e45a3bd051bd51bac2816c501af" +
-			"873b27f253ef9b92ba4d7a422e2fb26a35c1e99eca605acc10d2a60369d0" +
-			"1f52bca5850299a522b3aa126f470675fa2ec84793a31e9ac0d11beab08e" +
-			"2c66d989a1e1b89db8d11439ad0d0e79617eafe0160e88384f936c15eb15" +
-			"ece4ff00e1ba80b0f9fb7a7d6138bdf0bf48d5d2ad494deae0ccf448c4bd" +
-			"60f0788d3f2b76de8ad1456f7572bd0ffd27bc2836d704d95e9c0df34571" +
-			"9dab267dd805577fafda03b834dd225ad9714d2bd182b4103faa5975180f" +
-			"90d5d6cac1825a19b9d4c87cc825512ae9dbeb33d2759c990905050f960c" +
-			"db3eb364c15b593524c882902b2a1d7fe40ea3f54fb0202fd8821463c7e3" +
-			"4b02a1209ba0048a9805f0468a13e03d18009318ecd92042959be263a51a" +
-			"407f1e660632c4247419659a4e073a8e9cd4a226763a7daea464d5427270" +
-			"7efd053cb4efc0504602c4f63e7d247b55db2ce1c07138f585d16cec97a3" +
-			"0731d5aec2166cb4de41695feb76280cbae1af8a2e67c2d5a3ac5487ffe8" +
-			"640f308ace6137e83576b79d586b663122221c20aba7a6bf60f73958f436" +
-			"59f087f850ba6e2d7fd862249c5fa6b20e3e43d4f2aa10d4c9cebfcbdf02" +
-			"6b8d103e4f89b93dd8af172f421001c8b162bd6d0b847a58ac108b6d6cc4" +
-			"9c7a9ba069deee",
-	},
-	{
-		key: "e3d21f9674f72ae65661aebe726a8a6496dd3cc4b3319f797e75ccbc98125caa",
-		tag: "3c95668130de728d24f7bca0c91588bc",
-		in: "baaea2b4b4cbe9dbc4fa193c376271f40a9e216836dc35ac8012476e9abd" +
-			"43dac6b9ce67dc6815904e6c84a5730cea0f9b4c6900a04ae2f7344fd846" +
-			"58a99513ffb268c6899dfe98d605c11e7dc77de77b0d30986f3051754503" +
-			"7c26be7b719aa9ca1140cfdf4c586b7fe726a8bc403249396a11cfee0a6a" +
-			"f6c5e72259785cfd13c2897384fe527100170001ea19106aed38f7d5d9a7" +
-			"ad43f0b41451e19989192a46b4f9734a774b6304cb74feb7d83822044a24" +
-			"2e51d55c0b8318e0439493bd1a57cc13f6079166cabc46877d003dcd39b2" +
-			"c0b90f6b32fc77acf04a6c125e11b35d91e2b18401cd53df4aff804e3c67" +
-			"a8bb3894b27c6e9b0070b53a85aafab0c0a253f9cfd4d3cd3be52428385b" +
-			"24a3f9f71660ca2c38474d14a0309e2f400e2c21af6e379099283ff241d7" +
-			"51da5a96a8dcbfdc43b913b29cc8cf8020eebb4a67f5bed31f2e383f8656" +
-			"8c815ff172382b425e95902e80f5fc219eccb51b656d37b56660f749e5b1" +
-			"4976a23648680a472d02ba71476e0afb29a0e084984f4eac3befbf8dd802" +
-			"2b7dca4dadd18bbe58e49c49ce48a06a71557a9a620c51e2623f818e4d62" +
-			"c2564c7ba04595cc109685869b183faeff2ac7a65049fc57cb10fb01951e" +
-			"a525332782d691f9759ec2ecd68bebb9c7aece5d522a08ce7830be520db4" +
-			"c9d60a2e490eaa0c91e37b256a97f84b39fe3c77953748c3b86fd84e9547" +
-			"a298c049cb28b8c85d59548b8dce635d59487c9de615802d16a8adc4c0e7" +
-			"80f35b9f10588a431b39b499dca929ab9d225f26e5721820627fe62427fe" +
-			"06d5773a50878b6effe840dc55bd3ea0c35168f6b6a972d57e8f88c5993d" +
-			"1ae33e0b7e9459c123753b518c184de7aaf429df078c9a18a29af77c727b" +
-			"796f5c1a501fa8105ee873c4e78c907142eb19690638a182fddb413adb06" +
-			"d66db19c7f6f46dac582bd72a6347b4427a576eb769d233febaf7be8f768" +
-			"337273c12253924f15653f9f3602b783703a81454a1dd7a8772a9ab1eeb8" +
-			"51be33e0c6c0708f3cc2012cabe8e2f0c38e35372abe27bc148fc4e1054d" +
-			"9d151f80aec0232a3a92dd77928a3678ebd7d09ba7b4e1d83227257292c0" +
-			"b8bc4a76de36bff6c9deb383029afaf4f37d5b935dc080a18665545e4acc" +
-			"195da0b9545d8902408886204b64f8548b32d012e0cdc520c17d9fb3be97" +
-			"800c2e2b945cb09a75a0a49e5d4d81c4194d91e839333b2b9b9e34d588e4" +
-			"e20cc1e911ca0a1429fa70ff063f0090fd842f89dfc5cc44affcce4e1e1b" +
-			"8b11c612f66b074c03ac2a055fd8f51ac9ed4f2e624589ff5730721d077a" +
-			"fb4c19e43abf8cf3ffa698362be8be51e92c2c91a4a56be64d9ac6d3fbaf" +
-			"5536a24c7fd0adaf74ca84c508e5e8c8bf7d4254e0c44158bd26acdf3f64" +
-			"e78438b3aaff89ac9986cef1e3a88d5bf2016340367a1cacd01ec167ec6d" +
-			"185d93a2a220d718b43ce1d429d2cb598605660b030e51e8d75fdbdd5b8f" +
-			"8677675e196a40a88285b18b24c5d2d594bab3d457e6f9e503e38cd470a6" +
-			"9ff8037c9a0a0f110a434335d954fa856a3721e0edcfb14287c3dd9639ba" +
-			"4db32b7da0670dd0a872e468e3819741d0d4ecf0a4f7a011bbae1493c01e" +
-			"642757491189f8664be3ec6437c4f3c76abfb0276e44a4d28871d3487c2c" +
-			"ce2f230452cb06184bb8620919659a7ba0a3d5c12ec25678b03403715ee4" +
-			"acb6a53d281036d8f3a085143cf5ecc3a0c6c92129caa7ac1f645c7bb95e" +
-			"4f63da38dc319e2ccff4a9006f9b9b1a38c4c39f6dc686bb82d43fb9fce4" +
-			"0c767d3ff22f52c5f9900130c65bb6a9cc7408a777d49b70946665f4a733" +
-			"5099376b276a43dc9a6382bb2d40425f6481b1846148434c672b84dd7a20" +
-			"33deb5140d43ba39e04ffe83659b6deb48629e1abf51e68748deffb756a3" +
-			"ed9e0807506b248a024cd509f539f4161366547c62c72933584e851599b6" +
-			"82ec16f1d79e9c6a01cff6f51ba7f46b67cdca09f3ab8496322b990a6116" +
-			"8d7574854a1cb1cb8f30a303dbd13a095df56dbb940dd16ce79879cd2d73" +
-			"80a419842fa1b34da668286de4c1ff5917b7aaa64713c349dc8f855d04ae" +
-			"de9a3a4d0739dfc36510b1e7bb1695418164285c44631b4b1a7c5798ecb2" +
-			"d976c1a3679a827bf0e8c662567e402bcc1354222036ad5959a6f0b8508c" +
-			"6a8c7d4a63e7dde154d778fc80a011592771d55801c7e1297b00b77f80d6" +
-			"314ebd1f5b3057398d1943599897cfabb65e7568d8fbdfcbecfd4b8a83ca" +
-			"0a7bed08ab9a656424831e0d7718c15727af7c83b2ef5eb5684aa044eca2" +
-			"ba896811246766248b20a325094a4b4159f9cde1ee349be6dc3c9a190453" +
-			"0349212a9537f65ae333c288753cd2bef6c5beb2f4164168d965a2c0fb9c" +
-			"c8c73d9e776e23d53ddcfb83bb7dfe2a1b8c781280f449d6f310faf8b53e" +
-			"89e6a611d6d3f42f2aaed5259730d149b3e7dabdc9f865bc1555374738c8" +
-			"456abe112e9628fb31efc2ecdc972da05987aafce728ccaed246cfcdf518" +
-			"3fe5dae528bbfb99d33194167e0f84d462d3d0da83e92227cf57922c7956" +
-			"4fe44648d87c69ad708e797972c44c4a5183fd5d1150a1182e3d39c3cd16" +
-			"3920f1d7ed83992bc4116d9351ae1c6c4827d1374242e374310409f32d5f" +
-			"0f38c78b6489c568b791c70394d29ea2516dcb10e51bdad862ce3339d5e6" +
-			"14fe14f150961809c36e0a2c8eb872e9f7a1c0956fbc9194cb63ff9993e5" +
-			"d0dcf62c0f49e81dbe99f3656c4dea57b766ae9a11254f9970618f1b33c8" +
-			"f339f440de240170f7a21f03ff2da42102b323ce2b9b7d0de5aae324d1ba" +
-			"c87b1e4c5279a566bf659778f8b03882aded57377a0f1b063af2897060e4" +
-			"23be7cefd4aa9a28479c16773944d254fc21d3e1acdf508b7972372b5991" +
-			"3b8b088e93471a7d54c6ae4c52ba465ef07f19f269677fc2f64d3fb3d7f1" +
-			"9069d6c7001d4b002ed6683c59bd5651a450503b68a4a00820b8c17e3263" +
-			"18f32c21dfbcb2a02a104edaeff67ec09533aaf3d1a7fb41aa5d506ccdbb" +
-			"e6e35fa0a263c0aad3acc91182addf8c5bdfbd0626702694b8d652a63c65" +
-			"8d6b2b7c75d015630de508195e1fca9573b61bc549ca017c4bd888194d44" +
-			"3e031f36170215a301f922736a819f3ffda69117170d1933300366c5f2ae" +
-			"1052446ef7c3b82c5868be158a881597132f51c91c80c24ebf621393dc45" +
-			"05fe057364a76ae67494a8a5f67acb551cfe89f447df272ed9c1509fc330" +
-			"2c3e16541452d4d68438f26858724012ad3b72c094b9f166c6bedb8336a3" +
-			"41e032988f39cf53535789b320b5424d07b6bf5f8792e3aceb0e868765b8" +
-			"611d7905089949e0c273e2410c72a146cd63981f420405bd883e5390e985" +
-			"8214a8db714e8400a21d0636d7e5d9671a3582ab9ff032170b8dd6b9d5a2" +
-			"144d065228fa54aea9a22654df67f3f62c5fc59d68914d8b219829b536cd" +
-			"2ae937ecccdb6031d94cb3",
-	},
-	{
-		key: "84373472e362a356bd5c9b50f55c588d067b939009944f02564f136c62dac36b",
-		tag: "12dd5297cfcec53deae1dd5f9325d894",
-		in: "860d9b2954c3daf18fd67eb8bd9e6e3de2e4988ad9b04b1987219204dee2" +
-			"388db1c59a935de27bce29e7cd3ebdf038785efb35eabd4c3785a62b1d9c" +
-			"3ffa25e2273cfe5eb10b4ec6152cd8f21dea415421b452efc7cc4ea6bf1a" +
-			"b85fa6614e7f6d650125424865386ff8ab53247a63ff023b2d0753a9e5bd" +
-			"458d6ab0156fd3cf2d5002f902f927a847e8c4a8426b0a5191f5e237d590" +
-			"2659ce9be9024750d1d618a6b8dd57efb6c2bbac2930858f1132639391aa" +
-			"9e8a620a2a7d64bb7e943c77753401b5b619d95ef857df25a52b4eb97372" +
-			"a05416706b2644e2687bf1d42c0cf06e5eef8a1fc7e178440bfebb85c44a" +
-			"4837f69e43a1789728a999c5e04291576e757510f22bca11583a4e93688b" +
-			"442f2b2dab8d5ea9441ff09b8287862ca538ad979297cc75510a3d9ef36a" +
-			"662b4b7c373f184202befa5bf3f315642e6210763d033b7e2c59731cb356" +
-			"045e9470bf2f83cd62f11b3e904b0c0b1be99bcb805150ba7ef12b8df3ca" +
-			"bfc5055640687d710ab88e0fa8034b26112ebfd044a4b290b1c6f6d18c31" +
-			"ba9880b1cf2d81b5d02f00d6d351da5dbf47b6a5cb7b53eaf6de52c8a68d" +
-			"053602ccffa37ccb44a7683ab4f8a58c4bbc9e140e4e6f3cc10a5c07ebd6" +
-			"070818db983f9f415168606011efab6b8d7b4e61e8eadd8bfd8d028b89bf" +
-			"b0a16996252d7b4ee4f9ab50fc9d6e482ecf99beeabc38d70efbb9a0d4b7" +
-			"9a1c5d2835adf8e25111352eabd24d562644efc97637f695e4792f2049c6" +
-			"00f4d889ceb951cfe289adf159865d013046985d7fe2598014bf2dbbc528" +
-			"b4166fc2180e724ded8e7ea1c8d66338ec50d955d5594a0a7b4655338b70" +
-			"e8978485a722df814fdc6fd2436dbc060121fcb575672b2a5e454c1209bc" +
-			"2bb21a99d39dcb3c697306dbc2104d60fd8051c43ea2fce268987d0ec249" +
-			"a5c02f91d3b0dfee181b3cf8ef1ba9665daf7ea1f1d3b216e378943b78b6" +
-			"bb41e5dba095748bc776f8df6383033a1f5504955da3f42153b1c7ea83e2" +
-			"f90b990ea0c5bd3906b5c4060b19f447ec7762916b8766e5a23bc4d39cdf" +
-			"8e27752df8129b60ccee1731e47383b589d4fcad865eed4041a186df206e" +
-			"9fb69ab6ea092e36f186a6fea8d77bd7f3ab0fa0e29404d617317c75c832" +
-			"854427848237cfc18486c95f7213b9d53f324da036e8d298133b5003984a" +
-			"b9d71836f9f1b059db90005a9067c261bd85aaeed4d623df2220eb52b73d" +
-			"d683abcdee5cebd411996f853752f638bd28df6d78bec2ed3e00d7beea06" +
-			"2b81c19682ffb2f6abe3a3623a2e0570650c1384f1818d76fbefe3a7ef3f" +
-			"46138160ef897f9934e00e066e215230e719c23905dc60d7fa4d666fa52f" +
-			"e7737db15126d3262c3a4c385cdb23ff3b56c131e43b241f4a6062a1a248" +
-			"de9f13eb82c11f7b6a22c28904a1eb6513cdb11179067b13c7b5f83a58c1" +
-			"4f2753f19fdb356f124f52923249d6e4a2c8dadc8bb0fc91e360155a14c5" +
-			"c194334b9f0a566d51fad98592b59c1cc4b40eeddb34e64f337f83874884" +
-			"0583f853398c343dabc29b9444be1e316309fb8d81304d654b3d4bc4cff3" +
-			"55fc31278fe22e649324ef10acd247c0b72397edf96a1c16bbbef0640296" +
-			"4d219575fd23c36efc1fb8f8a34b510ba9bdfb3b478e236777ef7c6c47f5" +
-			"5a2bd0383d8eed3759456ffcffb15e61985b08c022658a5ffc875821bdf8" +
-			"83f69f096dcc72a96888c3af76db57a54be701759670bf05cc9015f5bf1a" +
-			"745cf755a25b1403a870875701427f820c4b29eccc260f30113629ba03e2" +
-			"785014bdcbf34d0c67aa6aca20d2dece811788686d5a45820d2980bf7d69" +
-			"d5c820a09bad7bd95166f63dcfbe8652565c285e60e2704955d69b3037d8" +
-			"7f5e6567d95b8891276d5cf7c59047d10a02ae4a28794405e2524ec2d595" +
-			"1b36ad1b9d5265fa098a033b88aa66cd9eaf01eea49c7dc4cc51c486f624" +
-			"507a2be23f152f43709b2cfecee44945ca506950e90e70164b77e12e1c13" +
-			"0b4d1021c2afa20038f190096276cd22e89b6e7dd10fd58fa033c9d42536" +
-			"98de3f4908203be8dbf259112f840c76726d982b4a837cae7139e27182b6" +
-			"1b4dfbcc50e42d5ab8532edfbd30f668879824e9ebc34b63ff1526cda81a" +
-			"e38352a774d79f73219500e57f0159a32326195d8895d965071834876a45" +
-			"c1a3c0bc4b1638535f7d40011cd5b23343fc27fa318c1aa3f9d8c43351c6" +
-			"6148dc2175e0e620813266da3000954dfa22048f305244629d512e852376" +
-			"6248a897a3ec3e2983aaa8a0f025f18feea57a5153a59b02604ebfcc7a9f" +
-			"b03e62443df88ead9dee955e23bcf6528c278a353f254c9484a67a7b263d" +
-			"a301923a4efb6866aeaaafd428e6da48781365bc49e90cd16b2388220d08" +
-			"bb9f79d14012b5a8299a651917b6a829488753b6ca449a14e8dd8c5fd5ef" +
-			"657d627b8e7773475b802655dc033694f24376e3b01e519d1aa8365d0e55" +
-			"92d0a4adbf555639b6d75d7ee59a7d12c6c11317b7927f11bbe75ed90508" +
-			"b0698420e231206704d22dd1f1740edbdcaf19a47d66ace4eecbcefb77b0" +
-			"85cfcfaced4d2d6048ce76434eb79990f0898adb4af2c377b581ebab3f3a" +
-			"150f40dcae002d4caa60050591c0de4ba83bfd59a08670beaa4641aa9829" +
-			"bdbb720d6eb8b2f3e864a98676a67271a82cffdca2b3590a0b5f97efa5d4" +
-			"ba062b4798707159782bedc75e5363d5f5d55ec2bef70db22955adf401fa" +
-			"c3b7af937816eb25d54d9f2a92e5a2a04bd8b8d7568204fd289f5ed2e033" +
-			"a76209d288e11e8a4dbb06b9029e90cb186446746853f02d738e06bba538" +
-			"894e03e2658ab3d7f9ac861d2cffdf12396004d1cd15f18812d3803ab9e0" +
-			"6f41c9b374d6a0678bb82ce06d9e3b9dbc8d2e90b8f64d0d040f3fa8a3fa" +
-			"8be71d2b3183cceae1bcbfa2353689d842f7d7052e5699dcc70ab2b58761" +
-			"7041e5aa1e2f41911d525505f061d3ca45152f5a7a1fab50c674e4597a52" +
-			"b46aafb4ba57413879cad1308321843abb7c39696fc2f2e225878bb1191e" +
-			"e151cc76f1a1b8d491c1672fecbf710db82dcd32554361967fc839c8e5d4" +
-			"e488856e1b9382eb3fc3bdc3b6886a3cd79761b02bafa080a745ef6afa26" +
-			"822f1d10d5e8eefb842837d82c9986e78fc3390caa142b7643de8f613e5a" +
-			"890a57f5883409549537f8139534f4ca1b60f33e42be25433f1d82add530" +
-			"6a4cfce258c0d4f1f3c9148ffb5c4b626d51f78ac20bff0393b7fdb4b9cd" +
-			"70fee7f69892c8a9ee089c6c5c7bee0a1b825e5b9517f2c82d6c149735fe" +
-			"45a8839812c2deb2a355b6230697053092eca450b7b0d3242b2689efe364" +
-			"09e820d91fa4932034d96495d9dd3baa4b385da815a7cb69438ff648b326" +
-			"e7efe8d688e88570ba59df7c439faf72c95317a10c984c5ec0043407e9fc" +
-			"9b46487810eac19d2bb40e0a654935f76e7d8861480c5f48419eb33084d4" +
-			"0e1070e5ad542c94f58b49e67dd05b6637a2c67d41451b7e00ba30eff221" +
-			"755d6d427ec634a2b95980d274a89579feccf1c7df3787a9435e588f2496" +
-			"06a93b7ac41c8aaa84b91c95cad9463d4881de7353d95b13bbde4c9da90b" +
-			"f1fe96257309a416407c64368b5564f022c4a493f2a39df1696f45801e42" +
-			"a5",
-	},
-	{
-		key: "2d0035a30d19b9cbc7a27561f3ab474c01115c4499b4adec660ea06ebaa1a14c",
-		tag: "a2c77b55cb0c076d8ea83cfe0e64f293",
-		in: "4e667580ba4f38f64e5cb5566bffb486dcae10cd17acb3754251e837767f" +
-			"16429bba2b832f29ba538f97f3556548d163be25e69f88fff0743150623b" +
-			"e0a1d82af9384ca335927a0e9cacc3dadbdf1e24fa5c81f2602d109e1400" +
-			"33929e409b9a0fa4f2653944edcb8b3ef963ba7f8806196c73bff0ded670" +
-			"c6def5d240c5f3daa121f8d5bec9b2a0b0f1d62d54b013dc742d6bd46325" +
-			"460f692b76d4991f0796820ddebf150c7d33829795784dd2759b334d2706" +
-			"70a7264941be5d99d460d078a9eedc3660cb3176ad302f9365f0bd698e46" +
-			"9f3e63511abc81109995dba17be1abe8bcd28407c7fc8d02c14794bb033e" +
-			"178a94f6dc73719d5bc235f980a16eccb4121ca83b13c4e165931ae4f192" +
-			"4292f8cfdf1c3ed40feb71e13d919b48fa296dddb4d23114a3d86ec10f16" +
-			"f314de4cef813ed24b49f4c7bc44cb8424df1f70e8d77366161c7cdd709e" +
-			"97610aca3a24fb2202ffe15eaaa25d711cb5179212a2c6497a13e5d7c365" +
-			"7bc502b3d2ebde2e57b714dd9bc21e73795f3d35d620613918c4c9aa0e89" +
-			"031481c97a5a4c15ec6abe42d40498c33d71c823bf1d5bb5fee457e2fff0" +
-			"bf777c80c6e3336ab3ce793440e74b336a8f7034f6ea2e4ff5ea4ea7c350" +
-			"65cf2ccd2da1d6df29bde10f4cc0202b5e4cf7ed097da49b970a6db41e5e" +
-			"98f3845b42f46663b1d1ff01da71389a8737ba8f51eac1ef357ba5ac9a80" +
-			"dd2c7f9476111dcd651fc33f4c86dc8658656f3f02a8878bc38ff0d0a1af" +
-			"2e31fb92eaef08c50195490818661feaf90e8b6f5daa1ebedb2cdbc8d5dc" +
-			"16db3505f9611ac46bc37931e02c1fd6aad6e4b7e187d5e6f990fddc9563" +
-			"2b33f55bf68b0db3890b11113ecc839a4fa4de25160e574289aabe4d8fb7" +
-			"9cecf9d2fa75ac8d0195beefbdfe0815f8d7d9751c1280a29b547149ec7c" +
-			"2295f5afa53cfb516158086bf203357eec2a5db71143f996c81555a47f92" +
-			"209719a71570a5553f1ff9b4b41827dd74657b463f36623565f0c9f4d2ee" +
-			"8735d6af56ceb3b3d0ec516b22f0ddafbc24647481f61ab169e2616c91c0" +
-			"e1f6a35436598ed801670e1dba76226cbd0544959ebe70f836c8a7df575c" +
-			"b907d780ed5aa0d6e4e8e0d2f457efe89a777374aa49d4961db96dbb787f" +
-			"021d99231001360d532a70ee1fb94bd6f26524dd4b7556c6d40e08723d7f" +
-			"9905aca66c4743f2bf8b34493bdabcfca617809a867bfe0a4f94c756a6a3" +
-			"dcd04ffc0a3ac671a0afefe0d5d447efcec48c6368998760db6a572676d4" +
-			"29b6d3d6e0c815650447748c4b27541c5447acfb8f7261b6378f3fc0fdd7" +
-			"375eb9d458648c7fe9cd96344f11aca912cc5098e9ee39e0b6794cc1dc2d" +
-			"f1b10f927102705efa20e667b63a91f935c17764650b287f5289d5790766" +
-			"555f31985c5aad94c652ba41fa9c0195d15405f1fcce9e23054a42c8a252" +
-			"da83bf6268782ba44edec5d8f94a20b1830cd1c5894cc6b9b52ad0b12a5e" +
-			"cf3195a32a0b02483ae3b954ac6f3af1e0f334221279d03a72138f3a2cb2" +
-			"1e706427c4d604674dab88d429f28a67be7a996126e077a1dcf8989d90d0" +
-			"8b08f4abb9a546b3c64ecaa287bf3468c59add86365b885f52afe13ed8d2" +
-			"69ea61832a7ecbb96ff3336f58a1eeaa6dde3611f3ff7c2cc8c9b745b0e8" +
-			"b5919914245a49ac192cd77d10deb9a249623f696065a532c20eef9e9b0f" +
-			"e706579566a9eeb14d4e8251a7750e29eaa60f034c1a7a1d51aa03a45fff" +
-			"89acf41080deec5506128b06f003fa46bc4021a82fad6a8052a49744ed69" +
-			"45bd9331b5ae80d873cd042bff079b2b9d8af8065a22c449c32a56dbbe7a" +
-			"80d0f3e30b9167532506915883dce0aa9cb749e4368c595c5bd33b57e36d" +
-			"98cc9bf91cbfa47331d69b5cbe9c92bc66c0fc9ca8717bfc108e1f710333" +
-			"14dba02a28b9aa05890cb01ae9175806c3c4215bd446f6cc96ec5d08982b" +
-			"4f83cd1646160e1d306b3cdec02d251f0901b03e8c3c35464eaa5082586b" +
-			"b55482db97599d513ed8d7a82e32fae302684b7ede058474c1fac7893444" +
-			"16fec93fb982accd162dd956ba2f31a894e9366eca00e6e997fbbf9a2980" +
-			"8b83a139f6432147a717381bb8baa2205715f735c1e0db273cdda6897c9f" +
-			"39bf0d7eb7caf93f657ef4d3fecea28baf69cf36d3cf347081df3114455e" +
-			"b4fe3e49ad3c3f14435e0b39b6c0d16db0fbcfd7ba8da8760d5952c03667" +
-			"251e7a4c3008cfb0904225e55c23b884bb09d26631650460c4240bd5a165" +
-			"b531ee76ba5749b3bc60adad35de519321c1672b47bc35fb59f7792a3495" +
-			"11b2bb3504ba4a28717823a27a1f99ce6970290b26efcf1e7a0399b10eb1" +
-			"0c1299c09b80f4520d00e7908d004d5b6a72a411759cfa9523f6b2912234" +
-			"481b1d8fe4c2365961c0528bd593d42bebb398b5836ae6ca013fe440adbb" +
-			"0090e8ea274f4d8bcae483e3663051a328f7c12870b40e4973a9797a2336" +
-			"3d3c53e1b0d1a9159bfb26158f44734b3c34b571be641bba2db937d4ae1e" +
-			"edc807b95b1c2a7d44804885536316ad38aedf0d83b1519661f2bb5283cb" +
-			"9c50dd61c3753433e988189f26962d1f4befd444257d0b6d5b819d5fd572" +
-			"22c9fdff032e07a4d8686d451e71de4748965309c0a2d7c422ab7cf3d96a" +
-			"8c0a1b0afb229debd1c9421cb828b9f2be96bb9d6b5be7ef8134bd9ccf81" +
-			"51620937d720d83dbdddbfaba8ecd2eab6f1974090efde0ca963e9fdd691" +
-			"ed0cc5e074c5780779222552fa46ddcd951763a32aa3a044ff4a73cbab41" +
-			"dabb3c2c03fcda68303477f0dc26f35bdb5c9bde721fba1a2db732a89629" +
-			"a8de3cfebc3918df1a9d5053d09da5b7316e3285bf62156ca28cb64d343e" +
-			"72445fd66757bf4ab374fe7932a65f3d7fb6e42cb12e5b67ddf8530383a4" +
-			"6c1ee7ec8883e454a467df1aa7e468a6e7035515f473901efca5d46ff358" +
-			"70e0cc2575bbd7f8866c8e73cb157903a1694ff3051424f28de826984dcd" +
-			"065dc3658df144ae3a6d37b88c367e3cf7c58169dfdedda4a2821ce22188" +
-			"40472ff72f0dd1a6b0100555ff188b80f835259a634405e3dad61fc299f9" +
-			"307e27503b2cb7714bf3b636cc64b61d2e374119c8ef8adb21f1516c7fe2" +
-			"38c807818065bf312003c12e02525d69d9629a99e4ac66ad2e792f302cd2" +
-			"a6f5f702dd28040738a084a7052f2c3ed0924c33b7a5d357b7c9a29cebd8" +
-			"621a4bfb7bb34676ff210d59f7f9d4eafb7c5c490c9ea48402af5bb072c4" +
-			"731bdebcbed4e8e08a67931b6d7342d4ef7bc4a75ca1dfbd32ed6027d8fc" +
-			"b71e3f55565c02e06daa8c579b69774889181291c470576a99e11f2c5acf" +
-			"77e091ef65ed243d4287176f7f6ac7aba6908c9ff1fa43b894a499b642ad" +
-			"c01b2fa1c4b58801411941bb448f1f7a04794d2cfe5db1be61f7b86d6eca" +
-			"c547ee51d4c9050f9e9f318dae958c150acc21c878f0c7df6065294eb1d9" +
-			"a278c920838a0db752b080a32e67ac312fa76b589a385f31847196076ed8" +
-			"1021fcc375bfcc8e1361878e2693860eb21ff0595e4eaaf7897f2b79367f" +
-			"7c4f711279bf0c93a97dcb1cd8d87e444ad5f4cb5c1de44e37868c6743f1" +
-			"cd72cec376726f26c8bd4836f9a9f9c68042f95ca6f9d7cde493e531c553" +
-			"8bf7ace6dd768db69ac7b41ce93e8ca27ff20a83ff2148ec5b89e05d8b8f" +
-			"5d78d0fe16b96f6eb8d3b20126a186085c6825df81aa16b3dbf57eabc360" +
-			"71299ccdda60e250c652408d9cd1da94d73c728440ae08fddb901aec0fac" +
-			"1050a778b10f94f84883bee158bc53b1c001807c43a3151fbf581b18dda2" +
-			"527430872834e5c380575c54b7aa50f817cf3249fb943d46933cad32092e" +
-			"bfc575bd31cc744b7405580a5f2eabe27a02eec31e0d7306750adbbb9f08" +
-			"c78cb2d4c738b2274c7310cbf8dd0e59138b6a91b8253ae9512fe3d7367e" +
-			"a965ac44d54a7ed664e5e5c3c6c2d942eac388cd32beffb38f",
-	},
-	{
-		key: "2f29d71d73f7af98f96b34e939e1a21e2789ec6271b878bbebd14d7942d30080",
-		tag: "ec02f4953a9a63ab6f2bfc3501e4fab8",
-		in: "0e0950987f3508239063e26a13727fefcdfd2cea6a903615c64bf12d9ed3" +
-			"887f9b2cf7ccaa196ccc7756b09471475b9daefd4261e69abd23b9faf9c5" +
-			"1fd5d5788bb39d3c068fa6807d30f6201d3f6dfd31715d08b1733440cde1" +
-			"049608d23c4e45c5ed61f863350232f85827e7c292dc5f1eced1cbc912e3" +
-			"f5c420bd945911d3881ede5153d3b2cc85371fff98d2caf97cad6ef59001" +
-			"4017f9690cab08989851c2647e77e81401714a93ed9f938b79f8f54e3133" +
-			"fc2cdef259df2ba0d48f37bf9e43792e3a777214cf4aab6dde6deeb543a8" +
-			"813b71b5974136c1220d6218a252881f0f5677ff5b6aba127f19a5f3c5aa" +
-			"c988543d7839a90a3f947c4e4d5c6ae1ab48dbd40456d1aa65339a4c15eb" +
-			"520e8ff9f965ac4c37735937cf09942e7958f8a6cddee41707423f715903" +
-			"ffe0d15af8c3140d3a736d23be7485fceb9f07c6509f2c506eda4ec9d30c" +
-			"cc133708f48d8828e332808c84a745d337296d871b9794de1c5d06534aaf" +
-			"65587526a84e2521f8b332645e0e72564bb308ecf99b7bc69608474389d1" +
-			"686ffab8c49b7f04dadc28d2ecdd0f508dad2135843304e378b3bc7a4f25" +
-			"7fa4316be956e0a021edb8045f39fa9f002087f067199bd6001acaadd261" +
-			"4bf6aefd3f098f92a959685f24bb2206c347359d9c6adc6847117bb434ac" +
-			"6c40ec618f6ae8b75a5e2e4d44c332b7b06c8b4d521493b9b0bde8894209" +
-			"717a24b320214297b62dec741cea018ea681c9b56702068528b3726953e8" +
-			"c5e4ccd5029e4183e772d9834a56a88d45bf87603dfda40e03f7e894766a" +
-			"7623ab4dcc0dfc3086d17566945069173935916f772e2a5f8e1547348f28" +
-			"782400fc069ac0e2b94242e9e0f1ba2d0e76898f9b986540e61ea64d7f69" +
-			"1006b86ce61565da75eb16a8b4c5865ca4eebdde2190e354734bda94fe7e" +
-			"12ff47dcb5d5e6ad93cfadcc491cb350b09ffe391a157e14b65e3a211b5d" +
-			"4e447c3ff95571dbab33a83126d68dfddf9383b4359d4103ca64af1e6963" +
-			"d09e17eb944aa71e76711dca33168586bfc44ebe9fdc55497d83f238c66d" +
-			"bcb16063bc85635f0f1a6280563bca49ef971db96a41b6ac5e0642643262" +
-			"61eb4662f3d6ad4cac826db895de22c9b8aa35e6464a7f44e1ae7238e355" +
-			"068d68754ffcca76c50b7ce7ef9bfebac9eeab32c87d059cc7ef2adb5d57" +
-			"c7419adb394eef48441952253e8391e555730e29789d6293c3696f441449" +
-			"0aebe2bbe541e191a6652ffbec1192f0f9395b7ea370aefc1f1cc8438035" +
-			"d7681f12f1e11d6e334da188b10c302fc0f4bcf1de448090510a8f1d5683" +
-			"0c943a3c388b33a038c26741a4cf3487313f755fe7a28e25e44b5383c5f4" +
-			"cd6ef34d7dd73462226281899dc3f2e69809a0150f694673f31addc89888" +
-			"072a7d4ecd63d6b90540f9522ec05829a7f17d48728345ad808fb0203883" +
-			"3cbd018d612992a88df944b8e34a70920b3f26cda2e8bb16c3aa38b12b33" +
-			"b395c9ba5e809f60ff05f087112151af1b5987403cff8bb2dce79093f431" +
-			"2c744f911a6f3091e4f9ef9375c4dce4c241d2f6024a1797321851ca316c" +
-			"4e460fc060e7839deaff8ab5e8bf682c0f21ab6952eb793cffe690db911f" +
-			"50b11f56ea352942c43bfff51d4360882754faeb7cf28b6b32bf7fc9ca71" +
-			"fbfe1d72be05b8bac9ba513d731e2c9d13d6f2f10eb926edaaf0e3996656" +
-			"da8718a8e103c59326529e91ebac6ed52657c9690ccbf81028cd9fb189ec" +
-			"4de94fc0771e53302c8d9082835a68780cccd772660a110a1b40c57bef3a" +
-			"c1d69428aea549ed17663a96895a66a3bb5ff6ff61dc64908df49b760caf" +
-			"a5aff05e2766a418dbaa1e7d189a9edd55a04fee8c9d6e506d299abc36a9" +
-			"d67be035fea5d220f41d081af67615fe627c4dd04bd8659c7fa4f57f35d0" +
-			"db40d9684aa178d7483ed5d86f04eaea412e0ea05a4698377dbff4fc3a39" +
-			"1f6ce0cb833d3118d6c69319b511cce65fdc74928e270da0c537f8201eff" +
-			"77416155d4a39c7ad38c22cdbf7d2b7ff7d85383c178a835ec604c3f9ee3" +
-			"7399f7dd826e34f1a35ab75da44ba56f86097ddc0f3658ef5bd65a24f4de" +
-			"4255d0b03411a9d7f0ddc29e33cb865da23393471aa94e6c9e72e789206d" +
-			"3ba118aecd39727068f528f01b25fae2280d70033e4ee46b41b864bb922e" +
-			"001d8bf46d6fbaa5a594e926f45eb3a4d2f074506d7834b606f43c89699a" +
-			"6db00b374658d9333700894d440a712a1f25f5538f9e7c8ee57ae7e612df" +
-			"13292c8ba9dbede4fb77cc6c8944aaef59ea6ad3b36db398f4bb0f82d40b" +
-			"44879835f224d6e05992b1b8a68dd58c3dbda2fd73786492ee48c7a25f87" +
-			"264b766930fe9427487504fad17f8d230934f044e49ba219f26ead728856" +
-			"cb30eecc33a3946d3b1b781061f2458c7c46f6d96f3e06f369f97be91835" +
-			"f23b38347d1e381ad5be4419275772c2abd549522a0203c1ee9c96faefe1" +
-			"df413c4b7b2624417890e0716854b7092b3b3b368cb674035d3e6bab2357" +
-			"e7c262b606f7141b6dad2f6145ebc1deb7597814719784f3c17848a90ffb" +
-			"cb0289e2f3cc7da12442b837c4e47f468bca3eb4e944a31c48562c2f144e" +
-			"9e920ab5e4cf90a14ccadbae29af13db38cda911e3c8f6f525e6722809b5" +
-			"31a4de1926ab12f643d25af87eb8610df59eded6ec278242247dc69a4213" +
-			"13f7c2b26ae7a917c1bdaf66c56876e9104d40b59e6ca1431ddb77fc89f3" +
-			"14b46a154cf127688564a4f9e120d7b5816cd24a6e095dc8ab8b43bc3639" +
-			"329719f0e0f723e2f5136d82638e2249e648ebca67cf0306741e9e8d45cb" +
-			"903bca85485c4007397c88a1ce07266f4f611b96b7e0ace3074247a7dfb1" +
-			"cdbbdd66e25e172fd2bda74abde7f3b4cb5cc7ee7859f053b2f04f9de03b" +
-			"a8e96264117f502087c3ddbee8d850bf3618b4de90f7b3e562dfa57e4426" +
-			"5357236e35e71d1669226d63bca50b1b944ac07a1f794e73e80985689b25" +
-			"f18fc709367d63b8639d71865cee667536040be827145c08cf3e57a66678" +
-			"4c81115706a146eccadc7aa1a9f074b47e95bcba7db8108a13279077bef2" +
-			"64699fb87e5abf5b05ff3879d7c7c5169c7cae817c13f0859d4e9c05db0f" +
-			"74c045ecc30a51e515feea627da387ff780719395b5b9ad93179b16fad10" +
-			"5856049169dcebd43a7f39c549762405f807378e854b1654a1179d895ef0" +
-			"85aafc72c7fe1e0e1cd3abf8e20935e331145bbcece4f17ad24ebb6c64ea" +
-			"73bd98a7494c134859206c9422f7c4a057db0ae0770c4bcb08c1a6b9ca4b" +
-			"7dd8c1cdb3e4977c7ce6c1e79b9d6ad98e27d2759b53cee73ec037a8b686" +
-			"f1ff78eb8421f41c74ce9c62a90d38b75159ec925f232e0db71362f31e29" +
-			"4336f5580a34b26c5a01ee3454cba227c7f400f6889a319d7121dcea27b9" +
-			"584f33ac796d48a9a24cc5b6799ee12f10725fbc10d7cf83e4b87d9c444b" +
-			"f43e2f5ee49d8f3b531ebb58fed4234cb8bcab1b8b18bf50956506baae8b" +
-			"c1b7492250f3adf64294310387f1d4bcac12652895d4f2dce26f380733ce" +
-			"0b5820e9fcd8512a1585a49940a32fc8875ac3c9542a4270602e5e97e720" +
-			"90ed71b51badb775340429fdbe45b887fb9ee61cf9e091c06092cf0a2129" +
-			"b26572574c46910cb458bca7c63eddd29d89753d57e568323e380065794d" +
-			"3fa1ffb874543f5b0ddc702b087e91e22604d9600d37fa0dd90d7acb2458" +
-			"4cd408a4e66bb781dde5f39efda6a8fc26be0d08ffdf851e422ab1500c28" +
-			"bf6b4c85bdfa94e8aef5cda22870c39ad49c3c6acdbb3b0d58cd05424c65" +
-			"20740b5c2bce4336545eda12716317df58e6fb764fcb3004f5248c5ccd84" +
-			"f63abdc0dd2a64e447c0de4da4a1082a729d8ebe14810d396933085cde18" +
-			"318278481fdb9a748b637cacb491f5234bfe16b53a35da6677336baeedb7" +
-			"4a28c19a412e7812dace251446d40ec07afd63854c3dffbd5c0f6a9a3cac" +
-			"ee3bab07fba94800fd1fa0fe44f5f2ecb2b4a188cd02b8a2df0728347c50" +
-			"7d0cc58fcd5d54dffdbda11dd1bcc59758396ed8db77498fbe13238d3d8a" +
-			"0040194dfe66811542ddaa658094a9580d4e4b4e29",
-	},
-	{
-		key: "1285f117bd90b70ef078ae62f37d2218419e894b7d334759ddb2d88833b287b5",
-		tag: "429b2b39195a10357043c9601590a277",
-		in: "00ef065a1adb4ce7108b497813ccc748933fa8442689a7cb8dc7c1ffdbf6" +
-			"c09adfe05ca2cc5ec3acb7493f3497ee8f9cd9bb8a4b332c18e33f78114a" +
-			"c8f9a72ddb9f13494e934ad711818909831013ba195b53f5e9e5b4689399" +
-			"6d0b669f3860958a32b85a21009d47fddbc8697b7c9b92dc75d5060eb4fb" +
-			"40aed7a1dbe69dbbeb6296f5467ea2426cd17d323671fa408855bc53e5c2" +
-			"d111203ae38cecac7719c0bd7f21f6bd6a1588187b3b513983627b80ac0b" +
-			"300b7fa038af1cc8512403ac2cea6e406595202ec3e74014d94cf8780ed0" +
-			"33c570e887ca7fb35ee4768202aa52427d02c24e63f7f2cede95ca9909e9" +
-			"dfa86246a27db757750667c198c9aff4ce348f7ac51864b36ef5695df713" +
-			"d17b8f561a972d0136bd9ee9aa16079c2ab5d29ac9ab472255ade05dc49c" +
-			"b966e0c1c04258ef9ec59ded01f402d9fdcd9a2020a2038a8c78892ca218" +
-			"30136069485527069132959dab2b81c73ca590fde2a7ecff761d95a54d63" +
-			"a2664aa5a6deec163e46b5225bc98976a4f363063b0f42e29f792d138af8" +
-			"eae68d3854b5c1985d5cd1c9f49f529b0b4d2c936887b5b92cdebacef992" +
-			"c35e0b7bbd52114aff8c6b261852e28e451b02099814f809b0289cba0586" +
-			"04a363e3f969aad3d982f645ec4c549f943fb360fb8fa0d5a597bf89842f" +
-			"8ced6014a5b2590ef71524a7ad50fe0ef0e2f81b6e26b99f9ebbc8036549" +
-			"f7eacbf6ab884710c6406ff59788e03ede35c30d4781ad5af171e0623e8f" +
-			"cf5344d71165f0475e256e9159040f702b359a2963116ed135dd6c1d111d" +
-			"2a1e33e15c178ca4f02c5fb15593c50cf9a8a492f01e04778dbb81d26c99" +
-			"0c58cf50a9bcf4fe38fbfc0fc0685d8bd422a773c7bce649f7a86c59118e" +
-			"f5f857b2c72508cd1ef05e1a0c0b7ab4687fdd57437092eb49bf41a9ae8b" +
-			"bd98272ea2f8ee2515ff267fa6ae892c266a7effe61ed54984924aefc461" +
-			"6cf483dec024ad666bc797beaa429a742d1b8806f67d451b6d3a85b4d474" +
-			"003cfe9e9dd906df47da5559c41f15afabecc3e6af279cca0f2a200eb2e8" +
-			"31437e034d457fc880f60f5ae635690bce82bf6d1ad6b4f5344ec042bf25" +
-			"7d010273c861e3ac516e9ee2bab3a255f570baa32298467bf704bf6d9076" +
-			"a4c0b08a528a05cd1fcbdf51f3885fbaba7891a144fc058919903b269b4a" +
-			"29f43926eda32c38853b814a7d528156c223748d674d8f7f5448350f011b" +
-			"bfab1511001b8014e20fee37ccd4a0456f638c197c86dc116b34f955c0b7" +
-			"dee10bac5ea0c2fec8a780ac05098b51b902ca6afff4db3c6fb4f761df79" +
-			"b2039dc5f16d9402442a6fcf6c4297769e6c36824d908beba8e584ea0b3a" +
-			"91b9017baeefac651d0307bd89f517789236c0693c65a5a20f244d39684c" +
-			"eb810cd2ffd3c78fe9285d2eb9f55d133b86113efb8dffcbc6d258e84c38" +
-			"2dd8f4d7d63b65672516d9bfcc3310a79ce244b60d380128d529487f99b7" +
-			"d532d5f5c28fad8b9a071fd2fab8fd98f6d7ed9dadbd2fc4396476eba6e2" +
-			"1a1b1cc594a31fbd3418d98e4aa736cab285a2786fbbd4650e49f9b080ed" +
-			"3fda34941c28d25545395e1408fc3e60730d0696061f821a4d24123cadf2" +
-			"3af3d37ba7ce1ba3cde1368d468f136df82c02f9be9210022192aa02117a" +
-			"ef5ff70bcfeffd47bc37b920826a4d3db001f956939abc0df520f3ec1613" +
-			"ba1c4b3385cad97e42bfd15a3150711fe86ba4562f17780cee1cdf198615" +
-			"ca06270db84986f33e1d53d552b0da82397c496a23c7a78ca7641a908e71" +
-			"89249cc657c0431f1e09ae0213f28a27e6267e9d17b5bba0ea4f3c21f266" +
-			"fe538e215ec62f85517ae6bd87799ac5ce68453f09cbbc50d6e2a168f0cf" +
-			"7166ad50cb65b6c76406c326573c00e04a3186251c6181933828c58f4198" +
-			"f8208c4484805639b0d428fd05b57e4356239638f458a84000c7a7a8de62" +
-			"ec25b54d1e39d2579ec9c512fec475f243576f35efc02a1cd6b0478e2dc8" +
-			"be5f17aa4e3849cd42e76fbffe6e7d6f912d6edf80f718f94a7e48e1fc10" +
-			"6cac29627d9d4b82f05a30cd7c739f7f3ef7ea368d22612f189da450e274" +
-			"de7b61c6361521e684d639be5af4cb11fefa5fce6f8a5065c90873e504c1" +
-			"2c940571ea7bd7e9221129b83039d2edb069e8b5bb68567d8fcae34c6ee0" +
-			"cb94474d8b056cc3c7403873f2fe6db3b567a44e702e4f4813b2a264231b" +
-			"0a998207b41916715ef94e5eec281589d0a711f8e74be32bc60f43d693de" +
-			"77f21d5f7eef892abe87725f3d2b01d9ddb6dee15f40735a8fb67766dbcd" +
-			"020a93b8eef4361dc3a891d521551f65dbe6e3f68c60819b0a540b0991c6" +
-			"4449d207cf5b1c198c17ad6caf3adc628d09fa0baae7a696d84e1879577c" +
-			"ffe9b3f62669d4ea5ebab6364f08c66d170ee4a94d61fb77d60b33dd6b60" +
-			"650f034c5c9879243d5c16f853dd7a89885a9047a341b076912d47872b3b" +
-			"3de49edf7451b435698ac4e182d16c339be83e18531a34aebad36c5c7c93" +
-			"aaf121cf99ff92d3844d40740fe001eeca9ee71300d826bc3cfc87a29d39" +
-			"ea108a3cf259657ec4b967fbb534e7513ef3a96bffb35abc5ce0e890696e" +
-			"54fab515af3d2c0be6e003747504e486c0ec6e30fa4ca79d6596ae0425f3" +
-			"396e40fd37432e52c74f812250dad603b3502f97ada48a26e39fd4d44584" +
-			"6591bfa5ffb3770d95d3dbd49e9c3a38c6305796b8f7d79bd0845170925d" +
-			"575774445299bdf9d3f8ad3dc2dc5cfd3ef0293b84d6e11370851af05ebf" +
-			"b3510a22edd930797dcb76b759a9b5a77ed8dd5130e79ff5ac44b01901bb" +
-			"79603cecf674202bc5d84076ff41b3c806454ce80cb9e5fa9db77294d20e" +
-			"6d3008ae3017aba712862ecd4b32daafef1b8cc8b19ee8f8bc3835e2372b" +
-			"5cec66222ad5ea9df753c033508ec43c8b5995e88c36c13ea3465c8bc462" +
-			"ae0a659d9767db34499e9d01fb1588410257d6f588b3fdb766a66bce28b5" +
-			"e0880f8cf988a2e5eb5bf80cd7d83192b7392fbb2e3a07d51aea2b6bfac0" +
-			"d74d304f56d5af3598a0712cb09c04c5dc14194eca8e1b9b29f88344c0ea" +
-			"55638c0f8ebb70b6242b797fe2525fa1bde76293dbc0a66ab4715e6f9b11" +
-			"f7ecd8f35a20ee4ff3552caf01bb307e257ec0576023d624d6094d43d25a" +
-			"aadfce939a6808f8baacb2109c3de50a1cfada9e384cdba3e97d2c9025a3" +
-			"2377bb195fce68c5569d2d1267e1bc68fcd925ddb4acf567fb29ea80517a" +
-			"7e4056fb014cdee597333ac2408157ff60cfa1afdc363a11fd4883308cab" +
-			"d9a8fe56c2b41c95eaef854f20bf5941ed23156d86de3bd413465a3bc74d" +
-			"5acffcd15722879849c261c1bbe987f89a1f00b3069453841b7da667d566" +
-			"e41fd894d94de44c23fed08d9bdffb723aa8449bf236261240d865efd7b1" +
-			"74a4460e5004ff77f4196d1d421227dff7c78f1726df7b5eebddb4bb5f57" +
-			"5ade25296dda2e71ab87ea2b44ef2ce8742a7ad5c1e7a40e097eb336561e" +
-			"865515f7ee0efbe01d5a928f208f7c9f2f58974d1c11af0e737c673dc446" +
-			"1795da9757010cefc6e7f2784658717938735ed8cbcbd7981a1bb8f31cab" +
-			"b901c87a3218dd1195c59f64d0bc3ce8b72580fe38e6dbf1181e0090e5c6" +
-			"d162df9f31cc52fa6a8ac61897e9b4b3cb0ca2bfb38a38d9b78e46d775d5" +
-			"7645d2d6da16bda8edd8675e2ba121f7f85400cf7cacb9ffcdfae583fb93" +
-			"753d07985a00afc3a4e26c9939a5116d9b61196502f5d774ab4c7fb6cfa6" +
-			"01bcfddcfabfcd28055e858d7d3c19feb6bd7c02565add3a3af61bfba8b6" +
-			"f4b52c072a8613e878368318383143059a98a85ba521f781a8983c2486ba" +
-			"b83f5b91fce02acee0be8d0dda7489975f0506c8f363b5adc48ba971adeb" +
-			"4e1c830b5f264ed42da36d2b5ce2fdab1e63333b1061ec5a44ec1b6e99da" +
-			"0f25e7f7250e788fe3f1b8e64467d3d709aeb7360720f854afe38e190cc0" +
-			"925c6cbd77fbfccc07d8beeb0ce68e47442fadaf13b53c30a03ce317cf79" +
-			"dc9155ddf96814583695f15c970fd0b6cea0b04b1825eb26e65ea9351bf2" +
-			"f7a841ddaa8c9f8e885b7c30b9985bac23d3ce777b",
-	},
-	{
-		key: "491ebd0dddefc9f0117176772f9bab61b92a1f1de13796176091c56d1e53dfbe",
-		tag: "fbd3f884a3dc2a8be06ce03883282e1e",
-		in: "953b9a40789b206fb507ec2c5e9c88ca1baf25ad24c11a62f664db1da8bf" +
-			"dbe9b54f8e93b0bfb4adb12f8873096b8960fd91eb92a8ddb53232ac9141" +
-			"57caced33424cff943a8db129049af7e7b733afbec6637d8ee4f39d063e2" +
-			"be241cca6a339e48d72372efabceac57220692c40856532d95529adfae87" +
-			"a71c72f30244126d01a875375ad8836ef8db929bc81027935042a05c346f" +
-			"bc94dcc057db015e55c56064d2b11154596b813ee64b73bcac05d2688bf6" +
-			"f1fbb0cf3f8307b3df44c3e2dd1d226a4d0e9dc5f7482bada9611970f887" +
-			"f656dcb19ce1f8c5c86f4cbd1e4f49b18f170ecfd184028e769e79d7424f" +
-			"d01cb315897c21111f53f4d41c3b71402eea695272cb5b4e5f33abb9df50" +
-			"cbdaa55ed629d3ed7d93b43e550295502db1f2ed884afc320518e88be4c6" +
-			"b62a13f8d3636ba091d07dbc6c20c7e7fda016c05b2fadcfc9ea32f4ee2c" +
-			"4893de78ad8a1771aacf6efdbd8fb1f6ee9b0572ced3edc6313185b5d398" +
-			"88ce77950aa4c5201a256e3ae3e74f05b70faada14124b35b105a70e7769" +
-			"7184576b69708eaabd36e0ba885fc6bafd5738a67307a1181792333cddfd" +
-			"a4ef19c88497c82fccff05a8f9f732fc7505f0467a14e135288ee018aef3" +
-			"d0412f6b0760573d8ee4ab455d2789b4d22a42eebdf60616fe403627cfca" +
-			"fea672bd0a49e8e7b80e7b7b8feebce3381f2fc16819a8996a99ea230c3a" +
-			"84b510cf2e0d914610d646a2f45a14268ec1d6fca03d0aea5c9ae1c8d519" +
-			"b0e8b0f6fb8ad176b5d6aa620b253cc492b5e5645353fbd9b6c02bea48f0" +
-			"286e2c669782b5ffefa4d8f3f1037151026d9cca78e7808dfbe61df29e82" +
-			"951d7154f3c97606cd1e99300012578ea6a776dcef0811338b56606b51a6" +
-			"9893fe68f762af6c9c26066b1d503e64877d8cd988b443af66a36af8bdfa" +
-			"41b4dfb3721d1d81895884755b9c52527030afdfaecd66d4638fab1d1786" +
-			"3d5517ef7ee7d081b5555d24991810f1edde30930fd392f817cfe632b4ca" +
-			"6fb0460c36bde4a5620b9c369bf51c7d870c43998b8171a553d2f643fe8a" +
-			"58aabfce8cf7363ea978ff4d53f58284db822ca95b80306ec02a64d26a29" +
-			"c98520f1924c70d161682c54d08a2c48f54bb72980a8cf5babd0aaf0fd72" +
-			"7d5b1b9d9b731dc49bad228fe83f7347750e277a4fbd526983c206e075d6" +
-			"a03d68957b3e925a71bc1ea7304c77660d112a5d19fd21a785d4a8d7f2eb" +
-			"dc4183376d8125341eb28b2df5be0b4e04bbf95c47d2fe2aed939619cb97" +
-			"79548b752f57b723cf8295dfce69c9b7486b75a4e900f91926636f3fc78f" +
-			"7b7720a5151abdf5868fecf1e1a1d830cd6a4c5e3cd739da4432cf1fe2af" +
-			"a1090d6a1eeb32e7236ecfddb9d07b97220ab8e23edcc93d91abc11b0c30" +
-			"460d2027869d1c2487070cf60b85ad0b8bc5df566f6fdb0e58fd044da530" +
-			"6d277e564ca6cbfa820ca73fb6201b240a5a94c4ecd11d466cdc44046a66" +
-			"32478221bfa69b3a2cebd16baa302a573c90895d7f4cab453b11e3a4d8bb" +
-			"b5a9bf264781ce5b9796e3c47d0fa57f46b923889af4d073270a360dae8d" +
-			"51d85ea916f14787c6500d2d906ccaaa92d20d93edd09139f79bfeb5fcd9" +
-			"8c1cdbcbe9f2587e9c9094e3c4a32ab9ba56f400b929e80c0551f953896b" +
-			"e8eda6ecf22e6d4a541957dec21d6a9cf388ff0ba58169ab934902892a58" +
-			"86e1126b16118e965a271495ffa339c49466209ed3875b568a4290b7b949" +
-			"69d0465744a3c2a75c599c3a04ab1a3fd09125fe8f45724b2f48c7822b9f" +
-			"ef95af4b758ae66a8b6646df7a0a1aabe2a24c052fd6d30561cae0389263" +
-			"e3388c4c1effe431a04356c334aac64f36593544885c4b7295b57dc39638" +
-			"b665b22dcbf7dd6da867615de38c6a575cc66391135d47f8e1f0c73c6129" +
-			"17ada4099723933a758d83311b384364263cad5fe14bdd7c825d9601c400" +
-			"3537a5aca7f9da4710c132ce8b0f1464cee625633ef57f507739a0ab1cd2" +
-			"21ae634d4d0b3ff07e9ecb1baaef0a82a97279d46543a0464855cd62c07d" +
-			"5e890265612906a9eac88bec07b1dea5f67054c31ae40f8c673296cc5df7" +
-			"f0dd8cc9e643b44fd90dc2d1e870ad8acdbe165237642fd04c00965837cf" +
-			"bd2344ae830887a5719a3c16dc8ec08bd9131d055bfb959b64ff4cb638a1" +
-			"002a4fe02e369871cc4e3ffda17dd85343e679fab43e11970e60198b424b" +
-			"676ab17fb0dee10cc9c2e92b32b68d5b05b7a559176f822850c0557ed98b" +
-			"7454916e32af549a0027db95f02b88cfc5e7e05f28f53757dd97cc0f0594" +
-			"212f8801e58043cb17b040413c226dfce2104a172d218caa4353890de17d" +
-			"be1f53af6ceda24b8781801516cc51de9ca459e469b3c322be13d8c9541f" +
-			"755c518ca41a0ed42e44b9f87faa2a968b0292216e9f3d3e8987282103e5" +
-			"016fe9f7681496e1e8d663eb2d8bc30b41d735465527f19e336a98d2dc54" +
-			"d7c020bfab30fe6c62cbae7d09f84af69bc2c51a1839ffba15015d381ba0" +
-			"a44a3758771c4f18d13827f518f30bb74f4bff29a87d4b9e949f1063f63f" +
-			"662721cfd64ffe1dab3761852387f78fa83fb48ae2c75fc567475b673da6" +
-			"fa8f53770b6e5a3c9fad951ec099c6bc1e72d1c489e1ae620e7f12ddc29f" +
-			"ed65f29c65cef75014b999d739e2e6e015f928a30f2fee3f2e59bf65b54d" +
-			"89948bf2bfde98b076e5460643952befd02fc1b0f472a8b75195c53ea296" +
-			"6403b9028db529cd04b97231bac3068855fa211f4d976a88bc27a0088f04" +
-			"576e2487ac0467992066ef7667ca8429faee92db38003728e5c219c751f6" +
-			"6f011b5d679fdd957f4575a0cfb6b54693a9624f2c7e66c578f5f0367005" +
-			"c66addd1e3ab7ea1ac404e357cbdab9438b9b4f80b3a6761b864b006f1df" +
-			"689ae4c0434b06b686d5353d3e421b57381ea24fdcf6199195ccdb3d5cf4" +
-			"623a6bb1f9eba9b22fa15395f65f8093b5f90455061c1cbf8128b44a31e3" +
-			"910862a59e187aa7f4d22e0317ae6c177cef24eebc44171f70c25efac73b" +
-			"38ada0cba0b74f72d1c171277a734819c1111ebe46d5db20a6ff20e2c1a9" +
-			"a57edae95a3c1f80ddf2b12c86d3df0078a7bf68695b16ccf92053c727a4" +
-			"80586b8d87d0d1772e456fde0c20a7927f351a641bff5f22f9ee2217b6a2" +
-			"d0983c8102d7d5356dea60a19e105ce366b9d000987c8c33396569f97c56" +
-			"2d0fc0bc5859779aa10efd1f8df0909c307a9110083cc6d9748456c9bddf" +
-			"16dccee52b7974867cec718bb0b76b3353379a621257094277a30148ac38" +
-			"e5cf67ed7cc9c1bae12dbdeb99d7d880ce98e17f0dc93c5330d1824a3c9e" +
-			"ffd86f89e15b59a4bee5a48d4f674766896e187abaa39917b83f8d2f3265" +
-			"bbe7aac44c9f8d92f775fe6493e85ab44e6e28f79f28eff156c21e1abdae" +
-			"d10a291b88c4020b1ae8be001080870847a852d073e82bfc751028ac62d5" +
-			"6aeac1b18f2cff1c0c7d336bf08f8cd5099d9d3b28f9e16077e9caabab49" +
-			"f2d234616a7522a6bde1a3b3c608df4cc74a6c633d4c8068138abda8d26b" +
-			"4ca70f95d152888fb32bdee5dfad8ff4a5b002a0a327c873656db8d6fdd8" +
-			"ed882e47ce8e47c729e1292db9122ce2e9fa275f9bb986eb7e0a1dccb7cf" +
-			"abd0449c92fd35e2aedc4aa89caf53bcd28170cae85e93f93988e723a896" +
-			"10cefb4edb6fa545835fba3107e21dceb272c5a32da26fa77df070f41d7c" +
-			"ad1d68b836199ff0f1221e36b9b976b5e69bed54b5bfec67fe9cbb383484" +
-			"696265204797634594bc335150daea92dbc1004f613b4c27bf5c699debf9" +
-			"4365041b5a894701da68a93bcb61f4e546c553fe61f14ab0322b45915da6" +
-			"ecacaa093b0071f2516ca8c3fef2f1e3c403993d734403c47bfe5f4379e9" +
-			"cb5b613fde3c0d880cecef4101aad8b8b1c60a92ac5185f6c243fdf1711b" +
-			"0b56f0fd8e5ed6cc0f99da888e4f156455a0f0eb365b8964347eedd15d80" +
-			"2f297977af667ed1376dfcc610f5152421b97afaaf16f9db57a435328595" +
-			"b9aa00b5ed9ff106c66970fafef379f4d2f98f2c5984ea05aad64651fbf7" +
-			"7968c8cbc4e959859b85302a88a3c2faed37765f3f6ced59d8feb6c72e71" +
-			"f9d4497d98bccf95fcb650f29131e1df1bf06a5443f8af844aa1a7b5a68e" +
-			"bb250c7de3a65ae9b1086cf83f832050e55030d0f67c6a54ea2a1dbe18e2" +
-			"8a96c9e0dea2966997bfc5c5afd4244e3c8477c4f5e8bee8fc8ca9a5cde4" +
-			"d9c5a2c7f3d2e811b1de7ce4279229319e432674c609b4c8b70dc6172e9e" +
-			"653fe1969bbc2cb3685e64fd81d96d33",
-	},
-	{
-		key: "b41db44465a0f0d70093f0303bbd7776017bca8461c92116595ae89f1da1e95f",
-		tag: "d8a111a09db22b841fa28367ce35438b",
-		in: "b074b0984fb83749586881e8ec2c5ce9e086cfb2aad17b42b2429d4cf43a" +
-			"0400fd15352d182e6c51e9338da892f886f460d40bd178d81c52e9ab9c1c" +
-			"bdd812594e6fe7a9bb7fb729c11328d3288604097600a0c151fa3d9e4268" +
-			"de75866558e9f47d8dd331994bf69f826fd4a6cb475ae5e18365f59a477a" +
-			"dde7fbcf7e40b4e3dee020a115830b86f0faae561751e9b596c07491c42d" +
-			"e02fc979e69071113953729d7b99f1867116d058a90f1b8c0f9ba12c6322" +
-			"4ebd1b563a87734f5d6e2d4e6715d5f0213e33316500cc4b23784f78a9bf" +
-			"13fdf99bfe149cf47aeaaeb9df1cee140c3c1264fe89bcde8acda6bde16c" +
-			"e3d770ba51950b67ad2c5232ae0cff048ddfda8540cf18e673582dc96987" +
-			"4b127f655e7d4e08859f2c6b95403cd5b4e2c21f72bb872e49e592306286" +
-			"48ba1b16fc9637709636b198f9a297aec364d4c3bc869dcad32b1830e434" +
-			"b556b429136f0012a0a0b6fb3797bc8668014b010ea51674ef8865348dcc" +
-			"197672047fcf72e6b6910a0e32a4f110d85e28db0e338d9cfdec715a8800" +
-			"b4f007a7951d09e41620815848c89f8768344c50bd522c46f64ac6c98e53" +
-			"92176651961c7a70b62f3d1819bfda674e2ecd3167415edc4b97419e8ae4" +
-			"9974b56cd8d52e1d05b82610b59606a750b34844ca33bfc9b21fb970738d" +
-			"b66f48928df79cf67730a30b0b612f8c15c22892120548ab460a6b9bb3ac" +
-			"e30554c86c9681c797821a1b1ce91d0e87fe90ad4097c974cfbdfd5c4c24" +
-			"a5f808f388e1b1473e858f48a387614501c8c39d6973ded69b1764663cd5" +
-			"166be02b596a49e392d637e3d8afc91323f7450318b79d5488c040e346cf" +
-			"0cee512044514b570aa66bb98d639a9ee23a7cebe28474592623d082873b" +
-			"73efb3eaa4721fc4761e15a390497cb13cce181107e8b1a0186b9e47a5a4" +
-			"b67a5be3cd88a43d341ef63f10af6970aaf56035db938655020809033a92" +
-			"8d4fe6d2f5424fbde2fe82adfd991d388edf293cb4e3eb68d876f225a5f1" +
-			"58208bcb1aaefcbc28d6763d267406aa8d6ecb413d18cff7a318ba031ba6" +
-			"0ac4560748c248de64eec56dd4540124b38581604f502d94a2004f9eb1d6" +
-			"edb009e16af6c6d3ccbea79b10743da98aee7ace407a90c6cfdde694f36b" +
-			"e0271e722618a457be68619b980754795f4ac95ebf4f1820b85ca8e3fbff" +
-			"a2430f8e01ab422d7140751f7741f2c921400dac404b04e049736738a87b" +
-			"6f49bd54b1b447b922c473831a65f224ab84fc96e4551a0333bc6187e15c" +
-			"c0f0ad628068bcd7c043bd1e3036ec01e7fdc3d157476149917baafaced0" +
-			"15d09fafb92181a0ec65b00c9c13631e65de184377416e04d3d93b847e0e" +
-			"286c1d88245d4d550d30d4fbfcb416ff26a39a94275631c2deafc7cb6780" +
-			"f149e4d0e9c4515b708fcd62be5252485407a6ceeb9247de34e0266ef384" +
-			"976f6d31284c97468b3b03e951d87a5a00836ea303a266147a79ff3431b4" +
-			"b382e86c74d92661e0f65e266b7d569c03994b667a8137f3080eda2ff542" +
-			"0f0b52b427558dc26932a22a615c9e6b1834a251c6b68fdfc0bbe0e8781e" +
-			"36adf669f2d78bd23509ef7e086634e526258e8d11a1e0be0a678ac09c7b" +
-			"b4e3c5758504011e701dc85997fe2a3e40c7af83f032bdbe7adc10ef1e4a" +
-			"666946c2bf31dd8e3a383211c9684d5302f89dafcf77976d5a02c14e2462" +
-			"09d2d99918e82402cb0eacaa12032ad8316315af1b3d3bd5058f7c935d35" +
-			"ef0d4e71373958fd5e4140a9a586d89c53e4144c00148a4706a524896eb0" +
-			"5b1479a0de5d3f57be46b3f5fa4e49bffe027c81a33e37abc01a4cafe08b" +
-			"8e21fa86b42be52d75d6407e6cdf399de7aedb9b61a6917b2677b211c979" +
-			"33536664c637a57ce2234e3319fe8b4a77d7285ae6347464dfd0aab3e6f1" +
-			"178e0029686770d3b0dd541490b097f001e95f27efe8eb16e4747937d643" +
-			"cdefd49e586ecad541270cedc3064bdb7c79f086bf1fa8c666304d977a15" +
-			"54ae268881e17d8bc3fe51fa9969f7e560e3d3e050424febec0998b35f2a" +
-			"7378b2c3e384cbfc80c4987734d76c78224cb81cc5376f88f0ceda28aa50" +
-			"44e956537c3ee209071d84a66173384e0aa466d989759fb1f2f17fe627a0" +
-			"ffeaae7c5a3884b237f5151278a07117c2e833f1815c7e0e0b1611f25058" +
-			"ca338d21deb1a571faf1d0486667cb7c58e2814c3722d24fb77ce1b7e018" +
-			"2ae5746442b5ad00208b17c0a68bab4df8a8f36edead4fbe79b4c9220dd6" +
-			"acea6d23c7caaf6ce7cabeeca677a1c764d610ea6c7e994d6a9c88f57fda" +
-			"ef160b251e7595578ea2cc1441d480c14b8b6945e76a001891b1f214979b" +
-			"c52ec15e9480d706a40cb6e3b259ee99a9e84e63a738f1b52cf71c8ecb04" +
-			"fc833c2c680bfed587aa1541e5ffe8bbd7b21302bbf745011e559f94f952" +
-			"8b7fad8a37f6d855306a5be22725859cc950bcc334179d49564af3b9c78c" +
-			"e1de59a9cb45086a33856ba7195c17cef573950155bea73ed16645768bf0" +
-			"a5cefce78ba3ff98a54a8e8afc5dfcb0d422bd811ba9b7770a663b081dbb" +
-			"40aefffbeabca955a9638830f0c5d70663cbf5b26067cd061c4a3f5cf8fa" +
-			"4b6678d82d9a2aa33f8538b7499a3466f6b0ae2a1daf280ab91a6c220684" +
-			"12705245f353b4b83db50bedd3bf99d42bde6363fd6212cb745467acb007" +
-			"b678128f6580629a06171f7f3af272f8900b801af3bf47439167871e7b0c" +
-			"33f198333992a6c52c32be46071738cfbf245937d48f816ebb88ff0e726a" +
-			"dc41de4c771ff0bd320a4c0b1fcccd9fd6c42ec9c5185943c70e9a4b7c26" +
-			"a980afe104bb1f99576671a254704c7d4233eaf9915e1d56c103ba9f6e8a" +
-			"46aff466933bf58c9842796ae9cd21f7ac6aa96ef42ca54e390203bac354" +
-			"b7c1de7d1887c48255201335f819020e2782a2ee8af92ceb206b651ae92b" +
-			"3f4fdefed05e08974aee0a353d104b1be9a5e75c7f958f1981271b0a6928" +
-			"05a7a2f28a0448d86102b4fadf9ab4ec2f98e31e64fcfdf2b524780b3342" +
-			"7a2a3100c2032fc93199f3ea7a9e8063fe73282dcb1fafaa9496c7da868f" +
-			"dcf33bbb761df0bfc6fef30fadd2b6efef4fd3216a8aee48a2ef28102491" +
-			"cf7278b567c272d1064a277eb193b3f6f01df641ddb729f72454943cbd3b" +
-			"671ec077f9e3548f5f57d063c653ebee4f228a78f8a128d26f7f4b44160a" +
-			"07e942bab87b2d043c77ecdf10c1a419e0a1c4162a99c21d4abae0558b8f" +
-			"4dc0b7f1ca3892a6babf71f2f70aaca26bb813ac884ee5d71abd273ff1c4" +
-			"add230a771b678afbb12a1ca7fbcb2c0f5589c9ce67fe8f78a8db87825b3" +
-			"09ca34f48ac35aa7ac69c2fb2423807650fcf47ee5529e9d79dd2628718e" +
-			"230ffe5b83f9d5bdfd9c5d211282e71cbcacf972995bf1b13d21419f7fa2" +
-			"8829ed1dcc459da35883b9269a474f7fceff01d44ab78caf1ef7d8117f50" +
-			"cc83eb624062b149a6ed06ddd1cd1feafccdee7122353e7b3eb82978ca69" +
-			"247fde52d2d6cfe7324f04af5259e1b5c2460889da4541b431ba342a1c25" +
-			"3a1b1b65fce7120829e5466e7ad2fe4e0f773c7c13954a9c92d906c91aa1" +
-			"de211f40916596bfa8245344e257e5907a2c49ebcc864cfbe28663e700d8" +
-			"472c50355313d5cf088e9e8a19cdd85bcfc483520498c6386050e53a3ff8" +
-			"1e2b77b55b116a853d71f60d621265166cd7e95ff5cb4466226d7cef68ff" +
-			"d0a35b61e76a43cdcfa8da7fff9558e2f89b981ec6be632b126303ca1fe8" +
-			"53d5c628d967d39317b60ac904d6a882beb0746f6925a86693aff4deaac2" +
-			"e5b64b611de86767d55a6e11221605508b1c5cc828251539b1b6f65c2c04" +
-			"8e65be5422c1b11194eb687d906c559068c0a810713b23b30d8b17f10df7" +
-			"0962c5e7e782aff7bb95adfe4cba9d90b0ebc975fa56822025100b5cb8b3" +
-			"8bdc8928c1a2a8034dd66e2a763696d7ce6cef4dd586b83f7d01749d37fc" +
-			"4fe8d7abd324d4ff1efdbdbfeb0a2fbb8b266fc2bce8e5e5b95d0089e7c5" +
-			"d7de4db837d1822ac8db8198889d6bfe778d0b19e842f12b5afd740aaecd" +
-			"e36e2cefc2cf0b082aa0c4f75684d024b8d828d8f2911fe1aae270251f62" +
-			"4f49584e40bb193577c9d8e04eb16c094653cdf9a15fe9210f724c7a7c73" +
-			"74cfd1a74abb5ceae88ea54f7e7569f8eb674529cbec965ed05bb62f1968" +
-			"8fdaa97297268bfeefd06eb21f700cc56f9bf7f6cecbbbe7278ada8399fb" +
-			"960371a2d5cdb852b11c9fa17650e614c5297bf46cb7889d52bcf49d2560" +
-			"720852822b75bb16524d88273cb366b84b88282da91875562e5a1fe73973" +
-			"afe90e5cdd3f5381612d3ba7bfa058d023a9326e403ec474d8938313fb32" +
-			"bdb5bf899b900c3818c43c8a0af6a061bd26e847ed75983402ee8a9cf4ef" +
-			"85bba5545a0d329ba81495157eda0286f1917de512fe448251697dea406d" +
-			"a510adcb05",
-	},
-	{
-		key: "b78d5b3019688e6ef5980c17d28d7f543ca5b8f9f360f805ee459717ca0d85a1",
-		tag: "f01babc4901e957d0c2032a7279321e1",
-		in: "ba7d35b2ef8af1118bce1e78018c9314b0c8c320591e103d23f715acb05e" +
-			"dc98fbc618de06627661df5842dbba9f604c2d20d664e5db06e949b11d49" +
-			"665088dbafdb0d39d20beaca7d723f8dcdc57e9c5583d303b6cdfdbecf95" +
-			"7d8daf2f1c72b2a6fa27e3d18841f4841abafd334c110cd2b74efb6191db" +
-			"ab9b8fc8427ee17664082f31db98d30bf15dda967e20730a9ef525abe9f3" +
-			"f620e559ed22bf74d347c9869f0311f33da7f1a3dc858b3a8aa73a35989d" +
-			"b055a4a2c269c95e352259c57de8b94d8de48984ecde426d3ef60ec1c7b4" +
-			"41cc950f7764f55bd0cf52d069b9ad446d1f765f35d02ec104ffcc00bf1e" +
-			"dc1b951ef953acd19984ff1b41041bea0e9f5326a7c9ed97e6aab42174ee" +
-			"971ea1dbe2fd1c1f67f977ab215962b0195417170f6b7748fd57262424d6" +
-			"cf7c235b34425f4047191232722932213b3eb73904cadd6a2e9c7571d7c6" +
-			"6c2f705b5039ff75e5e71c5aa738bf4177653e6eb0b49303a4bc0e641e91" +
-			"2691f217296a3325431d578d615afddf47784e4618a2ca40ccecb05d621d" +
-			"a52f272b8cf84f7fd8177c83af1580d25a764cc06436d67171cb5d1e3b39" +
-			"367b46d9a59d849d87ab6bfcf3fb9bac2b1ebfcd1cef4459e74b0e1b7080" +
-			"dabd2dea79f75581a55de63c4b23ff67d986ad060102933fc6cce8d614c9" +
-			"c86dc84068828dd9e21ffc5665c809d83b09432fd315dfce5d7a4ebd8143" +
-			"181953e3f8716e47b0b30cc1f753e31a7d509f2dbd4177b6da310cf3cd02" +
-			"5db270adf98e96259a5ae1b81f5be4d5c76f502a612ca73c76b91e0ca695" +
-			"aa921f9489948619482c2956205ae71fffc3aba4476ff754e4878e36c763" +
-			"2c935c076857c5b90cd63ea4764efbcee53e2ddc9bdce54b1cbbcf0e7544" +
-			"d023e7c2b79419ad92221a1f76abe31a8236e370d38e2493cc9ca2aaa811" +
-			"30fc713d11f500fd071d6eba6861e8b0859b372e62fe60b627a96c377f66" +
-			"236aedf307e1d148a61bdad072b93d7d2a73367c595b1e048f7023e72729" +
-			"1ec508326f5424a5bbf4e010d0240b71fa9137e6642ab40c5e4fff79877d" +
-			"b3253c663a221b49b3e77ea307c7b9f3f72a0f3a54d0112c45c64a0c0034" +
-			"baf2b55ae36ea6f811bbb480cee663136474dacac174c73b1e8be817916c" +
-			"fd4eb1876582bb3a36cfbabad91776aa676305ddf568a86e3a5eb687fa81" +
-			"67771fca7b5ca00e974b3cc3e322b4bd9bcee2a87d0ae7976da5e04fa18c" +
-			"219fa988d4f6fce62f194b05c26ed3ae1b066cd9751a2d916d53426a454d" +
-			"58f9c3b2fb49374e5791b412fdee1b6029144f1ca787f56fece4f64f4fac" +
-			"bfe4cfd8ba7c807a83cf44008fe5126a283ab2631a87acd8e2a3bd10979c" +
-			"4b07a84a49b0687a45a4798ded0b5e9b2acce30e714d78395bfa8f33ca91" +
-			"e68b2138bd67d8a694cd87c88dcefcd101a3b408d7a9095cc6a4b38898ec" +
-			"c8b375f5a67deaaf73eb7e99b10314ca6bba824658bee85dd731d9a1475f" +
-			"976b7c0aed4b67b088f0db5ca5091273217f724969dff6cf184181377c45" +
-			"5722beb23fd9d097a82ea2d8d527ba6284acc20cb30f2e52af28800c61fd" +
-			"1faf9f4f619550e0162a1a63758e202533889b27420fe7d0eac9a47a6e11" +
-			"1d80054412340e0426cdddbb3c7b9b823b8db3ef58230fad7a3ac21a7805" +
-			"d30878d4ea78dda95c951b7a5dc552e9434c35e03e1dd88652d3714f8fbe" +
-			"a39936cc0717c2e0335371f2a751204f5d9386baaec853f019325edfd1b0" +
-			"719d1fdac3fbd774a64bf957fc54039501f66df94b5b9b82c2076c597065" +
-			"dfcfe58b2e215a3734066aeb685ef97759c704b5f32dd672ba59b74806cf" +
-			"ad5daeeb98d16f7332ff0ca713d541c84e4aef0750bab7477ea707e2e497" +
-			"e12882dbc0765106070ec6a722d08fe5c84a677817b28fa3a41a6117f2f5" +
-			"465c2a2f0eb2b8be4f36e676b4115008bade3573c86cfb1370c03b6b0dc4" +
-			"bbbb0ada4dedac10a593655068a26febc2bf10d869cac84e046c9c846ce7" +
-			"927431f606f07b92abdfd81260199ae05ed01dfa07088c56a6a8de9c6d51" +
-			"d61d6a6d3f9904c216ea8329467a006a3d2495a768a39ef99a21827d2def" +
-			"909bb743fed7209f7fe59ff1c1e710095b05f166c6173deef5c6ec4105c5" +
-			"fc3b87c8269c786bebd999af4acbf12d20453b125f338aee87e9509ee405" +
-			"9c9e568e336304d7be9ffe81d1700555b0800242d9b7450d7256f2b17f6e" +
-			"d46a39f67bb2980572ce73169e352070dbafd4c7fa5a6be78cf9b72981c0" +
-			"a01f1e1e30ee3736c59828b791d2373799854497a28a44bbe0e074925723" +
-			"4986696fbb06ef9ea83fbd49c45a583ce12ff10258ba06127c67b0f66dd1" +
-			"09f1366d8036853973d8884f93de54fb2a12949eefc020717eff47898cef" +
-			"306b5de068411f1e113ffdfe2556e0faedc3e27d95a45b8afc15ba0eeeff" +
-			"eb86da7b4324e20af80c62bf0ceb4aee1515f5912f71c6bf2febf20123e3" +
-			"dd3a82dc1e58a108f1039942dcdacdeb1f0ad0b2ef34488d98d6a52311ae" +
-			"acbd03c12f6e775e375d5979c7c295bb049f2cfd3580e3da3841ddd8e6af" +
-			"4de5e6512ca79cebcab9280554524881da37984d340e8f0163fe10a02ed0" +
-			"88682560bc6d3c4dbcf1a542ffb3dcc2ed16a2eb96896e8269697ffeb50b" +
-			"73f2cc354092e782a0072fc12e1eaff117c2cc8a5a1ad8b47802ac9e23fb" +
-			"91a0cef9e4027595e0885464e61563093ee2b1dc5f22dfd04af7de6a70d5" +
-			"977d3751a4b3cc0c71a71c59c0534cb1f8c0eeddcf1c0e1b3e5ad0d083b6" +
-			"6e8b998ddf9ae9d3b365c851d42e995b9afdf8d66b2ac40bf514ce32e456" +
-			"0880afd38c42c08926067eb243c4b1184e667ba756c14ace5f525eb48df7" +
-			"ebb429d0a23d159664f8021d27dc7167081de331c7114c9c6456e1ffdb42" +
-			"2172a81c06d8deca995e158c48df27261a83f83e0127f5e056a139be9b76" +
-			"e25dadf534d3d1ed6ebc0b5d77d51e5b90ff86f30d4023066115bc11b33c" +
-			"c827b1103098826d0bf8777176b2da6f1e5b580e407ccf7e614fdf4f5b53" +
-			"3ef6d30b20c1bee61eab90e983b1a97173a62720ffd27abb8976a948d532" +
-			"d06596c23b0ef31c79831bead8f8e99ad209af3658cac0cb3c3f9c88379b" +
-			"9bc871d8e84171d53400902da1243f664afeaff60bd96ba2639a7644676c" +
-			"a79f43130af12ba2c877d67f7ec030a4217a72f5368af7c9f24e643db6ac" +
-			"97a04adaf57dbc53762d8dfa1afd49667c4041adcb5ec303e191b786273b" +
-			"bb065cd9f16a3a4a399c6a7aab9c1a6604998264e8b3dbd13d8f2228b13b" +
-			"2c2b9fec5055d8e9f2df1d9a25e4bfe2029776389877bbef7e2c7621f06b" +
-			"c0b7fc0786e2b2d042483ccd4a59d2872a6c5ac73e217123e5c8401580a8" +
-			"d967e0895aaa28f4d25ce68c90b4394d8113bc423e9fae46ac47bc2ac191" +
-			"fb97b80b5a85feb2bb54f84c493235c1408662fe253c6786fcf6fdb8be87" +
-			"dc66a72cc847f94dfb5214af5905b7039a7363a1b23a07853daa26862783" +
-			"ba08a80846fbb93ce98700a4f9961115128dd67bd7d19e0c588fdf6196c1" +
-			"1cb0154002ae862f11421f5dc3a57b6c0870b452272be556a1d14eab1af0" +
-			"a91ff5b89de6bbeed6e03bc64f5efddf9e54da71c594bc5ef78e0192cfde" +
-			"da36e4ad1a6b0b51110c1b24d20dea1f19e18cb1184d80189f842d4f07ac" +
-			"834744dd009aa3771b1e5502fe4b65a403a4bb319e1880ff6ba852e90a8f" +
-			"4fcb52cf374c88408428cdb1255291b04ed58c992310955198d61fa1fd9d" +
-			"762d48f2f65a287773efc67d549981c291b427889d3e3dfc0cc6cd68415c" +
-			"dbed81b516786dacf431472a7dfc99688d15bb6c1b85b1a2015a106e5de8" +
-			"cb9eec4c80b17d00fdcf4a9c64de4643a95dade8fa9f1bc5c839037d86c1" +
-			"3800a244188e3b18561a74912ed72f99f2365f0126732d037dd54a3ab77f" +
-			"9a9f6a1c1469ea92eb707482066bd4990dec4d7614ccb4ea6dd4deb8bee2" +
-			"2c4dc0b9b4d4cc70a500d2c8a5ac3ef88a38439b7dc254a6d920cfd317a8" +
-			"4d7747148c65b6730709e43369d4c995b03c58b9df444f77f216944e70f6" +
-			"6446554d8d513b8f7f28ef0a2d7ad5ca2f6110304196953247a7ac184f68" +
-			"61fba896c2d5a59007ec2b2c8e263957e54cdc1f3b4a145228823fdf0960" +
-			"c33a28f59b03ee4be21001d2f56fd49ed14db33b2c4eec2c3f41b250a624" +
-			"99a9b6602c1e838526a54cdcd058af1c252d56009d4c7769deace53bdb66" +
-			"543f5a081cdde775e61efa70956fe2a7a6019a164c6e413ded314bc928b4" +
-			"aebccb946ffdf3eb33e187bf421febe26112b3262a526de65678cd1fa03b" +
-			"83513705108fe0bb87aa99aceb28af3641c46a2c4427cc1063de01aedaea" +
-			"fba68155d4de494a27ff6b7fcc8f5c5c3f7d3a115c397a1a295bc55aec8f" +
-			"7f150cbce2a8aa4706d54ec863877bb966ad441c57e612a1b5d438b98d9e" +
-			"fcdfe6d4f66e885f96407e038015cf974ae5a3540692b054d2ddfde59b28" +
-			"ede7e2f581eeb56c5b88e2779aea60c1d8ca6107b0cdda1ac93e6c7520da" +
-			"edc66afeed12f980e20e1e1c327d15ade4bb90de30b011a9cb33855ca3ca" +
-			"e2",
-	},
-	{
-		key: "2b0b0fd3347e73c2fa3a9234e2787e690a11aec97a1c6d555ff7b4047b36f372",
-		tag: "81b1a6633f849ab0aa7baafa58a5d9b8",
-		in: "427f3a7a5f1142ffa68e83df5f917e07b2bc454f3adce068a8ae9e0908e1" +
-			"3e0099aaa9074697593c6d8c2528fedddeca05e3888be1a0a201c389a72d" +
-			"20cb661017544d95a431e70e7c6580d8fb46ea4495bc59db6ae2cd69510a" +
-			"02426c50de1b6110120f759960605aca718d4d0a497e003e1ea2b8ae9a53" +
-			"df3c1eb4f704eb32f8f05eb08cecba0fd4a94f0daa3b0984c30a38f94b7a" +
-			"10cde723182d30588bc40f1f9d38a3bab4800fdd5148e34e396144763696" +
-			"c9b3e9b8adfdb337123d54237c7413f98bb2056152b256e37a27bb947c67" +
-			"240fa3ce8da62ab367db540bcdd9eb873d6c71c75a08fe99b5c11ec8e6af" +
-			"f926d2adfcf073479de394d4aac5fdc6241824d944b8773db604c59afc01" +
-			"495ee755905e5616f256c8a64321d743a1c9368d46418826d99b762e2f6b" +
-			"f998d37a995969cdc1de85f0ce3987c6550459f5e5bfd9173bfcb9e0112a" +
-			"d91f092de446beba14fb3b8ce3fb2f9c941815b2cb5a3b406e2d887b7912" +
-			"bba07c8dc7caab9836827da93ca71fa5ada810da1e5e9b09738524564d8c" +
-			"923746d19c78dc9107b9f20f653e05d7f2eb6bd90cf5eb30fdd7b587eb46" +
-			"74a1064c70ef0af2e75373044d32b78d96eb1db3112342d38dca0e47b96e" +
-			"9307fcdd711b1c66355186369a28481cb47ef6bf6651c2ff7ee4665247cb" +
-			"12b573933d3b626d1c6264c88bd77873c2e73e73ee649216bf0b6d6615ab" +
-			"245c43569d0b8096596f25ceca8667661de1cd60dd575697370ebd63f7e9" +
-			"5333e8a2cdb829b75ea83d72cd246d50358f7c094c8a515805fda03165d5" +
-			"21391617c9f9a2ea562b419632df611a67912d2b369e5e505dbd5c719253" +
-			"16d66cd608cc4a9583a8eaa4661b7279870345fac3031631c1a220551527" +
-			"5be7d8d89b71960e687aace3a0e8f206e475053d6fbf97717b154c75406f" +
-			"2caa97d1ab66048f1c99281c188a2f37b8bfc736c25840a9130ef2031c05" +
-			"6acd9dc10592eddf94f5bac85319b10ae46cc136a0738aa803837287ed7e" +
-			"dafe08d1fcf31d5e63763e39a5e1f4d7d0edab368d44e63fdb33c28905ff" +
-			"d6be406a024c017081b4f2d70860776e9d2556cd008fa5017b58733da13c" +
-			"634938407a118827a80baa28d4e605db59430f65862b90cd8356baa287b8" +
-			"4e6d9199fd80abb9fa697e2c2c4c760128e4ec0438388cf407e2a2fe0f57" +
-			"908187ed8efd4c5cb83cc91dbe6a11444eede85099149ca82921bc28bdd6" +
-			"b9999594a41d97307f8854b1bf77b697e8cdd4daead2aa49fbc571aa44c0" +
-			"bc84a57cb5fd85f06847ad897ceaf449eec45bddd4e4eb1e1e119d15d5e7" +
-			"90957e686acbdda1bbe47ea935ebc4b8c2e3cf9b7157cc6dc03bcb19508d" +
-			"a9e19cb76d166da55559ec7e0995d9b50c6c45932d5b46eee400c56d9dee" +
-			"618977dcf6f76e3e86bc5207493afbc2aae9f569ec9277f33d9f61c03d59" +
-			"dd6d8250ee8cb3e54e5e941afb74f0735c41d52ef967610c9f55b2b52868" +
-			"4b549a99ae3392a7237bb52ff5f8d97327e2837268e767bed0bea51f76bf" +
-			"88bf0286bf22b881f93f1d54fab5cd4e3c148c96c39e7aeef375de249df0" +
-			"4d89d1bd97a7afb2be0cbfd3380cb861d31e4ad1ea8627721e4518b9db3c" +
-			"cda20273ec23549c4adc3c027e3ac9558de2010a0263c1225a77dac8be60" +
-			"d498b913f91391d8b2656ffddb06e748cb454dc2b7226745f11030a6b9ae" +
-			"09ac8ac428d9c6500801fb540650c94610ab70465b1210c6db2064dc84dd" +
-			"7f52573f8f40c281470e85176c85ec6de3c718663d30ad6b3dfc1a3a9606" +
-			"1936744357ca62fb8bb066aa1fcac6d7a2adf0a635cd546bef39fbd3ee0a" +
-			"8802ab0466ec9b049b5892a9befa4377cd199a887c34569b6f90852139a7" +
-			"86babc0049ee2b527aa96b988237a52eae8b4b49d2ee15ee5294118cee62" +
-			"3c3e11cecb836b21af88555f10be2eff8379beb615b7b3d6c01d545cacf6" +
-			"61be8ebbf7a3c58ac5e0e7b17997659a2bf15f2b2e3d680d142fd29d23a7" +
-			"aea9890f3ff7c337fce49ecedaf38573edfae07810ba9806723e576d687e" +
-			"a11700b8ccb96a6559259c367cef4e3999a05a373ab00a5672ce8b3d1dec" +
-			"a414187f383e449d10021b73c1f7e39ce01516b7af96193f9993036049fc" +
-			"72ac059ef36b2bcfbe13acf140d41592880fb8294ebffb98eb428ce9e65e" +
-			"1094521bcf8ecd71b84c7064539a7a1aac1ad2a8a22558fb3febe8a44b87" +
-			"72fc00c735773d4ce2868a0b478ee574b4f2e2ceb189221d36780b66212c" +
-			"dd8fd3627cf2faaa23a3d0b3cd7779b4d2b7f5b01eb8f1d78f5b6549c32a" +
-			"cc27945b5209f2dc82979324aebb5a80ab8a3b02129d358a7a98003e701c" +
-			"788a64de89726da470010eda8fdcf3da58b020fadc8970fafb08a29bef20" +
-			"2bd0707e994015258b08958fc2af4c86c3a570443fe6e1d786d7617b0c66" +
-			"29a6d9a97740c487622b5b8186c529d7f8af04d9f0a9f883043f08103ca4" +
-			"d70057ee76639f3b1046d86928d54cd79fb5bb7b46defdf15d2f8578568f" +
-			"1d7b73e475e798ec6812586700e038ed4791b23ac9439d679a1a4bc04cea" +
-			"e328330c24b065c9cdcdcedfbaf58e5299779e6f48783d29ec3b1643bc8f" +
-			"1095c724dea75770583b15797fc666f787510d91e65a8e2090cc1ed2013f" +
-			"e63ab17bc7640ee817487f4eac8326e9c4698cb4df05d01bae8c0d00fc00" +
-			"08919484d5e386c8f60b8ac097c93c025d74faa56e8cb688d1f0c554fc95" +
-			"aae30873e09aae39b2b53b1fd330b8546e82d9e09bbb80132d794c46263f" +
-			"4fd7b45fda61f86576dec52c49f2373e4dca31f276d033e155bbcdda82af" +
-			"8f823948498f4949bf23a08f4c8ca5fcc8598b89c7691a13e5aba3299ee0" +
-			"0b479b031463a11b97a9d0ed3189d60a6b6c2390fa5c27ce27e28384e4fb" +
-			"04291b476f01689292ace4db14abcb22a1a37556675c3497ac08098dfd94" +
-			"d682401cabec239377dff592c91aca7eb86634e9d5a2848161dc9f8c0c3a" +
-			"f7b6a728371fac9be057107b32634478476a34cbc8b95f83e5b7c08d28f6" +
-			"fb793e557513ca4c5342b124ad7808c7de9ecd2ac22d35d6d3c9ce2f8418" +
-			"7f16103879ed1f4827d1537f7a92b5bbd7cd12d1ecc13b91b2257ad073b7" +
-			"a9b1ea8f56b781bea1bddf19b3d7b5973f1065fb72105bb4aeecca5b7513" +
-			"ffd44d62bf41751e58490f171eb9e9eb6d57ffebedd4f77dd32f4016b769" +
-			"fed08dd96929e8efb39774d3c694b0d30c58610541dcfab3c1cd34970195" +
-			"7bf50204acd498da7e83947815e40f42338204392563a7b9039c8583a4dc" +
-			"faba5eaf2d0c27ada3b357b4fccd1595b9de09c607ebf20c537eb5b214b8" +
-			"e358cd97992fa5487bc1572c8459c583116a71e87c45c0ba2ca801931a47" +
-			"a18ef0785ebbe420790a30278d2d0d42a0225d211900618438d1a0b2d5be" +
-			"d14f8b4be850dc8cb08d775a011683a69ee1970bb114d8d5017de492f672" +
-			"09062d9ba3616e256d24078536f30489e4dacd6429ed37aab9b73c53fdd8" +
-			"a8a7aff1b914b9d82d75a46d0ccf85f48d3ce9a8d3f959b596ae9994ac3e" +
-			"3b4af137d0c8e07ece1b21fd8aa05522ba98f85a7ab24ed8c1e265fadf4e" +
-			"9a18c5ab5684d8ba8d3382ad53b415c73ebfaba35abeebaf973b6f18e0d8" +
-			"7f019420eb34e09bbb12afc5b149f1e9e9b6ae36ebde429d437ada1a2d52" +
-			"b998f7c75ef731132aafc3bb106a2ad3ae11223a355804d4869ebaa47166" +
-			"2df261d95d48ac6eb17c1781e81c0027ccf8f05c39e1eda7793cb16622be" +
-			"ce7a1ad5d2f72f8bf4bdb2f4f4dcadac3db3bf727f0d447adddad4500360" +
-			"09ee011bf4155e5e46c74b00d72e8e6a88de9a81a5a4685651b90e874dfe" +
-			"eba41698c98370fd9e99619ce59ebb8342417d03fc724f9c910ae36ac5e5" +
-			"b46c424141073199aaac34232a8e17ebbfdd80eb75e82290de92968f3893" +
-			"0ab53dc83ac433833576e86fbabfb9d7cd792c7e062811f4cb017710f841" +
-			"1e0fb65ea4b3cd68b0af132cb08330aa13579196ec632091476f268b44ba" +
-			"8f2e64b482427dfc535d40d3f58b4dee99053b35a3fed1cb245c711fa16f" +
-			"c141974c8db04f4c525205dad6ca23ccaebde585cd3bc91f5874452ed473" +
-			"08de95cb6164102744f90b3007e511e091653c97d364fe0cbd7f4cd3249c" +
-			"1f5c452becd722ccc8c6b4e371e2631337dff78efd903a8fc195a90ca5a2" +
-			"aa4513bc63cd43794ff06c5337329055c43d4fb547e63d6e4d14fbe37b52" +
-			"1411caf2f1b0df51a68f677db59aa227c725cf494ccb7f8cacc5a06ac5bd" +
-			"f135a2603175a5fd5e5af615fd2e7cea61934e6d938b9e672290aaccd99a" +
-			"7e26dc55efe928e56ae6354168264e61668a61f842a581cd0c4b39e0e429" +
-			"04631c01320857b4d7e260a39c7fbed0593875b495a76aa782b51fee4f88" +
-			"84ca8ddb8dda560b695323cdde78f82dd85757cadea12ef7cf205138c7ba" +
-			"db6a7361a8d7868c7aefa7aaf15f212f5f5ab090fd40113e5e3ad1ab04f9" +
-			"b7f68a12ad0c6db642d4efb3d9f54070cc80d05842272991bcdae54cd484" +
-			"9a017d2879fd2f6d6ebce27469dda28ad5c345c7f3c9738038667cc9a5bf" +
-			"97f8f3bc",
-	},
-	{
-		key: "aa3a83a6843cec16ab9a02db3725654cb177e55ec9c0c4abd03ada0fbafca99a",
-		tag: "719dbe5a028d634398ce98e6702a164b",
-		in: "643883153c215352a4ff2bb2d6c857bafa6444f910653cacd2bbdb50ffdb" +
-			"cae23cc297a66e3afefbd85ab885e8ccf8d8f4930e403662fb4db5121aca" +
-			"82dfcc3069bd5f90be4f5bfd3c10f8038272021f155e5de0a381d1716abe" +
-			"0b64b6d0f73c30baf6ddfe0e6a700483cad0fa14f637afb2f72361e84915" +
-			"78ba117e1c03f01fd61aa8f31da6464f3d0c529524d12dc53b68f4d4b326" +
-			"db7fc45c63f75244002b8f9a185556f8aab85948647818f1486d32c73614" +
-			"b8c4763e2645bdb457721ff3901327588da01622a37ccbbd0374fec6fd1b" +
-			"cce62157e64c4cde22c3a5f14c54cd6db63db0bd77e14579989f1dd46461" +
-			"4c8691ef26406984b3f794bb7b612e8b160374be11586ec91e3dbb3d2ccc" +
-			"dbfd9c4b52f0069df27f04853e7cc8b2e382323345b82ce19473c30296cc" +
-			"453f479af9a09ec759597337221e37e395b5ef958d91767eeb2df37069a4" +
-			"f3a530399961b6bf01a88ce9dfcc21c573e899b7951723d76d3993666b7e" +
-			"24dc2570afe738cbe215272ccedb9d752e1a2da00d76adb4bc0bd05b52c3" +
-			"fa08445671c7c99981a1b535582e9b3228ce61662a1d90a9c79afbdcfcd4" +
-			"74def2b7880cac6533ba0a73fa0ba595e81fd9a72ec26965acc0f4159ba5" +
-			"08cd42553c23540bc582e6e9ac996a95a63309f3fa012eac14128818a377" +
-			"4d39936338827bbaafad7316e500a89ed0df7af81be99e2f6aae6bb62568" +
-			"1dfa7e100ebca5c8d70f67be3c1e534f25446738d990ee821c195c98d19c" +
-			"fd901e7722b4e388da90b95ac0b5b5dc5d052ad6b54f6ea34a824bcf0cd8" +
-			"7f1fc9a07e8f5b8aa0793e3c9c1022109a7c7ae97ee2a2867fd0cf0f8971" +
-			"34b3d150d3b24fcf8323de929b73cca01244df02510393f0b3905caa0268" +
-			"7fe35f64391e7d4b30be1cc98319716528ca4f35bb75d7e55cf7749968c5" +
-			"37136eddb149a9f91c456fde51937c0f35e7e524647311077e6fbe7f3c12" +
-			"37b9584fcf3b0f78744c7b2d3b452823aca06d144e4463eb5b01014201cc" +
-			"bfed1adf3414427072135d48e705b1b36ab602cae69428e7c19d39cbb4e0" +
-			"ca26a871d607ed4daa158b5c58a0a9f4aa935c18a66bdeff42f3dc44166b" +
-			"a299d71a2141877f23213b11c52d068b5afadc1fad76387cf1e76571e334" +
-			"0b066ade8da02fe3b0bdc575b1d9ec5d5f5a5f78599f14b62db0bef7ccc6" +
-			"1711482dfa4787957d42a58fdc2f99525c32962b06492229399980601bd2" +
-			"ee252306b1464914424de9aa414a0a6e5dadf8ffbf789e6d18a761035d3e" +
-			"f2ff0753becbd2dd19fc1c28f9acebec86f934f20b608a9ef735ac91f6b7" +
-			"83d9327cce7f4870d39bbbfb0100838dee83e6baf2b40cfc98415dd174ed" +
-			"72e393ad0459e8035dce7eb18eb3af2f39d2712846b9e1852cd61d06dfc3" +
-			"5e34fb761b67e2a711ceb4a82557371ed32ca8db2e4cd7fea0b6bd026177" +
-			"4057b9abc45dae6869cab1097459473a389a80a4523e5de696554f8b0bec" +
-			"0ca605e6acfaa00386fb5a48e0f5893860a29f35e680be979cf3bf81ee7e" +
-			"ed88262dc80af042b8cfe6359cf8b475560bb704728034e2bd67e590bd76" +
-			"1632e516e3292b564c7265d7a6dc15c75ba6f6a447b1c98c25315ac7de59" +
-			"9edc4993e4dc7d1dbfcea7e50ebd0b226e096500216c42de3abe352e5b09" +
-			"a3c9754aa35d00883906599c90a80284d172a90abbeaf7e156fe2166ada1" +
-			"794420fe55b1a166d752d0eb7f04e822d021c615e84777101e7c9f9dd12e" +
-			"565b7d093fe978f85e6142c1ca26798b45f4b8d23ecff6be836e810e314f" +
-			"ebd2ea66f2ac95bad84b39b7a6bac41448f237b45e9ec579235ba2bf5fa1" +
-			"f00286379ec107c743f06ae0d11b57a2f5b32e3bc5f1697aae812d7ca303" +
-			"b196a8a43259257f7697bae67adc7f121be561b2d0725982532ffc06cb22" +
-			"839d9066dce0e4d683d9348899089f6732de62751ca77f1c439e43054468" +
-			"2c531b9c61977bc221b66030f7571dfb3ddfb91d9838529dbc99612f650a" +
-			"d72bb78de061192068941a81d6ac341101aeb745b61bd7a87a35a2714d50" +
-			"c3eb2c3ea148fb9ebed948307f8b491aec277ac01903ba36e6ad54f89fe4" +
-			"280a17f8e7ae639e75aec16d56576f03c2a1efe4af995eb825ccaa6efe0f" +
-			"d6d878299a351591d791c286cac5cb049834580d47a9bb7720d0603e3141" +
-			"ad7c1ec2dd23d3002e15d73c1828a7f08062848b1b6fcf816bd954743547" +
-			"6f0d6f882125bd03095eb1b1a846d535730e258fc279f7095de7c2d3fcca" +
-			"a4640a2e2d5ce0974c1e073c60bb78171c1c88ae62c7213a95d36ea9ab17" +
-			"59093813b85d17ff106e69100bd739ede9656388bf47cc52730766a8a186" +
-			"9dcc623e09e43cfba1f83ae1d9f16789064ec73504c29686760ea02c6634" +
-			"a929ca10c6d334b1751494c6d143671ce8e1e7dcc9bcda25af895a193032" +
-			"ce27c1016ccc4d85507fd2265ebf280d3419f54f66ba2a161c068491578f" +
-			"be056f02f97be745db443e25ed2647c5348f278f4ad8bf5b2a2c2d56e795" +
-			"532e25585984a3a94f435ef2742a0413abed7230ff2e9724187c91f73a7a" +
-			"726ebf36bc8d0d959418dd586452664990889358c56720c1001c004ff768" +
-			"54b9850890ce1b31735fd9f4a3640622ef0b25c659e8a937daa0df7a21f1" +
-			"77be13dfdb8f729da1f48e39a05f592d8c98da416b022fd8edab8e6132eb" +
-			"a80c00501f5cc1e0243b6b096c8dbe7f8c6ffa2f8bcc7f309fb80b489b92" +
-			"c4878fabad42d91876e10ee64ccd415124461cdc7d86c7bb6bcd9133f3c0" +
-			"dfa8f629ddb43ab914c0ac5ecddf4398052229876fd838b9ae72523946cb" +
-			"bba0906a6b3ef26672c78cb24cbf691a5ec869d9fc912009d840772b7da0" +
-			"c7f47856037c7608705cd533918c207a744f75fdfac618a6981778e09332" +
-			"5c7d22170da85bdc61044b4c397919d601a30746cefefa798c58f02cb827" +
-			"0d130c813cbeb67b77fe67da37a1b04bf3f1e9ee95b104939220fb8a0394" +
-			"86ab8954b2a1468016f546406d1946d531966eadce8af3e02a1f59043ff6" +
-			"e1efc237dbf4dfd482c876531d131c9b120af8b8fd9662cef1a47a32da40" +
-			"da96c57dc4efad707a4e86d0b84262d850b451bda48e630c482ef7ede5bd" +
-			"c55147f69e2ff8d49262d9fe66368d1e38ecdb5c1d4e4042effff0670e69" +
-			"04e47d7d3047a971d65372126ff5d0426d82b12b253bb4b55005e7a22de5" +
-			"6fa54f1dfcce30b1e4b4f12b1e3c0de27cea30ce79b08c8c1aceb1ffa285" +
-			"c317d203a9f2e01d542874fc8035b7670f3648eec79561d6ff2fc20d114f" +
-			"ba4fbed462f1cd975ee78763c41663849b44cb2827ee875e500b445193e1" +
-			"4556bcccfaba833bb4ea331d24a6a3bd8ec09906c7b75598b44ce1820a49" +
-			"fca4a0c1501e6c67515d4fa7f88f6aa3cd7fbc6802131a7b14b219e154db" +
-			"9ed241133e10ace40e4d963f904dd9f3bdaaade99f19de1ddfe8af2b3cc4" +
-			"0a48374dd8eb559782bea5410f8f9a1cd128523c0157b6baad9ea331c273" +
-			"311492fa65c032d0d3b513d23b13b86201840d51759021e4133f873f2781" +
-			"8f54f34ba73b4f33107d49c8de1533856ec37bb440f3c67d42148765610c" +
-			"3296bce932c839fd866bec3762a38406ac2b39d0d93730d0c88cb8f765dc" +
-			"d8ee71263fc96068b538da06fc49e25dbeaa10a5111a9af8e8f8d78e6ed1" +
-			"3752ad021d9f2c6b5ff18a859fee9651d23a7237bd5a5c29029db3882c47" +
-			"0470de59fd19fb3bfbd25d116f2f13ef5c534bf3a84284ae03e3cf9cf01d" +
-			"9e984af9a2e63de54e030857b1a071267cc33d22843b28b64b66e4e02803" +
-			"c6ab5635291aefa69cfeb3958c09d0b37176842b902da26caae3f0d305e7" +
-			"c6ab550414e862e1d13d9bb9dc6122cb90ddb1a7bc6d31c55f146659baa9" +
-			"6cca4ea283e5e1639967889543ecb6849e355b6c0227572097221dd46c1d" +
-			"f8600b230e9644ba611ba45cd83fa4ac7df647b3be57387b6db12682018a" +
-			"de9be50a8ea7d5f7c743bf0c6382964bb385b3c207c0cdd63279c16130b3" +
-			"73ba974125291673344b35c8ef9a33be5a8a394e28dc1448f54d46af675a" +
-			"edc88ce85a11ad7e50058df4f3f2364abd243683d58a2b13fcb0dc0eed21" +
-			"380b666eb87f4be75e7f2842bae916c15af3e9658c55408537b2301faa6e" +
-			"42af4d94e3eda6a41d6d302be281e2a9299e9d0fb1f20cf4ca978e66bdd7" +
-			"4c8bea0f15c84d6513cdea787dacbd4bb529ed03528284cb12f6ecd841d3" +
-			"c58c3a57c6bc19b65d6d10692f4e1ad63b091137c8acacc6bc1496953f81" +
-			"2972bf6362cf883bb75a2d10614029596bf9f35e92addbb50315b30161b7" +
-			"de8867a1393d9583887a292cadceb54078c9c846ec30882e6ff987494060" +
-			"721d3c761940b91a126e8d1e0118617bdae01a7f9c1aa96bdd6c78ca06f2" +
-			"6c8d85664a8705334f4997c724ef98fe265985593d5a9c30798714e6de1e" +
-			"bd04b648be47a6b5d986a3103e738a5cd114b19b7ba99d2e2eec6181bf3d" +
-			"ff0fec8c54ae6118be8702c3e775d493a6fafb509712a43ee66c3f4b75b0" +
-			"194c88937cffa5fa17b284d2556f2b0eebf876e05f92c065515198bd5e83" +
-			"00d0db432cb256a4a0f9963a05694ffce3ecbd182209e0b7bb50120f6be4" +
-			"eeb9d268b17790ee14a2c887dc5753e0086630b3123734053aa37595aa8f" +
-			"31968ddae4991af4ab970c1e3cfa1146a2efd9dc42abd6af14777b8a0455" +
-			"3865691cbac4b4417b3fa13c154d581b498f3b8cb77adf0e42dc2f2fb521" +
-			"732447de97271e542c6cf8cad3ba0148cc3ba1f2983ead836a25a2c022d0" +
-			"43ba18fcd009d518d07b53344a5bc4d626b3b38405a114471f75dc70e015" +
-			"d11e8f6f57d087fa72909785573008b1",
-	},
-	{
-		key: "1793bfda9c8666f0839b4b983776735a927bdaa3da99b13c9f3d1cc57d4d6b03",
-		tag: "bc89cfec34ab2f4f2d5308b8c1a5e70a",
-		in: "a09f661aa125471417d88912f0a4a14115df9a3a19c1de184878291acb0e" +
-			"89ee1f9d8213f62df442f8969a9a5a7c402fea09bdbe236fb832544e1f93" +
-			"9cdd4873802b2bb8fc35ba06b7ff96da6dc7efddfeeda84116bc525a7fc5" +
-			"2d84d2e63cbac00b122dc64f2d15b36595259d81a1d2a09f204c54072751" +
-			"dd812259df1104bb2d2ee58baee917c5d0aa2649c8a1503114501e6ed6fe" +
-			"239847d3d88dccd63d5f842426b600079c6bf06e80a2813b2208181163b8" +
-			"61dca07fa4d88254e84dac1c78c38397a016b5ad55a6b58878f99036db56" +
-			"89871ab3c321f6ed5895f218f8fd976c348b3f1269fcdf4d38c9492b4721" +
-			"6c45f499f5705830b33114d721f9731acf6c69fca681b74c2d82c92e145b" +
-			"7bab77110821d3a12cc818d7595a5c60c4b5e5219376c38a4dd52d435d41" +
-			"562802ff65ba2bba5c331c333d5adf194d29b2cd9ebb55927bb4ec17681a" +
-			"3f5574ad34fb4e964f2c756f6dbbb7a6876a21579a515263444de7a30a33" +
-			"15005458bc137ccfdff18a3892fc9f58f1de10d4de20bbcf860f5f036d8e" +
-			"8a188f18e5cf7ea3cd260710e7491befcb131d49a28dfb1ef688fd021a1e" +
-			"e4420d32fbfb03b47f5e85c37d91e49a1b0db85d966eb5434c4197433eb4" +
-			"9d56f2ff999c9a72230447032dc949202468261b48b6ac212e3f651d6c63" +
-			"03a06c90bb2d3a755ed91ba73bcdc28e1c5b0936e51e0a9f69c3ebabd3db" +
-			"add7abab6d8f6a44daeb3126429a01815f57444fb7022a4a510f8b564ae2" +
-			"dd9779b3a273fef15859a33e233724846c30d89fb78a595b6ff6c834812c" +
-			"00a991e405806aafd0c26a788895ad00a5e43c5426197aa8247207077548" +
-			"ee67db4cd6f878431a2e36e952d84b5fb89d681f553198e2c066310ea6ac" +
-			"3a31f5b1792620616f6c41d486fb844eeacc7fd36971abf416e8d6d50985" +
-			"c83cc92ea46ac37da8f0026aba30c945d8bb15080d2d95e4081bad626199" +
-			"3f95f57ed3252822a7caa035ae22a36c35e280cbbc82d729346cacdb1794" +
-			"ae9a9bb2793fd1d5c47121b135c2836063367339c5151b4e35278e97f62a" +
-			"fdd2f231d4b47812d083a829ebb9c374ff2ae8479cc4b76d55f9cef3ec6c" +
-			"4894f53e8caaeb0d8cd072960cedaf758e48e3640590d4f728626e0a08ee" +
-			"ebf719c96bf8ed4d0c283be09c0ae67b609e22d3b9aa6b03642854909de0" +
-			"5ed52b39673867bf586a632ab8072de15c637cc212cba8387515c9c9c433" +
-			"abd7ba6b02abd09da06a34694ad34f88515b65c0c9c247fdf9819fb05a1a" +
-			"ea4728c1182f8a08a64b7581cd0fb2131265edcb3d4874b009aede0e87ed" +
-			"463a2e4392aefd55e008eb7ba931788262f56e53193122a3555d4c08133b" +
-			"66020154b15643fa7f4f5e9f17621d350ede3dc70be02c59e40fea74dbbd" +
-			"7919d1a8d4e22ef07c916fa65e7d4b89fb11a7c24ddc4ca5f43344c753b6" +
-			"1331c3fa4558738ba7832b5b2a275bc9b7989b6e6888865793329806cd3b" +
-			"f0ba57c941d4428623e062f4ac05e7cd79ad5446f8838f2b247b66bddadf" +
-			"540845a1bb304a04b7edbbff579c8d37e2f6718f8690abd5231822c7e565" +
-			"69365ce532449a41ae963ec23a2a75e88307dc6b59cbb3fab913e43ed74d" +
-			"841ca9f6e4ef96dfd9f04e29e89361aece439c0b2e1943b30410a63d495c" +
-			"522ac3ec1b04ec4cb345f7f86969957ad750e5bd7dbf1d6a22eed02f70b8" +
-			"1cb5b2b020c0694d7f63044f9de0c3de1ede52009c858992d01ebb92ff19" +
-			"a9e0fbea18942fbafb77746c8e9e687dd58ccc569e767528bde43b62c7c1" +
-			"270a5721f1212de2b29a7aae2d6ba6cd173d7fbc78aec4356ce2e8ba9164" +
-			"d97dec061dd0c3a0e3c520a7611ac99739049dd5825537c70b7ef660046c" +
-			"1785546cd99aa400da848eb7c3c91247415c8e245d0f14c30d482c5849ae" +
-			"aaeab2568288229b08267818dae8f76fc674c684c99eb5faf88a0783813d" +
-			"f7298e0b50cb233f78471e5ca9cc3b04927c26a3871cf253798cc49aa717" +
-			"d8f18a1ddcbdc26497d188f15f86ec494dcf8f942c3e07e572385c6fa0ef" +
-			"40c0b625f1737543074a747a369482a0b342a08b3eccac9f9209be31aefe" +
-			"5a7794974f71ac0bc9a58026397ea3dd4f5e40511d58d2a3b45925c194ef" +
-			"13987037d736dd48b509d003a86471d5f161e0e5dd168b4f1ce32f703b89" +
-			"15004d8dfc708a5bb02b2e6fb67424b2cbcb31ddaa0114c4016b0917382d" +
-			"aad11815ff5b6e37d5af48daa5ef67cee3439283712bc51b5adf2356cb2a" +
-			"5181b8941fd78945c7c9d61497683e44fee456ad345e12b4258f15945d45" +
-			"b6ca4369ee792d849112d583fdb39cd4d333ee057355f0abc8d1eea4640c" +
-			"128cc1617982db0394233dbd416102eec1874081247d2982bbf9fed1b1b3" +
-			"8f4da923d68c8975c698f189a4d7840fd7aca9dceb7d91c076f85e1c546f" +
-			"4d5de4f60c91348455aaea30cac134c844dad93d583c139dd52b3be6346c" +
-			"4d2e6864125c5a2d0aed8f67930e1ebf8700ca88aacc914ea76ff17148f0" +
-			"777738cc126e75a2c81110faf02fefc47c91edbab7814599000ce55fe20e" +
-			"f313566e9b62457acf2f22e1141e220bd9d4747417d03e703d4e39282803" +
-			"386327fc65dd597f723ee28185c78d9195fc70a75706c36287ab9c6e00e8" +
-			"5cecbbd6043c6af8d30df6cdd8777be0686853b7c8a55a5b1e03e4431d39" +
-			"1725ff99875a85cae6926998723b36d13ad458220712209bfc5e8d2ca5d4" +
-			"4ea044d5ba846b4035e7ac7e9885f55d3f85c0c1b3d09fe929a74450f5d2" +
-			"9c9672e42d3f59be4ca9d864a4322cc454c2578493bd498a51bbe960e657" +
-			"3e5dd02c4a3a386d4f29e4578a39e9184024cd28d0e86ecac893b8e271bf" +
-			"ce3f944d130817378c74d471bd20a4086f2429ed66c5c99969fd8da358ff" +
-			"5c3be72bf356ae49a385aa0a631b588ddb63628fd162673e915cfc4de56e" +
-			"ae6ff7101df3b33125c9bab95928f6e61c60039b6cc07a66f9c733251447" +
-			"ef9c1ffefa2158a8ddf89dc08686a4cf9b86ea09914e79842d72a3236afc" +
-			"98a3afa0a1cac5590ab6a923e35a2ab8db6410a9d33cb84d1c48a054377e" +
-			"549774b25f50fbb343ecd5db095155cce9fb0c77d09752f62d4bbf16a770" +
-			"30452a75f6bdf73f7807d8f3a6bae16ad06b22175fee60549c22548de9c1" +
-			"3df35ef4e7bf7b66491a62b93c2c3fb0c5edc51f60f5704b56af30f1079d" +
-			"7c385b99f958ef8209e030e381d1ee8d67d3cb84f32e030e8ea2c1d0c77f" +
-			"d6b242a9f48707557c8682a08e1127f51221a55c733ab1edd00a9c2912cb" +
-			"36dde85f73b524e1a4f4da6414c5e4c18d9537722b2becc8a91bcc63f2b0" +
-			"9f32409c53c2beee0de6726dabcd6bf33118a5c23fb9c5c1810476efe658" +
-			"4bb6109c516b45e16b2f79f96755680374d82b91f2c519639a1815fd485b" +
-			"a3c00b46fbefeafcf25554ec5a6a5ae2da07c85b8a0f9fcde50263d9ed85" +
-			"038b2f7aadb9de765655bd201235218bfc74bcad6a9ddf4506167a649afa" +
-			"df400b85752d68a92b7a97f26b334dd77fce824862046b286a7c8e0adc36" +
-			"f713a252a673d4d995b268badf4bec8b8eefe85c25b823b6728582d35c4a" +
-			"60041114dab72b0623b99e2758f6a1e97365279bfba0eb1fc8952ca4f2c6" +
-			"fbffd9f5fd7dcad1125b18a796981b5ead0b6431141315898ace96f0d38f" +
-			"865698df8822ca7b65644b6b1f0a0f0d2e5850d4c93ec48ca3eba1b919e2" +
-			"4413a46d595ffa427715e499db3b7b9ab53c64abec7302bc737a5bd124bc" +
-			"da756abbca132f7f67e6989e09bfb23b497da31bf156bb9c69ae54588df1" +
-			"7420e8fe989f0472c8893b2bfe57cdae265a8cc7aeb39624167a567a6fbe" +
-			"bb1aa30c3dcfd14f2808a070994085e6e1fa79021e77c399f90ab1f995a7" +
-			"baff672cb693bd39b798b4c890b7d0a57978d6b9bcdc5bf3f4d205f8f24b" +
-			"2b43d3ae300a96971c9182be297618b9adceebedba1ab0f324b01d23d7e6" +
-			"35f009db3dbbc643c2d787567594bc639bfd78c4f3e6d948caf06f013423" +
-			"eb3c764666b58f886d5d28137c053c2a28535efcea400147e92ac6753574" +
-			"3b47f9cb48852abed1d057647d5b1c6f334eab1a813401fccd3dae332738" +
-			"776bb223e359f3c459b5c573ba64fa945bdd66c5ac0fcbd53b67032a7b80" +
-			"25f551e8d1fd2a4291bdb7941cbabe3a09765dc263e2bbb6db7077cc8fe6" +
-			"790d4bed5e36bd976d1e37dfdba36aafcdaa10c5f3ed51ba973379bcb8fd" +
-			"203d8b7282abbd271ecf947e54486e8653b7712c9df996a8ad035f41f29c" +
-			"ab81509f922c67dacb03f25f8f120cb1365ab3c1c286849c2722448ba9bc" +
-			"ff42a6b8a7a52f2c79b2bfcbdd22ef8a5651c18879a9575dac35f57d8107" +
-			"d6bece37b15d7dfff480c01f4461ef11f22228792accda4f7936d29d4c56" +
-			"cbba103b6d3e6db86e39e5f1bb9e9fd955df65b8a6e44a148620f02b5b90" +
-			"b2be9e5bb526d0ec75b1e723e94da933a356d7ca42d0ce8349699f730b8e" +
-			"59bac24a6b633759c88041d29399ce60a2ca2261c7eec1acb9a56e0e65bd" +
-			"e37653ce2cf7eb83a4d019c755bdc5d685b6394ecddb9006823182dd8138" +
-			"a1bf79a32d07a8e5e8ab221995c714e571b40bb255b79e328ab883542c16" +
-			"4899fffa16eb3296f310e302512352a864fd809beaab4169113027c6ccca" +
-			"99a92c6ce35c30f9449a3add70f10db1ed08078e8e6cbaafef630aab7e9f" +
-			"c8adb09c18e33fe1af3620d1e4d069ac11325e23cc18e5519a1ed249caf8" +
-			"ddba871c701f1287cc160019766988f63e089bd9bf1af7e6f5b9002e3b6c" +
-			"264d69a8bac16914ab55c418d3a8e974677cdcbea36c912e90386a839a37" +
-			"77b878e680c07c7cc99f42a7dd71924babf7fb0627d1f2cc60d9d390d1e1" +
-			"50d47386be6eefec9ddbb83b28fa7e2fd28cc3867cbe42d13b00545af8a0" +
-			"48cc07016ec79808b180e0b258c564739185da754f2e",
-	},
-	{
-		key: "0d41cb4ac25217feb20e86fc2490e8d2ea2e8225c051252a9395cc4f56e1ae5a",
-		tag: "42df9f9a59d6dc05c98fd9e9577f7176",
-		in: "01caba7a19cdb09dc0ec6c522c61c628eacf17ef15485aa5710fed723875" +
-			"2e4e8e93dd4bbc414e4c5620bab596876dfbea33987e568ddabf7814b318" +
-			"8210a5f8d70041351e4d8410840642a29cc8d901c25fa67cc8f9664ea5e1" +
-			"9e433eaff7c722d0258ae112b7aca47120aa8af4420d4412a10732551db2" +
-			"cd3e0af6e5855d5eea61035af15a4d0d898d04033809e995706eba750a7c" +
-			"ac07aaa0dc71477d3020f778d0347f1a8e37c18540deb9ae967e734c0264" +
-			"df0e1f52b0b5334805579ea744c8784c3ae0c3ff8217cd3f53cb747f6996" +
-			"f3d2147699799e649061b205f97f7992e147fb20f21ff862c6c512e95534" +
-			"f03075e8e52f162e0d70d7a259e3618474427f400f44f75198edebae6e40" +
-			"a2173257d114e1bb5a13cf419c821eb124d90e89a938d91f4d2e70dfd1ab" +
-			"60446f1b602614930a329e98a0c30f107d342281db25b8f8259933e14d20" +
-			"8bbd991e42969e8b0600272f9bd408483cddfc4cb8dfe7bc19be1989c7fa" +
-			"129d38e1078d094b82e0a845040ddd69f220dc4aa2b236c44101d7da7779" +
-			"9827a7b037561b51e50fa033a045571c7267af93b96192df3bf6180c9a30" +
-			"7e8c8f2b1d6b9391767369625015da02730ad6070df4595eb8099bd8e484" +
-			"59214310cb62c3a91a4fa8ac3b3d7b2017d4254fb465f0a248e1bf45819b" +
-			"4f0360f37c9a79d405e2bb72e5c25a1b4df192cfd524d61e1e8b274f2fe0" +
-			"634c73f0653c7c9e9062c9d081f22a8b0327897eed7c6e870f2815bbac8f" +
-			"585c1bd868759a98dcb5c3db2f6c53244b9cc494a56f28a9ba673167cea8" +
-			"b799f37049ee7b0772972b3a6603f0b80eddb58ef03f916106814d72f000" +
-			"250b3573c97c5c105910d79b2f85ad9d56002a76a1f43d9d1c244ef56d3e" +
-			"032a9bab95fe3bd5dd830ad7d7e341f28b58c0440658f7fc2ca98f157708" +
-			"1c647e91432cb0739d9acdbf973ceb9b0047634d695279e8837b04dc5357" +
-			"f013fde3c55c9c53bf1d817ec59a1b18ed0ac0081ed9bbb3bcd1a5d3634f" +
-			"50f7506f79dc6a4ebfa640bf65682fe9aeca68088e276937669250064de1" +
-			"c19ad6d5c697f862114d0f81d2cc52be831ed20d3aab1e41fe6f476b5392" +
-			"af4799392464c51394c2d1a8325ee2e84f1635d295ee663490e538eb338c" +
-			"7126a8e731ad5c0becf144c7a9cae5c6493350b589385de29e1a0ad6716c" +
-			"346ec4f0a31ca5ea35c59ab6b099f65d7f0b3d00925a1da1b5777c029aea" +
-			"9679e895d7100645dc83f81d82a6174beab2357f7888ea640900cf3ee67a" +
-			"e0724a123919d78e70e05288f67e5e69ffa6f345be8a96e58bbe260184b5" +
-			"ec5c0c1354cfd516ebdb8d420029137d41b029641959cc07fa7b4e16b39d" +
-			"17f36b2367057410a42e0550e9ec1dcd2df4604d52d4f9dd1140d57af08d" +
-			"50e1527dad793b6d649324de799754f755818bf10e6d1ab614958dbb24ac" +
-			"8e2c01270a90ec3df4379c3f509b5ef721b0fd4f91a1bdb8127ae4dc74d0" +
-			"75f6cd8bb28319d6f8e8d8ff64fb4a42d646e9365156c6bc72cc46e9cd1c" +
-			"f9e735549e3df9a8e6b5fe541948b126190117db71fd1d61ad84be0f725f" +
-			"20b99eb141b240326d399976c4f2ce5823d94649a9580e1e8820bf49184d" +
-			"fc34378a60bea89b12aca69cb996c17847b7fb517cf2d51f16d78e3875ce" +
-			"aa33be15f6a154004f0e1134c6652c815c705efc34bcf35bd7743d28f0a2" +
-			"77d82dea4709dab41fbfb4e0cbc118c17aa00808872f0edc6437c357cd31" +
-			"74a02aee61890464e03e9458853189431bf5df6a0ad5d69951e24be7f266" +
-			"5bb3c904aa03f799fe7edc7bc6779d621cab7e520b5994f81505d0f01e55" +
-			"96e14b4c1efdf3e8aadee866c5337c1e50066b3acc039c84567b29b7d957" +
-			"683cadfb04fb35402acaba631e46ca83dbdd8adf28e377ec147e4d555a21" +
-			"e6d779d7c5a3078ab72702234d36ca65f68bd01221c9411f68f32e16ef04" +
-			"99a20c2d945fa31b79d9965853d38ada9d48eead9084d868c6bad974b0f4" +
-			"0956aa0fcbce6dac905858e46c4b62c0ee576b8db7d484a524e951f4c179" +
-			"decfc7d6f619e86dee808f246dd71c7e0b51d28bc958110d122fa2717148" +
-			"77823242711632f6e1c7c15248655ced8e451a107707cec8c84929beece4" +
-			"efe5503d3c1763d0ab7f139f043e26027d5e52a00d5414dd98a324a8fc2a" +
-			"06a1345cbde747f41099c3377b86bbdc5a17c8f6e5b773a761f78573832e" +
-			"4359b143810361dedc79142fffc49ddc0b32f225d50d360ceec3920fb0ba" +
-			"0693b644ee07fbd1ce829e223a02794b197614061c4bfa46112d105c2b7b" +
-			"4efea448501d146dece44f6640d674d5749db498b32969de6e165e705a18" +
-			"2aa1f3d8e16892b0120337640d52c9bee35e5b4b17f03eaeb31205c8ecbe" +
-			"1ae1b110023016e40ee87370a65c5c20bfb00f100d3c6c1de6e4a1c90162" +
-			"f25bddbf300ed637330206788a4ff96903f971c9618493ad074412af625c" +
-			"ff9e0f8f183bbd5e96c1f28307e6cae8b50cc0eb1a3a8154e44e9de947af" +
-			"002e4d1098d6b0ee3f2e71a10d03eb444729c42461283f37be8af2ce81ba" +
-			"bac246a05c2c94efacc43f0cf9ff3df38ab6fc1648c796ae7026ea95752e" +
-			"b70873a6da59da10d8b5316126431c4a17289466e95dc739c061d7a4b13a" +
-			"450809479eef421bddcdade77a6df133410328c754af8999a09b1a5c056b" +
-			"ecbb6fc2c339586ab92100f46d2fa1fa689994b36aa70703d76bf7738adc" +
-			"f0589fdfa6bd215339ad69ed983f62efce0add5a63fe7dfe4bfa006ff16e" +
-			"0cc06d39199ad60adcae12b75ca98d764502a783373da3a41281e03c2037" +
-			"e1b3ca7f7eb60e2b67427e97ec72d36670db7662c6daa505701fd279f116" +
-			"ac0ef569471f204e1531c25a4ac3ce19b6f68a8994b6f89b5abf034a6507" +
-			"32c7fad4206eb4eaa7cd9a710d866bf3c3f13c16faa268ae0cf4f69be909" +
-			"bb9b79aab80dd25101d4cc813a48d3f38d870f10ac0b6768005aa0e69e87" +
-			"dfc0424deef06414c9ba6f498c93c41c692a7a6221fb5595b390a32c70e0" +
-			"2cd64471c797ee8a143725849c1e054ee2043dcfc0b4cb1c00be21a14be9" +
-			"2d9a07f1b4e975d4c86b8a5c1387e6c42bf393e078fe86d24612d497e14b" +
-			"874485a3cc922b5b6d91295d7b79ab8bfa1c7f64b51e761d19bb9da82a5a" +
-			"a34aa469699036b6b2c55e2b84f84942f10585027ab07e2e0e562e0fc3dd" +
-			"36047850ded84be4416e22aa41c7a2f7d4a4d8e3dd420d746a1d8d56d87e" +
-			"5133a1b4380bd9a89500fd6d7e68a1ec02eb9e79e4a13edfdde1273466e4" +
-			"6b0e6a75f59ff6175716629da52463ad21de27f40fa2e25a566eec4b2696" +
-			"4af3a717dfb0170a73144c0bd9b00bed67ad8c0a146eb5a055812d071209" +
-			"c9d530cd4f50a41488c2238898dea8bb36b0f1496d3ea8c4ff8e263b367f" +
-			"64977679e697d88e5295bd97ac16a0420850d1ead9621e25a3f58925c266" +
-			"ef5246488b1c15a8fe0d8ec4291864faa5a67b2388b7786f47b6d27e8fe8" +
-			"46f85f85163e54155ef95cea4901e712a44404a4d3f27f28dd961ce36b84" +
-			"f3856770f07f20a2ebd34d77405beab04ddfc09770167d7d6340f494dc6b" +
-			"7e4c3df896bd974730193b1e862b58d4a5938e6e4ae8897dba8812924379" +
-			"e54f51a71364d39f76e24fdf2c6c704479ce85b456558ca6947b8fd76f03" +
-			"78273f0a7bcd1d860ef1defe4eea8fdb81c73eda028d82fdcb2248582ac4" +
-			"59eb7698a811e6c5823be886410f6b8577ff2e8252343b6ea890016ae846" +
-			"01c5894cfb988121059fd9c8fbc1596da470a149404fc67baa15383d38cb" +
-			"d17ac107b4ff3c1ca4c76b7930de02b240e7547d39f4978e0cc1fa37f8c1" +
-			"012b677f07bb4df4486196e9b0beb823a3827585475b878e3f6f0a2d3836" +
-			"2c7d34f9f3c91ed46c39cec95c2a0b6f0279a03a00ed5035b0725c393849" +
-			"cdb1ed3c0ecbcf3c2ce108017f468e1c3d469c03e8231d4195344ced70cf" +
-			"daa667252cc1554dce8d0c54eb4cf4da62367d77d7dcc02f81e788ce9f8d" +
-			"d306ba1b48192359cfe92bdbea9980f87ea0677d7d2082205a436cf514e6" +
-			"fde5eadd21b13dc836ce33b5dfb6118bcac79ae00fbb16d61f00a923b145" +
-			"f9caa9f3a2c7f0104f8b052e390987e57c8dc80cd5f0358afb0111af1fc4" +
-			"e31f92bd832ad35fd2e0bdf768272de52ce0b152f74d43a8973ad516b3ea" +
-			"f5937ec8a236ebc86adeba610de0cf7168453111f3c983b64df07678cae0" +
-			"a75466ae15adfb127328e716448cdbd2c1b73424cc29d93df11a765441e0" +
-			"0eeed72228e1099bd20569d9d0e9e5a0b3c11d0002e2896631186483db61" +
-			"c1a0cb407951f9b1ea6d3ebc79b37afb5a7037e957985e4955979b91fb85" +
-			"61ca7d5e8b9cdd5b7ce0130a880d9241027b011fea7696b0c695d4949ca2" +
-			"d0cf22d44b9fee073ecaef66d4981e172e03ea71a6edc7144393bfea5071" +
-			"2afac137f091bae2f5700bfb073a6d57fddcba674a899d7349044a10aadb" +
-			"2e7f547887dd2f765f394de5dc9ef5dbf1eab4d869be8cb68aad8e2614ac" +
-			"37bbf21ccd5a832ee09fdd07ce50a580a2af36256b1046e646fe3dff6d20" +
-			"0c5110f1ad1311bc39b8114cd11ecdb87f94df43d4f6468932fc0ed892d0" +
-			"3d8f3db3f8323ebb29776ab7d260493a36700bcda668abd62126a8189e91" +
-			"df2d2970ef688d4e8172fc942e69ba63941a36b79ac546fff38f5f7d1176" +
-			"57612a662ea38134e1090c3e903c9adacdeefd3ac2a0467e9f5125058c19" +
-			"7b2260d2afad2b0e627a9ae52cd579ee27168065658089e1b83a2d8cdb47" +
-			"e08966e4ec0018e78c4d267f9575b8fea2a42de5c2d25356fe4b8c9cb1ac" +
-			"daf0d1af4bf58b9704cd4bc08471e3b9a0e45a5693433ede2eb1374bce44" +
-			"1f1811cdc7612d7bb61f4f34aea0a44757bbcc12a55c1ba41a7901eb004e" +
-			"689587a38e5b4df4574ddcc7b2eda97f6e480d7d39f45247ea3b03c90a93" +
-			"0dd168b65d52a59ce9c2cb4e860cc6aaa0ee02a58d0c8ba990194bce80fe" +
-			"8c34ba5693fb0943ec2cbfc919e534cc47c04f502b6c217c2f860d1d482a" +
-			"a016aa02adfc2bea3171fc4e27e2a262fd37b824099aa227fccca508f778" +
-			"b8c6ec7aaff1d15f6497753f439daa9e52060fd6e9e056e6843d770fb057" +
-			"6d9e2e782db4843c0c2c7f408a17376719a3c5cf9fa08f04f8a779885a16" +
-			"5cf93ce404be",
-	},
-	{
-		key: "ddbd5d6c5ebd61fa72b453dd849dc302c98a0f3e300f4768bf1dc698a3827dd2",
-		tag: "af608b71a353e63c64911558baa122f3",
-		in: "c67e2524b0de16483158a0232078fadcf611e4fbdb9e642e397b21222423" +
-			"cc2ed42ed34ffcb178448919ee337eff9d7d691f622e70fd3317cfd271df" +
-			"fe6a9d9b7e07db0d20813e2331164a654386db2ab06ae2983bf2460eaaa6" +
-			"3aa0171fb87afb82e85b40d95c8993b2039d32e9d38473dd13f41fb1ff1e" +
-			"261752ab004b221a4472b9b1a0e139f0c999f826a26a7e7df362b0611aac" +
-			"fa83c55cca2f7c0138d2c30313c2f6eb357278328ea6ebd6a5077947e18a" +
-			"a97c34b9dde3b6f2de4b83778ffcebc8c9cb58756691d5e2a3d15a759a2e" +
-			"5050b6da937a6f5551aec069a08027d60dd870d175d2a5b5f0b4f3143904" +
-			"7445c368a5c866370e9426abbc1a1c5a272b96731c4128aedeee93e8e00b" +
-			"b450601a6d31ea279b9450e738b4a47c0dc22d2d8ed5d44257f6318e0c59" +
-			"b951fb6b57746062ab95cd73c23ef0a5c000a7d14c18bfff172e59b6f6de" +
-			"aa61b81009e803eb05e24fb0b706870e18889a9180ac16a042d12dfff9d9" +
-			"1b88130f045d2342fd5ddc5f443681c31090459f262d1a65654c55251fc7" +
-			"d5a67bd2e62940ccd606f3e50700e4d1e992a3fdf0388b9ce3df9de6dda1" +
-			"5c1cd6b70622ac062dcb7ed7058872c00ff3df94032853927126cf6fa4cd" +
-			"c468d91c9b52dcbc272fd7ba920dcd3ea1e048af9c3286dba74d988ce9ce" +
-			"77174e25a87935352721dc23b60a9549322fadbe6a00dd1197dfa25b33fd" +
-			"9e5713afcfd0fae6dbcf27147fa58d995580d7e0a903c895752fe9819f5b" +
-			"b002ed752719552d0f3575312f2e618173a8ae7c147ca64a709053e5d2e1" +
-			"2f4d1ea337afa9ac4f9ba62760046ec1e48f4ed8f6df66786c9fd9f5bc7f" +
-			"9ca2526e1327b042f4657c405757690e190c91f260dee2dd3d2e6616b721" +
-			"e489c7c3cb828478a3d953b88f09904e7927cdf6dbd6a5419eeeb83c0be2" +
-			"51934a80dfe61e09442f0761aa2d013e10aeec3a32df204571ce8984a430" +
-			"9bbe30ccc91977790bf0305d2651ee450b749c3e7761534e45970e70a0a8" +
-			"473cadbc88f096970c275f188c9d2644e237fd50c2e24c1eabbf7578e80e" +
-			"6500762ac513fcd68cf6f8bb7a9d9eedadca059d9ecec07fe6fe7792b468" +
-			"9311861728dd482f087c28374cf9c5ea20b2c8630029e8485fa6fe518c74" +
-			"ef77d44eb7526ca764e50b5f34ed0f253a91fb2af6e59338e2af6e041e01" +
-			"084e1efade1aebb7d1b698ccdb8b4248ac89cd40d9517d840960c08f5e86" +
-			"88d8ba2b54889c1870d315498b70e0e9720f2c8c53a3377a8c0bd2d6a1c6" +
-			"f17c6ff847eb14def6855dc3886b99039e528b421ccbf6064e39263f8f3d" +
-			"340d5d20b1b14c264ac2310b5f3a0c6f0c1006d0d4f1a69af68d28ab447f" +
-			"cd17387e1fc98f164982a6d05dd32d6b4f0f1b04e40c6c6e0fb4467dd6b1" +
-			"0c5a9c92cc8c2bc97ef669b6d55cdd0aa8a15c46af954359165949012713" +
-			"4ea9f74181d54a300d3172c9f01db73288ef6a709c763a4891666d0baf88" +
-			"8531dcc77f0911412d096aef9033fa36b5c1ed283b8b5c109e45b5cde911" +
-			"6f3da2533fa0ab81929bd5783271d5501a9e4fce2aff9eb5a70a4215b253" +
-			"46885d7e4225fe34bb55b309a114a312693d60ccc61267359a8c2dd28141" +
-			"226e7cfd99f0f12c69df57d75dd790dbabfe3145f7fd1a24fa58e03bc2e2" +
-			"6ea19288af4929e5acc517d8f52a074745ff4644d94179eae6ba7d267292" +
-			"bbd2053167a0da9be5e4b6cd0a4200fcac5182d9957dffbefa857e662b82" +
-			"fc3a7cc32506e78030ed5c5d448d7f1b4fd854a735a0c50016bb85e6e716" +
-			"0f87527bca0de235f4b7dacb75be84919c15a5b8cf6bec035795cb67061b" +
-			"7855c2134c1b1bfa6affe04b7db239f73af6ea9c02bc9f7972b7f6400b6b" +
-			"838f4653aefc42179c21765e3ca7a5e96b4402ff544d4bc2332756a23500" +
-			"11241dc42ec6848afe127c00b9c333e69bb5a54ea5c7193e59ea22bd6d32" +
-			"af4f56b1bd2d5982ef7d9c1b02d7668525e4e81b68a400f7afc2653f0f41" +
-			"a03e11c7a02bd094830093481afbab96397245b9f37a568ea1c4ae248cdf" +
-			"afc87f88b1fb5dc300d8e9039af4e6e701b458ed3f32d693f2e869b76bb5" +
-			"1358cbbe5b5089013bf452734388a176cccfc1ae9b7cff603631ca48e129" +
-			"b5c9573d4e379547272cce8aeeeb407d3fc57f782a0eb5fcbd41e6fb13be" +
-			"7e4f1067cd407b42a6121b2969c384916ba2b32563e659f52aae09c8ce2e" +
-			"3c500fbb7e58be74cc1592dcfacd9f0d4cea1a90a18658147c81cccf6fb3" +
-			"078ed27f369e7646f551386a74e1b07074d93e0c1f298c761af46cdaae9f" +
-			"f4be86808b66d0e228016d27a3a77c843365cb847fddccb0bbcfb3b9008a" +
-			"1bacac59ffb0aa759a0568c72c556caf0ac1091431b574687c5fc7bd486e" +
-			"963e0fc3bdc828d988734a21070747c955cf8dba2df1c3a0ba8146cd58b5" +
-			"91b6d54712db67a9851b1607c8445bc97406eeb7488f5f85e547850d619c" +
-			"407f97632ca1801f52c09c2b314b4ab0f8e7fb5851fd60852f4666913ca6" +
-			"bc840c1ec8f8f06caefdbfbf02ce00f20b87b14ba9e651c80f40a31d0306" +
-			"403f541776075fbf23733a6b19e3b44d04b455b29ef8effa70cce0c59331" +
-			"7119abc07aa8c8d0246a760b0b36a3d87b244e83bae8a745b8277a531298" +
-			"f5d0283498a509c89898ddf0f7a7455be1f8a6889c46d323f1dd18c3babe" +
-			"1751a05f871f0639f50967afa46c19cb93d9c2a79c81e2436a7a62f225bc" +
-			"37c90698640f5b43673e1dc276de05ff1e29acdb4ace5121659db5f23c49" +
-			"57aae22f53e6f2cc935824fbd07c2ac87672eeeab895c3f06e09e178560e" +
-			"2fcfa7097f10201dfb8b1ebac08ca806c1b3ba3aff9284846a1a3beada53" +
-			"e9f7ade12eb89b5591f462b2543bb4090e081fee9fb53bbf821dc92d6b16" +
-			"fe820ab2ee4b1f6c0b6a6f19edb0bf6479e257fc73bcd60dc2261d0a4752" +
-			"e23a0be18abf355f3065177d8c3c14e21edc178d0abd1b39f703e6335131" +
-			"ec90cba3d9846cee7354a06c320a3f61b8a269abc7138831614f57ca6c19" +
-			"a4a621142889cd924bf4ffb82b57f871b854f3157e8874c22d43a5726900" +
-			"bafbb8f2260a1eba3a462e23d4def2ccf68ebaae8e52739a1ce67c039eaf" +
-			"9a6c3232fbb5a91d1e59a8dcd3798ba71345fbf83d09b83b41cc49d5ff5f" +
-			"2e809d2b1d5fbc1e7001ea76b9b2d8f896eb6609e2e1c5c562d2a6e74960" +
-			"2d67a0f6b43a201d5087509b8dc7b0440144e308c18ff8b96b607de2f20c" +
-			"6ee99bb05367a8b25947011889f724965a2b5c52c9db1e0622df9343c548" +
-			"d054699badeb15fc41055af0d79a2bfc1a5b4574634fa0dd9dd10a6213ed" +
-			"b6991187dc560facdc27440456a0a209fd7f5ee4fb350ae71f869723e5eb" +
-			"5338e3d1448bc993afca6957f4cc7b047a2c7c9593b7234725e66cc0eb23" +
-			"3824eb4cb905701cc522ec210950b871397c6c0bb3d0b839f2eb1a120f70" +
-			"36107246df4dfb2c24891bef0bd1dc131f2c9d7c295ee967e3184d963037" +
-			"fcc9e0b8c7011c8e04b4e70038150d34caab4f8c0230418cd2d8a91146e4" +
-			"4e11cf6707452ddc03d9b4e6380658135dfb48f62c0690ebad75167f4dd1" +
-			"c0df3ed555b5081a7b82616d9e501757c83c2193d0f640236d59f9c97a4a" +
-			"5c8bf532aea2cf5964ed2dbd8a70c01ca5c7677224cf2a37f3b24d8fe4ba" +
-			"91cd3b5033715de227de51deed15afb8eda9d2b9615d197b8f98322d7096" +
-			"79c5131eed48050fbe0145a9284e236605c25a4876e2adba42f4e35a8949" +
-			"3d59bbf44b3338d9d2e65a7d7ec6c863cd47cae9e23181b07298078a5e9b" +
-			"06a5c7e1059f474eb1a4247e8f02cdd4efdca67d22035b12abecf9b15982" +
-			"de4932a28e797bc4de38442cff2cba263eeddba0ab14fc706dbca04eaca1" +
-			"b4cc13000a10e35b32461424809b299798e4d8e66c92aa3181c5df16ab65" +
-			"9611cb625e895a8021af8c60960227d6f2ebeacb17b13536a5ff139734ef" +
-			"37cb67018ef9a410b856e6f6eddbe3f59b088d538c50a8f3f0912d06e47b" +
-			"88d773069aa759cc614e1f53cf6e572c127123d1ab56b79ee753a921cb22" +
-			"a60e4e6cae768c9966de4e2625484f2e990154da7fca84b6e6c0b59201e7" +
-			"fb8a729cb20b4c774381e84f1bd6e304543d952dc76ef741b72f3a4ca7a6" +
-			"ea7958b8b6337994ed82dcf988eb70f509610b9a279ab4d0f28cc2b2dd99" +
-			"3b8637a6be0cb4b5f67c79654c6b15e1b61120374ba9b974a628c547f11e" +
-			"52d72d39f8f9c5dbfc23a89f22d38984dd8d5c3ca72cd54e6adfe2b3d163" +
-			"86afdb50967846a4c311351a51e5fd322757bdb061d44c8796a61fa4db36" +
-			"793bc11984eac83bbcefb40d0bc7bab0ca81e7df3a7f58c6fe800396716d" +
-			"832acaddff6d72c8e19dc9ea838294ead800deadb6bc18d3e399fa76c46c" +
-			"5d88ee72a86a87399423b0578eb6e27d78156ea2abf6f08b5cbf747f2f74" +
-			"5301b694bfba84bfe3c5527acd50660eea5105a2644c1aa92f954a604fb6" +
-			"a1b3b2d0331497deafc3aaadc7040b9188a36cf607ee85a0655ae963fd32" +
-			"91dd58f8bb50b4e46dcf7c2957639bffa6b12d895660dc0323b7a092f999" +
-			"813380b820e1873c60d3e3038129c66d507862100a5d5842150869e7873d" +
-			"6bb6ad022350ffa3813aca26c80ccae72692bed9c77c9d4da23178c57153" +
-			"90b5f4505240a796ec9d10a7f280bd60a570b1b693453807707651fc0464" +
-			"03e4768965a6f42f112152942134f0a38c84137c7a6e086ef1ab9ad20d24" +
-			"3b93356b305c0996ab7d02c02c44cbaf8f7e60b8c0b8c9fece3f189b099d" +
-			"dbd126b7357c1c4ea1c8bc1ad93db91ea9bf043a4320acb60b502bec37b8" +
-			"6b2a5004b8225e549e613c6f83b97b7e4aeda1b013e0a442d7ce2f14e78e" +
-			"a94bab700c9ac0abba945e28f39fdadff223c4498cb204f01ddfcb450a41" +
-			"f32ae47f99a49114c6646a5cb103e9cd75f9d81dba417e48c4053e3b0295" +
-			"2267cd30589b0f5d993a5485a6ead1ffab9f2f4294c5853ba76383a326a6" +
-			"a42fb8b78948aa49f0f1f614bd0a3fbd2a58a3197daf2094605bd838285a" +
-			"1260f1265dca74aadd95652632335fd17cafcb73b202c3f0e5da836c2dcf" +
-			"2934f005935dca80154af43fa34c8ba440d1581b74ff17dfaca369dc9aa6" +
-			"734c03916d78e1b952691cef918fe033d33f7f4323cf724ffb8cd6c219bd" +
-			"046e9f268eb0601098e93daa59dde370e46269dd7c54891f71bee2829a53" +
-			"df86a2c7fb1046cd7c98fa21cd83597be554997a70acebe0b6e60f1f7098" +
-			"6f65adcae24385cb7102bdd3e01300ffd15d00f9764b3a5c51e35e5c9cdd" +
-			"da84f4b656fe514ec4ff8dcd774373f8a9103cf36abefe875f7084b9bbd9" +
-			"42e0c997ec2d860a4b622ff1a39a628582fd81f237d3d8f6843d26ac77cf" +
-			"bd48003e8e8c591ff813a9a897e3149ff0297ff476299d717e54d885cdd4" +
-			"4c3ba6ebf54bc7a1",
-	},
-	{
-		key: "b15578da1020f662ada0ad4f33a180d9f8ad4991b3720bc42a22b52625c7414a",
-		tag: "b0e4ad4a010afd6dd41ed82868cda555",
-		in: "6d2afb7a9154064341bdbb533f11990d4987e7c90fbfc0167c1e58d6efff" +
-			"6010f7ed569dac62ad37183b0d384519ebed0bf9c6e05a070b4858e6b846" +
-			"547ab5e45619c866f83cce83dcdab6a8a6c36b115ac832de1c6d433b94fa" +
-			"35803fa1a36f1ee114f8632402a027a74ac110394f32ec4006beb0057f09" +
-			"a94dada8bd0d1ca9a14b1f2efb8f526d79d6438bbbaac0ca1a43935627e5" +
-			"d129d52c06bf6413af07513bc579447eccc3a9406645c94dae59dab98d6a" +
-			"f92fa90fd4efaaa4bec466806ed401d2083cda587139ad7e9ee2adbb1dfe" +
-			"a88b59dd788b954a0f52c3854a3fffecb4bea83debbb2f5f8883e6415d3b" +
-			"ac1b872df1afe185468adc59364c173082f1dd6da9d348f5f5ba2d216243" +
-			"23de1f623eeec875bf31d12acec40dc0c1b9562826f3105cdad4c43cf45d" +
-			"829aa8b14012c47847aef7a2a6e3935fd972235f5d3a7ce4ad3582785393" +
-			"602e2e27329914021eff38ed2926c88acec1551f17a1b818fc1c3ed4b3b6" +
-			"6825d55bea269d710123b52e12ca9520a069d9c6a21df3a0253b3a4a6a8c" +
-			"dc226d667541548834da6bdbbdc165f39e40047d4b647c507d981be17b3a" +
-			"836063436241a8bb46b11a2867b621413c42d838e4578b72cc1982e34bde" +
-			"c303b5575ef4b8dd9fea8ed5bf69539413909d03461d3853b5fbf714a61c" +
-			"769569f42b38fac4b849104e2f2ac1dad0e388646278789f83e0b0511571" +
-			"019d3bfc5b03ca4cb5564e4e75e103ea1b6000be6588e27105d7cdc2d2f1" +
-			"f680ad34ef823ac4bd4068146e9997834665aec7dcc7a82ff28d85d52dd6" +
-			"9c18dd35f326bcf709f74df5981bb90ca8e765fef9f0698a19e12220b287" +
-			"24a6d9e4f4c7ce93f8ca9a126689ad1df820072557ce3db246cdf41599dd" +
-			"44ca841bece6c7869358005536e1189aa86b764e890ef90970d6e3831def" +
-			"fa890bf8692381123924e7d9df804fd770a0a30ee97d5dcdca302833efe8" +
-			"1d4b2505b17382f0b3429b38c41269ac95e36e9f5a1dbc6e6c8963741917" +
-			"02a23198decb4efe6809fcbeb5d0c9098a4c300155dc841610e55c8a6e27" +
-			"2a38a39de3d8ebf38a750af25836ffb1bb7822bb98886280f0cab6838c01" +
-			"cec57961bdc2e1bf158248309ff9294adcb962252b1c24646d132a3be2c9" +
-			"1ff82e8e101facbdb807826cc9d1840a90874ba08692e808c336c9d280ee" +
-			"f36a43a75c746fb864f85711e802546ab5cc3f8f117904ba1a85d6e4b729" +
-			"85122c5041891e16d55b93d6fc1b7fcfdc80ed3d72d55d64b8895bbf2f8e" +
-			"d188684e7e89afdc1e6a7ab9bd1d3da95d68698df2cdcbb2e1a4ae70e2fd" +
-			"dd4760f9e5cf4255eeb1e9e8009ab507395bacb8b2177e7c5757ad02baa9" +
-			"a96db967d20a150d2dd7f3081d90675fe0c82f94aa3cfdf6ac5585583901" +
-			"7a8e122170cc817f327a3c8ef44acd6e4fa81b73bcd0bcb5792eed470481" +
-			"152e87f7a20c3f7c69d5a8199bf9bb7c7269b450dc37a9b22102acaa8438" +
-			"134d6d733d231cee9522f7d02fbb37b5818ad3ca72df4752230ee11392ef" +
-			"8f8219be55202bc3d476f5a9078b32fb63d42bed4cda5ef90cc62467bf5e" +
-			"418ecd9d5d0cf1a33eb9a930e652ce96057fef40b65588aac67621d651a0" +
-			"9003dbc3925912e385296cd3b2b386a44113308ddf2af52ca390487eb20c" +
-			"716b76d78ad45129e7c285d918de7107ea8c3b0cfd9e73933b87c0b2b505" +
-			"cb4c95794f2ee6d6d43e2e76026923a0bbfbc3bb22df9ad729452283ce62" +
-			"dc9b26684fd45e07650581afd73713a708869a069c58b599ab478974f206" +
-			"dbd3e4e563e346ff1881723c5fd440bdf9f70f761c6f746113397d7c04b6" +
-			"b341d7e44de7de0aae79badaaef5ed372ef629dffd52926110683ab2d4da" +
-			"a4be83eb86c8700703a660edd5a5029f66f1581da96fe1feefc970ab4086" +
-			"a83ae02e959821967bd27b3b629652f5bc3db2b7f1af674f9f3fb3a788f7" +
-			"88e6dc1722382971831a7ed72502f85b25888c1534d81c0a4f7351ecc40f" +
-			"4e0412e05718403fae5746d313a78c80ac297f1391ad389070410e1330a1" +
-			"b07d683d1c795bda74bde947f2cf0dc9638b5d0851cda27df030403816dd" +
-			"3b70f042888c9c192656cc4b9fea10b81b5347900d9199c8f0f47d42f2ee" +
-			"482b68acfa5ff47d9950c950a926a497d94c6a796e0b715416520bd6c59f" +
-			"30217718d5f1d7bf7c24039f6467214ac8783cf011b25c37c67dfddde426" +
-			"40afe97f94879f4586954737b86701b32d560f08caec3fc45184bc719c7c" +
-			"5bf699074fde814acae32c189158c737665a8f94637068322f0c23ff8860" +
-			"f1b1c1bd766440afee290aa6f7150c7adefa6d72a738cd2268da7c94788e" +
-			"bb39002e9a328a51f3a92dc5c7cd9e4faed5702d3592ad16217c4978f84e" +
-			"af0fd2c9e4c6f4dcdd9112c781eb41a9aacb0f7935bb5c92d41e67cfff6b" +
-			"991ccefbd667ffeded1de325da50c33e28e2eef2f636c9726dc5bfe753ee" +
-			"c7bb6e1f080c89451f81bc8c29dc9067ce83deed02769714fa9bb477aca5" +
-			"c09089934674a0cc8e4b2c3136b2e4af8040cc601b90a4dec898dc922ca4" +
-			"976ab5ae4ac5af93fa5b1854a76ac3bcc2090bdeaa49ec4f319cf7c7b674" +
-			"6d8e617abb3361b28b27983dd1b139ec4f5af7e116439d7ecb16534817bf" +
-			"264dbd8f59e80b443be12c17fa013c7f4d029504c9bb62b296c2326f4f49" +
-			"cc3201b70ac3f62abb683c630179594a6d4cf30fd55b163bf8d01986bb6b" +
-			"cb7050fd527f095c45661920268e56f760fee80a29c9d37b7fc23f608710" +
-			"1e723038e64ee1b91c4849d69bd95fc9bc24fc4a234f4855f2a203e3f699" +
-			"c32698585c83781677739f2c48697c93b3388dcc64aa61f01118495ded33" +
-			"21ef9a1c949481f96005f8d5b277a7d6a0d906ec304cf4292df172e72d20" +
-			"29ecdeb65f06267a605f376804bf7bc5b82d5c8facfe7e41dc10806d27e0" +
-			"bcc5a341d80b3c1532407f75088716d732632cd88b0037f0d829bf385fec" +
-			"b52a202956489f61f16b0f4781bf59068b33d7330571d0b4a6ed91830258" +
-			"e1220b308784fa155be9bc821f5c0009a33802fa66dd66d1dde997dddd97" +
-			"873ddf65927dc1be979af2b5f110eee627dc1e210326ac20544a757ac168" +
-			"1823f3dd04b1ddc4bf96677a0a87633994e7af2ec99b7d5dfe44c6192be6" +
-			"a6e69d17b074256da3947808fbf68c7506a7e2c99e6b64d1ffadbd6285d8" +
-			"e7e032e24d42dde0594bf03fd550be05e5d66c91a660cd1ab7cb1f43fa9d" +
-			"69885203a7aee35a28f117427d7ac02b742f53d13b818f8631081b1730d1" +
-			"5b4e1e283cc8e5c4fc3b4652fce05fd8db821f99fcf93e6842816a549791" +
-			"7f6c49cc53d733788b2fe3c687de58bfe6153c70d99380df1fd566a7c758" +
-			"8052c62e73340d6a9eccd2ed26b763d518f3a0c4d6362212fbecebb4ffb7" +
-			"dc94d29944fcc4ab37725b105aa7571f364146782356d8ef056a0be93a55" +
-			"0c890df8fecc178776fe40703ad1bd2443d92c420be4306d99686592c030" +
-			"fd3e2230c0b48d8db79002e8a832ef27edb53a45532955f1171203d38414" +
-			"b4692e901e9f40f918528fc494430f86cf967452f456b01846ac6a383fc0" +
-			"de2243c7d804e8643aabcb78e2653b145f400a999670217c8da43bbb9c11" +
-			"e074176424be0c116c304a420120138e901eca4b12ce68fec460b23bc0c7" +
-			"765a74fc66cbda0e503e7b1baf5883744e468c97c5f1c4b0acc4b87de9f1" +
-			"4b537405dfb28195439d1ff848d9cd28a8d375038ebb540a9075b7b5074b" +
-			"ebc18418a370f1d3ac5d68f5d239513002ad11bfc2b7ff53e2e41ccffc4b" +
-			"0503acc4967c93ae8590a43439b5e7987d10cb8d1957bd9ef717ee3d12df" +
-			"5d6736c1d8bd8da102337a94b7d14f830f6c403cbaf7925a8a2a7af1311c" +
-			"57224967a38f6ca374013a9819c55fd2e2a5fac4f2490be5b059f4cd9c60" +
-			"2d62f80789eb8d9ab893c7f44a4945e41886af218179dfa754bbb59aab68" +
-			"13b71d2202eb8fc8a425625d21176a28a620e21bb0dad820c0b7051ce8d1" +
-			"3a33f3af0958bb6cd89f9d6414ab00ddd1d2f9fdece9183d0c05fcdfd117" +
-			"10d250e4b2029e6992a88293d0457e73e5b1b6a1aae182c69b9cb664992f" +
-			"073595ef68117026ad7ea579a4043cda318931eee7b2946a34cdc7c9755f" +
-			"80cc79a2bfe3ed9c79dc52faa5126b824868c965eeb37e9e4e6a49600f3a" +
-			"cce93c0853b546edb310dcd16a5755f15b1098b2f59dbd2d90e2ea8360ba" +
-			"f12108236e854465456598ae2f7bc380f008f2e3cd7c98c87643cafd7c36" +
-			"d40e2597236428d46aa5b260f84b4212d5e26804086adcf00363ce4becb4" +
-			"9b57eb2847b2f18ec82c99714ad4ddfe4ff3bcac1d0fcaa32660a1dccc68" +
-			"5bed83254c8e2ea0ae3632a70cfbcbeadef922d78a006d43ac7ab1f8a609" +
-			"c6e0ebc3ca6bb8430f1a562f41010db74b9febf931ca794fa08d1bc17780" +
-			"532ae76f25c4ee679d788835dfa4e70ca154c9e2865c3750ffe7b837eed1" +
-			"972be058fdf2bdb3eb301867bb132306c7aa237f6771d60bbc56cf31cb30" +
-			"32a87204d454542de747418470025ab84935d3eaaca01dbbdae9ef6b5d3a" +
-			"ca62ce9f871a3e1272b2b671582c096a349c00f32d742ddb17993994d8ae" +
-			"fc178cbcf9abc03114ff2bf7db8f757c63d6898faccd822f5c2e9a7570fb" +
-			"9cfff148570888be24ae42644c1a5bebb6f6287147a4bcc01c7675be9e4a" +
-			"897519dd3132a7cc2e778f8c90d23dc8073f6fa108d7ef82d561794bd9d5" +
-			"f1faa306334f338ac3ba99c853f79c24f7048fa906fde87d1ed28a7b11c0" +
-			"66a3bb98f8d21055aaafdf7e069b77b60b3d5cbe7c5e4379c7651af955cd" +
-			"82a19a09caf36becb6cd3fe9e12f40379941542709991066df21b7b12dfb" +
-			"2416d83fcdc33bb583e3b42f24f53edf8dc7c579ad3be831c99f72bf9fb7" +
-			"a35b6562e824e039e6bf1adc8f5ca53846de7bae11c4317e696d887df33c" +
-			"525f0a9c01fc29f2c26c90b85fe82ed8bd50954cd4e9ac7c85c7f3efec75" +
-			"da1da4ed173cb695cee295190527edb3cb06c5dbdabe0228cc60b6455153" +
-			"76244f27aa56da2db10f2659090137ffb82c57233c833e0bbf22d6f647fb" +
-			"97b3652d2888b3ab08010b8e8a6967d560b747757806736dc98b78226634" +
-			"f1eecaa4a2e23ba36591acb5737d735c5bc7a2e36f1a46946927e061fdf7" +
-			"7a3b68ef582c26b01f5aa9a438ecc26c6941221d1590c838072f9e471fe7" +
-			"fd59dacb0d092d40d76ea2f7c6e954a132a015bd4cb31147f3ebe4518322" +
-			"916438a62836ac85a4cf4492190a85bcc8edb37e38b99ea552d749c30f74" +
-			"ca20c298165e8ed02d4671e0b41cac3a32a345b9349ad22c2a4bb2c16a4c" +
-			"e0613ca0f0518759f7d2b33cfad2fae764f410d4d9ff8a76ae02a8107e7e" +
-			"01d9cd0552676b85ba002f19c01ad5f416d1d08bb84fec7c3555b098dbce" +
-			"48e1a5d847895e54db9c5b80cc22d5b87cd41a1a94be102bdd45a3cda5d1" +
-			"181e10446d213d6b3fdc350d486d2011d705c5f16ccf7519065c47bad7d6" +
-			"89c71e5fdf9d04bfb91eb1f07fa0f001009c1d4b1f6a116a570823a8580b",
-	},
-	{
-		key: "392468efccff36dade31fc1c62eb38bb61394fe448def9d9d9beec2413ddb418",
-		tag: "e1122e7c8e6965b90addbd46d8a548d6",
-		in: "6a13d37f0ec933194c227351f4a19b507d93465b1f3e88dcb5f1ed1262fa" +
-			"58ea99ff31e6fc85c39c04129fa69195b71b2060122fe618dd9430a63f97" +
-			"54b52a80b3cd099f248f91a468bae211a27bdb47ba005d29881ea5143a82" +
-			"967c4c30c9a4f0dba1a4975e6407fe296d40023a00efa06be763f2d73d46" +
-			"a2901ae28b3d8ce18009a462e223b71476d7b954c138e177d15a390847de" +
-			"96a7f7fd0598748e86b0f08e64d915e67c7e3cf936f3dcd60edebd36e2a1" +
-			"d65b6ac29530c48ab3bd52d45b4f938a19b9b31e2911105a8561600d5377" +
-			"905a67112ec28025aa680350ff85b808c5b4c98b7b9567d03f5ed3911ec9" +
-			"365a8de4b15ca62adaa69e5ba710eb1756a346016c67a297d8624f9f1ab5" +
-			"b3fbce98b141049f0ce26c85d2f8a9cc6ca8ab6c6e148be968931430dcc6" +
-			"2bf58ea9698ef52a5d271cf48e6748ac9e04bc7ae7da205a1a7535478322" +
-			"d820eca146cedf4b2f9aa9fcfd77ab56a7276977401dcc1f96baa1b607e0" +
-			"256bd04ec324ec67a4313e2d5a53d3a3fb5332927929b20c63bde805f637" +
-			"eb1050fee2a152a0405634f55c48a59fe370d54b2ab1671dae2c7fd92243" +
-			"10627808e553127c74f724362b4a6ee49b697daae7df3ddc5d2ed9d6befd" +
-			"77fb9f68fe3041f6ef13f46f34ab682ab8563e8996344f82b2ef006a8d54" +
-			"3dd9c1db4979d7da97bda45e722065f8a238f0873217b783a9a629a12b3a" +
-			"4de437445039997bd243efbf5e3b6059b9459d395290efb9081c632fb694" +
-			"81000dc74c395cb507422df181aba20f776ce3fd8765ac485021992c98b1" +
-			"67c68805662cb4356a0ee7ba6bdae51ac10cd06bb5b2f3a72841c714c8ed" +
-			"bc56998fe2fefb9bf69e172fdf54b2ab138ae59372c52a67e93882a3000f" +
-			"d966992aa2250c6ff93e9cac89645d70625d79332ade5dab7eb1adbe7dce" +
-			"5a013fb65ad32fe22ed16fb9bb35eca1f37a0433c320e8752f8fc4b7618c" +
-			"5e4df2efece832e259ad98b895c474e47d0e3fc488bea8f717a17de0dcf7" +
-			"597fb8fe12e62246296f9a887dcc3a700820c190a55a4931a7d44bd3bb2e" +
-			"ab6c8a8126f1be93790cebabc1d69e01796e6cc80e7c16bbc82fb333fb21" +
-			"c774ab7db843242838e82d8e1cb8ccab385e67a4271fe7031d74b6e8edcc" +
-			"8ed585d1c05a365c7665899c1dbc561151d3b44bceace77c4f53c0e0f6f7" +
-			"74d42f9ad3e56f1c2a8d53879d695f895690afb4698472a3d52d67159313" +
-			"133c87823fe0500eb68fe286f8b9a2f59f12785d026dc97bdbf793c7d1eb" +
-			"155f1f136aae66c256583e987f718afbe733e0a5ce30d021493fb84e2242" +
-			"5b18754d126235ef80335004fa84f88361a584753df409360cd8bd45bace" +
-			"8f48156bec66577bf2c685089f5ac7e7ec76c0df068fbaa47661f8517f92" +
-			"e14723b3b278f151816537a7212c96bd340a00c15c9c9bc9a2a5d163655d" +
-			"84b38073e2be9217cad97d362d89d4baf3ce0a8d8562f19a8c97a9aaf5e7" +
-			"77d60456360ffb77b30f177d2809052020d141697ecf9cb65f42b9190caf" +
-			"6540b2c82f6e5a8482934a6a1a5711a8c24546cd8ba432068404eae5a827" +
-			"2e09efc3c6037af4feaac0a46329229b010ecac6b9f077a9b076bb6d9ce1" +
-			"38401eb38d124baa11507a994185295020bf9b754fcf78430db9253f5929" +
-			"87c46c0f8589c4e463b15a3840b1cea795e24cf6b20f29a630136e0589b3" +
-			"8dd7fbe5ea21da72c88bd8e56473586822aa3765660a45a988df9b8eb8e8" +
-			"141939d3e4cc637c5d788064d40a9f7c734e43fdf8d7189a5d76700d9743" +
-			"fe0122944663afdb88c5201318ca782f6848b742ddebe7463fd4a32280ac" +
-			"1cf8311e9137d319de05ce9cd85abab24c5364041c14d3b4ce650400498e" +
-			"122166eccc12784b7ac3b262ac0b198ffc26eeed9a5da5374f7a2a53c87a" +
-			"78c217ea1fbf8d38f62511657b73109f31691aef14d82ce6e1010eae9e6f" +
-			"a419e5c1c16c0cc70651eb3374c03549a1bc7d3ed42d60f886102c798dbc" +
-			"ba56f0a2b3b9b412530c35f5f7ed06311ee14571f9c26ed9c81ef38ff000" +
-			"2f5ef3aab7351e32049a6ef8f48a43da1d84402d229df513dfaf1b2e4043" +
-			"6ce68c70ebeddd7477c9164f0dce45a6fc5de050f52ec269659d5854bcae" +
-			"f7762ed7400713c27a4d523eaf8c136c4a1ca00b9e9e55902daf6cdf8528" +
-			"c22ca1f2fa7ce87902d75a6850e1a5a4592497be1bb401878f18b189b0e2" +
-			"c59d10705bfabde3cd2da01eb452006b294108d5d42e88e9e15424d8cd0b" +
-			"8ab43a6c546b3dbf52e47b59cde6a3e417b0395220b6d63736d429da3458" +
-			"9a2524f1629320206fa7f1d8a041e17222c4a5814561937e1030e6375c77" +
-			"9dc988bb928bbdbe2c2eb20111639725d82b5d7192cd3e4acc27581f0ba7" +
-			"286cff41f97aa5a52ea0083de5057fd2ba985aa738e4d03fcf11ebab1d97" +
-			"e2ac77d1c2beb8799150a421a07b3777d0b850f24194b8309135b13da6c7" +
-			"e38653a711e407a1811290fbb7bc15d8b12efc6916e97ead41e042a44721" +
-			"e9cde3388073d921595bcddcac758dc675173f38242e65e4a284aaa7e8fa" +
-			"6adddaf00bc46428ab2d8601205b8895bcedfc80ca0aa4619ed6bb082ddf" +
-			"33ec04fa5d417f33fcdd238c6b11320c5a08f800e0f350b75d81e3bcbd15" +
-			"58a1eab87a3c8c2ffd7ba1d7e754e607cf98ba22a3fc766c45bd6f2569b4" +
-			"84639e6611714119d188a24a5e963089a16ed34e20b9f154cad8ac6031dd" +
-			"7a3a885afc2ae5e003ae8d4e4aabdb3e51dfc423b8cf4ed9ae2010072cbb" +
-			"b1108c7da1ff075e54ed827a0963ac5523ecdf3fc5eee7b4d1a6773764ec" +
-			"5c30f41690523fd70d895edb7ca6a1806d54240c4c7b43410da73503a323" +
-			"90d9070ed30da3a2fb5eccd40d083be7cf8bf40b4279f819cf795b6f075b" +
-			"5a67a10a06a6076d0d83c72efea05f244901c4b5fd9eb380432519311baf" +
-			"8c81f6325df4d37ff4d30d318f904ebb837ec76b341dd00a8f247cf0bbe9" +
-			"6f3784dc8f5feb344958fdf1a9ececb105f8770826db1f17a5281e997951" +
-			"d3c60cc28fc3e66ffeb5dbac315f98f6d240208043f28dee963d843e68ab" +
-			"57d847f76ae2f96ce6e37f377ef5dfef2176ecd7440ce4dadcec2231b606" +
-			"e4a80420fb3ed135640e1f05d6bd58b8dce062dd7d36b885d424f6318e5e" +
-			"a0753efbb33bbc7360d2b5dfab3ae0d5e000b8d31f2ba0f5fd8b34f96b55" +
-			"28fff35e769461d0f03cf3bfdf0b801dcbbf2838180cb9b108e06c353e3f" +
-			"0b9ef61678cfed1ea37ae76bccb5ef5957ac2c8e8f4794c8145a15f1cc88" +
-			"bfb0881080326c481b373c3bc9b07a9b60a0c8bd5fa4f6f90145590a5227" +
-			"6fcc0ccc2375d0ccb571d414d1b0c38b4e02c39db4d701c5e25e90785ef4" +
-			"d26f35edd8c4b96455bdca7245cfefd9cfbd2f319615e5fdf07bb9564fa0" +
-			"44bb35a58391d02e3927780b4076bc0893dfcb4b63a32cd7a541a4a8c253" +
-			"0349c6e96e378dbeb66dedf87d813d0b744452c1c4088507dca722193827" +
-			"9e2dfa24e4a409de494acf654f44262db9206a7717fa434ac4fdc6a6eb5b" +
-			"1fd5a193b6043bc4327c8c09fd6822eaa9df37bbcac1077754a295621601" +
-			"267b68733b62dadc2563f1700af180141f29899e2689dbbe9745ba8477f4" +
-			"352921900b403a01c9dd042a8c1b0e0489959fb0b0a8431c97b41e202204" +
-			"212ebfa00c593399dbd14d7aec07b8292d2e40b48f05fcd54a15da4a24d7" +
-			"2759e409f4c7b5b98fce4abac6c30e4872d92efa1f96479ec30f21699825" +
-			"50fa60584f5a09051a00f8e7dbb3853e66ca3f05fbfe43bef9b120a25a01" +
-			"eb436ba8ecda715201eda72e517d628f883386c1503aa8b8e75610f7155e" +
-			"9f916335ab6d6f0f9589b6220cd2b81c2c937dc065d3d14a7df8cc916cd0" +
-			"0ce1bb53fd9c8974298d3bd316f3658aa8cc6904f073a1472149e4b08c64" +
-			"5e11abe0428ccb6174df2103edd735965d6454b543d3f01410f77053f65e" +
-			"c1d1aee56fdd3af23bcd4e1a7fcc4e600c4831007c33fe5f0c8300f686eb" +
-			"9b4d1e4f08fe4ddc8a90be14dc3a5a88ff96716509341d5db24c0d016863" +
-			"998b1859c5021df815a6f1ca9845f1a8e99dbad132b406227c5897a1bdf3" +
-			"e698962f799133ff4429decbef6ce036296facf38e4812fec102b76c6d30" +
-			"beba1b70722254fafbc471096153478c971db7d96263660209265cb10f13" +
-			"b34b5fd55c4abe818a5f9715d8a85094e2946b7a001b47f629e26c636d86" +
-			"4968ad2ab616dfe28840bd60b4b9855c8dbe1cb873fcbc4577b5fefeb8bb" +
-			"4832039867dc35db9c036c83bc204396e3474ddfe806c77c65c936f488b6" +
-			"7c1028739562d7bb055d21441af29ae2921290e548dccf8a56021385422b" +
-			"15da6b232b24151309a75a00296d11aa1952a1513110b0faa93d1d8cd9ae" +
-			"fa9f1c59377ec9165b2c9e07cbde40db7b81bca6d58fc28bae8f473cd0e9" +
-			"a2420e0b943a83d284108626c24ac570b1d6c1ab971e71f43fbd6c00e171" +
-			"238141a6dc987a60385c3a04dd147a2f8e80dfe727b104c0fdd80b326f59" +
-			"0b9f86fd7b2fd1122a390979889eabd803ab57159c8509a1443eb6789382" +
-			"090a770ae4eba03306f96e50e19a7d44c584ccc230d104548946efca4520" +
-			"d61de5f473e2f4eada6c8ce9c7ee975eb4f63c0483cb775ed7d3cf690a61" +
-			"7d6656d683a8512707d81ca5ba176a42bcffcfa692129f292607d2a47536" +
-			"ccaeb464c9272d6f3816074b712af602470088b253deba18771e5f67734b" +
-			"587707cdd06f35264b2262fd253c25b5d38ee7db287610e5398062b7a34e" +
-			"6e4cf7447d00873b930ad148fd96f0ab18771bc468b874bb109924101c84" +
-			"c4e239ecc7687d875e4d94a1a973620ca61e35a872c2e2e61a502169f1bb" +
-			"4e5ff5fa2bff657be6195b3e2c7151a52fc0096d98e7f08f5a98f570aee1" +
-			"7b4275f1356e87e080ce0e1b9bbabe7dea48b5903bc390ce23472ad64a89" +
-			"41c3247bfd23ea90b2dee09085571bad85568040105e098f993bb37e43c3" +
-			"e6d511171c77cfc450570dfb9fc6a3930ef43c03f8213f6203d545d791c7" +
-			"d3fa42d5dde1655038d35c5dfacc12e9dee24fe833977549eda68ae8b508" +
-			"be277e743921b584f9dfa0eefbd8bf3c23f51efdef7f7487001d29e8097b" +
-			"ba63289cfca743023d1668555a46fe6d5b7421377414df1e9ef135480622" +
-			"22e2e9a7baa618d88f407517f6317b6a0ba3384ace16d68631d59ea169d5" +
-			"092d20afc1a481b82be5e734bb092953a0a94702bae1a0f48d2a22b9a05f" +
-			"f64493b7b2e984f27582b1eb937fddf8512c49830435d146dcc291a4118d" +
-			"5dc638b99cdcbcc5860de7a92c5b13cbd1e01e051f01af40afe124346320" +
-			"d3626bf9d8f7850744e032a993c276fd388718237740c6caf260fca60b8d" +
-			"d846102e3262b6e05ceca00c6affe938fac1847350865fc858d3ddd1d130" +
-			"71d1221ce7c5d575587fcba580e544b74d877ed5ca92763ef0ca0d7bfa08" +
-			"d57a0216b2a01a2b9ec74b8430051e0074862b7be25b6766ab520f2eb75d" +
-			"eeb979c28f03795f6f1e4b8410beab19a20febc91985b8a7c298534a6598" +
-			"f2c5b0dc5de9f5e55a97791507bc6373db26",
-	},
-}
diff --git a/src/ssl/test/runner/prf.go b/src/ssl/test/runner/prf.go
index 96e7f24..73251c6 100644
--- a/src/ssl/test/runner/prf.go
+++ b/src/ssl/test/runner/prf.go
@@ -11,6 +11,8 @@
 	"crypto/sha1"
 	"crypto/sha256"
 	"hash"
+
+	"golang.org/x/crypto/hkdf"
 )
 
 // Split a premaster secret in two as specified in RFC 4346, section 5.
@@ -391,7 +393,7 @@
 
 // addEntropy incorporates ikm into the running TLS 1.3 secret with HKDF-Expand.
 func (h *finishedHash) addEntropy(ikm []byte) {
-	h.secret = hkdfExtract(h.hash.New, h.secret, ikm)
+	h.secret = hkdf.Extract(h.hash.New, ikm, h.secret)
 }
 
 func (h *finishedHash) nextSecret() {
@@ -418,7 +420,11 @@
 	x = x[len(label):]
 	x[0] = byte(len(hashValue))
 	copy(x[1:], hashValue)
-	return hkdfExpand(hash.New, secret, hkdfLabel, length)
+	ret := make([]byte, length)
+	if n, err := hkdf.Expand(hash.New, secret, hkdfLabel).Read(ret); err != nil || n != length {
+		panic("hkdfExpandLabel: hkdf.Expand unexpectedly failed")
+	}
+	return ret
 }
 
 // appendContextHashes returns the concatenation of the handshake hash and the
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 6026c48..aac4567 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -53,13 +53,14 @@
 	useValgrind              = flag.Bool("valgrind", false, "If true, run code under valgrind")
 	useGDB                   = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
 	useLLDB                  = flag.Bool("lldb", false, "If true, run BoringSSL code under lldb")
+	waitForDebugger          = flag.Bool("wait-for-debugger", false, "If true, jobs will run one at a time and pause for a debugger to attach")
 	flagDebug                = flag.Bool("debug", false, "Hexdump the contents of the connection")
 	mallocTest               = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
 	mallocTestDebug          = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
 	jsonOutput               = flag.String("json-output", "", "The file to output JSON results to.")
 	pipe                     = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
 	testToRun                = flag.String("test", "", "The pattern to filter tests to run, or empty to run all tests")
-	numWorkers               = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
+	numWorkersFlag           = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
 	shimPath                 = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
 	handshakerPath           = flag.String("handshaker-path", "../../../build/ssl/test/handshaker", "The location of the handshaker binary.")
 	resourceDir              = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
@@ -249,6 +250,10 @@
 	garbageCertificate.PrivateKey = rsaCertificate.PrivateKey
 }
 
+func useDebugger() bool {
+	return *useGDB || *useLLDB || *waitForDebugger
+}
+
 // delegatedCredentialConfig specifies the shape of a delegated credential, not
 // including the keys themselves.
 type delegatedCredentialConfig struct {
@@ -469,6 +474,18 @@
 	quic
 )
 
+func (p protocol) String() string {
+	switch p {
+	case tls:
+		return "TLS"
+	case dtls:
+		return "DTLS"
+	case quic:
+		return "QUIC"
+	}
+	return "unknown protocol"
+}
+
 const (
 	alpn = 1
 	npn  = 2
@@ -636,6 +653,12 @@
 	// exportTrafficSecrets, if true, configures the test to export the TLS 1.3
 	// traffic secrets and confirms that they match.
 	exportTrafficSecrets bool
+	// skipTransportParamsConfig, if true, will skip automatic configuration of
+	// sending QUIC transport parameters when protocol == quic.
+	skipTransportParamsConfig bool
+	// skipQUICALPNConfig, if true, will skip automatic configuration of
+	// sending a fake ALPN when protocol == quic.
+	skipQUICALPNConfig bool
 }
 
 var testCases []testCase
@@ -710,7 +733,9 @@
 		config.Time = func() time.Time { return time.Unix(1234, 1234) }
 	}
 
-	conn = &timeoutConn{conn, *idleTimeout}
+	if !useDebugger() {
+		conn = &timeoutConn{conn, *idleTimeout}
+	}
 
 	if test.protocol == dtls {
 		config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
@@ -1153,7 +1178,7 @@
 	}
 	connChan := make(chan connOrError, 1)
 	go func() {
-		if !*useGDB {
+		if !useDebugger() {
 			listener.SetDeadline(time.Now().Add(*idleTimeout))
 		}
 		conn, err := listener.Accept()
@@ -1181,7 +1206,7 @@
 	return errorStr
 }
 
-func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
+func runTest(statusChan chan statusMsg, test *testCase, shimPath string, mallocNumToFail int64) error {
 	// Help debugging panics on the Go side.
 	defer func() {
 		if r := recover(); r != nil {
@@ -1244,6 +1269,34 @@
 		flags = append(flags, "-dtls")
 	} else if test.protocol == quic {
 		flags = append(flags, "-quic")
+		if !test.skipTransportParamsConfig {
+			test.config.QUICTransportParams = []byte{1, 2}
+			if test.resumeConfig != nil {
+				test.resumeConfig.QUICTransportParams = []byte{1, 2}
+			}
+			test.expectedQUICTransportParams = []byte{3, 4}
+			flags = append(flags,
+				[]string{
+					"-quic-transport-params",
+					base64.StdEncoding.EncodeToString([]byte{3, 4}),
+					"-expect-quic-transport-params",
+					base64.StdEncoding.EncodeToString([]byte{1, 2}),
+				}...)
+		}
+		if !test.skipQUICALPNConfig {
+			flags = append(flags,
+				[]string{
+					"-advertise-alpn", "\x03foo",
+					"-select-alpn", "foo",
+					"-expect-alpn", "foo",
+				}...)
+			test.config.NextProtos = []string{"foo"}
+			if test.resumeConfig != nil {
+				test.resumeConfig.NextProtos = []string{"foo"}
+			}
+			test.expectedNextProto = "foo"
+			test.expectedNextProtoType = alpn
+		}
 	}
 
 	var resumeCount int
@@ -1295,6 +1348,10 @@
 
 	flags = append(flags, "-handshaker-path", *handshakerPath)
 
+	if *waitForDebugger {
+		flags = append(flags, "-wait-for-debugger")
+	}
+
 	var transcriptPrefix string
 	var transcripts [][]byte
 	if len(*transcriptDir) != 0 {
@@ -1346,6 +1403,7 @@
 	if err := shim.Start(); err != nil {
 		panic(err)
 	}
+	statusChan <- statusMsg{test: test, statusType: statusShimStarted, pid: shim.Process.Pid}
 	waitChan := make(chan error, 1)
 	go func() { waitChan <- shim.Wait() }()
 
@@ -1388,7 +1446,7 @@
 	listener = nil
 
 	var childErr error
-	if *useGDB {
+	if !useDebugger() {
 		childErr = <-waitChan
 	} else {
 		waitTimeout := time.AfterFunc(*idleTimeout, func() {
@@ -3334,25 +3392,32 @@
 		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:",
+	})
 }
 
 func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol protocol) {
 	const psk = "12345"
 	const pskIdentity = "luggage combo"
 
-	var prefix string
-	if protocol == dtls {
-		if !ver.hasDTLS {
-			return
-		}
-		prefix = "D"
+	if !ver.supportsProtocol(protocol) {
+		return
 	}
-	if protocol == quic {
-		if !ver.hasQUIC {
-			return
-		}
-		prefix = "QUIC-"
-	}
+	prefix := protocol.String() + "-"
 
 	var cert Certificate
 	var certFile string
@@ -3479,7 +3544,9 @@
 		expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"
 	}
 
-	// TODO(nharper): Consider enabling this test for QUIC.
+	// 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,
@@ -4418,18 +4485,24 @@
 // various conditions. Some of these are redundant with other tests, but they
 // only cover the synchronous case.
 func addAllStateMachineCoverageTests() {
-	// TODO(nharper): Add QUIC support for these tests?
 	for _, async := range []bool{false, true} {
-		for _, protocol := range []protocol{tls, dtls} {
+		for _, protocol := range []protocol{tls, dtls, quic} {
+			if protocol == quic && async == true {
+				// QUIC doesn't work with async mode.
+				continue
+			}
 			addStateMachineCoverageTests(stateMachineTestConfig{
 				protocol: protocol,
 				async:    async,
 			})
-			addStateMachineCoverageTests(stateMachineTestConfig{
-				protocol:          protocol,
-				async:             async,
-				implicitHandshake: true,
-			})
+			// QUIC doesn't work with implicit handshakes.
+			if protocol != quic {
+				addStateMachineCoverageTests(stateMachineTestConfig{
+					protocol:          protocol,
+					async:             async,
+					implicitHandshake: true,
+				})
+			}
 			addStateMachineCoverageTests(stateMachineTestConfig{
 				protocol:       protocol,
 				async:          async,
@@ -4449,73 +4522,77 @@
 
 	// Basic handshake, with resumption. Client and server,
 	// session ID and session ticket.
-	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,
+	// 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,
 			},
-		},
-		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,
+			// 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,
+				},
 			},
-		},
-		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,
-	})
+			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.
-	if config.protocol == tls {
+	// TLS 1.3 basic handshake shapes. DTLS 1.3 isn't supported yet.
+	if config.protocol != dtls {
 		tests = append(tests, testCase{
 			name: "TLS13-1RTT-Client",
 			config: Config{
@@ -4577,31 +4654,34 @@
 			flags:         []string{"-expect-hrr"},
 		})
 
-		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{{'h', 'e'}},
+		// Tests that specify a MaxEarlyDataSize don't work with QUIC.
+		if config.protocol != quic {
+			tests = append(tests, testCase{
+				testType: clientTest,
+				name:     "TLS13-EarlyData-TooMuchData-Client",
+				config: Config{
+					MaxVersion:       VersionTLS13,
+					MinVersion:       VersionTLS13,
+					MaxEarlyDataSize: 2,
 				},
-			},
-			resumeShimPrefix: "llo",
-			resumeSession:    true,
-			flags: []string{
-				"-enable-early-data",
-				"-expect-ticket-supports-early-data",
-				"-on-resume-expect-accept-early-data",
-				"-on-resume-shim-writes-first",
-			},
-		})
+				resumeConfig: &Config{
+					MaxVersion:       VersionTLS13,
+					MinVersion:       VersionTLS13,
+					MaxEarlyDataSize: 2,
+					Bugs: ProtocolBugs{
+						ExpectEarlyData: [][]byte{{'h', 'e'}},
+					},
+				},
+				resumeShimPrefix: "llo",
+				resumeSession:    true,
+				flags: []string{
+					"-enable-early-data",
+					"-expect-ticket-supports-early-data",
+					"-on-resume-expect-accept-early-data",
+					"-on-resume-shim-writes-first",
+				},
+			})
+		}
 
 		// Unfinished writes can only be tested when operations are async. EarlyData
 		// can't be tested as part of an ImplicitHandshake in this case since
@@ -4663,47 +4743,54 @@
 			})
 		}
 
-		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,
+		// Early data has no size limit in QUIC.
+		if config.protocol != 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,
-			flags: []string{
-				"-enable-early-data",
-				"-on-resume-expect-accept-early-data",
-			},
-			shouldFail:    true,
-			expectedError: ":TOO_MUCH_READ_EARLY_DATA:",
-		})
+				messageCount:  2,
+				resumeSession: true,
+				flags: []string{
+					"-enable-early-data",
+					"-on-resume-expect-accept-early-data",
+				},
+				shouldFail:    true,
+				expectedError: ":TOO_MUCH_READ_EARLY_DATA:",
+			})
+		}
 	}
 
 	// TLS client auth.
-	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 == tls {
+	// 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",
@@ -4722,18 +4809,20 @@
 			flags: []string{"-verify-peer"},
 		})
 	}
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "ClientAuth-RSA-Client",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			ClientAuth: RequireAnyClientCert,
-		},
-		flags: []string{
-			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
-			"-key-file", path.Join(*resourceDir, rsaKeyFile),
-		},
-	})
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-RSA-Client",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequireAnyClientCert,
+			},
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+				"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			},
+		})
+	}
 	tests = append(tests, testCase{
 		testType: clientTest,
 		name:     "ClientAuth-RSA-Client-TLS13",
@@ -4746,18 +4835,20 @@
 			"-key-file", path.Join(*resourceDir, rsaKeyFile),
 		},
 	})
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "ClientAuth-ECDSA-Client",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			ClientAuth: RequireAnyClientCert,
-		},
-		flags: []string{
-			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
-			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
-		},
-	})
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-ECDSA-Client",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequireAnyClientCert,
+			},
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+				"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
+			},
+		})
+	}
 	tests = append(tests, testCase{
 		testType: clientTest,
 		name:     "ClientAuth-ECDSA-Client-TLS13",
@@ -4770,15 +4861,17 @@
 			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
 		},
 	})
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "ClientAuth-NoCertificate-OldCallback",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			ClientAuth: RequestClientCert,
-		},
-		flags: []string{"-use-old-client-cert-callback"},
-	})
+	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",
@@ -4788,19 +4881,21 @@
 		},
 		flags: []string{"-use-old-client-cert-callback"},
 	})
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "ClientAuth-OldCallback",
-		config: Config{
-			MaxVersion: VersionTLS12,
-			ClientAuth: RequireAnyClientCert,
-		},
-		flags: []string{
-			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
-			"-key-file", path.Join(*resourceDir, rsaKeyFile),
-			"-use-old-client-cert-callback",
-		},
-	})
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-OldCallback",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequireAnyClientCert,
+			},
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+				"-key-file", path.Join(*resourceDir, rsaKeyFile),
+				"-use-old-client-cert-callback",
+			},
+		})
+	}
 	tests = append(tests, testCase{
 		testType: clientTest,
 		name:     "ClientAuth-OldCallback-TLS13",
@@ -4814,15 +4909,17 @@
 			"-use-old-client-cert-callback",
 		},
 	})
-	tests = append(tests, testCase{
-		testType: serverTest,
-		name:     "ClientAuth-Server",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			Certificates: []Certificate{rsaCertificate},
-		},
-		flags: []string{"-require-any-client-certificate"},
-	})
+	if config.protocol != quic {
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "ClientAuth-Server",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				Certificates: []Certificate{rsaCertificate},
+			},
+			flags: []string{"-require-any-client-certificate"},
+		})
+	}
 	tests = append(tests, testCase{
 		testType: serverTest,
 		name:     "ClientAuth-Server-TLS13",
@@ -4834,100 +4931,99 @@
 	})
 
 	// Test each key exchange on the server side for async keys.
-	tests = append(tests, testCase{
-		testType: serverTest,
-		name:     "Basic-Server-RSA",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
-		},
-		flags: []string{
-			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
-			"-key-file", path.Join(*resourceDir, rsaKeyFile),
-		},
-	})
-	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},
-		},
-		flags: []string{
-			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
-			"-key-file", path.Join(*resourceDir, rsaKeyFile),
-		},
-	})
-	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},
-		},
-		flags: []string{
-			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
-			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
-		},
-	})
-	tests = append(tests, testCase{
-		testType: serverTest,
-		name:     "Basic-Server-Ed25519",
-		config: Config{
-			MaxVersion:   VersionTLS12,
-			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-		},
-		flags: []string{
-			"-cert-file", path.Join(*resourceDir, ed25519CertificateFile),
-			"-key-file", path.Join(*resourceDir, ed25519KeyFile),
-			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
-		},
-	})
+	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},
+			},
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+				"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			},
+		})
+		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},
+			},
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+				"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			},
+		})
+		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},
+			},
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+				"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "Basic-Server-Ed25519",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+			},
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, ed25519CertificateFile),
+				"-key-file", path.Join(*resourceDir, ed25519KeyFile),
+				"-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,
-		},
-	})
+		// 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"},
-	})
+		// 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 tlsVersions {
-		if !vers.supportsProtocol(config.protocol) {
-			continue
-		}
+	for _, vers := range allVersions(config.protocol) {
 		tests = append(tests, testCase{
 			testType: clientTest,
 			name:     "OCSPStapling-Client-" + vers.name,
@@ -5069,10 +5165,7 @@
 	}
 
 	// Certificate verification tests.
-	for _, vers := range tlsVersions {
-		if !vers.supportsProtocol(config.protocol) {
-			continue
-		}
+	for _, vers := range allVersions(config.protocol) {
 		for _, useCustomCallback := range []bool{false, true} {
 			for _, testType := range []testType{clientTest, serverTest} {
 				suffix := "-Client"
@@ -5513,8 +5606,58 @@
 			},
 		})
 
+		// 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", path.Join(*resourceDir, channelIDKeyFile),
+				"-select-next-proto", "foo",
+			},
+			resumeSession:         true,
+			expectChannelID:       true,
+			expectedNextProto:     "foo",
+			expectedNextProtoType: 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",
+				base64.StdEncoding.EncodeToString(channelIDBytes),
+				"-advertise-npn", "\x03foo\x03bar\x03baz",
+				"-expect-next-proto", "bar",
+			},
+			resumeSession:         true,
+			expectChannelID:       true,
+			expectedNextProto:     "bar",
+			expectedNextProtoType: 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 tlsVersions {
+		for _, ver := range allVersions(config.protocol) {
 			if ver.version < VersionTLS10 {
 				continue
 			}
@@ -5592,180 +5735,137 @@
 			}
 		}
 
-		// 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", path.Join(*resourceDir, channelIDKeyFile),
-				"-select-next-proto", "foo",
-			},
-			resumeSession:         true,
-			expectChannelID:       true,
-			expectedNextProto:     "foo",
-			expectedNextProtoType: 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",
-				base64.StdEncoding.EncodeToString(channelIDBytes),
-				"-advertise-npn", "\x03foo\x03bar\x03baz",
-				"-expect-next-proto", "bar",
-			},
-			resumeSession:         true,
-			expectChannelID:       true,
-			expectedNextProto:     "bar",
-			expectedNextProtoType: 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.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 = 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,
+			// 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,
-				messageCount:      1,
-				sendEmptyRecords:  1,
-				sendWarningAlerts: 1,
-				flags:             []string{"-check-close-notify"},
-				shouldFail:        true,
-				expectedError:     ":APPLICATION_DATA_ON_SHUTDOWN:",
-			})
+					shimShutsDown:     true,
+					sendEmptyRecords:  1,
+					sendWarningAlerts: 1,
+					flags:             []string{"-check-close-notify"},
+				})
 
-			// 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,
+				// 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,
-				sendKeyUpdates:   1,
-				keyUpdateRequest: keyUpdateRequested,
-				flags:            []string{"-check-close-notify"},
-			})
+					shimShutsDown:     true,
+					messageCount:      1,
+					sendEmptyRecords:  1,
+					sendWarningAlerts: 1,
+					flags:             []string{"-check-close-notify"},
+					shouldFail:        true,
+					expectedError:     ":APPLICATION_DATA_ON_SHUTDOWN:",
+				})
 
-			// 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,
+				// 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,
-				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",
-				},
-			})
+					shimShutsDown:    true,
+					sendKeyUpdates:   1,
+					keyUpdateRequest: keyUpdateRequested,
+					flags:            []string{"-check-close-notify"},
+				})
 
-			tests = append(tests, testCase{
-				testType: serverTest,
-				name:     "Shutdown-Shim-Renegotiate-Server-Forbidden",
-				config: Config{
-					MaxVersion: VersionTLS12,
-					Bugs: ProtocolBugs{
-						ExpectCloseNotify: true,
+				// 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,
-				renegotiate:   1,
-				shouldFail:    true,
-				expectedError: ":NO_RENEGOTIATION:",
-				flags: []string{
-					"-check-close-notify",
-				},
-			})
+					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",
+					},
+				})
+			}
 		}
-	} else {
+	}
+	if config.protocol == dtls {
 		// TODO(davidben): DTLS 1.3 will want a similar thing for
 		// HelloRetryRequest.
 		tests = append(tests, testCase{
@@ -5781,12 +5881,7 @@
 
 	for _, test := range tests {
 		test.protocol = config.protocol
-		if config.protocol == dtls {
-			test.name += "-DTLS"
-		}
-		if config.protocol == quic {
-			test.name += "-QUIC"
-		}
+		test.name += "-" + config.protocol.String()
 		if config.async {
 			test.name += "-Async"
 			test.flags = append(test.flags, "-async")
@@ -5899,12 +5994,7 @@
 				}
 
 				suffix := shimVers.name + "-" + runnerVers.name
-				if protocol == dtls {
-					suffix += "-DTLS"
-				}
-				if protocol == quic {
-					suffix += "-QUIC"
-				}
+				suffix += "-" + protocol.String()
 
 				// Determine the expected initial record-layer versions.
 				clientVers := shimVers.version
@@ -5976,22 +6066,9 @@
 	}
 
 	// Test the version extension at all versions.
-	for _, vers := range tlsVersions {
-		protocols := []protocol{tls}
-		if vers.hasDTLS {
-			protocols = append(protocols, dtls)
-		}
-		if vers.hasQUIC {
-			protocols = append(protocols, quic)
-		}
-		for _, protocol := range protocols {
-			suffix := vers.name
-			if protocol == dtls {
-				suffix += "-DTLS"
-			}
-			if protocol == quic {
-				suffix += "-QUIC"
-			}
+	for _, protocol := range []protocol{tls, dtls, quic} {
+		for _, vers := range allVersions(protocol) {
+			suffix := vers.name + "-" + protocol.String()
 
 			testCases = append(testCases, testCase{
 				protocol: protocol,
@@ -6343,12 +6420,7 @@
 
 			for _, runnerVers := range allVersions(protocol) {
 				suffix := shimVers.name + "-" + runnerVers.name
-				if protocol == dtls {
-					suffix += "-DTLS"
-				}
-				if protocol == quic {
-					suffix += "-QUIC"
-				}
+				suffix += "-" + protocol.String()
 
 				var expectedVersion uint16
 				var shouldFail bool
@@ -6761,6 +6833,68 @@
 			})
 		}
 
+		// Test missing ALPN in QUIC
+		if ver.version >= VersionTLS13 {
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: quic,
+				name:     "QUIC-Client-ALPNMissingFromConfig-" + ver.name,
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+				},
+				skipQUICALPNConfig: true,
+				shouldFail:         true,
+				expectedError:      ":MISSING_ALPN:",
+			})
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: quic,
+				name:     "QUIC-Client-ALPNMissing-" + ver.name,
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+				},
+				flags: []string{
+					"-advertise-alpn", "\x03foo",
+				},
+				skipQUICALPNConfig: true,
+				shouldFail:         true,
+				expectedError:      ":MISSING_ALPN:",
+				expectedLocalError: "remote error: no application protocol",
+			})
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: quic,
+				name:     "QUIC-Server-ALPNMissing-" + ver.name,
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+				},
+				skipQUICALPNConfig: true,
+				shouldFail:         true,
+				expectedError:      ":MISSING_ALPN:",
+				expectedLocalError: "remote error: no application protocol",
+			})
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				protocol: quic,
+				name:     "QUIC-Server-ALPNMismatch-" + ver.name,
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo"},
+				},
+				flags: []string{
+					"-decline-alpn",
+				},
+				skipQUICALPNConfig: true,
+				shouldFail:         true,
+				expectedError:      ":MISSING_ALPN:",
+				expectedLocalError: "remote error: no application protocol",
+			})
+		}
+
 		// Test Token Binding.
 
 		const maxTokenBindingVersion = 16
@@ -7146,6 +7280,7 @@
 			// Client sends params
 			testCases = append(testCases, testCase{
 				testType: clientTest,
+				protocol: quic,
 				name:     "QUICTransportParams-Client-" + ver.name,
 				config: Config{
 					MinVersion:          ver.version,
@@ -7159,10 +7294,28 @@
 					base64.StdEncoding.EncodeToString([]byte{1, 2}),
 				},
 				expectedQUICTransportParams: []byte{3, 4},
+				skipTransportParamsConfig:   true,
+			})
+			testCases = append(testCases, testCase{
+				testType: clientTest,
+				protocol: quic,
+				name:     "QUICTransportParams-Client-RejectMissing-" + ver.name,
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+				},
+				flags: []string{
+					"-quic-transport-params",
+					base64.StdEncoding.EncodeToString([]byte{3, 4}),
+				},
+				shouldFail:                true,
+				expectedError:             ":MISSING_EXTENSION:",
+				skipTransportParamsConfig: true,
 			})
 			// Server sends params
 			testCases = append(testCases, testCase{
 				testType: serverTest,
+				protocol: quic,
 				name:     "QUICTransportParams-Server-" + ver.name,
 				config: Config{
 					MinVersion:          ver.version,
@@ -7176,65 +7329,59 @@
 					base64.StdEncoding.EncodeToString([]byte{1, 2}),
 				},
 				expectedQUICTransportParams: []byte{3, 4},
+				skipTransportParamsConfig:   true,
 			})
-		} else {
 			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     "QUICTransportParams-Client-NotSent-" + ver.name,
+				testType: serverTest,
+				protocol: quic,
+				name:     "QUICTransportParams-Server-RejectMissing-" + ver.name,
 				config: Config{
 					MinVersion: ver.version,
 					MaxVersion: ver.version,
 				},
 				flags: []string{
-					"-max-version",
-					strconv.Itoa(int(ver.version)),
 					"-quic-transport-params",
 					base64.StdEncoding.EncodeToString([]byte{3, 4}),
 				},
-			})
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     "QUICTransportParams-Client-Rejected-" + ver.name,
-				config: Config{
-					MinVersion:          ver.version,
-					MaxVersion:          ver.version,
-					QUICTransportParams: []byte{1, 2},
-				},
-				flags: []string{
-					"-quic-transport-params",
-					base64.StdEncoding.EncodeToString([]byte{3, 4}),
-				},
-				shouldFail:    true,
-				expectedError: ":ERROR_PARSING_EXTENSION:",
-			})
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				name:     "QUICTransportParams-Server-Rejected-" + ver.name,
-				config: Config{
-					MinVersion:          ver.version,
-					MaxVersion:          ver.version,
-					QUICTransportParams: []byte{1, 2},
-				},
-				flags: []string{
-					"-expect-quic-transport-params",
-					base64.StdEncoding.EncodeToString([]byte{1, 2}),
-				},
-				shouldFail:    true,
-				expectedError: "QUIC transport params mismatch",
-			})
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				name:     "QUICTransportParams-OldServerIgnores-" + ver.name,
-				config: Config{
-					MaxVersion:          VersionTLS13,
-					QUICTransportParams: []byte{1, 2},
-				},
-				flags: []string{
-					"-min-version", ver.shimFlag(tls),
-					"-max-version", ver.shimFlag(tls),
-				},
+				expectedQUICTransportParams: []byte{3, 4},
+				shouldFail:                  true,
+				expectedError:               ":MISSING_EXTENSION:",
+				skipTransportParamsConfig:   true,
 			})
 		}
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "QUICTransportParams-Client-NotSentInTLS-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+			},
+			flags: []string{
+				"-max-version",
+				strconv.Itoa(int(ver.version)),
+				"-quic-transport-params",
+				base64.StdEncoding.EncodeToString([]byte{3, 4}),
+			},
+			shouldFail:                true,
+			expectedError:             ":QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED:",
+			skipTransportParamsConfig: true,
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "QUICTransportParams-Server-RejectedInTLS-" + ver.name,
+			config: Config{
+				MinVersion:          ver.version,
+				MaxVersion:          ver.version,
+				QUICTransportParams: []byte{1, 2},
+			},
+			flags: []string{
+				"-expect-quic-transport-params",
+				base64.StdEncoding.EncodeToString([]byte{1, 2}),
+			},
+			shouldFail:                true,
+			expectedLocalError:        "remote error: unsupported extension",
+			skipTransportParamsConfig: true,
+		})
 
 		// Test ticket behavior.
 
@@ -7800,12 +7947,7 @@
 			}
 			for _, protocol := range protocols {
 				suffix := "-" + sessionVers.name + "-" + resumeVers.name
-				if protocol == dtls {
-					suffix += "-DTLS"
-				}
-				if protocol == quic {
-					suffix += "-QUIC"
-				}
+				suffix += "-" + protocol.String()
 
 				if sessionVers.version == resumeVers.version {
 					testCases = append(testCases, testCase{
@@ -9357,7 +9499,8 @@
 				signatureRSAPKCS1WithSHA1,
 			},
 			Bugs: ProtocolBugs{
-				NoSignatureAlgorithms: true,
+				NoSignatureAlgorithms:       true,
+				DisableDelegatedCredentials: true,
 			},
 		},
 		shouldFail:    true,
@@ -11892,14 +12035,9 @@
 // WrongMessageType to fully test a per-message bug.
 func makePerMessageTests() []perMessageTest {
 	var ret []perMessageTest
-	// TODO(nharper): Consider supporting QUIC?
+	// The following tests are limited to TLS 1.2, so QUIC is not tested.
 	for _, protocol := range []protocol{tls, dtls} {
-		var suffix string
-		if protocol == dtls {
-			suffix = "-DTLS"
-		} else if protocol == quic {
-			suffix = "-QUIC"
-		}
+		suffix := "-" + protocol.String()
 
 		ret = append(ret, perMessageTest{
 			messageType: typeClientHello,
@@ -12104,134 +12242,137 @@
 
 	}
 
-	ret = append(ret, perMessageTest{
-		messageType: typeClientHello,
-		test: testCase{
-			testType: serverTest,
-			name:     "TLS13-ClientHello",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-		},
-	})
-
-	ret = append(ret, perMessageTest{
-		messageType: typeServerHello,
-		test: testCase{
-			name: "TLS13-ServerHello",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-		},
-	})
-
-	ret = append(ret, perMessageTest{
-		messageType: typeEncryptedExtensions,
-		test: testCase{
-			name: "TLS13-EncryptedExtensions",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-		},
-	})
-
-	ret = append(ret, perMessageTest{
-		messageType: typeCertificateRequest,
-		test: testCase{
-			name: "TLS13-CertificateRequest",
-			config: Config{
-				MaxVersion: VersionTLS13,
-				ClientAuth: RequireAnyClientCert,
-			},
-		},
-	})
-
-	ret = append(ret, perMessageTest{
-		messageType: typeCertificate,
-		test: testCase{
-			name: "TLS13-ServerCertificate",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-		},
-	})
-
-	ret = append(ret, perMessageTest{
-		messageType: typeCertificateVerify,
-		test: testCase{
-			name: "TLS13-ServerCertificateVerify",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-		},
-	})
-
-	ret = append(ret, perMessageTest{
-		messageType: typeFinished,
-		test: testCase{
-			name: "TLS13-ServerFinished",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-		},
-	})
-
-	ret = append(ret, perMessageTest{
-		messageType: typeCertificate,
-		test: testCase{
-			testType: serverTest,
-			name:     "TLS13-ClientCertificate",
-			config: Config{
-				Certificates: []Certificate{rsaCertificate},
-				MaxVersion:   VersionTLS13,
-			},
-			flags: []string{"-require-any-client-certificate"},
-		},
-	})
-
-	ret = append(ret, perMessageTest{
-		messageType: typeCertificateVerify,
-		test: testCase{
-			testType: serverTest,
-			name:     "TLS13-ClientCertificateVerify",
-			config: Config{
-				Certificates: []Certificate{rsaCertificate},
-				MaxVersion:   VersionTLS13,
-			},
-			flags: []string{"-require-any-client-certificate"},
-		},
-	})
-
-	ret = append(ret, perMessageTest{
-		messageType: typeFinished,
-		test: testCase{
-			testType: serverTest,
-			name:     "TLS13-ClientFinished",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-		},
-	})
-
-	ret = append(ret, perMessageTest{
-		messageType: typeEndOfEarlyData,
-		test: testCase{
-			testType: serverTest,
-			name:     "TLS13-EndOfEarlyData",
-			config: Config{
-				MaxVersion: VersionTLS13,
-			},
-			resumeConfig: &Config{
-				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					SendEarlyData:           [][]byte{{1, 2, 3, 4}},
-					ExpectEarlyDataAccepted: true,
+	for _, protocol := range []protocol{tls, quic} {
+		suffix := "-" + protocol.String()
+		ret = append(ret, perMessageTest{
+			messageType: typeClientHello,
+			test: testCase{
+				testType: serverTest,
+				name:     "TLS13-ClientHello" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
 				},
 			},
-			resumeSession: true,
-			flags:         []string{"-enable-early-data"},
-		},
-	})
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeServerHello,
+			test: testCase{
+				name: "TLS13-ServerHello" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeEncryptedExtensions,
+			test: testCase{
+				name: "TLS13-EncryptedExtensions" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateRequest,
+			test: testCase{
+				name: "TLS13-CertificateRequest" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
+					ClientAuth: RequireAnyClientCert,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificate,
+			test: testCase{
+				name: "TLS13-ServerCertificate" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateVerify,
+			test: testCase{
+				name: "TLS13-ServerCertificateVerify" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeFinished,
+			test: testCase{
+				name: "TLS13-ServerFinished" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificate,
+			test: testCase{
+				testType: serverTest,
+				name:     "TLS13-ClientCertificate" + suffix,
+				config: Config{
+					Certificates: []Certificate{rsaCertificate},
+					MaxVersion:   VersionTLS13,
+				},
+				flags: []string{"-require-any-client-certificate"},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateVerify,
+			test: testCase{
+				testType: serverTest,
+				name:     "TLS13-ClientCertificateVerify" + suffix,
+				config: Config{
+					Certificates: []Certificate{rsaCertificate},
+					MaxVersion:   VersionTLS13,
+				},
+				flags: []string{"-require-any-client-certificate"},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeFinished,
+			test: testCase{
+				testType: serverTest,
+				name:     "TLS13-ClientFinished" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeEndOfEarlyData,
+			test: testCase{
+				testType: serverTest,
+				name:     "TLS13-EndOfEarlyData" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS13,
+				},
+				resumeConfig: &Config{
+					MaxVersion: VersionTLS13,
+					Bugs: ProtocolBugs{
+						SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+						ExpectEarlyDataAccepted: true,
+					},
+				},
+				resumeSession: true,
+				flags:         []string{"-enable-early-data"},
+			},
+		})
+	}
 
 	return ret
 }
@@ -14594,7 +14735,7 @@
 
 		testCases = append(testCases, testCase{
 			testType: clientTest,
-			name:     "ECDSAKeyUsage-" + ver.name,
+			name:     "ECDSAKeyUsage-Client-" + ver.name,
 			config: Config{
 				MinVersion:   ver.version,
 				MaxVersion:   ver.version,
@@ -14603,6 +14744,19 @@
 			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,
+				Certificates: []Certificate{cert},
+			},
+			flags:         []string{"-require-any-client-certificate"},
+			shouldFail:    true,
+			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
+		})
 	}
 }
 
@@ -14672,7 +14826,7 @@
 	for _, ver := range tlsVersions {
 		testCases = append(testCases, testCase{
 			testType: clientTest,
-			name:     "RSAKeyUsage-WantSignature-GotEncipherment-" + ver.name,
+			name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-" + ver.name,
 			config: Config{
 				MinVersion:   ver.version,
 				MaxVersion:   ver.version,
@@ -14688,7 +14842,7 @@
 
 		testCases = append(testCases, testCase{
 			testType: clientTest,
-			name:     "RSAKeyUsage-WantSignature-GotSignature-" + ver.name,
+			name:     "RSAKeyUsage-Client-WantSignature-GotSignature-" + ver.name,
 			config: Config{
 				MinVersion:   ver.version,
 				MaxVersion:   ver.version,
@@ -14704,7 +14858,7 @@
 		if ver.version < VersionTLS13 {
 			testCases = append(testCases, testCase{
 				testType: clientTest,
-				name:     "RSAKeyUsage-WantEncipherment-GotEncipherment" + ver.name,
+				name:     "RSAKeyUsage-Client-WantEncipherment-GotEncipherment" + ver.name,
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
@@ -14718,7 +14872,7 @@
 
 			testCases = append(testCases, testCase{
 				testType: clientTest,
-				name:     "RSAKeyUsage-WantEncipherment-GotSignature-" + ver.name,
+				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-" + ver.name,
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
@@ -14735,7 +14889,7 @@
 			// In 1.2 and below, we should not enforce without the enforce-rsa-key-usage flag.
 			testCases = append(testCases, testCase{
 				testType: clientTest,
-				name:     "RSAKeyUsage-WantSignature-GotEncipherment-Unenforced" + ver.name,
+				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Unenforced" + ver.name,
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
@@ -14746,7 +14900,7 @@
 
 			testCases = append(testCases, testCase{
 				testType: clientTest,
-				name:     "RSAKeyUsage-WantEncipherment-GotSignature-Unenforced" + ver.name,
+				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-Unenforced" + ver.name,
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
@@ -14754,14 +14908,13 @@
 					CipherSuites: dsSuites,
 				},
 			})
-
 		}
 
 		if ver.version >= VersionTLS13 {
 			// In 1.3 and above, we enforce keyUsage even without the flag.
 			testCases = append(testCases, testCase{
 				testType: clientTest,
-				name:     "RSAKeyUsage-WantSignature-GotEncipherment-Enforced" + ver.name,
+				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Enforced" + ver.name,
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
@@ -14771,8 +14924,33 @@
 				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,
+				Certificates: []Certificate{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,
+				Certificates: []Certificate{dsCert},
+			},
+			flags: []string{"-require-any-client-certificate"},
+		})
+
 	}
 }
 
@@ -15478,8 +15656,8 @@
 
 		if *mallocTest >= 0 {
 			for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
-				statusChan <- statusMsg{test: test, started: true}
-				if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
+				statusChan <- statusMsg{test: test, statusType: statusStarted}
+				if err = runTest(statusChan, test, shimPath, mallocNumToFail); err != errMoreMallocs {
 					if err != nil {
 						fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
 					}
@@ -15488,21 +15666,30 @@
 			}
 		} else if *repeatUntilFailure {
 			for err == nil {
-				statusChan <- statusMsg{test: test, started: true}
-				err = runTest(test, shimPath, -1)
+				statusChan <- statusMsg{test: test, statusType: statusStarted}
+				err = runTest(statusChan, test, shimPath, -1)
 			}
 		} else {
-			statusChan <- statusMsg{test: test, started: true}
-			err = runTest(test, shimPath, -1)
+			statusChan <- statusMsg{test: test, statusType: statusStarted}
+			err = runTest(statusChan, test, shimPath, -1)
 		}
-		statusChan <- statusMsg{test: test, err: err}
+		statusChan <- statusMsg{test: test, statusType: statusDone, err: err}
 	}
 }
 
+type statusType int
+
+const (
+	statusStarted statusType = iota
+	statusShimStarted
+	statusDone
+)
+
 type statusMsg struct {
-	test    *testCase
-	started bool
-	err     error
+	test       *testCase
+	statusType statusType
+	pid        int
+	err        error
 }
 
 func statusPrinter(doneChan chan *testresult.Results, statusChan chan statusMsg, total int) {
@@ -15519,9 +15706,9 @@
 			fmt.Print(erase)
 		}
 
-		if msg.started {
+		if msg.statusType == statusStarted {
 			started++
-		} else {
+		} else if msg.statusType == statusDone {
 			done++
 
 			if msg.err != nil {
@@ -15553,6 +15740,11 @@
 		if !*pipe {
 			// Print a new status line.
 			line := fmt.Sprintf("%d/%d/%d/%d/%d", failed, unimplemented, done, started, total)
+			if msg.statusType == statusShimStarted && *waitForDebugger {
+				// Note -wait-for-debugger limits the test to one worker,
+				// otherwise some output would be skipped.
+				line += fmt.Sprintf(" (%s: attach to process %d to continue)", msg.test.name, msg.pid)
+			}
 			lineLen = len(line)
 			os.Stdout.WriteString(line)
 		}
@@ -15613,8 +15805,13 @@
 
 	var wg sync.WaitGroup
 
-	statusChan := make(chan statusMsg, *numWorkers)
-	testChan := make(chan *testCase, *numWorkers)
+	numWorkers := *numWorkersFlag
+	if useDebugger() {
+		numWorkers = 1
+	}
+
+	statusChan := make(chan statusMsg, numWorkers)
+	testChan := make(chan *testCase, numWorkers)
 	doneChan := make(chan *testresult.Results)
 
 	if len(*shimConfigFile) != 0 {
@@ -15632,7 +15829,7 @@
 
 	go statusPrinter(doneChan, statusChan, len(testCases))
 
-	for i := 0; i < *numWorkers; i++ {
+	for i := 0; i < numWorkers; i++ {
 		wg.Add(1)
 		go worker(statusChan, testChan, *shimPath, &wg)
 	}
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index f497704..062a43a 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -152,6 +152,7 @@
      &TestConfig::expect_delegated_credential_used},
     {"-expect-hrr", &TestConfig::expect_hrr},
     {"-expect-no-hrr", &TestConfig::expect_no_hrr},
+    {"-wait-for-debugger", &TestConfig::wait_for_debugger},
 };
 
 const Flag<std::string> kStringFlags[] = {
@@ -307,12 +308,6 @@
     return true;
   }
 
-  if (strcmp(flag, "-enable-ed25519") == 0) {
-    // Old argument; ignored for split-handshake compat testing.
-    // Remove after 2020-06-01.
-    return true;
-  }
-
   fprintf(stderr, "Unknown argument: %s.\n", flag);
   return false;
 }
@@ -1136,12 +1131,18 @@
   return ssl_select_cert_success;
 }
 
-static int SetQuicEncryptionSecrets(SSL *ssl, enum ssl_encryption_level_t level,
-                                    const uint8_t *read_secret,
-                                    const uint8_t *write_secret,
-                                    size_t secret_len) {
-  return GetTestState(ssl)->quic_transport->SetSecrets(
-      level, read_secret, write_secret, secret_len);
+static int SetQuicReadSecret(SSL *ssl, enum ssl_encryption_level_t level,
+                             const SSL_CIPHER *cipher, const uint8_t *secret,
+                             size_t secret_len) {
+  return GetTestState(ssl)->quic_transport->SetReadSecret(level, cipher, secret,
+                                                          secret_len);
+}
+
+static int SetQuicWriteSecret(SSL *ssl, enum ssl_encryption_level_t level,
+                              const SSL_CIPHER *cipher, const uint8_t *secret,
+                              size_t secret_len) {
+  return GetTestState(ssl)->quic_transport->SetWriteSecret(level, cipher,
+                                                           secret, secret_len);
 }
 
 static int AddQuicHandshakeData(SSL *ssl, enum ssl_encryption_level_t level,
@@ -1156,12 +1157,12 @@
 
 static int SendQuicAlert(SSL *ssl, enum ssl_encryption_level_t level,
                          uint8_t alert) {
-  // TODO(nharper): Support processing alerts.
-  return 0;
+  return GetTestState(ssl)->quic_transport->SendAlert(level, alert);
 }
 
 static const SSL_QUIC_METHOD g_quic_method = {
-    SetQuicEncryptionSecrets,
+    SetQuicReadSecret,
+    SetQuicWriteSecret,
     AddQuicHandshakeData,
     FlushQuicFlight,
     SendQuicAlert,
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index 0974a16..f424f8b 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -177,6 +177,7 @@
   std::string expect_early_data_reason;
   bool expect_hrr = false;
   bool expect_no_hrr = false;
+  bool wait_for_debugger = false;
 
   int argc;
   char **argv;
diff --git a/src/ssl/tls13_client.cc b/src/ssl/tls13_client.cc
index 9418185..cb379b0 100644
--- a/src/ssl/tls13_client.cc
+++ b/src/ssl/tls13_client.cc
@@ -75,20 +75,24 @@
   // We do not currently implement DTLS 1.3 and, in QUIC, the caller handles
   // 0-RTT data, so we can skip installing 0-RTT keys and act as if there is one
   // write level. If we implement DTLS 1.3, we'll need to model this better.
-  if (level == ssl_encryption_initial) {
-    bssl::UniquePtr<SSLAEADContext> null_ctx =
-        SSLAEADContext::CreateNullCipher(SSL_is_dtls(ssl));
-    if (!null_ctx || !ssl->method->set_write_state(ssl, ssl_encryption_initial,
-                                                   std::move(null_ctx))) {
-      return false;
-    }
-    ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->version);
-  } else {
-    assert(level == ssl_encryption_handshake);
-    if (!tls13_set_traffic_key(ssl, ssl_encryption_handshake, evp_aead_seal,
-                               hs->new_session.get(),
-                               hs->client_handshake_secret())) {
-      return false;
+  if (ssl->quic_method == nullptr) {
+    if (level == ssl_encryption_initial) {
+      bssl::UniquePtr<SSLAEADContext> null_ctx =
+          SSLAEADContext::CreateNullCipher(SSL_is_dtls(ssl));
+      if (!null_ctx ||
+          !ssl->method->set_write_state(ssl, ssl_encryption_initial,
+                                        std::move(null_ctx),
+                                        /*secret_for_quic=*/{})) {
+        return false;
+      }
+      ssl->s3->aead_write_ctx->SetVersionIfNullCipher(ssl->version);
+    } else {
+      assert(level == ssl_encryption_handshake);
+      if (!tls13_set_traffic_key(ssl, ssl_encryption_handshake, evp_aead_seal,
+                                 hs->new_session.get(),
+                                 hs->client_handshake_secret())) {
+        return false;
+      }
     }
   }
 
@@ -437,18 +441,15 @@
 
   if (!tls13_advance_key_schedule(hs, dhe_secret) ||
       !ssl_hash_message(hs, msg) ||
-      !tls13_derive_handshake_secrets(hs) ||
-      !tls13_set_traffic_key(ssl, ssl_encryption_handshake, evp_aead_open,
-                             hs->new_session.get(),
-                             hs->server_handshake_secret())) {
+      !tls13_derive_handshake_secrets(hs)) {
     return ssl_hs_error;
   }
 
-  // If currently sending early data, we defer installing client traffic keys to
-  // when the early data stream is closed. See |close_early_data|. Note if the
-  // server has already rejected 0-RTT via HelloRetryRequest, |in_early_data| is
-  // already false.
-  if (!hs->in_early_data) {
+  // If currently sending early data over TCP, we defer installing client
+  // traffic keys to when the early data stream is closed. See
+  // |close_early_data|. Note if the server has already rejected 0-RTT via
+  // HelloRetryRequest, |in_early_data| is already false.
+  if (!hs->in_early_data || ssl->quic_method != nullptr) {
     if (!tls13_set_traffic_key(ssl, ssl_encryption_handshake, evp_aead_seal,
                                hs->new_session.get(),
                                hs->client_handshake_secret())) {
@@ -456,6 +457,12 @@
     }
   }
 
+  if (!tls13_set_traffic_key(ssl, ssl_encryption_handshake, evp_aead_open,
+                             hs->new_session.get(),
+                             hs->server_handshake_secret())) {
+    return ssl_hs_error;
+  }
+
   ssl->method->next_message(ssl);
   hs->tls13_state = state_read_encrypted_extensions;
   return ssl_hs_ok;
@@ -803,12 +810,12 @@
   }
 
   // Derive the final keys and enable them.
-  if (!tls13_set_traffic_key(ssl, ssl_encryption_application, evp_aead_open,
-                             hs->new_session.get(),
-                             hs->server_traffic_secret_0()) ||
-      !tls13_set_traffic_key(ssl, ssl_encryption_application, evp_aead_seal,
+  if (!tls13_set_traffic_key(ssl, ssl_encryption_application, evp_aead_seal,
                              hs->new_session.get(),
                              hs->client_traffic_secret_0()) ||
+      !tls13_set_traffic_key(ssl, ssl_encryption_application, evp_aead_open,
+                             hs->new_session.get(),
+                             hs->server_traffic_secret_0()) ||
       !tls13_derive_resumption_secret(hs)) {
     return ssl_hs_error;
   }
@@ -924,26 +931,43 @@
     return true;
   }
 
+  CBS body = msg.body;
+  UniquePtr<SSL_SESSION> session = tls13_create_session_with_ticket(ssl, &body);
+  if (!session) {
+    return false;
+  }
+
+  if ((ssl->session_ctx->session_cache_mode & SSL_SESS_CACHE_CLIENT) &&
+      ssl->session_ctx->new_session_cb != NULL &&
+      ssl->session_ctx->new_session_cb(ssl, session.get())) {
+    // |new_session_cb|'s return value signals that it took ownership.
+    session.release();
+  }
+
+  return true;
+}
+
+UniquePtr<SSL_SESSION> tls13_create_session_with_ticket(SSL *ssl, CBS *body) {
   UniquePtr<SSL_SESSION> session = SSL_SESSION_dup(
       ssl->s3->established_session.get(), SSL_SESSION_INCLUDE_NONAUTH);
   if (!session) {
-    return false;
+    return nullptr;
   }
 
   ssl_session_rebase_time(ssl, session.get());
 
   uint32_t server_timeout;
-  CBS body = msg.body, ticket_nonce, ticket, extensions;
-  if (!CBS_get_u32(&body, &server_timeout) ||
-      !CBS_get_u32(&body, &session->ticket_age_add) ||
-      !CBS_get_u8_length_prefixed(&body, &ticket_nonce) ||
-      !CBS_get_u16_length_prefixed(&body, &ticket) ||
+  CBS ticket_nonce, ticket, extensions;
+  if (!CBS_get_u32(body, &server_timeout) ||
+      !CBS_get_u32(body, &session->ticket_age_add) ||
+      !CBS_get_u8_length_prefixed(body, &ticket_nonce) ||
+      !CBS_get_u16_length_prefixed(body, &ticket) ||
       !session->ticket.CopyFrom(ticket) ||
-      !CBS_get_u16_length_prefixed(&body, &extensions) ||
-      CBS_len(&body) != 0) {
+      !CBS_get_u16_length_prefixed(body, &extensions) ||
+      CBS_len(body) != 0) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    return false;
+    return nullptr;
   }
 
   // Cap the renewable lifetime by the server advertised value. This avoids
@@ -953,7 +977,7 @@
   }
 
   if (!tls13_derive_session_psk(session.get(), ticket_nonce)) {
-    return false;
+    return nullptr;
   }
 
   // Parse out the extensions.
@@ -968,7 +992,7 @@
                             OPENSSL_ARRAY_SIZE(ext_types),
                             1 /* ignore unknown */)) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, alert);
-    return false;
+    return nullptr;
   }
 
   if (have_early_data) {
@@ -976,7 +1000,7 @@
         CBS_len(&early_data) != 0) {
       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      return false;
+      return nullptr;
     }
 
     // QUIC does not use the max_early_data_size parameter and always sets it to
@@ -985,7 +1009,7 @@
         session->ticket_max_early_data != 0xffffffff) {
       ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
       OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      return false;
+      return nullptr;
     }
   }
 
@@ -997,14 +1021,7 @@
   session->ticket_age_add_valid = true;
   session->not_resumable = false;
 
-  if ((ssl->session_ctx->session_cache_mode & SSL_SESS_CACHE_CLIENT) &&
-      ssl->session_ctx->new_session_cb != NULL &&
-      ssl->session_ctx->new_session_cb(ssl, session.get())) {
-    // |new_session_cb|'s return value signals that it took ownership.
-    session.release();
-  }
-
-  return true;
+  return session;
 }
 
 BSSL_NAMESPACE_END
diff --git a/src/ssl/tls13_enc.cc b/src/ssl/tls13_enc.cc
index bd12f63..69a5578 100644
--- a/src/ssl/tls13_enc.cc
+++ b/src/ssl/tls13_enc.cc
@@ -142,9 +142,15 @@
                            const SSL_SESSION *session,
                            Span<const uint8_t> traffic_secret) {
   uint16_t version = ssl_session_protocol_version(session);
-
   UniquePtr<SSLAEADContext> traffic_aead;
-  if (ssl->quic_method == nullptr) {
+  Span<const uint8_t> secret_for_quic;
+  if (ssl->quic_method != nullptr) {
+    // Install a placeholder SSLAEADContext so that SSL accessors work. The
+    // encryption itself will be handled by the SSL_QUIC_METHOD.
+    traffic_aead =
+        SSLAEADContext::CreatePlaceholderForQUIC(version, session->cipher);
+    secret_for_quic = traffic_secret;
+  } else {
     // Look up cipher suite properties.
     const EVP_AEAD *aead;
     size_t discard;
@@ -173,17 +179,9 @@
       return false;
     }
 
-
     traffic_aead = SSLAEADContext::Create(direction, session->ssl_version,
                                           SSL_is_dtls(ssl), session->cipher,
                                           key, Span<const uint8_t>(), iv);
-  } else {
-    // Install a placeholder SSLAEADContext so that SSL accessors work. The
-    // encryption itself will be handled by the SSL_QUIC_METHOD.
-    traffic_aead =
-        SSLAEADContext::CreatePlaceholderForQUIC(version, session->cipher);
-    // QUIC never installs early data keys at the TLS layer.
-    assert(level != ssl_encryption_early_data);
   }
 
   if (!traffic_aead) {
@@ -199,14 +197,16 @@
   }
 
   if (direction == evp_aead_open) {
-    if (!ssl->method->set_read_state(ssl, level, std::move(traffic_aead))) {
+    if (!ssl->method->set_read_state(ssl, level, std::move(traffic_aead),
+                                     secret_for_quic)) {
       return false;
     }
     OPENSSL_memmove(ssl->s3->read_traffic_secret, traffic_secret.data(),
                     traffic_secret.size());
     ssl->s3->read_traffic_secret_len = traffic_secret.size();
   } else {
-    if (!ssl->method->set_write_state(ssl, level, std::move(traffic_aead))) {
+    if (!ssl->method->set_write_state(ssl, level, std::move(traffic_aead),
+                                      secret_for_quic)) {
       return false;
     }
     OPENSSL_memmove(ssl->s3->write_traffic_secret, traffic_secret.data(),
@@ -237,47 +237,6 @@
   return true;
 }
 
-bool tls13_set_early_secret_for_quic(SSL_HANDSHAKE *hs) {
-  SSL *const ssl = hs->ssl;
-  if (ssl->quic_method == nullptr) {
-    return true;
-  }
-  if (ssl->server) {
-    if (!ssl->quic_method->set_encryption_secrets(
-            ssl, ssl_encryption_early_data, hs->early_traffic_secret().data(),
-            /*write_secret=*/nullptr, hs->early_traffic_secret().size())) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
-      return false;
-    }
-  } else {
-    if (!ssl->quic_method->set_encryption_secrets(
-            ssl, ssl_encryption_early_data, /*read_secret=*/nullptr,
-            hs->early_traffic_secret().data(),
-            hs->early_traffic_secret().size())) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_QUIC_INTERNAL_ERROR);
-      return false;
-    }
-  }
-  return true;
-}
-
-static bool set_quic_secrets(SSL_HANDSHAKE *hs, ssl_encryption_level_t level,
-                             Span<const uint8_t> client_write_secret,
-                             Span<const uint8_t> server_write_secret) {
-  SSL *const ssl = hs->ssl;
-  assert(client_write_secret.size() == server_write_secret.size());
-  if (ssl->quic_method == nullptr) {
-    return true;
-  }
-  if (!ssl->server) {
-    std::swap(client_write_secret, server_write_secret);
-  }
-  return ssl->quic_method->set_encryption_secrets(
-      ssl, level,
-      /*read_secret=*/client_write_secret.data(),
-      /*write_secret=*/server_write_secret.data(), client_write_secret.size());
-}
-
 bool tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
   if (!derive_secret(hs, hs->client_handshake_secret(),
@@ -287,10 +246,7 @@
       !derive_secret(hs, hs->server_handshake_secret(),
                      label_to_span(kTLS13LabelServerHandshakeTraffic)) ||
       !ssl_log_secret(ssl, "SERVER_HANDSHAKE_TRAFFIC_SECRET",
-                      hs->server_handshake_secret()) ||
-      !set_quic_secrets(hs, ssl_encryption_handshake,
-                        hs->client_handshake_secret(),
-                        hs->server_handshake_secret())) {
+                      hs->server_handshake_secret())) {
     return false;
   }
 
@@ -313,10 +269,7 @@
           label_to_span(kTLS13LabelExporter)) ||
       !ssl_log_secret(ssl, "EXPORTER_SECRET",
                       MakeConstSpan(ssl->s3->exporter_secret,
-                                    ssl->s3->exporter_secret_len)) ||
-      !set_quic_secrets(hs, ssl_encryption_application,
-                        hs->client_traffic_secret_0(),
-                        hs->server_traffic_secret_0())) {
+                                    ssl->s3->exporter_secret_len))) {
     return false;
   }
 
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index f796260..0105f1c 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -127,7 +127,10 @@
       return false;
     }
     session->ticket_age_add_valid = true;
-    if (ssl->enable_early_data) {
+    bool enable_early_data =
+        ssl->enable_early_data &&
+        (!ssl->quic_method || !ssl->config->quic_early_data_context.empty());
+    if (enable_early_data) {
       // QUIC does not use the max_early_data_size parameter and always sets it
       // to a fixed value. See draft-ietf-quic-tls-22, section 4.5.
       session->ticket_max_early_data =
@@ -152,7 +155,7 @@
       return false;
     }
 
-    if (ssl->enable_early_data) {
+    if (enable_early_data) {
       CBB early_data;
       if (!CBB_add_u16(&extensions, TLSEXT_TYPE_early_data) ||
           !CBB_add_u16_length_prefixed(&extensions, &early_data) ||
@@ -193,6 +196,11 @@
     return ssl_hs_error;
   }
 
+  if (ssl->quic_method != nullptr && client_hello.session_id_len > 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_COMPATIBILITY_MODE);
+    ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+    return ssl_hs_error;
+  }
   OPENSSL_memcpy(hs->session_id, client_hello.session_id,
                  client_hello.session_id_len);
   hs->session_id_len = client_hello.session_id_len;
@@ -309,6 +317,23 @@
   return ssl_ticket_aead_success;
 }
 
+static bool quic_ticket_compatible(const SSL_SESSION *session,
+                                   const SSL_CONFIG *config) {
+  if (!session->is_quic) {
+    return true;
+  }
+
+  if (session->quic_early_data_context.empty() ||
+      config->quic_early_data_context.size() !=
+          session->quic_early_data_context.size() ||
+      CRYPTO_memcmp(config->quic_early_data_context.data(),
+                    session->quic_early_data_context.data(),
+                    session->quic_early_data_context.size()) != 0) {
+    return false;
+  }
+  return true;
+}
+
 static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
   SSLMessage msg;
@@ -374,6 +399,8 @@
       } else if (ssl->s3->ticket_age_skew < -kMaxTicketAgeSkewSeconds ||
                  kMaxTicketAgeSkewSeconds < ssl->s3->ticket_age_skew) {
         ssl->s3->early_data_reason = ssl_early_data_ticket_age_skew;
+      } else if (!quic_ticket_compatible(session.get(), hs->config)) {
+        ssl->s3->early_data_reason = ssl_early_data_quic_parameter_mismatch;
       } else {
         ssl->s3->early_data_reason = ssl_early_data_accepted;
         ssl->s3->early_data_accepted = true;
@@ -474,7 +501,7 @@
       !CBB_add_bytes(&body, kHelloRetryRequest, SSL3_RANDOM_SIZE) ||
       !CBB_add_u8_length_prefixed(&body, &session_id) ||
       !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) ||
-      !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
+      !CBB_add_u16(&body, SSL_CIPHER_get_protocol_id(hs->new_cipher)) ||
       !CBB_add_u8(&body, 0 /* no compression */) ||
       !tls1_get_shared_group(hs, &group_id) ||
       !CBB_add_u16_length_prefixed(&body, &extensions) ||
@@ -586,7 +613,7 @@
       !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
       !CBB_add_u8_length_prefixed(&body, &session_id) ||
       !CBB_add_bytes(&session_id, hs->session_id, hs->session_id_len) ||
-      !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
+      !CBB_add_u16(&body, SSL_CIPHER_get_protocol_id(hs->new_cipher)) ||
       !CBB_add_u8(&body, 0) ||
       !CBB_add_u16_length_prefixed(&body, &extensions) ||
       !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) ||
@@ -718,19 +745,6 @@
   SSL *const ssl = hs->ssl;
 
   if (ssl->s3->early_data_accepted) {
-    // We defer releasing the early traffic secret to QUIC to this point. First,
-    // the early traffic secret is derived before ECDHE, but ECDHE may later
-    // reject 0-RTT. We only release the secret after 0-RTT is fully resolved.
-    //
-    // Second, 0-RTT data is acknowledged with 1-RTT keys. Both are derived as
-    // part of the ServerHello flight, but future TLS extensions may insert an
-    // asynchronous point in the middle of this flight. We defer releasing the
-    // 0-RTT keys to ensure the QUIC implementation never installs read keys
-    // without the write keys to send the corresponding ACKs.
-    if (!tls13_set_early_secret_for_quic(hs)) {
-      return ssl_hs_error;
-    }
-
     // If accepting 0-RTT, we send tickets half-RTT. This gets the tickets on
     // the wire sooner and also avoids triggering a write on |SSL_read| when
     // processing the client Finished. This requires computing the client
@@ -779,9 +793,7 @@
 static enum ssl_hs_wait_t do_read_second_client_flight(SSL_HANDSHAKE *hs) {
   SSL *const ssl = hs->ssl;
   if (ssl->s3->early_data_accepted) {
-    // QUIC never receives handshake messages under 0-RTT keys.
-    if (ssl->quic_method == nullptr &&
-        !tls13_set_traffic_key(ssl, ssl_encryption_early_data, evp_aead_open,
+    if (!tls13_set_traffic_key(ssl, ssl_encryption_early_data, evp_aead_open,
                                hs->new_session.get(),
                                hs->early_traffic_secret())) {
       return ssl_hs_error;
diff --git a/src/ssl/tls_method.cc b/src/ssl/tls_method.cc
index 3868852..8165d1c 100644
--- a/src/ssl/tls_method.cc
+++ b/src/ssl/tls_method.cc
@@ -83,7 +83,8 @@
 }
 
 static bool tls_set_read_state(SSL *ssl, ssl_encryption_level_t level,
-                               UniquePtr<SSLAEADContext> aead_ctx) {
+                               UniquePtr<SSLAEADContext> aead_ctx,
+                               Span<const uint8_t> secret_for_quic) {
   // Cipher changes are forbidden if the current epoch has leftover data.
   if (tls_has_unprocessed_handshake_data(ssl)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESS_HANDSHAKE_DATA);
@@ -91,6 +92,21 @@
     return false;
   }
 
+  if (ssl->quic_method != nullptr) {
+    if (!ssl->quic_method->set_read_secret(ssl, level, aead_ctx->cipher(),
+                                           secret_for_quic.data(),
+                                           secret_for_quic.size())) {
+      return false;
+    }
+
+    // QUIC only uses |ssl| for handshake messages, which never use early data
+    // keys, so we return without installing anything. This avoids needing to
+    // have two secrets active at once in 0-RTT.
+    if (level == ssl_encryption_early_data) {
+      return true;
+    }
+  }
+
   OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
   ssl->s3->aead_read_ctx = std::move(aead_ctx);
   ssl->s3->read_level = level;
@@ -98,11 +114,27 @@
 }
 
 static bool tls_set_write_state(SSL *ssl, ssl_encryption_level_t level,
-                                UniquePtr<SSLAEADContext> aead_ctx) {
+                                UniquePtr<SSLAEADContext> aead_ctx,
+                                Span<const uint8_t> secret_for_quic) {
   if (!tls_flush_pending_hs_data(ssl)) {
     return false;
   }
 
+  if (ssl->quic_method != nullptr) {
+    if (!ssl->quic_method->set_write_secret(ssl, level, aead_ctx->cipher(),
+                                            secret_for_quic.data(),
+                                            secret_for_quic.size())) {
+      return false;
+    }
+
+    // QUIC only uses |ssl| for handshake messages, which never use early data
+    // keys, so we return without installing anything. This avoids needing to
+    // have two secrets active at once in 0-RTT.
+    if (level == ssl_encryption_early_data) {
+      return true;
+    }
+  }
+
   OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
   ssl->s3->aead_write_ctx = std::move(aead_ctx);
   ssl->s3->write_level = level;
diff --git a/src/ssl/tls_record.cc b/src/ssl/tls_record.cc
index 464c5c5..acff1ad 100644
--- a/src/ssl/tls_record.cc
+++ b/src/ssl/tls_record.cc
@@ -447,13 +447,15 @@
     // TLS 1.3 adds an extra byte for encrypted record type.
     extra_in_len = 1;
   }
-  if (type == SSL3_RT_APPLICATION_DATA &&  // clang-format off
+  // clang-format off
+  if (type == SSL3_RT_APPLICATION_DATA &&
       in_len > 1 &&
       ssl_needs_record_splitting(ssl)) {
     // With record splitting enabled, the first byte gets sealed into a separate
     // record which is written into the prefix.
     in_len -= 1;
   }
+  // clang-format on
   return ssl->s3->aead_write_ctx->SuffixLen(out_suffix_len, in_len, extra_in_len);
 }
 
@@ -465,8 +467,8 @@
 // |tls_seal_scatter_record| implements TLS 1.0 CBC 1/n-1 record splitting and
 // may write two records concatenated.
 static bool tls_seal_scatter_record(SSL *ssl, uint8_t *out_prefix, uint8_t *out,
-                                   uint8_t *out_suffix, uint8_t type,
-                                   const uint8_t *in, size_t in_len) {
+                                    uint8_t *out_suffix, uint8_t type,
+                                    const uint8_t *in, size_t in_len) {
   if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 &&
       ssl_needs_record_splitting(ssl)) {
     assert(ssl->s3->aead_write_ctx->ExplicitNonceLen() == 0);