external/boringssl: Sync to faa539f877432814d0f2de19846eb99f2ea1e207.

This includes the following changes:

https://boringssl.googlesource.com/boringssl/+log/bbfe603519bc54fbc4c8dd87efe1ed385df550b4..faa539f877432814d0f2de19846eb99f2ea1e207

Test: BoringSSL CTS Presubmits
Change-Id: I3ea66c6a16d30b31f9a51e8154fa581a7d386918
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index 4d70d6c..ce6eb7a 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-bbfe603519bc54fbc4c8dd87efe1ed385df550b4
+faa539f877432814d0f2de19846eb99f2ea1e207
diff --git a/linux-arm/crypto/aes/bsaes-armv7.S b/linux-arm/crypto/aes/bsaes-armv7.S
index 1db7bbe..0b1a9f7 100644
--- a/linux-arm/crypto/aes/bsaes-armv7.S
+++ b/linux-arm/crypto/aes/bsaes-armv7.S
@@ -1,4 +1,11 @@
 #if defined(__arm__)
+@ Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
+@
+@ Licensed under the OpenSSL license (the "License").  You may not use
+@ this file except in compliance with the License.  You can obtain a copy
+@ in the file LICENSE in the source distribution or at
+@ https://www.openssl.org/source/license.html
+
 
 @ ====================================================================
 @ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -77,6 +84,7 @@
 .thumb
 #else
 .code	32
+# undef __thumb2__
 #endif
 
 .type	_bsaes_decrypt8,%function
@@ -1313,7 +1321,7 @@
 	vmov	q4,q15		@ just in case ensure that IV
 	vmov	q5,q0			@ and input are preserved
 	bl	AES_decrypt
-	vld1.8	{q0}, [r9,:64]		@ load result
+	vld1.8	{q0}, [r9]		@ load result
 	veor	q0, q0, q4	@ ^= IV
 	vmov	q15, q5		@ q5 holds input
 	vst1.8	{q0}, [r10]		@ write output
diff --git a/linux-x86_64/crypto/aes/aes-x86_64.S b/linux-x86_64/crypto/aes/aes-x86_64.S
index ab1168e..1a0a512 100644
--- a/linux-x86_64/crypto/aes/aes-x86_64.S
+++ b/linux-x86_64/crypto/aes/aes-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 .type	_x86_64_AES_encrypt,@function
 .align	16
diff --git a/linux-x86_64/crypto/aes/aesni-x86_64.S b/linux-x86_64/crypto/aes/aesni-x86_64.S
index a90e935..2890ccf 100644
--- a/linux-x86_64/crypto/aes/aesni-x86_64.S
+++ b/linux-x86_64/crypto/aes/aesni-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 .extern	OPENSSL_ia32cap_P
 .hidden OPENSSL_ia32cap_P
diff --git a/linux-x86_64/crypto/aes/bsaes-x86_64.S b/linux-x86_64/crypto/aes/bsaes-x86_64.S
index 3f3c73b..04b161c 100644
--- a/linux-x86_64/crypto/aes/bsaes-x86_64.S
+++ b/linux-x86_64/crypto/aes/bsaes-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .extern	asm_AES_encrypt
diff --git a/linux-x86_64/crypto/aes/vpaes-x86_64.S b/linux-x86_64/crypto/aes/vpaes-x86_64.S
index 4dfafa9..f3a089d 100644
--- a/linux-x86_64/crypto/aes/vpaes-x86_64.S
+++ b/linux-x86_64/crypto/aes/vpaes-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/linux-x86_64/crypto/bn/rsaz-avx2.S b/linux-x86_64/crypto/bn/rsaz-avx2.S
index db078a9..08f38e8 100644
--- a/linux-x86_64/crypto/bn/rsaz-avx2.S
+++ b/linux-x86_64/crypto/bn/rsaz-avx2.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .globl	rsaz_1024_sqr_avx2
diff --git a/linux-x86_64/crypto/bn/x86_64-mont.S b/linux-x86_64/crypto/bn/x86_64-mont.S
index 0d2cea2..1f673ef 100644
--- a/linux-x86_64/crypto/bn/x86_64-mont.S
+++ b/linux-x86_64/crypto/bn/x86_64-mont.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .extern	OPENSSL_ia32cap_P
diff --git a/linux-x86_64/crypto/bn/x86_64-mont5.S b/linux-x86_64/crypto/bn/x86_64-mont5.S
index 33ca3c4..1ec58ca 100644
--- a/linux-x86_64/crypto/bn/x86_64-mont5.S
+++ b/linux-x86_64/crypto/bn/x86_64-mont5.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .extern	OPENSSL_ia32cap_P
diff --git a/linux-x86_64/crypto/chacha/chacha-x86_64.S b/linux-x86_64/crypto/chacha/chacha-x86_64.S
index 25ec715..62dc779 100644
--- a/linux-x86_64/crypto/chacha/chacha-x86_64.S
+++ b/linux-x86_64/crypto/chacha/chacha-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .extern	OPENSSL_ia32cap_P
diff --git a/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S b/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
index c7e673f..d149d0f 100644
--- a/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
+++ b/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 .extern	OPENSSL_ia32cap_P
 .hidden OPENSSL_ia32cap_P
diff --git a/linux-x86_64/crypto/ec/p256-x86_64-asm.S b/linux-x86_64/crypto/ec/p256-x86_64-asm.S
index 785f269..2f9a5f4 100644
--- a/linux-x86_64/crypto/ec/p256-x86_64-asm.S
+++ b/linux-x86_64/crypto/ec/p256-x86_64-asm.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 .extern	OPENSSL_ia32cap_P
 .hidden OPENSSL_ia32cap_P
diff --git a/linux-x86_64/crypto/md5/md5-x86_64.S b/linux-x86_64/crypto/md5/md5-x86_64.S
index 05369e2..8af6504 100644
--- a/linux-x86_64/crypto/md5/md5-x86_64.S
+++ b/linux-x86_64/crypto/md5/md5-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 .align	16
 
diff --git a/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S b/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S
index 9953e4c..62c6cd6 100644
--- a/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S
+++ b/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .type	_aesni_ctr32_ghash_6x,@function
diff --git a/linux-x86_64/crypto/modes/ghash-x86_64.S b/linux-x86_64/crypto/modes/ghash-x86_64.S
index 8842c27..4afbc52 100644
--- a/linux-x86_64/crypto/modes/ghash-x86_64.S
+++ b/linux-x86_64/crypto/modes/ghash-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 .extern	OPENSSL_ia32cap_P
 .hidden OPENSSL_ia32cap_P
diff --git a/linux-x86_64/crypto/rand/rdrand-x86_64.S b/linux-x86_64/crypto/rand/rdrand-x86_64.S
index 94aab9c..7c1eeb7 100644
--- a/linux-x86_64/crypto/rand/rdrand-x86_64.S
+++ b/linux-x86_64/crypto/rand/rdrand-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/linux-x86_64/crypto/sha/sha1-x86_64.S b/linux-x86_64/crypto/sha/sha1-x86_64.S
index 567bdfd..350d7d6 100644
--- a/linux-x86_64/crypto/sha/sha1-x86_64.S
+++ b/linux-x86_64/crypto/sha/sha1-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 .extern	OPENSSL_ia32cap_P
 .hidden OPENSSL_ia32cap_P
diff --git a/linux-x86_64/crypto/sha/sha256-x86_64.S b/linux-x86_64/crypto/sha/sha256-x86_64.S
index 273b7a5..62534be 100644
--- a/linux-x86_64/crypto/sha/sha256-x86_64.S
+++ b/linux-x86_64/crypto/sha/sha256-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .extern	OPENSSL_ia32cap_P
diff --git a/linux-x86_64/crypto/sha/sha512-x86_64.S b/linux-x86_64/crypto/sha/sha512-x86_64.S
index f272b64..1f1793b 100644
--- a/linux-x86_64/crypto/sha/sha512-x86_64.S
+++ b/linux-x86_64/crypto/sha/sha512-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .extern	OPENSSL_ia32cap_P
diff --git a/mac-x86_64/crypto/aes/aes-x86_64.S b/mac-x86_64/crypto/aes/aes-x86_64.S
index 52df2ae..d60757b 100644
--- a/mac-x86_64/crypto/aes/aes-x86_64.S
+++ b/mac-x86_64/crypto/aes/aes-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .p2align	4
diff --git a/mac-x86_64/crypto/aes/aesni-x86_64.S b/mac-x86_64/crypto/aes/aesni-x86_64.S
index 4e3b7d0..fd62bc8 100644
--- a/mac-x86_64/crypto/aes/aesni-x86_64.S
+++ b/mac-x86_64/crypto/aes/aesni-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .globl	_aesni_encrypt
diff --git a/mac-x86_64/crypto/aes/bsaes-x86_64.S b/mac-x86_64/crypto/aes/bsaes-x86_64.S
index 6e679c1..195abd3 100644
--- a/mac-x86_64/crypto/aes/bsaes-x86_64.S
+++ b/mac-x86_64/crypto/aes/bsaes-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/aes/vpaes-x86_64.S b/mac-x86_64/crypto/aes/vpaes-x86_64.S
index 997cde8..867df68 100644
--- a/mac-x86_64/crypto/aes/vpaes-x86_64.S
+++ b/mac-x86_64/crypto/aes/vpaes-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/bn/rsaz-avx2.S b/mac-x86_64/crypto/bn/rsaz-avx2.S
index a913507..d25a2e0 100644
--- a/mac-x86_64/crypto/bn/rsaz-avx2.S
+++ b/mac-x86_64/crypto/bn/rsaz-avx2.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 .globl	_rsaz_1024_sqr_avx2
diff --git a/mac-x86_64/crypto/bn/x86_64-mont.S b/mac-x86_64/crypto/bn/x86_64-mont.S
index 41a0926..be3d13a 100644
--- a/mac-x86_64/crypto/bn/x86_64-mont.S
+++ b/mac-x86_64/crypto/bn/x86_64-mont.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/bn/x86_64-mont5.S b/mac-x86_64/crypto/bn/x86_64-mont5.S
index 24b56de..91980d8 100644
--- a/mac-x86_64/crypto/bn/x86_64-mont5.S
+++ b/mac-x86_64/crypto/bn/x86_64-mont5.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/chacha/chacha-x86_64.S b/mac-x86_64/crypto/chacha/chacha-x86_64.S
index 51c0caa..30edc7b 100644
--- a/mac-x86_64/crypto/chacha/chacha-x86_64.S
+++ b/mac-x86_64/crypto/chacha/chacha-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S b/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
index 62d114d..9db2a58 100644
--- a/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
+++ b/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/ec/p256-x86_64-asm.S b/mac-x86_64/crypto/ec/p256-x86_64-asm.S
index aa434bf..2c58d48 100644
--- a/mac-x86_64/crypto/ec/p256-x86_64-asm.S
+++ b/mac-x86_64/crypto/ec/p256-x86_64-asm.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/md5/md5-x86_64.S b/mac-x86_64/crypto/md5/md5-x86_64.S
index 16fd2cc..776c116 100644
--- a/mac-x86_64/crypto/md5/md5-x86_64.S
+++ b/mac-x86_64/crypto/md5/md5-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 .p2align	4
 
diff --git a/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S b/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S
index 901bb96..f185d0c 100644
--- a/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S
+++ b/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/modes/ghash-x86_64.S b/mac-x86_64/crypto/modes/ghash-x86_64.S
index 814d796..4c98a93 100644
--- a/mac-x86_64/crypto/modes/ghash-x86_64.S
+++ b/mac-x86_64/crypto/modes/ghash-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/rand/rdrand-x86_64.S b/mac-x86_64/crypto/rand/rdrand-x86_64.S
index f0df296..b259286 100644
--- a/mac-x86_64/crypto/rand/rdrand-x86_64.S
+++ b/mac-x86_64/crypto/rand/rdrand-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/sha/sha1-x86_64.S b/mac-x86_64/crypto/sha/sha1-x86_64.S
index cf45d8a..ee70a4b 100644
--- a/mac-x86_64/crypto/sha/sha1-x86_64.S
+++ b/mac-x86_64/crypto/sha/sha1-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/sha/sha256-x86_64.S b/mac-x86_64/crypto/sha/sha256-x86_64.S
index f00ef6d..ac6559e 100644
--- a/mac-x86_64/crypto/sha/sha256-x86_64.S
+++ b/mac-x86_64/crypto/sha/sha256-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/mac-x86_64/crypto/sha/sha512-x86_64.S b/mac-x86_64/crypto/sha/sha512-x86_64.S
index eabcb3a..0b738e6 100644
--- a/mac-x86_64/crypto/sha/sha512-x86_64.S
+++ b/mac-x86_64/crypto/sha/sha512-x86_64.S
@@ -1,4 +1,4 @@
-#if defined(__x86_64__)
+#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)
 .text	
 
 
diff --git a/src/FUZZING.md b/src/FUZZING.md
index 70660ab..abf5d97 100644
--- a/src/FUZZING.md
+++ b/src/FUZZING.md
@@ -80,5 +80,5 @@
 
 ```
 cd fuzz
-./refresh_fuzzer_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
+./refresh_ssl_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
 ```
diff --git a/src/crypto/aes/asm/bsaes-armv7.pl b/src/crypto/aes/asm/bsaes-armv7.pl
index d645de4..92f5ece 100644
--- a/src/crypto/aes/asm/bsaes-armv7.pl
+++ b/src/crypto/aes/asm/bsaes-armv7.pl
@@ -1,4 +1,11 @@
-#!/usr/bin/env perl
+#! /usr/bin/env perl
+# Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
 
 # ====================================================================
 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -731,6 +738,7 @@
 .thumb
 #else
 .code   32
+# undef __thumb2__
 #endif
 
 .type	_bsaes_decrypt8,%function
@@ -1357,7 +1365,7 @@
 	vmov	@XMM[4],@XMM[15]		@ just in case ensure that IV
 	vmov	@XMM[5],@XMM[0]			@ and input are preserved
 	bl	AES_decrypt
-	vld1.8	{@XMM[0]}, [$fp,:64]		@ load result
+	vld1.8	{@XMM[0]}, [$fp]		@ load result
 	veor	@XMM[0], @XMM[0], @XMM[4]	@ ^= IV
 	vmov	@XMM[15], @XMM[5]		@ @XMM[5] holds input
 	vst1.8	{@XMM[0]}, [$rounds]		@ write output
diff --git a/src/crypto/cipher/e_tls.c b/src/crypto/cipher/e_tls.c
index 7d9bbee..41b7470 100644
--- a/src/crypto/cipher/e_tls.c
+++ b/src/crypto/cipher/e_tls.c
@@ -262,24 +262,24 @@
 
   /* Remove CBC padding. Code from here on is timing-sensitive with respect to
    * |padding_ok| and |data_plus_mac_len| for CBC ciphers. */
-  unsigned padding_ok, data_plus_mac_len;
+  size_t padding_ok, data_plus_mac_len;
   if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
     if (!EVP_tls_cbc_remove_padding(
             &padding_ok, &data_plus_mac_len, out, total,
             EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx),
-            (unsigned)HMAC_size(&tls_ctx->hmac_ctx))) {
+            HMAC_size(&tls_ctx->hmac_ctx))) {
       /* Publicly invalid. This can be rejected in non-constant time. */
       OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
       return 0;
     }
   } else {
-    padding_ok = ~0u;
+    padding_ok = CONSTTIME_TRUE_S;
     data_plus_mac_len = total;
     /* |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has
      * already been checked against the MAC size at the top of the function. */
     assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx));
   }
-  unsigned data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
+  size_t data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
 
   /* At this point, if the padding is valid, the first |data_plus_mac_len| bytes
    * after |out| are the plaintext and MAC. Otherwise, |data_plus_mac_len| is
@@ -332,8 +332,8 @@
    * safe to simply perform the padding check first, but it would not be under a
    * different choice of MAC location on padding failure. See
    * EVP_tls_cbc_remove_padding. */
-  unsigned good = constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len),
-                                       0);
+  size_t good =
+      constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len), 0);
   good &= padding_ok;
   if (!good) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
diff --git a/src/crypto/cipher/internal.h b/src/crypto/cipher/internal.h
index d29ce59..b9f88f2 100644
--- a/src/crypto/cipher/internal.h
+++ b/src/crypto/cipher/internal.h
@@ -110,9 +110,9 @@
  * If the function returns one, it runs in time independent of the contents of
  * |in|. It is also guaranteed that |*out_len| >= |mac_size|, satisfying
  * |EVP_tls_cbc_copy_mac|'s precondition. */
-int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
-                               const uint8_t *in, unsigned in_len,
-                               unsigned block_size, unsigned mac_size);
+int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
+                               const uint8_t *in, size_t in_len,
+                               size_t block_size, size_t mac_size);
 
 /* EVP_tls_cbc_copy_mac copies |md_size| bytes from the end of the first
  * |in_len| bytes of |in| to |out| in constant time (independent of the concrete
@@ -122,9 +122,8 @@
  * On entry:
  *   orig_len >= in_len >= md_size
  *   md_size <= EVP_MAX_MD_SIZE */
-void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
-                          const uint8_t *in, unsigned in_len,
-                          unsigned orig_len);
+void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
+                          size_t in_len, size_t orig_len);
 
 /* EVP_tls_cbc_record_digest_supported returns 1 iff |md| is a hash function
  * which EVP_tls_cbc_digest_record supports. */
diff --git a/src/crypto/cipher/tls_cbc.c b/src/crypto/cipher/tls_cbc.c
index 52880b0..a825c1c 100644
--- a/src/crypto/cipher/tls_cbc.c
+++ b/src/crypto/cipher/tls_cbc.c
@@ -73,20 +73,19 @@
  * supported by TLS.) */
 #define MAX_HASH_BLOCK_SIZE 128
 
-int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
-                               const uint8_t *in, unsigned in_len,
-                               unsigned block_size, unsigned mac_size) {
-  unsigned padding_length, good, to_check, i;
-  const unsigned overhead = 1 /* padding length byte */ + mac_size;
+int EVP_tls_cbc_remove_padding(size_t *out_padding_ok, size_t *out_len,
+                               const uint8_t *in, size_t in_len,
+                               size_t block_size, size_t mac_size) {
+  const size_t overhead = 1 /* padding length byte */ + mac_size;
 
   /* These lengths are all public so we can test them in non-constant time. */
   if (overhead > in_len) {
     return 0;
   }
 
-  padding_length = in[in_len - 1];
+  size_t padding_length = in[in_len - 1];
 
-  good = constant_time_ge(in_len, overhead + padding_length);
+  size_t good = constant_time_ge_s(in_len, overhead + padding_length);
   /* The padding consists of a length byte at the end of the record and
    * then that many bytes of padding, all with the same value as the
    * length byte. Thus, with the length byte included, there are i+1
@@ -96,12 +95,12 @@
    * decrypted information. Therefore we always have to check the maximum
    * amount of padding possible. (Again, the length of the record is
    * public information so we can use it.) */
-  to_check = 256; /* maximum amount of padding, inc length byte. */
+  size_t to_check = 256; /* maximum amount of padding, inc length byte. */
   if (to_check > in_len) {
     to_check = in_len;
   }
 
-  for (i = 0; i < to_check; i++) {
+  for (size_t i = 0; i < to_check; i++) {
     uint8_t mask = constant_time_ge_8(padding_length, i);
     uint8_t b = in[in_len - 1 - i];
     /* The final |padding_length+1| bytes should all have the value
@@ -111,7 +110,7 @@
 
   /* If any of the final |padding_length+1| bytes had the wrong value,
    * one or more of the lower eight bits of |good| will be cleared. */
-  good = constant_time_eq(0xff, good & 0xff);
+  good = constant_time_eq_s(0xff, good & 0xff);
 
   /* Always treat |padding_length| as zero on error. If, assuming block size of
    * 16, a padding of [<15 arbitrary bytes> 15] treated |padding_length| as 16
@@ -123,16 +122,15 @@
   return 1;
 }
 
-void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
-                          const uint8_t *in, unsigned in_len,
-                          unsigned orig_len) {
+void EVP_tls_cbc_copy_mac(uint8_t *out, size_t md_size, const uint8_t *in,
+                          size_t in_len, size_t orig_len) {
   uint8_t rotated_mac1[EVP_MAX_MD_SIZE], rotated_mac2[EVP_MAX_MD_SIZE];
   uint8_t *rotated_mac = rotated_mac1;
   uint8_t *rotated_mac_tmp = rotated_mac2;
 
   /* mac_end is the index of |in| just after the end of the MAC. */
-  unsigned mac_end = in_len;
-  unsigned mac_start = mac_end - md_size;
+  size_t mac_end = in_len;
+  size_t mac_start = mac_end - md_size;
 
   assert(orig_len >= in_len);
   assert(in_len >= md_size);
@@ -140,20 +138,20 @@
 
   /* scan_start contains the number of bytes that we can ignore because
    * the MAC's position can only vary by 255 bytes. */
-  unsigned scan_start = 0;
+  size_t scan_start = 0;
   /* This information is public so it's safe to branch based on it. */
   if (orig_len > md_size + 255 + 1) {
     scan_start = orig_len - (md_size + 255 + 1);
   }
 
-  unsigned rotate_offset = 0;
+  size_t rotate_offset = 0;
   uint8_t mac_started = 0;
   OPENSSL_memset(rotated_mac, 0, md_size);
-  for (unsigned i = scan_start, j = 0; i < orig_len; i++, j++) {
+  for (size_t i = scan_start, j = 0; i < orig_len; i++, j++) {
     if (j >= md_size) {
       j -= md_size;
     }
-    unsigned is_mac_start = constant_time_eq(i, mac_start);
+    size_t is_mac_start = constant_time_eq_s(i, mac_start);
     mac_started |= is_mac_start;
     uint8_t mac_ended = constant_time_ge_8(i, mac_end);
     rotated_mac[j] |= in[i] & mac_started & ~mac_ended;
@@ -163,12 +161,11 @@
 
   /* Now rotate the MAC. We rotate in log(md_size) steps, one for each bit
    * position. */
-  for (unsigned offset = 1; offset < md_size;
-       offset <<= 1, rotate_offset >>= 1) {
+  for (size_t offset = 1; offset < md_size; offset <<= 1, rotate_offset >>= 1) {
     /* Rotate by |offset| iff the corresponding bit is set in
      * |rotate_offset|, placing the result in |rotated_mac_tmp|. */
     const uint8_t skip_rotate = (rotate_offset & 1) - 1;
-    for (unsigned i = 0, j = offset; i < md_size; i++, j++) {
+    for (size_t i = 0, j = offset; i < md_size; i++, j++) {
       if (j >= md_size) {
         j -= md_size;
       }
@@ -211,40 +208,49 @@
     *((p)++) = (uint8_t)((n));       \
   } while (0)
 
+typedef union {
+  SHA_CTX sha1;
+  SHA256_CTX sha256;
+  SHA512_CTX sha512;
+} HASH_CTX;
+
+static void tls1_sha1_transform(HASH_CTX *ctx, const uint8_t *block) {
+  SHA1_Transform(&ctx->sha1, block);
+}
+
+static void tls1_sha256_transform(HASH_CTX *ctx, const uint8_t *block) {
+  SHA256_Transform(&ctx->sha256, block);
+}
+
+static void tls1_sha512_transform(HASH_CTX *ctx, const uint8_t *block) {
+  SHA512_Transform(&ctx->sha512, block);
+}
+
 /* These functions serialize the state of a hash and thus perform the standard
  * "final" operation without adding the padding and length that such a function
  * typically does. */
-static void tls1_sha1_final_raw(void *ctx, uint8_t *md_out) {
-  SHA_CTX *sha1 = ctx;
+static void tls1_sha1_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
+  SHA_CTX *sha1 = &ctx->sha1;
   u32toBE(sha1->h[0], md_out);
   u32toBE(sha1->h[1], md_out);
   u32toBE(sha1->h[2], md_out);
   u32toBE(sha1->h[3], md_out);
   u32toBE(sha1->h[4], md_out);
 }
-#define LARGEST_DIGEST_CTX SHA_CTX
 
-static void tls1_sha256_final_raw(void *ctx, uint8_t *md_out) {
-  SHA256_CTX *sha256 = ctx;
-  unsigned i;
-
-  for (i = 0; i < 8; i++) {
+static void tls1_sha256_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
+  SHA256_CTX *sha256 = &ctx->sha256;
+  for (unsigned i = 0; i < 8; i++) {
     u32toBE(sha256->h[i], md_out);
   }
 }
-#undef  LARGEST_DIGEST_CTX
-#define LARGEST_DIGEST_CTX SHA256_CTX
 
-static void tls1_sha512_final_raw(void *ctx, uint8_t *md_out) {
-  SHA512_CTX *sha512 = ctx;
-  unsigned i;
-
-  for (i = 0; i < 8; i++) {
+static void tls1_sha512_final_raw(HASH_CTX *ctx, uint8_t *md_out) {
+  SHA512_CTX *sha512 = &ctx->sha512;
+  for (unsigned i = 0; i < 8; i++) {
     u64toBE(sha512->h[i], md_out);
   }
 }
-#undef  LARGEST_DIGEST_CTX
-#define LARGEST_DIGEST_CTX SHA512_CTX
 
 int EVP_tls_cbc_record_digest_supported(const EVP_MD *md) {
   switch (EVP_MD_type(md)) {
@@ -264,54 +270,42 @@
                               size_t data_plus_mac_plus_padding_size,
                               const uint8_t *mac_secret,
                               unsigned mac_secret_length) {
-  union {
-    double align;
-    uint8_t c[sizeof(LARGEST_DIGEST_CTX)];
-  } md_state;
-  void (*md_final_raw)(void *ctx, uint8_t *md_out);
-  void (*md_transform)(void *ctx, const uint8_t *block);
+  HASH_CTX md_state;
+  void (*md_final_raw)(HASH_CTX *ctx, uint8_t *md_out);
+  void (*md_transform)(HASH_CTX *ctx, const uint8_t *block);
   unsigned md_size, md_block_size = 64;
-  unsigned len, max_mac_bytes, num_blocks, num_starting_blocks, k,
-           mac_end_offset, c, index_a, index_b;
-  unsigned int bits; /* at most 18 bits */
-  uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
-  /* hmac_pad is the masked HMAC key. */
-  uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
-  uint8_t first_block[MAX_HASH_BLOCK_SIZE];
-  uint8_t mac_out[EVP_MAX_MD_SIZE];
-  unsigned i, j, md_out_size_u;
-  EVP_MD_CTX md_ctx;
-  /* mdLengthSize is the number of bytes in the length field that terminates
-  * the hash. */
+  /* md_length_size is the number of bytes in the length field that terminates
+   * the hash. */
   unsigned md_length_size = 8;
 
-  /* This is a, hopefully redundant, check that allows us to forget about
-   * many possible overflows later in this function. */
-  assert(data_plus_mac_plus_padding_size < 1024 * 1024);
+  /* Bound the acceptable input so we can forget about many possible overflows
+   * later in this function. This is redundant with the record size limits in
+   * TLS. */
+  if (data_plus_mac_plus_padding_size >= 1024 * 1024) {
+    assert(0);
+    return 0;
+  }
 
   switch (EVP_MD_type(md)) {
     case NID_sha1:
-      SHA1_Init((SHA_CTX *)md_state.c);
+      SHA1_Init(&md_state.sha1);
       md_final_raw = tls1_sha1_final_raw;
-      md_transform =
-          (void (*)(void *ctx, const uint8_t *block))SHA1_Transform;
-      md_size = 20;
+      md_transform = tls1_sha1_transform;
+      md_size = SHA_DIGEST_LENGTH;
       break;
 
     case NID_sha256:
-      SHA256_Init((SHA256_CTX *)md_state.c);
+      SHA256_Init(&md_state.sha256);
       md_final_raw = tls1_sha256_final_raw;
-      md_transform =
-          (void (*)(void *ctx, const uint8_t *block))SHA256_Transform;
-      md_size = 32;
+      md_transform = tls1_sha256_transform;
+      md_size = SHA256_DIGEST_LENGTH;
       break;
 
     case NID_sha384:
-      SHA384_Init((SHA512_CTX *)md_state.c);
+      SHA384_Init(&md_state.sha512);
       md_final_raw = tls1_sha512_final_raw;
-      md_transform =
-          (void (*)(void *ctx, const uint8_t *block))SHA512_Transform;
-      md_size = 384 / 8;
+      md_transform = tls1_sha512_transform;
+      md_size = SHA384_DIGEST_LENGTH;
       md_block_size = 128;
       md_length_size = 16;
       break;
@@ -328,7 +322,7 @@
   assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
   assert(md_size <= EVP_MAX_MD_SIZE);
 
-  static const unsigned kHeaderLength = 13;
+  static const size_t kHeaderLength = 13;
 
   /* kVarianceBlocks is the number of blocks of the hash that we have to
    * calculate in constant time because they could be altered by the
@@ -337,16 +331,16 @@
    * TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
    * required to be minimal. Therefore we say that the final six blocks
    * can vary based on the padding. */
-  static const unsigned kVarianceBlocks = 6;
+  static const size_t kVarianceBlocks = 6;
 
   /* From now on we're dealing with the MAC, which conceptually has 13
    * bytes of `header' before the start of the data. */
-  len = data_plus_mac_plus_padding_size + kHeaderLength;
+  size_t len = data_plus_mac_plus_padding_size + kHeaderLength;
   /* max_mac_bytes contains the maximum bytes of bytes in the MAC, including
-  * |header|, assuming that there's no padding. */
-  max_mac_bytes = len - md_size - 1;
+   * |header|, assuming that there's no padding. */
+  size_t max_mac_bytes = len - md_size - 1;
   /* num_blocks is the maximum number of hash blocks. */
-  num_blocks =
+  size_t num_blocks =
       (max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
   /* In order to calculate the MAC in constant time we have to handle
    * the final blocks specially because the padding value could cause the
@@ -354,43 +348,47 @@
    * can't leak where. However, |num_starting_blocks| worth of data can
    * be hashed right away because no padding value can affect whether
    * they are plaintext. */
-  num_starting_blocks = 0;
+  size_t num_starting_blocks = 0;
   /* k is the starting byte offset into the conceptual header||data where
    * we start processing. */
-  k = 0;
+  size_t k = 0;
   /* mac_end_offset is the index just past the end of the data to be
    * MACed. */
-  mac_end_offset = data_plus_mac_size + kHeaderLength - md_size;
+  size_t mac_end_offset = data_plus_mac_size + kHeaderLength - md_size;
   /* c is the index of the 0x80 byte in the final hash block that
    * contains application data. */
-  c = mac_end_offset % md_block_size;
+  size_t c = mac_end_offset % md_block_size;
   /* index_a is the hash block number that contains the 0x80 terminating
    * value. */
-  index_a = mac_end_offset / md_block_size;
+  size_t index_a = mac_end_offset / md_block_size;
   /* index_b is the hash block number that contains the 64-bit hash
    * length, in bits. */
-  index_b = (mac_end_offset + md_length_size) / md_block_size;
-  /* bits is the hash-length in bits. It includes the additional hash
-   * block for the masked HMAC key. */
+  size_t index_b = (mac_end_offset + md_length_size) / md_block_size;
 
   if (num_blocks > kVarianceBlocks) {
     num_starting_blocks = num_blocks - kVarianceBlocks;
     k = md_block_size * num_starting_blocks;
   }
 
-  bits = 8 * mac_end_offset;
+  /* bits is the hash-length in bits. It includes the additional hash
+   * block for the masked HMAC key. */
+  size_t bits = 8 * mac_end_offset; /* at most 18 bits to represent */
 
   /* Compute the initial HMAC block. */
   bits += 8 * md_block_size;
+  /* hmac_pad is the masked HMAC key. */
+  uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
   OPENSSL_memset(hmac_pad, 0, md_block_size);
   assert(mac_secret_length <= sizeof(hmac_pad));
   OPENSSL_memcpy(hmac_pad, mac_secret, mac_secret_length);
-  for (i = 0; i < md_block_size; i++) {
+  for (size_t i = 0; i < md_block_size; i++) {
     hmac_pad[i] ^= 0x36;
   }
 
-  md_transform(md_state.c, hmac_pad);
+  md_transform(&md_state, hmac_pad);
 
+  /* The length check means |bits| fits in four bytes. */
+  uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
   OPENSSL_memset(length_bytes, 0, md_length_size - 4);
   length_bytes[md_length_size - 4] = (uint8_t)(bits >> 24);
   length_bytes[md_length_size - 3] = (uint8_t)(bits >> 16);
@@ -399,27 +397,29 @@
 
   if (k > 0) {
     /* k is a multiple of md_block_size. */
+    uint8_t first_block[MAX_HASH_BLOCK_SIZE];
     OPENSSL_memcpy(first_block, header, 13);
     OPENSSL_memcpy(first_block + 13, data, md_block_size - 13);
-    md_transform(md_state.c, first_block);
-    for (i = 1; i < k / md_block_size; i++) {
-      md_transform(md_state.c, data + md_block_size * i - 13);
+    md_transform(&md_state, first_block);
+    for (size_t i = 1; i < k / md_block_size; i++) {
+      md_transform(&md_state, data + md_block_size * i - 13);
     }
   }
 
+  uint8_t mac_out[EVP_MAX_MD_SIZE];
   OPENSSL_memset(mac_out, 0, sizeof(mac_out));
 
   /* We now process the final hash blocks. For each block, we construct
    * it in constant time. If the |i==index_a| then we'll include the 0x80
    * bytes and zero pad etc. For each block we selectively copy it, in
    * constant time, to |mac_out|. */
-  for (i = num_starting_blocks; i <= num_starting_blocks + kVarianceBlocks;
-       i++) {
+  for (size_t i = num_starting_blocks;
+       i <= num_starting_blocks + kVarianceBlocks; i++) {
     uint8_t block[MAX_HASH_BLOCK_SIZE];
     uint8_t is_block_a = constant_time_eq_8(i, index_a);
     uint8_t is_block_b = constant_time_eq_8(i, index_b);
-    for (j = 0; j < md_block_size; j++) {
-      uint8_t b = 0, is_past_c, is_past_cp1;
+    for (size_t j = 0; j < md_block_size; j++) {
+      uint8_t b = 0;
       if (k < kHeaderLength) {
         b = header[k];
       } else if (k < data_plus_mac_plus_padding_size + kHeaderLength) {
@@ -427,8 +427,8 @@
       }
       k++;
 
-      is_past_c = is_block_a & constant_time_ge_8(j, c);
-      is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
+      uint8_t is_past_c = is_block_a & constant_time_ge_8(j, c);
+      uint8_t is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
       /* If this is the block containing the end of the
        * application data, and we are at the offset for the
        * 0x80 value, then overwrite b with 0x80. */
@@ -453,14 +453,15 @@
       block[j] = b;
     }
 
-    md_transform(md_state.c, block);
-    md_final_raw(md_state.c, block);
+    md_transform(&md_state, block);
+    md_final_raw(&md_state, block);
     /* If this is index_b, copy the hash value to |mac_out|. */
-    for (j = 0; j < md_size; j++) {
+    for (size_t j = 0; j < md_size; j++) {
       mac_out[j] |= block[j] & is_block_b;
     }
   }
 
+  EVP_MD_CTX md_ctx;
   EVP_MD_CTX_init(&md_ctx);
   if (!EVP_DigestInit_ex(&md_ctx, md, NULL /* engine */)) {
     EVP_MD_CTX_cleanup(&md_ctx);
@@ -468,12 +469,13 @@
   }
 
   /* Complete the HMAC in the standard manner. */
-  for (i = 0; i < md_block_size; i++) {
+  for (size_t i = 0; i < md_block_size; i++) {
     hmac_pad[i] ^= 0x6a;
   }
 
   EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
   EVP_DigestUpdate(&md_ctx, mac_out, md_size);
+  unsigned md_out_size_u;
   EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
   *md_out_size = md_out_size_u;
   EVP_MD_CTX_cleanup(&md_ctx);
diff --git a/src/crypto/constant_time_test.cc b/src/crypto/constant_time_test.cc
index adfe272..0ad7192 100644
--- a/src/crypto/constant_time_test.cc
+++ b/src/crypto/constant_time_test.cc
@@ -49,62 +49,66 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <limits>
+
 #include <gtest/gtest.h>
 
 
-static const unsigned CONSTTIME_TRUE = (unsigned)(~0);
-static const unsigned CONSTTIME_FALSE = 0;
-static const uint8_t CONSTTIME_TRUE_8 = 0xff;
-static const uint8_t CONSTTIME_FALSE_8 = 0;
-
-static unsigned FromBool(bool b) {
-  return b ? CONSTTIME_TRUE : CONSTTIME_FALSE;
-}
-
 static uint8_t FromBool8(bool b) {
   return b ? CONSTTIME_TRUE_8 : CONSTTIME_FALSE_8;
 }
 
-static unsigned test_values[] = {
+static size_t FromBoolS(bool b) {
+  return b ? CONSTTIME_TRUE_S : CONSTTIME_FALSE_S;
+}
+
+static const uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
+
+static size_t test_values_s[] = {
     0,
     1,
     1024,
     12345,
     32000,
-    UINT_MAX / 2 - 1,
-    UINT_MAX / 2,
-    UINT_MAX / 2 + 1,
-    UINT_MAX - 1,
-    UINT_MAX,
+#if defined(OPENSSL_64_BIT)
+    0xffffffff / 2 - 1,
+    0xffffffff / 2,
+    0xffffffff / 2 + 1,
+    0xffffffff - 1,
+    0xffffffff,
+#endif
+    std::numeric_limits<size_t>::max() / 2 - 1,
+    std::numeric_limits<size_t>::max() / 2,
+    std::numeric_limits<size_t>::max() / 2 + 1,
+    std::numeric_limits<size_t>::max() - 1,
+    std::numeric_limits<size_t>::max(),
 };
 
-static uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
-
 static int signed_test_values[] = {
     0,     1,      -1,      1024,    -1024,       12345,      -12345,
     32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1};
 
 TEST(ConstantTimeTest, Test) {
-  for (unsigned a : test_values) {
+  for (size_t a : test_values_s) {
     SCOPED_TRACE(a);
 
-    EXPECT_EQ(FromBool(a == 0), constant_time_is_zero(a));
+    EXPECT_EQ(FromBoolS(a == 0), constant_time_is_zero_s(a));
     EXPECT_EQ(FromBool8(a == 0), constant_time_is_zero_8(a));
 
-    for (unsigned b : test_values) {
+    for (size_t b : test_values_s) {
       SCOPED_TRACE(b);
 
-      EXPECT_EQ(FromBool(a < b), constant_time_lt(a, b));
+      EXPECT_EQ(FromBoolS(a < b), constant_time_lt_s(a, b));
       EXPECT_EQ(FromBool8(a < b), constant_time_lt_8(a, b));
 
-      EXPECT_EQ(FromBool(a >= b), constant_time_ge(a, b));
+      EXPECT_EQ(FromBoolS(a >= b), constant_time_ge_s(a, b));
       EXPECT_EQ(FromBool8(a >= b), constant_time_ge_8(a, b));
 
-      EXPECT_EQ(FromBool(a == b), constant_time_eq(a, b));
+      EXPECT_EQ(FromBoolS(a == b), constant_time_eq_s(a, b));
       EXPECT_EQ(FromBool8(a == b), constant_time_eq_8(a, b));
 
-      EXPECT_EQ(a, constant_time_select(CONSTTIME_TRUE, a, b));
-      EXPECT_EQ(b, constant_time_select(CONSTTIME_FALSE, a, b));
+      EXPECT_EQ(a, constant_time_select_s(CONSTTIME_TRUE_S, a, b));
+      EXPECT_EQ(b, constant_time_select_s(CONSTTIME_FALSE_S, a, b));
     }
   }
 
@@ -113,10 +117,10 @@
     for (int b : signed_test_values) {
       SCOPED_TRACE(b);
 
-      EXPECT_EQ(a, constant_time_select_int(CONSTTIME_TRUE, a, b));
-      EXPECT_EQ(b, constant_time_select_int(CONSTTIME_FALSE, a, b));
+      EXPECT_EQ(a, constant_time_select_int(CONSTTIME_TRUE_S, a, b));
+      EXPECT_EQ(b, constant_time_select_int(CONSTTIME_FALSE_S, a, b));
 
-      EXPECT_EQ(FromBool(a == b), constant_time_eq_int(a, b));
+      EXPECT_EQ(FromBoolS(a == b), constant_time_eq_int(a, b));
       EXPECT_EQ(FromBool8(a == b), constant_time_eq_int_8(a, b));
     }
   }
diff --git a/src/crypto/curve25519/ed25519_tests.txt b/src/crypto/curve25519/ed25519_tests.txt
index 4d43417..2e185a7e3 100644
--- a/src/crypto/curve25519/ed25519_tests.txt
+++ b/src/crypto/curve25519/ed25519_tests.txt
@@ -2575,3 +2575,16 @@
 PUB: c94576641f4a893cdfcee7b39fc21929b86b349976d7b0a46d39a588bcfe4357
 MESSAGE: db8ef02e3033e6b96a56cab05082fb4695f4a1c916250dd75173f430a10c9468817709d37623346ae8245b42bda0da6b60462ccfdfc75a9ab994e66c9ab9fecdd8599610910affe4f10215cb280bf8f9f2700a444796dae93e06c6bea7d8b4fe1301baa79ccec769368feb2442c7de84f095e6b3bff63d388cbafb2b9809dc38e9b12ebd039c0a57f4d522e91ec8d1f2b8d23a4a0ae059af85393bb0a15f749110f6774a1fd731a6ec213e4ff435daab546d31ed9ec3b6d8cc2edacebf4facc5566556eea92e5b3f2542239b25e28012dd4ef40072eebf83ed2a255181f3a442189d68c6c609f4dfdf3db7d67d087a2fcd6d2dc50bbfed8bfbbfcb74d3c41f02a87865b13b8efcf5c3581257be0aa913f60c370527bde11a475c136a17c5eefeb03f5bff28693ed841e8ed1f7c29102f5599dd444009bcea6a92d5574152458e0caf8a36aa72b5dc4908a6461c9b741453005c8fbcc68113ae184208ee14b835480c6efafed18a76000b38e5858290f4d51f52f096cbe490e1eb5cacb226ec495a55a7fa457843d57fab67f8be7e209334785bdd665d7b63e4daf57b6e78928b603c8c0f9bc85464733b61273ef9e2b8a0cd7c3bf8ee0a6872e34d5a27a625e35eaf7ff5440b8b141af704df70c9c18623bd11209513192505105cd7bcfa5f0d919da706948fbe1f761f315846aa3b4813dd9ba3d81b9204e5409c0382b6eb
 SIG: 0f80ff5d17488fe26f93c543b04ed959b5f0643fc61c7f2c3bc60132ba9c6210c8b250ea5e84d07b01de68bc174414eeeb31fdc2ba6823e231e312a91ededd02
+
+
+# Additional test vectors from RFC 8032
+
+PRIV: f5e5767cf153319517630f226876b86c8160cc583bc013744c6bf255f5cc0ee5278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e
+PUB: 278117fc144c72340f67d0f2316e8386ceffbf2b2428c9c51fef7c597f1d426e
+MESSAGE: 08b8b2b733424243760fe426a4b54908632110a66c2f6591eabd3345e3e4eb98fa6e264bf09efe12ee50f8f54e9f77b1e355f6c50544e23fb1433ddf73be84d879de7c0046dc4996d9e773f4bc9efe5738829adb26c81b37c93a1b270b20329d658675fc6ea534e0810a4432826bf58c941efb65d57a338bbd2e26640f89ffbc1a858efcb8550ee3a5e1998bd177e93a7363c344fe6b199ee5d02e82d522c4feba15452f80288a821a579116ec6dad2b3b310da903401aa62100ab5d1a36553e06203b33890cc9b832f79ef80560ccb9a39ce767967ed628c6ad573cb116dbefefd75499da96bd68a8a97b928a8bbc103b6621fcde2beca1231d206be6cd9ec7aff6f6c94fcd7204ed3455c68c83f4a41da4af2b74ef5c53f1d8ac70bdcb7ed185ce81bd84359d44254d95629e9855a94a7c1958d1f8ada5d0532ed8a5aa3fb2d17ba70eb6248e594e1a2297acbbb39d502f1a8c6eb6f1ce22b3de1a1f40cc24554119a831a9aad6079cad88425de6bde1a9187ebb6092cf67bf2b13fd65f27088d78b7e883c8759d2c4f5c65adb7553878ad575f9fad878e80a0c9ba63bcbcc2732e69485bbc9c90bfbd62481d9089beccf80cfe2df16a2cf65bd92dd597b0707e0917af48bbb75fed413d238f5555a7a569d80c3414a8d0859dc65a46128bab27af87a71314f318c782b23ebfe808b82b0ce26401d2e22f04d83d1255dc51addd3b75a2b1ae0784504df543af8969be3ea7082ff7fc9888c144da2af58429ec96031dbcad3dad9af0dcbaaaf268cb8fcffead94f3c7ca495e056a9b47acdb751fb73e666c6c655ade8297297d07ad1ba5e43f1bca32301651339e22904cc8c42f58c30c04aafdb038dda0847dd988dcda6f3bfd15c4b4c4525004aa06eeff8ca61783aacec57fb3d1f92b0fe2fd1a85f6724517b65e614ad6808d6f6ee34dff7310fdc82aebfd904b01e1dc54b2927094b2db68d6f903b68401adebf5a7e08d78ff4ef5d63653a65040cf9bfd4aca7984a74d37145986780fc0b16ac451649de6188a7dbdf191f64b5fc5e2ab47b57f7f7276cd419c17a3ca8e1b939ae49e488acba6b965610b5480109c8b17b80e1b7b750dfc7598d5d5011fd2dcc5600a32ef5b52a1ecc820e308aa342721aac0943bf6686b64b2579376504ccc493d97e6aed3fb0f9cd71a43dd497f01f17c0e2cb3797aa2a2f256656168e6c496afc5fb93246f6b1116398a346f1a641f3b041e989f7914f90cc2c7fff357876e506b50d334ba77c225bc307ba537152f3f1610e4eafe595f6d9d90d11faa933a15ef1369546868a7f3a45a96768d40fd9d03412c091c6315cf4fde7cb68606937380db2eaaa707b4c4185c32eddcdd306705e4dc1ffc872eeee475a64dfac86aba41c0618983f8741c5ef68d3a101e8a3b8cac60c905c15fc910840b94c00a0b9d0
+SIG: 0aab4c900501b3e24d7cdf4663326a3a87df5e4843b2cbdb67cbf6e460fec350aa5371b1508f9f4528ecea23c436d94b5e8fcd4f681e30a6ac00a9704a188a03
+
+PRIV: 833fe62409237b9d62ec77587520911e9a759cec1d19755b7da901b96dca3d42ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf
+PUB: ec172b93ad5e563bf4932c70e1245034c35467ef2efd4d64ebf819683467e2bf
+MESSAGE: ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
+SIG: dc2a4459e7369633a52b1bf277839a00201009a3efbf3ecb69bea2186c26b58909351fc9ac90b3ecfdfbc7c66431e0303dca179c138ac17ad9bef1177331a704
diff --git a/src/crypto/digest/digest_test.cc b/src/crypto/digest/digest_test.cc
index 36a62ab..15c48e0 100644
--- a/src/crypto/digest/digest_test.cc
+++ b/src/crypto/digest/digest_test.cc
@@ -225,13 +225,6 @@
     if (!CompareDigest(test, digest.get(), EVP_MD_size(test->md.func()))) {
       return false;
     }
-
-    // Test the deprecated static buffer variant, until it's removed.
-    out = test->md.one_shot_func((const uint8_t *)test->input,
-                                 strlen(test->input), NULL);
-    if (!CompareDigest(test, out, EVP_MD_size(test->md.func()))) {
-      return false;
-    }
   }
 
   return true;
diff --git a/src/crypto/evp/evp.c b/src/crypto/evp/evp.c
index f083879..f8fe6ce 100644
--- a/src/crypto/evp/evp.c
+++ b/src/crypto/evp/evp.c
@@ -120,13 +120,6 @@
   return 0;
 }
 
-int EVP_PKEY_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
-  if (pkey->ameth && pkey->ameth->pkey_supports_digest) {
-    return pkey->ameth->pkey_supports_digest(pkey, md);
-  }
-  return 1;
-}
-
 int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
   if (a->type != b->type) {
     return -1;
diff --git a/src/crypto/evp/internal.h b/src/crypto/evp/internal.h
index 0783143..cdbd56a 100644
--- a/src/crypto/evp/internal.h
+++ b/src/crypto/evp/internal.h
@@ -100,12 +100,6 @@
    * custom implementations which do not expose key material and parameters.*/
   int (*pkey_opaque)(const EVP_PKEY *pk);
 
-  /* pkey_supports_digest returns one if |pkey| supports digests of
-   * type |md|. This is intended for use with EVP_PKEYs backing custom
-   * implementations which can't sign all digests. If null, it is
-   * assumed that all digests are supported. */
-  int (*pkey_supports_digest)(const EVP_PKEY *pkey, const EVP_MD *md);
-
   int (*pkey_size)(const EVP_PKEY *pk);
   int (*pkey_bits)(const EVP_PKEY *pk);
 
diff --git a/src/crypto/evp/p_dsa_asn1.c b/src/crypto/evp/p_dsa_asn1.c
index d4f4132..0e5cdee 100644
--- a/src/crypto/evp/p_dsa_asn1.c
+++ b/src/crypto/evp/p_dsa_asn1.c
@@ -256,7 +256,6 @@
   dsa_priv_encode,
 
   NULL /* pkey_opaque */,
-  NULL /* pkey_supports_digest */,
 
   int_dsa_size,
   dsa_bits,
diff --git a/src/crypto/evp/p_ec_asn1.c b/src/crypto/evp/p_ec_asn1.c
index 8d44dcd..1f1bf2f 100644
--- a/src/crypto/evp/p_ec_asn1.c
+++ b/src/crypto/evp/p_ec_asn1.c
@@ -244,7 +244,6 @@
   eckey_priv_encode,
 
   eckey_opaque,
-  0 /* pkey_supports_digest */,
 
   int_ec_size,
   ec_bits,
diff --git a/src/crypto/evp/p_rsa.c b/src/crypto/evp/p_rsa.c
index ea2ba99..6b25fa2 100644
--- a/src/crypto/evp/p_rsa.c
+++ b/src/crypto/evp/p_rsa.c
@@ -386,22 +386,15 @@
   }
 
   if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
-    size_t plaintext_len;
-    int message_len;
-
+    size_t padded_len;
     if (!setup_tbuf(rctx, ctx) ||
-        !RSA_decrypt(rsa, &plaintext_len, rctx->tbuf, key_len, in, inlen,
-                     RSA_NO_PADDING)) {
+        !RSA_decrypt(rsa, &padded_len, rctx->tbuf, key_len, in, inlen,
+                     RSA_NO_PADDING) ||
+        !RSA_padding_check_PKCS1_OAEP_mgf1(
+            out, outlen, key_len, rctx->tbuf, padded_len, rctx->oaep_label,
+            rctx->oaep_labellen, rctx->md, rctx->mgf1md)) {
       return 0;
     }
-
-    message_len = RSA_padding_check_PKCS1_OAEP_mgf1(
-        out, key_len, rctx->tbuf, plaintext_len, rctx->oaep_label,
-        rctx->oaep_labellen, rctx->md, rctx->mgf1md);
-    if (message_len < 0) {
-      return 0;
-    }
-    *outlen = message_len;
     return 1;
   }
 
diff --git a/src/crypto/evp/p_rsa_asn1.c b/src/crypto/evp/p_rsa_asn1.c
index 2c4b266..2072595 100644
--- a/src/crypto/evp/p_rsa_asn1.c
+++ b/src/crypto/evp/p_rsa_asn1.c
@@ -162,10 +162,6 @@
   return RSA_is_opaque(pkey->pkey.rsa);
 }
 
-static int rsa_supports_digest(const EVP_PKEY *pkey, const EVP_MD *md) {
-  return RSA_supports_digest(pkey->pkey.rsa, md);
-}
-
 static int int_rsa_size(const EVP_PKEY *pkey) {
   return RSA_size(pkey->pkey.rsa);
 }
@@ -189,7 +185,6 @@
   rsa_priv_encode,
 
   rsa_opaque,
-  rsa_supports_digest,
 
   int_rsa_size,
   rsa_bits,
diff --git a/src/crypto/hmac/hmac.c b/src/crypto/hmac/hmac.c
index a252667..931f7a1 100644
--- a/src/crypto/hmac/hmac.c
+++ b/src/crypto/hmac/hmac.c
@@ -69,15 +69,6 @@
               const uint8_t *data, size_t data_len, uint8_t *out,
               unsigned int *out_len) {
   HMAC_CTX ctx;
-  static uint8_t static_out_buffer[EVP_MAX_MD_SIZE];
-
-  /* OpenSSL has traditionally supported using a static buffer if |out| is
-   * NULL. We maintain that but don't document it. This behaviour should be
-   * considered to be deprecated. */
-  if (out == NULL) {
-    out = static_out_buffer;
-  }
-
   HMAC_CTX_init(&ctx);
   if (!HMAC_Init_ex(&ctx, key, key_len, evp_md, NULL) ||
       !HMAC_Update(&ctx, data, data_len) ||
diff --git a/src/crypto/internal.h b/src/crypto/internal.h
index 2724956..7ce99a4 100644
--- a/src/crypto/internal.h
+++ b/src/crypto/internal.h
@@ -183,17 +183,22 @@
  *
  * can be written as
  *
- * unsigned int lt = constant_time_lt(a, b);
- * c = constant_time_select(lt, a, b); */
+ * size_t lt = constant_time_lt_s(a, b);
+ * c = constant_time_select_s(lt, a, b); */
 
-/* constant_time_msb returns the given value with the MSB copied to all the
+#define CONSTTIME_TRUE_S ~((size_t)0)
+#define CONSTTIME_FALSE_S ((size_t)0)
+#define CONSTTIME_TRUE_8 ((uint8_t)0xff)
+#define CONSTTIME_FALSE_8 ((uint8_t)0)
+
+/* constant_time_msb_s returns the given value with the MSB copied to all the
  * other bits. */
-static inline unsigned int constant_time_msb(unsigned int a) {
-  return (unsigned int)((int)(a) >> (sizeof(int) * 8 - 1));
+static inline size_t constant_time_msb_s(size_t a) {
+  return 0u - (a >> (sizeof(a) * 8 - 1));
 }
 
-/* constant_time_lt returns 0xff..f if a < b and 0 otherwise. */
-static inline unsigned int constant_time_lt(unsigned int a, unsigned int b) {
+/* constant_time_lt_s returns 0xff..f if a < b and 0 otherwise. */
+static inline size_t constant_time_lt_s(size_t a, size_t b) {
   /* Consider the two cases of the problem:
    *   msb(a) == msb(b): a < b iff the MSB of a - b is set.
    *   msb(a) != msb(b): a < b iff the MSB of b is set.
@@ -225,26 +230,28 @@
    * (check-sat)
    * (get-model)
    */
-  return constant_time_msb(a^((a^b)|((a-b)^a)));
+  return constant_time_msb_s(a^((a^b)|((a-b)^a)));
 }
 
-/* constant_time_lt_8 acts like |constant_time_lt| but returns an 8-bit mask. */
-static inline uint8_t constant_time_lt_8(unsigned int a, unsigned int b) {
-  return (uint8_t)(constant_time_lt(a, b));
+/* constant_time_lt_8 acts like |constant_time_lt_s| but returns an 8-bit
+ * mask. */
+static inline uint8_t constant_time_lt_8(size_t a, size_t b) {
+  return (uint8_t)(constant_time_lt_s(a, b));
 }
 
-/* constant_time_gt returns 0xff..f if a >= b and 0 otherwise. */
-static inline unsigned int constant_time_ge(unsigned int a, unsigned int b) {
-  return ~constant_time_lt(a, b);
+/* constant_time_ge_s returns 0xff..f if a >= b and 0 otherwise. */
+static inline size_t constant_time_ge_s(size_t a, size_t b) {
+  return ~constant_time_lt_s(a, b);
 }
 
-/* constant_time_ge_8 acts like |constant_time_ge| but returns an 8-bit mask. */
-static inline uint8_t constant_time_ge_8(unsigned int a, unsigned int b) {
-  return (uint8_t)(constant_time_ge(a, b));
+/* constant_time_ge_8 acts like |constant_time_ge_s| but returns an 8-bit
+ * mask. */
+static inline uint8_t constant_time_ge_8(size_t a, size_t b) {
+  return (uint8_t)(constant_time_ge_s(a, b));
 }
 
 /* constant_time_is_zero returns 0xff..f if a == 0 and 0 otherwise. */
-static inline unsigned int constant_time_is_zero(unsigned int a) {
+static inline size_t constant_time_is_zero_s(size_t a) {
   /* Here is an SMT-LIB verification of this formula:
    *
    * (define-fun is_zero ((a (_ BitVec 32))) (_ BitVec 32)
@@ -257,41 +264,42 @@
    * (check-sat)
    * (get-model)
    */
-  return constant_time_msb(~a & (a - 1));
+  return constant_time_msb_s(~a & (a - 1));
 }
 
-/* constant_time_is_zero_8 acts like constant_time_is_zero but returns an 8-bit
+/* constant_time_is_zero_8 acts like |constant_time_is_zero_s| but returns an
+ * 8-bit mask. */
+static inline uint8_t constant_time_is_zero_8(size_t a) {
+  return (uint8_t)(constant_time_is_zero_s(a));
+}
+
+/* constant_time_eq_s returns 0xff..f if a == b and 0 otherwise. */
+static inline size_t constant_time_eq_s(size_t a, size_t b) {
+  return constant_time_is_zero_s(a ^ b);
+}
+
+/* constant_time_eq_8 acts like |constant_time_eq_s| but returns an 8-bit
  * mask. */
-static inline uint8_t constant_time_is_zero_8(unsigned int a) {
-  return (uint8_t)(constant_time_is_zero(a));
+static inline uint8_t constant_time_eq_8(size_t a, size_t b) {
+  return (uint8_t)(constant_time_eq_s(a, b));
 }
 
-/* constant_time_eq returns 0xff..f if a == b and 0 otherwise. */
-static inline unsigned int constant_time_eq(unsigned int a, unsigned int b) {
-  return constant_time_is_zero(a ^ b);
-}
-
-/* constant_time_eq_8 acts like |constant_time_eq| but returns an 8-bit mask. */
-static inline uint8_t constant_time_eq_8(unsigned int a, unsigned int b) {
-  return (uint8_t)(constant_time_eq(a, b));
-}
-
-/* constant_time_eq_int acts like |constant_time_eq| but works on int values. */
-static inline unsigned int constant_time_eq_int(int a, int b) {
-  return constant_time_eq((unsigned)(a), (unsigned)(b));
+/* constant_time_eq_int acts like |constant_time_eq_s| but works on int
+ * values. */
+static inline size_t constant_time_eq_int(int a, int b) {
+  return constant_time_eq_s((size_t)(a), (size_t)(b));
 }
 
 /* constant_time_eq_int_8 acts like |constant_time_eq_int| but returns an 8-bit
  * mask. */
 static inline uint8_t constant_time_eq_int_8(int a, int b) {
-  return constant_time_eq_8((unsigned)(a), (unsigned)(b));
+  return constant_time_eq_8((size_t)(a), (size_t)(b));
 }
 
-/* constant_time_select returns (mask & a) | (~mask & b). When |mask| is all 1s
- * or all 0s (as returned by the methods above), the select methods return
+/* constant_time_select_s returns (mask & a) | (~mask & b). When |mask| is all
+ * 1s or all 0s (as returned by the methods above), the select methods return
  * either |a| (if |mask| is nonzero) or |b| (if |mask| is zero). */
-static inline unsigned int constant_time_select(unsigned int mask,
-                                                unsigned int a, unsigned int b) {
+static inline size_t constant_time_select_s(size_t mask, size_t a, size_t b) {
   return (mask & a) | (~mask & b);
 }
 
@@ -299,13 +307,13 @@
  * 8-bit values. */
 static inline uint8_t constant_time_select_8(uint8_t mask, uint8_t a,
                                              uint8_t b) {
-  return (uint8_t)(constant_time_select(mask, a, b));
+  return (uint8_t)(constant_time_select_s(mask, a, b));
 }
 
 /* constant_time_select_int acts like |constant_time_select| but operates on
  * ints. */
-static inline int constant_time_select_int(unsigned int mask, int a, int b) {
-  return (int)(constant_time_select(mask, (unsigned)(a), (unsigned)(b)));
+static inline int constant_time_select_int(size_t mask, int a, int b) {
+  return (int)(constant_time_select_s(mask, (size_t)(a), (size_t)(b)));
 }
 
 
diff --git a/src/crypto/md5/md5.c b/src/crypto/md5/md5.c
index 7712f47..adc5957 100644
--- a/src/crypto/md5/md5.c
+++ b/src/crypto/md5/md5.c
@@ -65,13 +65,6 @@
 
 uint8_t *MD5(const uint8_t *data, size_t len, uint8_t *out) {
   MD5_CTX ctx;
-  static uint8_t digest[MD5_DIGEST_LENGTH];
-
-  /* TODO(fork): remove this static buffer. */
-  if (out == NULL) {
-    out = digest;
-  }
-
   MD5_Init(&ctx);
   MD5_Update(&ctx, data, len);
   MD5_Final(out, &ctx);
diff --git a/src/crypto/modes/polyval.c b/src/crypto/modes/polyval.c
index 33d37eb..83df0ab 100644
--- a/src/crypto/modes/polyval.c
+++ b/src/crypto/modes/polyval.c
@@ -36,11 +36,11 @@
 static void reverse_and_mulX_ghash(polyval_block *b) {
   uint64_t hi = b->u[0];
   uint64_t lo = b->u[1];
-  const unsigned carry = constant_time_eq(hi & 1, 1);
+  const size_t carry = constant_time_eq_s(hi & 1, 1);
   hi >>= 1;
   hi |= lo << 63;
   lo >>= 1;
-  lo ^= ((uint64_t) constant_time_select(carry, 0xe1, 0)) << 56;
+  lo ^= ((uint64_t) constant_time_select_s(carry, 0xe1, 0)) << 56;
 
   b->u[0] = CRYPTO_bswap8(lo);
   b->u[1] = CRYPTO_bswap8(hi);
diff --git a/src/crypto/perlasm/x86_64-xlate.pl b/src/crypto/perlasm/x86_64-xlate.pl
index 6e487b8..6043bc7 100755
--- a/src/crypto/perlasm/x86_64-xlate.pl
+++ b/src/crypto/perlasm/x86_64-xlate.pl
@@ -1134,7 +1134,7 @@
 OPTION	DOTNAME
 ___
 }
-print STDOUT "#if defined(__x86_64__)\n" if ($gas);
+print STDOUT "#if defined(__x86_64__) && !defined(OPENSSL_NO_ASM)\n" if ($gas);
 
 while(defined(my $line=<>)) {
 
diff --git a/src/crypto/rsa/internal.h b/src/crypto/rsa/internal.h
index b6a0727..b865a0a 100644
--- a/src/crypto/rsa/internal.h
+++ b/src/crypto/rsa/internal.h
@@ -97,16 +97,19 @@
 
 int RSA_padding_add_PKCS1_type_1(uint8_t *to, size_t to_len,
                                  const uint8_t *from, size_t from_len);
-int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
-                                   const uint8_t *from, unsigned from_len);
+int RSA_padding_check_PKCS1_type_1(uint8_t *out, size_t *out_len,
+                                   size_t max_out, const uint8_t *from,
+                                   size_t from_len);
 int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len,
                                  const uint8_t *from, size_t from_len);
-int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
-                                   const uint8_t *from, unsigned from_len);
-int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
-                                      const uint8_t *from, unsigned from_len,
-                                      const uint8_t *param, unsigned plen,
-                                      const EVP_MD *md, const EVP_MD *mgf1md);
+int RSA_padding_check_PKCS1_type_2(uint8_t *out, size_t *out_len,
+                                   size_t max_out, const uint8_t *from,
+                                   size_t from_len);
+int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len,
+                                      size_t max_out, const uint8_t *from,
+                                      size_t from_len, const uint8_t *param,
+                                      size_t param_len, const EVP_MD *md,
+                                      const EVP_MD *mgf1md);
 int RSA_padding_add_none(uint8_t *to, size_t to_len, const uint8_t *from,
                          size_t from_len);
 
diff --git a/src/crypto/rsa/padding.c b/src/crypto/rsa/padding.c
index ac583c4..dee44dd 100644
--- a/src/crypto/rsa/padding.c
+++ b/src/crypto/rsa/padding.c
@@ -92,56 +92,56 @@
   return 1;
 }
 
-int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
-                                   const uint8_t *from, unsigned from_len) {
-  unsigned i, j;
-  const uint8_t *p;
-
+int RSA_padding_check_PKCS1_type_1(uint8_t *out, size_t *out_len,
+                                   size_t max_out, const uint8_t *from,
+                                   size_t from_len) {
+  /* See RFC 8017, section 9.2. This is part of signature verification and thus
+   * does not need to run in constant-time. */
   if (from_len < 2) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_SMALL);
-    return -1;
+    return 0;
   }
 
-  p = from;
-  if ((*(p++) != 0) || (*(p++) != 1)) {
+  /* Check the header. */
+  if (from[0] != 0 || from[1] != 1) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_BLOCK_TYPE_IS_NOT_01);
-    return -1;
+    return 0;
   }
 
-  /* scan over padding data */
-  j = from_len - 2; /* one for leading 00, one for type. */
-  for (i = 0; i < j; i++) {
-    /* should decrypt to 0xff */
-    if (*p != 0xff) {
-      if (*p == 0) {
-        p++;
-        break;
-      } else {
-        OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_FIXED_HEADER_DECRYPT);
-        return -1;
-      }
+  /* Scan over padded data, looking for the 00. */
+  size_t pad;
+  for (pad = 2 /* header */; pad < from_len; pad++) {
+    if (from[pad] == 0x00) {
+      break;
     }
-    p++;
+
+    if (from[pad] != 0xff) {
+      OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_FIXED_HEADER_DECRYPT);
+      return 0;
+    }
   }
 
-  if (i == j) {
+  if (pad == from_len) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_NULL_BEFORE_BLOCK_MISSING);
-    return -1;
+    return 0;
   }
 
-  if (i < 8) {
+  if (pad < 2 /* header */ + 8) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_PAD_BYTE_COUNT);
-    return -1;
+    return 0;
   }
-  i++; /* Skip over the '\0' */
-  j -= i;
-  if (j > to_len) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
-    return -1;
-  }
-  OPENSSL_memcpy(to, p, j);
 
-  return j;
+  /* Skip over the 00. */
+  pad++;
+
+  if (from_len - pad > max_out) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
+    return 0;
+  }
+
+  OPENSSL_memcpy(out, from + pad, from_len - pad);
+  *out_len = from_len - pad;
+  return 1;
 }
 
 static int rand_nonzero(uint8_t *out, size_t len) {
@@ -186,11 +186,12 @@
   return 1;
 }
 
-int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
-                                   const uint8_t *from, unsigned from_len) {
+int RSA_padding_check_PKCS1_type_2(uint8_t *out, size_t *out_len,
+                                   size_t max_out, const uint8_t *from,
+                                   size_t from_len) {
   if (from_len == 0) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY);
-    return -1;
+    return 0;
   }
 
   /* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography
@@ -199,29 +200,29 @@
     /* |from| is zero-padded to the size of the RSA modulus, a public value, so
      * this can be rejected in non-constant time. */
     OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
-    return -1;
+    return 0;
   }
 
-  unsigned first_byte_is_zero = constant_time_eq(from[0], 0);
-  unsigned second_byte_is_two = constant_time_eq(from[1], 2);
+  size_t first_byte_is_zero = constant_time_eq_s(from[0], 0);
+  size_t second_byte_is_two = constant_time_eq_s(from[1], 2);
 
-  unsigned i, zero_index = 0, looking_for_index = ~0u;
-  for (i = 2; i < from_len; i++) {
-    unsigned equals0 = constant_time_is_zero(from[i]);
-    zero_index = constant_time_select(looking_for_index & equals0, (unsigned)i,
-                                      zero_index);
-    looking_for_index = constant_time_select(equals0, 0, looking_for_index);
+  size_t zero_index = 0, looking_for_index = CONSTTIME_TRUE_S;
+  for (size_t i = 2; i < from_len; i++) {
+    size_t equals0 = constant_time_is_zero_s(from[i]);
+    zero_index =
+        constant_time_select_s(looking_for_index & equals0, i, zero_index);
+    looking_for_index = constant_time_select_s(equals0, 0, looking_for_index);
   }
 
   /* The input must begin with 00 02. */
-  unsigned valid_index = first_byte_is_zero;
+  size_t valid_index = first_byte_is_zero;
   valid_index &= second_byte_is_two;
 
   /* We must have found the end of PS. */
   valid_index &= ~looking_for_index;
 
   /* PS must be at least 8 bytes long, and it starts two bytes into |from|. */
-  valid_index &= constant_time_ge(zero_index, 2 + 8);
+  valid_index &= constant_time_ge_s(zero_index, 2 + 8);
 
   /* Skip the zero byte. */
   zero_index++;
@@ -229,27 +230,24 @@
   /* NOTE: Although this logic attempts to be constant time, the API contracts
    * of this function and |RSA_decrypt| with |RSA_PKCS1_PADDING| make it
    * impossible to completely avoid Bleichenbacher's attack. Consumers should
-   * use |RSA_unpad_key_pkcs1|. */
+   * use |RSA_PADDING_NONE| and perform the padding check in constant-time
+   * combined with a swap to a random session key or other mitigation. */
   if (!valid_index) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
-    return -1;
+    return 0;
   }
 
-  const unsigned msg_len = from_len - zero_index;
-  if (msg_len > to_len) {
+  const size_t msg_len = from_len - zero_index;
+  if (msg_len > max_out) {
     /* This shouldn't happen because this function is always called with
-     * |to_len| as the key size and |from_len| is bounded by the key size. */
+     * |max_out| as the key size and |from_len| is bounded by the key size. */
     OPENSSL_PUT_ERROR(RSA, RSA_R_PKCS_DECODING_ERROR);
-    return -1;
+    return 0;
   }
 
-  if (msg_len > INT_MAX) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
-    return -1;
-  }
-
-  OPENSSL_memcpy(to, &from[zero_index], msg_len);
-  return (int)msg_len;
+  OPENSSL_memcpy(out, &from[zero_index], msg_len);
+  *out_len = msg_len;
+  return 1;
 }
 
 int RSA_padding_add_none(uint8_t *to, size_t to_len, const uint8_t *from,
@@ -382,13 +380,12 @@
   return ret;
 }
 
-int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
-                                      const uint8_t *from, unsigned from_len,
-                                      const uint8_t *param, unsigned param_len,
-                                      const EVP_MD *md, const EVP_MD *mgf1md) {
-  unsigned i, dblen, mlen = -1, mdlen, bad, looking_for_one_byte, one_index = 0;
-  const uint8_t *maskeddb, *maskedseed;
-  uint8_t *db = NULL, seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE];
+int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *out, size_t *out_len,
+                                      size_t max_out, const uint8_t *from,
+                                      size_t from_len, const uint8_t *param,
+                                      size_t param_len, const EVP_MD *md,
+                                      const EVP_MD *mgf1md) {
+  uint8_t *db = NULL;
 
   if (md == NULL) {
     md = EVP_sha1();
@@ -397,7 +394,7 @@
     mgf1md = md;
   }
 
-  mdlen = EVP_MD_size(md);
+  size_t mdlen = EVP_MD_size(md);
 
   /* The encoded message is one byte smaller than the modulus to ensure that it
    * doesn't end up greater than the modulus. Thus there's an extra "+1" here
@@ -408,45 +405,47 @@
     goto decoding_err;
   }
 
-  dblen = from_len - mdlen - 1;
+  size_t dblen = from_len - mdlen - 1;
   db = OPENSSL_malloc(dblen);
   if (db == NULL) {
     OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
     goto err;
   }
 
-  maskedseed = from + 1;
-  maskeddb = from + 1 + mdlen;
+  const uint8_t *maskedseed = from + 1;
+  const uint8_t *maskeddb = from + 1 + mdlen;
 
+  uint8_t seed[EVP_MAX_MD_SIZE];
   if (!PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) {
     goto err;
   }
-  for (i = 0; i < mdlen; i++) {
+  for (size_t i = 0; i < mdlen; i++) {
     seed[i] ^= maskedseed[i];
   }
 
   if (!PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) {
     goto err;
   }
-  for (i = 0; i < dblen; i++) {
+  for (size_t i = 0; i < dblen; i++) {
     db[i] ^= maskeddb[i];
   }
 
+  uint8_t phash[EVP_MAX_MD_SIZE];
   if (!EVP_Digest(param, param_len, phash, NULL, md, NULL)) {
     goto err;
   }
 
-  bad = ~constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen));
-  bad |= ~constant_time_is_zero(from[0]);
+  size_t bad = ~constant_time_is_zero_s(CRYPTO_memcmp(db, phash, mdlen));
+  bad |= ~constant_time_is_zero_s(from[0]);
 
-  looking_for_one_byte = ~0u;
-  for (i = mdlen; i < dblen; i++) {
-    unsigned equals1 = constant_time_eq(db[i], 1);
-    unsigned equals0 = constant_time_eq(db[i], 0);
-    one_index = constant_time_select(looking_for_one_byte & equals1, i,
-                                     one_index);
+  size_t looking_for_one_byte = CONSTTIME_TRUE_S, one_index = 0;
+  for (size_t i = mdlen; i < dblen; i++) {
+    size_t equals1 = constant_time_eq_s(db[i], 1);
+    size_t equals0 = constant_time_eq_s(db[i], 0);
+    one_index =
+        constant_time_select_s(looking_for_one_byte & equals1, i, one_index);
     looking_for_one_byte =
-        constant_time_select(equals1, 0, looking_for_one_byte);
+        constant_time_select_s(equals1, 0, looking_for_one_byte);
     bad |= looking_for_one_byte & ~equals0;
   }
 
@@ -457,16 +456,16 @@
   }
 
   one_index++;
-  mlen = dblen - one_index;
-  if (to_len < mlen) {
+  size_t mlen = dblen - one_index;
+  if (max_out < mlen) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
-    mlen = -1;
-  } else {
-    OPENSSL_memcpy(to, db + one_index, mlen);
+    goto err;
   }
 
+  OPENSSL_memcpy(out, db + one_index, mlen);
+  *out_len = mlen;
   OPENSSL_free(db);
-  return mlen;
+  return 1;
 
 decoding_err:
   /* to avoid chosen ciphertext attacks, the error message should not reveal
@@ -474,7 +473,7 @@
   OPENSSL_PUT_ERROR(RSA, RSA_R_OAEP_DECODING_ERROR);
  err:
   OPENSSL_free(db);
-  return -1;
+  return 0;
 }
 
 static const uint8_t kPSSZeroes[] = {0, 0, 0, 0, 0, 0, 0, 0};
diff --git a/src/crypto/rsa/rsa.c b/src/crypto/rsa/rsa.c
index 731293f..6d56238 100644
--- a/src/crypto/rsa/rsa.c
+++ b/src/crypto/rsa/rsa.c
@@ -321,13 +321,6 @@
   return rsa->meth && (rsa->meth->flags & RSA_FLAG_OPAQUE);
 }
 
-int RSA_supports_digest(const RSA *rsa, const EVP_MD *md) {
-  if (rsa->meth && rsa->meth->supports_digest) {
-    return rsa->meth->supports_digest(rsa, md);
-  }
-  return 1;
-}
-
 int RSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
                          CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
   int index;
diff --git a/src/crypto/rsa/rsa_impl.c b/src/crypto/rsa/rsa_impl.c
index 8e0aa9c..e385e60 100644
--- a/src/crypto/rsa/rsa_impl.c
+++ b/src/crypto/rsa/rsa_impl.c
@@ -363,7 +363,6 @@
 int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
                         const uint8_t *in, size_t in_len, int padding) {
   const unsigned rsa_size = RSA_size(rsa);
-  int r = -1;
   uint8_t *buf = NULL;
   int ret = 0;
 
@@ -394,26 +393,25 @@
 
   switch (padding) {
     case RSA_PKCS1_PADDING:
-      r = RSA_padding_check_PKCS1_type_2(out, rsa_size, buf, rsa_size);
+      ret =
+          RSA_padding_check_PKCS1_type_2(out, out_len, rsa_size, buf, rsa_size);
       break;
     case RSA_PKCS1_OAEP_PADDING:
       /* Use the default parameters: SHA-1 for both hashes and no label. */
-      r = RSA_padding_check_PKCS1_OAEP_mgf1(out, rsa_size, buf, rsa_size,
-                                            NULL, 0, NULL, NULL);
+      ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, out_len, rsa_size, buf,
+                                              rsa_size, NULL, 0, NULL, NULL);
       break;
     case RSA_NO_PADDING:
-      r = rsa_size;
+      *out_len = rsa_size;
+      ret = 1;
       break;
     default:
       OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
       goto err;
   }
 
-  if (r < 0) {
+  if (!ret) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED);
-  } else {
-    *out_len = r;
-    ret = 1;
   }
 
 err:
@@ -436,7 +434,6 @@
 
   const unsigned rsa_size = RSA_size(rsa);
   BIGNUM *f, *result;
-  int r = -1;
 
   if (max_out < rsa_size) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
@@ -500,21 +497,21 @@
 
   switch (padding) {
     case RSA_PKCS1_PADDING:
-      r = RSA_padding_check_PKCS1_type_1(out, rsa_size, buf, rsa_size);
+      ret =
+          RSA_padding_check_PKCS1_type_1(out, out_len, rsa_size, buf, rsa_size);
       break;
     case RSA_NO_PADDING:
-      r = rsa_size;
+      ret = 1;
+      *out_len = rsa_size;
       break;
     default:
       OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
       goto err;
   }
 
-  if (r < 0) {
+  if (!ret) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED);
-  } else {
-    *out_len = r;
-    ret = 1;
+    goto err;
   }
 
 err:
diff --git a/src/crypto/sha/sha1-altivec.c b/src/crypto/sha/sha1-altivec.c
index 500986e..0b64315 100644
--- a/src/crypto/sha/sha1-altivec.c
+++ b/src/crypto/sha/sha1-altivec.c
@@ -105,7 +105,9 @@
  * Byte shifting code below may not be correct for big-endian systems. */
 static vec_uint32_t sched_00_15(vec_uint32_t *pre_added, const void *data,
                                 vec_uint32_t k) {
-  const vec_uint32_t v = *((const vec_uint32_t *)data);
+  const vector unsigned char unaligned_data =
+    vec_vsx_ld(0, (const unsigned char*) data);
+  const vec_uint32_t v = (vec_uint32_t) unaligned_data;
   const vec_uint32_t w = vec_perm(v, v, k_swap_endianness);
   vec_st(w + k, 0, pre_added);
   return w;
diff --git a/src/crypto/sha/sha1.c b/src/crypto/sha/sha1.c
index 7c72713..4eb8189 100644
--- a/src/crypto/sha/sha1.c
+++ b/src/crypto/sha/sha1.c
@@ -82,12 +82,6 @@
 
 uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t *out) {
   SHA_CTX ctx;
-  static uint8_t buf[SHA_DIGEST_LENGTH];
-
-  /* TODO(fork): remove this static buffer. */
-  if (out == NULL) {
-    out = buf;
-  }
   if (!SHA1_Init(&ctx)) {
     return NULL;
   }
diff --git a/src/crypto/sha/sha256.c b/src/crypto/sha/sha256.c
index fb950d7..c3bd5ad 100644
--- a/src/crypto/sha/sha256.c
+++ b/src/crypto/sha/sha256.c
@@ -99,12 +99,6 @@
 
 uint8_t *SHA224(const uint8_t *data, size_t len, uint8_t *out) {
   SHA256_CTX ctx;
-  static uint8_t buf[SHA224_DIGEST_LENGTH];
-
-  /* TODO(fork): remove this static buffer. */
-  if (out == NULL) {
-    out = buf;
-  }
   SHA224_Init(&ctx);
   SHA224_Update(&ctx, data, len);
   SHA224_Final(out, &ctx);
@@ -114,12 +108,6 @@
 
 uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out) {
   SHA256_CTX ctx;
-  static uint8_t buf[SHA256_DIGEST_LENGTH];
-
-  /* TODO(fork): remove this static buffer. */
-  if (out == NULL) {
-    out = buf;
-  }
   SHA256_Init(&ctx);
   SHA256_Update(&ctx, data, len);
   SHA256_Final(out, &ctx);
diff --git a/src/crypto/sha/sha512.c b/src/crypto/sha/sha512.c
index 8761150..e8284f1 100644
--- a/src/crypto/sha/sha512.c
+++ b/src/crypto/sha/sha512.c
@@ -123,13 +123,6 @@
 
 uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out) {
   SHA512_CTX ctx;
-  static uint8_t buf[SHA384_DIGEST_LENGTH];
-
-  /* TODO(fork): remove this static buffer. */
-  if (out == NULL) {
-    out = buf;
-  }
-
   SHA384_Init(&ctx);
   SHA384_Update(&ctx, data, len);
   SHA384_Final(out, &ctx);
@@ -139,12 +132,6 @@
 
 uint8_t *SHA512(const uint8_t *data, size_t len, uint8_t *out) {
   SHA512_CTX ctx;
-  static uint8_t buf[SHA512_DIGEST_LENGTH];
-
-  /* TODO(fork): remove this static buffer. */
-  if (out == NULL) {
-    out = buf;
-  }
   SHA512_Init(&ctx);
   SHA512_Update(&ctx, data, len);
   SHA512_Final(out, &ctx);
diff --git a/src/include/openssl/curve25519.h b/src/include/openssl/curve25519.h
index 1bbb69a..97be067 100644
--- a/src/include/openssl/curve25519.h
+++ b/src/include/openssl/curve25519.h
@@ -61,7 +61,12 @@
 /* Ed25519.
  *
  * Ed25519 is a signature scheme using a twisted-Edwards curve that is
- * birationally equivalent to curve25519. */
+ * birationally equivalent to curve25519.
+ *
+ * Note that, unlike RFC 8032's formulation, our private key representation
+ * includes a public key suffix to make multiple key signing operations with the
+ * same key more efficient. The RFC 8032 key private key is referred to in this
+ * implementation as the "seed" and is the first 32 bytes of our private key. */
 
 #define ED25519_PRIVATE_KEY_LEN 64
 #define ED25519_PUBLIC_KEY_LEN 32
diff --git a/src/include/openssl/evp.h b/src/include/openssl/evp.h
index 7debbc5..9abce9d 100644
--- a/src/include/openssl/evp.h
+++ b/src/include/openssl/evp.h
@@ -97,12 +97,6 @@
  * an error to attempt to duplicate, export, or compare an opaque key. */
 OPENSSL_EXPORT int EVP_PKEY_is_opaque(const EVP_PKEY *pkey);
 
-/* EVP_PKEY_supports_digest returns one if |pkey| supports digests of
- * type |md|. This is intended for use with EVP_PKEYs backing custom
- * implementations which can't sign all digests. */
-OPENSSL_EXPORT int EVP_PKEY_supports_digest(const EVP_PKEY *pkey,
-                                            const EVP_MD *md);
-
 /* EVP_PKEY_cmp compares |a| and |b| and returns one if they are equal, zero if
  * not and a negative number on error.
  *
diff --git a/src/include/openssl/rsa.h b/src/include/openssl/rsa.h
index d8f76f0..2377ca2 100644
--- a/src/include/openssl/rsa.h
+++ b/src/include/openssl/rsa.h
@@ -292,10 +292,6 @@
  * material. Otherwise it returns zero. */
 OPENSSL_EXPORT int RSA_is_opaque(const RSA *rsa);
 
-/* RSA_supports_digest returns one if |rsa| supports signing digests
- * of type |md|. Otherwise it returns zero. */
-OPENSSL_EXPORT int RSA_supports_digest(const RSA *rsa, const EVP_MD *md);
-
 /* RSAPublicKey_dup allocates a fresh |RSA| and copies the public key from
  * |rsa| into it. It returns the fresh |RSA| object, or NULL on error. */
 OPENSSL_EXPORT RSA *RSAPublicKey_dup(const RSA *rsa);
@@ -587,8 +583,7 @@
   int (*multi_prime_keygen)(RSA *rsa, int bits, int num_primes, BIGNUM *e,
                             BN_GENCB *cb);
 
-  /* supports_digest returns one if |rsa| supports digests of type
-   * |md|. If null, it is assumed that all digests are supported. */
+  /* supports_digest is deprecated and ignored. Set it to NULL. */
   int (*supports_digest)(const RSA *rsa, const EVP_MD *md);
 };
 
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 5182df7..b476592 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -2105,6 +2105,7 @@
 OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves);
 
 /* SSL_CURVE_* define TLS curve IDs. */
+#define SSL_CURVE_SECP224R1 21
 #define SSL_CURVE_SECP256R1 23
 #define SSL_CURVE_SECP384R1 24
 #define SSL_CURVE_SECP521R1 25
diff --git a/src/ssl/handshake_server.c b/src/ssl/handshake_server.c
index a1341d6..cc1897f 100644
--- a/src/ssl/handshake_server.c
+++ b/src/ssl/handshake_server.c
@@ -728,11 +728,7 @@
     SSL_HANDSHAKE *hs, const SSL_CLIENT_HELLO *client_hello,
     const struct ssl_cipher_preference_list_st *server_pref) {
   SSL *const ssl = hs->ssl;
-  const SSL_CIPHER *c, *ret = NULL;
-  STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
-  int ok;
-  size_t cipher_index;
-  uint32_t alg_k, alg_a, mask_k, mask_a;
+  STACK_OF(SSL_CIPHER) *prio, *allow;
   /* in_group_flags will either be NULL, or will point to an array of bytes
    * which indicate equal-preference groups in the |prio| stack. See the
    * comment about |in_group_flags| in the |ssl_cipher_preference_list_st|
@@ -742,40 +738,38 @@
    * such value exists yet. */
   int group_min = -1;
 
-  STACK_OF(SSL_CIPHER) *clnt = ssl_parse_client_cipher_list(client_hello);
-  if (clnt == NULL) {
+  STACK_OF(SSL_CIPHER) *client_pref =
+      ssl_parse_client_cipher_list(client_hello);
+  if (client_pref == NULL) {
     return NULL;
   }
 
   if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
-    prio = srvr;
+    prio = server_pref->ciphers;
     in_group_flags = server_pref->in_group_flags;
-    allow = clnt;
+    allow = client_pref;
   } else {
-    prio = clnt;
+    prio = client_pref;
     in_group_flags = NULL;
-    allow = srvr;
+    allow = server_pref->ciphers;
   }
 
+  uint32_t mask_k, mask_a;
   ssl_get_compatible_server_ciphers(hs, &mask_k, &mask_a);
 
+  const SSL_CIPHER *ret = NULL;
   for (size_t i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
-    c = sk_SSL_CIPHER_value(prio, i);
+    const SSL_CIPHER *c = sk_SSL_CIPHER_value(prio, i);
 
-    ok = 1;
-
-    /* Check the TLS version. */
-    if (SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) ||
-        SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl)) {
-      ok = 0;
-    }
-
-    alg_k = c->algorithm_mkey;
-    alg_a = c->algorithm_auth;
-
-    ok = ok && (alg_k & mask_k) && (alg_a & mask_a);
-
-    if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c)) {
+    size_t cipher_index;
+    if (/* Check if the cipher is supported for the current version. */
+        SSL_CIPHER_get_min_version(c) <= ssl3_protocol_version(ssl) &&
+        ssl3_protocol_version(ssl) <= SSL_CIPHER_get_max_version(c) &&
+        /* Check the cipher is supported for the server configuration. */
+        (c->algorithm_mkey & mask_k) &&
+        (c->algorithm_auth & mask_a) &&
+        /* Check the cipher is in the |allow| list. */
+        sk_SSL_CIPHER_find(allow, &cipher_index, c)) {
       if (in_group_flags != NULL && in_group_flags[i] == 1) {
         /* This element of |prio| is in a group. Update the minimum index found
          * so far and continue looking. */
@@ -799,7 +793,7 @@
     }
   }
 
-  sk_SSL_CIPHER_free(clnt);
+  sk_SSL_CIPHER_free(client_pref);
   return ret;
 }
 
diff --git a/src/ssl/s3_pkt.c b/src/ssl/s3_pkt.c
index c2d30ca..fc21c2c 100644
--- a/src/ssl/s3_pkt.c
+++ b/src/ssl/s3_pkt.c
@@ -190,6 +190,7 @@
 
 int ssl3_write_app_data(SSL *ssl, const uint8_t *buf, int len) {
   assert(ssl_can_write(ssl));
+  assert(ssl->s3->aead_write_ctx != NULL);
 
   unsigned tot, n, nw;
 
@@ -326,6 +327,7 @@
 int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
                        int peek) {
   assert(ssl_can_read(ssl));
+  assert(ssl->s3->aead_read_ctx != NULL);
   *out_got_handshake = 0;
 
   ssl->method->release_current_message(ssl, 0 /* don't free buffer */);
diff --git a/src/ssl/ssl_buffer.c b/src/ssl/ssl_buffer.c
index c27db8b..aefc044 100644
--- a/src/ssl/ssl_buffer.c
+++ b/src/ssl/ssl_buffer.c
@@ -225,26 +225,7 @@
     return 0;
   }
 
-  size_t header_len = ssl_seal_align_prefix_len(ssl);
-
-  /* TODO(davidben): This matches the original behavior in keeping the malloc
-   * size consistent. Does this matter? |cap| could just be |max_len|. */
-  size_t cap = SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
-  if (SSL_is_dtls(ssl)) {
-    cap += DTLS1_RT_HEADER_LENGTH;
-  } else {
-    cap += SSL3_RT_HEADER_LENGTH;
-    if (ssl->mode & SSL_MODE_CBC_RECORD_SPLITTING) {
-      cap += SSL3_RT_HEADER_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
-    }
-  }
-
-  if (max_len > cap) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
-    return 0;
-  }
-
-  if (!setup_buffer(buf, header_len, cap)) {
+  if (!setup_buffer(buf, ssl_seal_align_prefix_len(ssl), max_len)) {
     return 0;
   }
   *out_ptr = buf->buf + buf->offset;
diff --git a/src/ssl/ssl_ecdh.c b/src/ssl/ssl_ecdh.c
index f49d566..25e3df9 100644
--- a/src/ssl/ssl_ecdh.c
+++ b/src/ssl/ssl_ecdh.c
@@ -300,6 +300,17 @@
 
 static const SSL_ECDH_METHOD kMethods[] = {
     {
+        NID_secp224r1,
+        SSL_CURVE_SECP224R1,
+        "P-224",
+        ssl_ec_point_cleanup,
+        ssl_ec_point_offer,
+        ssl_ec_point_accept,
+        ssl_ec_point_finish,
+        CBS_get_u8_length_prefixed,
+        CBB_add_u8_length_prefixed,
+    },
+    {
         NID_X9_62_prime256v1,
         SSL_CURVE_SECP256R1,
         "P-256",
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 21497fd..70ea664 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -1793,7 +1793,8 @@
   }
   if (config->enable_all_curves) {
     static const int kAllCurves[] = {
-      NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_X25519,
+        NID_secp224r1, NID_X9_62_prime256v1, NID_secp384r1,
+        NID_secp521r1, NID_X25519,
     };
     if (!SSL_set1_curves(ssl.get(), kAllCurves,
                          OPENSSL_ARRAY_SIZE(kAllCurves))) {
@@ -1883,6 +1884,22 @@
       return false;
     }
 
+    if (config->handshake_twice) {
+      do {
+        ret = SSL_do_handshake(ssl.get());
+      } while (config->async && RetryAsync(ssl.get(), ret));
+      if (ret != 1) {
+        return false;
+      }
+    }
+
+    // Skip the |config->async| logic as this should be a no-op.
+    if (config->no_op_extra_handshake &&
+        SSL_do_handshake(ssl.get()) != 1) {
+      fprintf(stderr, "Extra SSL_do_handshake was not a no-op.\n");
+      return false;
+    }
+
     // Reset the state to assert later that the callback isn't called in
     // renegotations.
     GetTestState(ssl.get())->got_new_session = false;
diff --git a/src/ssl/test/runner/curve25519/const_amd64.h b/src/ssl/test/runner/curve25519/const_amd64.h
new file mode 100644
index 0000000..80ad222
--- /dev/null
+++ b/src/ssl/test/runner/curve25519/const_amd64.h
@@ -0,0 +1,8 @@
+// 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
index 797f9b0..0ad5398 100644
--- a/src/ssl/test/runner/curve25519/const_amd64.s
+++ b/src/ssl/test/runner/curve25519/const_amd64.s
@@ -7,8 +7,8 @@
 
 // +build amd64,!gccgo,!appengine
 
-DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
-GLOBL ·REDMASK51(SB), 8, $8
+// 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
diff --git a/src/ssl/test/runner/curve25519/freeze_amd64.s b/src/ssl/test/runner/curve25519/freeze_amd64.s
index 37599fa..536479b 100644
--- a/src/ssl/test/runner/curve25519/freeze_amd64.s
+++ b/src/ssl/test/runner/curve25519/freeze_amd64.s
@@ -7,29 +7,18 @@
 
 // +build amd64,!gccgo,!appengine
 
+#include "const_amd64.h"
+
 // func freeze(inout *[5]uint64)
-TEXT ·freeze(SB),7,$96-8
+TEXT ·freeze(SB),7,$0-8
 	MOVQ inout+0(FP), DI
 
-	MOVQ SP,R11
-	MOVQ $31,CX
-	NOTQ CX
-	ANDQ CX,SP
-	ADDQ $32,SP
-
-	MOVQ R11,0(SP)
-	MOVQ R12,8(SP)
-	MOVQ R13,16(SP)
-	MOVQ R14,24(SP)
-	MOVQ R15,32(SP)
-	MOVQ BX,40(SP)
-	MOVQ BP,48(SP)
 	MOVQ 0(DI),SI
 	MOVQ 8(DI),DX
 	MOVQ 16(DI),CX
 	MOVQ 24(DI),R8
 	MOVQ 32(DI),R9
-	MOVQ ·REDMASK51(SB),AX
+	MOVQ $REDMASK51,AX
 	MOVQ AX,R10
 	SUBQ $18,R10
 	MOVQ $3,R11
@@ -81,14 +70,4 @@
 	MOVQ CX,16(DI)
 	MOVQ R8,24(DI)
 	MOVQ R9,32(DI)
-	MOVQ 0(SP),R11
-	MOVQ 8(SP),R12
-	MOVQ 16(SP),R13
-	MOVQ 24(SP),R14
-	MOVQ 32(SP),R15
-	MOVQ 40(SP),BX
-	MOVQ 48(SP),BP
-	MOVQ R11,SP
-	MOVQ DI,AX
-	MOVQ SI,DX
 	RET
diff --git a/src/ssl/test/runner/curve25519/ladderstep_amd64.s b/src/ssl/test/runner/curve25519/ladderstep_amd64.s
index 3949f9c..7074e5c 100644
--- a/src/ssl/test/runner/curve25519/ladderstep_amd64.s
+++ b/src/ssl/test/runner/curve25519/ladderstep_amd64.s
@@ -7,23 +7,12 @@
 
 // +build amd64,!gccgo,!appengine
 
+#include "const_amd64.h"
+
 // func ladderstep(inout *[5][5]uint64)
-TEXT ·ladderstep(SB),0,$384-8
+TEXT ·ladderstep(SB),0,$296-8
 	MOVQ inout+0(FP),DI
 
-	MOVQ SP,R11
-	MOVQ $31,CX
-	NOTQ CX
-	ANDQ CX,SP
-	ADDQ $32,SP
-
-	MOVQ R11,0(SP)
-	MOVQ R12,8(SP)
-	MOVQ R13,16(SP)
-	MOVQ R14,24(SP)
-	MOVQ R15,32(SP)
-	MOVQ BX,40(SP)
-	MOVQ BP,48(SP)
 	MOVQ 40(DI),SI
 	MOVQ 48(DI),DX
 	MOVQ 56(DI),CX
@@ -49,204 +38,89 @@
 	SUBQ 96(DI),R11
 	SUBQ 104(DI),R12
 	SUBQ 112(DI),R13
-	MOVQ SI,56(SP)
-	MOVQ DX,64(SP)
-	MOVQ CX,72(SP)
-	MOVQ R8,80(SP)
-	MOVQ R9,88(SP)
-	MOVQ AX,96(SP)
-	MOVQ R10,104(SP)
-	MOVQ R11,112(SP)
-	MOVQ R12,120(SP)
-	MOVQ R13,128(SP)
-	MOVQ 96(SP),AX
-	MULQ 96(SP)
+	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 96(SP),AX
+	MOVQ 40(SP),AX
 	SHLQ $1,AX
-	MULQ 104(SP)
+	MULQ 48(SP)
 	MOVQ AX,R8
 	MOVQ DX,R9
-	MOVQ 96(SP),AX
+	MOVQ 40(SP),AX
 	SHLQ $1,AX
-	MULQ 112(SP)
+	MULQ 56(SP)
 	MOVQ AX,R10
 	MOVQ DX,R11
-	MOVQ 96(SP),AX
+	MOVQ 40(SP),AX
 	SHLQ $1,AX
-	MULQ 120(SP)
+	MULQ 64(SP)
 	MOVQ AX,R12
 	MOVQ DX,R13
-	MOVQ 96(SP),AX
+	MOVQ 40(SP),AX
 	SHLQ $1,AX
-	MULQ 128(SP)
+	MULQ 72(SP)
 	MOVQ AX,R14
 	MOVQ DX,R15
-	MOVQ 104(SP),AX
-	MULQ 104(SP)
+	MOVQ 48(SP),AX
+	MULQ 48(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 104(SP),AX
+	MOVQ 48(SP),AX
 	SHLQ $1,AX
-	MULQ 112(SP)
+	MULQ 56(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ 104(SP),AX
+	MOVQ 48(SP),AX
 	SHLQ $1,AX
-	MULQ 120(SP)
+	MULQ 64(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 104(SP),DX
+	MOVQ 48(SP),DX
 	IMUL3Q $38,DX,AX
-	MULQ 128(SP)
+	MULQ 72(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 112(SP),AX
-	MULQ 112(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 112(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 120(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 112(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 128(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 120(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 120(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 120(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 128(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 128(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 128(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),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,136(SP)
-	MOVQ R8,144(SP)
-	MOVQ R9,152(SP)
-	MOVQ AX,160(SP)
-	MOVQ R10,168(SP)
 	MOVQ 56(SP),AX
 	MULQ 56(SP)
-	MOVQ AX,SI
-	MOVQ DX,CX
-	MOVQ 56(SP),AX
-	SHLQ $1,AX
-	MULQ 64(SP)
-	MOVQ AX,R8
-	MOVQ DX,R9
-	MOVQ 56(SP),AX
-	SHLQ $1,AX
-	MULQ 72(SP)
-	MOVQ AX,R10
-	MOVQ DX,R11
-	MOVQ 56(SP),AX
-	SHLQ $1,AX
-	MULQ 80(SP)
-	MOVQ AX,R12
-	MOVQ DX,R13
-	MOVQ 56(SP),AX
-	SHLQ $1,AX
-	MULQ 88(SP)
-	MOVQ AX,R14
-	MOVQ DX,R15
-	MOVQ 64(SP),AX
-	MULQ 64(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 64(SP),AX
-	SHLQ $1,AX
-	MULQ 72(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 64(SP),AX
-	SHLQ $1,AX
-	MULQ 80(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 88(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 72(SP),AX
 	MULQ 72(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 72(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 80(SP)
-	ADDQ AX,SI
-	ADCQ DX,CX
-	MOVQ 72(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 88(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 80(SP),DX
-	IMUL3Q $19,DX,AX
-	MULQ 80(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 80(SP),DX
-	IMUL3Q $38,DX,AX
-	MULQ 88(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 88(SP),DX
+	MOVQ 72(SP),DX
 	IMUL3Q $19,DX,AX
-	MULQ 88(SP)
+	MULQ 72(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -284,11 +158,126 @@
 	IMUL3Q $19,CX,CX
 	ADDQ CX,SI
 	ANDQ DX,R10
-	MOVQ SI,176(SP)
-	MOVQ R8,184(SP)
-	MOVQ R9,192(SP)
-	MOVQ AX,200(SP)
-	MOVQ R10,208(SP)
+	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
@@ -299,16 +288,16 @@
 	ADDQ ·_2P1234(SB),CX
 	ADDQ ·_2P1234(SB),R8
 	ADDQ ·_2P1234(SB),R9
-	SUBQ 136(SP),SI
-	SUBQ 144(SP),DX
-	SUBQ 152(SP),CX
-	SUBQ 160(SP),R8
-	SUBQ 168(SP),R9
-	MOVQ SI,216(SP)
-	MOVQ DX,224(SP)
-	MOVQ CX,232(SP)
-	MOVQ R8,240(SP)
-	MOVQ R9,248(SP)
+	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
@@ -334,124 +323,124 @@
 	SUBQ 176(DI),R11
 	SUBQ 184(DI),R12
 	SUBQ 192(DI),R13
-	MOVQ SI,256(SP)
-	MOVQ DX,264(SP)
-	MOVQ CX,272(SP)
-	MOVQ R8,280(SP)
-	MOVQ R9,288(SP)
-	MOVQ AX,296(SP)
-	MOVQ R10,304(SP)
-	MOVQ R11,312(SP)
-	MOVQ R12,320(SP)
-	MOVQ R13,328(SP)
-	MOVQ 280(SP),SI
+	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,336(SP)
-	MULQ 112(SP)
+	MOVQ AX,280(SP)
+	MULQ 56(SP)
 	MOVQ AX,SI
 	MOVQ DX,CX
-	MOVQ 288(SP),DX
+	MOVQ 232(SP),DX
 	IMUL3Q $19,DX,AX
-	MOVQ AX,344(SP)
-	MULQ 104(SP)
+	MOVQ AX,288(SP)
+	MULQ 48(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 256(SP),AX
-	MULQ 96(SP)
+	MOVQ 200(SP),AX
+	MULQ 40(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 256(SP),AX
-	MULQ 104(SP)
+	MOVQ 200(SP),AX
+	MULQ 48(SP)
 	MOVQ AX,R8
 	MOVQ DX,R9
-	MOVQ 256(SP),AX
-	MULQ 112(SP)
+	MOVQ 200(SP),AX
+	MULQ 56(SP)
 	MOVQ AX,R10
 	MOVQ DX,R11
-	MOVQ 256(SP),AX
-	MULQ 120(SP)
+	MOVQ 200(SP),AX
+	MULQ 64(SP)
 	MOVQ AX,R12
 	MOVQ DX,R13
-	MOVQ 256(SP),AX
-	MULQ 128(SP)
+	MOVQ 200(SP),AX
+	MULQ 72(SP)
 	MOVQ AX,R14
 	MOVQ DX,R15
-	MOVQ 264(SP),AX
-	MULQ 96(SP)
+	MOVQ 208(SP),AX
+	MULQ 40(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 264(SP),AX
-	MULQ 104(SP)
+	MOVQ 208(SP),AX
+	MULQ 48(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 264(SP),AX
-	MULQ 112(SP)
+	MOVQ 208(SP),AX
+	MULQ 56(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ 264(SP),AX
-	MULQ 120(SP)
+	MOVQ 208(SP),AX
+	MULQ 64(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 264(SP),DX
+	MOVQ 208(SP),DX
 	IMUL3Q $19,DX,AX
-	MULQ 128(SP)
+	MULQ 72(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 272(SP),AX
-	MULQ 96(SP)
+	MOVQ 216(SP),AX
+	MULQ 40(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 272(SP),AX
-	MULQ 104(SP)
+	MOVQ 216(SP),AX
+	MULQ 48(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ 272(SP),AX
-	MULQ 112(SP)
+	MOVQ 216(SP),AX
+	MULQ 56(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 272(SP),DX
+	MOVQ 216(SP),DX
 	IMUL3Q $19,DX,AX
-	MULQ 120(SP)
+	MULQ 64(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 272(SP),DX
+	MOVQ 216(SP),DX
 	IMUL3Q $19,DX,AX
-	MULQ 128(SP)
+	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 96(SP)
-	ADDQ AX,R12
-	ADCQ DX,R13
-	MOVQ 280(SP),AX
-	MULQ 104(SP)
+	MULQ 72(SP)
+	ADDQ AX,R10
+	ADCQ DX,R11
+	MOVQ 232(SP),AX
+	MULQ 40(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 336(SP),AX
-	MULQ 120(SP)
+	MOVQ 288(SP),AX
+	MULQ 56(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 336(SP),AX
-	MULQ 128(SP)
+	MOVQ 288(SP),AX
+	MULQ 64(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
 	MOVQ 288(SP),AX
-	MULQ 96(SP)
-	ADDQ AX,R14
-	ADCQ DX,R15
-	MOVQ 344(SP),AX
-	MULQ 112(SP)
-	ADDQ AX,R8
-	ADCQ DX,R9
-	MOVQ 344(SP),AX
-	MULQ 120(SP)
-	ADDQ AX,R10
-	ADCQ DX,R11
-	MOVQ 344(SP),AX
-	MULQ 128(SP)
+	MULQ 72(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -489,119 +478,119 @@
 	IMUL3Q $19,CX,CX
 	ADDQ CX,SI
 	ANDQ DX,R10
-	MOVQ SI,96(SP)
-	MOVQ R8,104(SP)
-	MOVQ R9,112(SP)
-	MOVQ AX,120(SP)
-	MOVQ R10,128(SP)
-	MOVQ 320(SP),SI
+	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,256(SP)
-	MULQ 72(SP)
+	MOVQ AX,200(SP)
+	MULQ 16(SP)
 	MOVQ AX,SI
 	MOVQ DX,CX
-	MOVQ 328(SP),DX
+	MOVQ 272(SP),DX
 	IMUL3Q $19,DX,AX
-	MOVQ AX,264(SP)
-	MULQ 64(SP)
+	MOVQ AX,208(SP)
+	MULQ 8(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 296(SP),AX
-	MULQ 56(SP)
+	MOVQ 240(SP),AX
+	MULQ 0(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 296(SP),AX
-	MULQ 64(SP)
+	MOVQ 240(SP),AX
+	MULQ 8(SP)
 	MOVQ AX,R8
 	MOVQ DX,R9
-	MOVQ 296(SP),AX
-	MULQ 72(SP)
+	MOVQ 240(SP),AX
+	MULQ 16(SP)
 	MOVQ AX,R10
 	MOVQ DX,R11
-	MOVQ 296(SP),AX
-	MULQ 80(SP)
+	MOVQ 240(SP),AX
+	MULQ 24(SP)
 	MOVQ AX,R12
 	MOVQ DX,R13
-	MOVQ 296(SP),AX
-	MULQ 88(SP)
+	MOVQ 240(SP),AX
+	MULQ 32(SP)
 	MOVQ AX,R14
 	MOVQ DX,R15
-	MOVQ 304(SP),AX
-	MULQ 56(SP)
+	MOVQ 248(SP),AX
+	MULQ 0(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 304(SP),AX
-	MULQ 64(SP)
+	MOVQ 248(SP),AX
+	MULQ 8(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 304(SP),AX
-	MULQ 72(SP)
+	MOVQ 248(SP),AX
+	MULQ 16(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ 304(SP),AX
-	MULQ 80(SP)
+	MOVQ 248(SP),AX
+	MULQ 24(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 304(SP),DX
+	MOVQ 248(SP),DX
 	IMUL3Q $19,DX,AX
-	MULQ 88(SP)
+	MULQ 32(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 312(SP),AX
-	MULQ 56(SP)
+	MOVQ 256(SP),AX
+	MULQ 0(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 312(SP),AX
-	MULQ 64(SP)
+	MOVQ 256(SP),AX
+	MULQ 8(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ 312(SP),AX
-	MULQ 72(SP)
+	MOVQ 256(SP),AX
+	MULQ 16(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 312(SP),DX
+	MOVQ 256(SP),DX
 	IMUL3Q $19,DX,AX
-	MULQ 80(SP)
+	MULQ 24(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 312(SP),DX
+	MOVQ 256(SP),DX
 	IMUL3Q $19,DX,AX
-	MULQ 88(SP)
+	MULQ 32(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 320(SP),AX
-	MULQ 56(SP)
+	MOVQ 264(SP),AX
+	MULQ 0(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ 320(SP),AX
-	MULQ 64(SP)
+	MOVQ 264(SP),AX
+	MULQ 8(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 256(SP),AX
-	MULQ 80(SP)
+	MOVQ 200(SP),AX
+	MULQ 24(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 256(SP),AX
-	MULQ 88(SP)
+	MOVQ 200(SP),AX
+	MULQ 32(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 328(SP),AX
-	MULQ 56(SP)
+	MOVQ 272(SP),AX
+	MULQ 0(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 264(SP),AX
-	MULQ 72(SP)
+	MOVQ 208(SP),AX
+	MULQ 16(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 264(SP),AX
-	MULQ 80(SP)
+	MOVQ 208(SP),AX
+	MULQ 24(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 264(SP),AX
-	MULQ 88(SP)
+	MOVQ 208(SP),AX
+	MULQ 32(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -649,16 +638,16 @@
 	ADDQ ·_2P1234(SB),R11
 	ADDQ ·_2P1234(SB),R12
 	ADDQ ·_2P1234(SB),R13
-	ADDQ 96(SP),SI
-	ADDQ 104(SP),R8
-	ADDQ 112(SP),R9
-	ADDQ 120(SP),AX
-	ADDQ 128(SP),R10
-	SUBQ 96(SP),DX
-	SUBQ 104(SP),CX
-	SUBQ 112(SP),R11
-	SUBQ 120(SP),R12
-	SUBQ 128(SP),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)
@@ -741,7 +730,7 @@
 	MULQ 152(DI)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -856,7 +845,7 @@
 	MULQ 192(DI)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -901,13 +890,13 @@
 	MOVQ R10,192(DI)
 	MOVQ 184(DI),SI
 	IMUL3Q $19,SI,AX
-	MOVQ AX,56(SP)
+	MOVQ AX,0(SP)
 	MULQ 16(DI)
 	MOVQ AX,SI
 	MOVQ DX,CX
 	MOVQ 192(DI),DX
 	IMUL3Q $19,DX,AX
-	MOVQ AX,64(SP)
+	MOVQ AX,8(SP)
 	MULQ 8(DI)
 	ADDQ AX,SI
 	ADCQ DX,CX
@@ -982,11 +971,11 @@
 	MULQ 8(DI)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 56(SP),AX
+	MOVQ 0(SP),AX
 	MULQ 24(DI)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 56(SP),AX
+	MOVQ 0(SP),AX
 	MULQ 32(DI)
 	ADDQ AX,R10
 	ADCQ DX,R11
@@ -994,19 +983,19 @@
 	MULQ 0(DI)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 64(SP),AX
+	MOVQ 8(SP),AX
 	MULQ 16(DI)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 64(SP),AX
+	MOVQ 8(SP),AX
 	MULQ 24(DI)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 64(SP),AX
+	MOVQ 8(SP),AX
 	MULQ 32(DI)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -1049,114 +1038,114 @@
 	MOVQ R9,176(DI)
 	MOVQ AX,184(DI)
 	MOVQ R10,192(DI)
-	MOVQ 200(SP),SI
+	MOVQ 144(SP),SI
 	IMUL3Q $19,SI,AX
-	MOVQ AX,56(SP)
-	MULQ 152(SP)
+	MOVQ AX,0(SP)
+	MULQ 96(SP)
 	MOVQ AX,SI
 	MOVQ DX,CX
-	MOVQ 208(SP),DX
+	MOVQ 152(SP),DX
 	IMUL3Q $19,DX,AX
-	MOVQ AX,64(SP)
-	MULQ 144(SP)
+	MOVQ AX,8(SP)
+	MULQ 88(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 176(SP),AX
-	MULQ 136(SP)
+	MOVQ 120(SP),AX
+	MULQ 80(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 176(SP),AX
-	MULQ 144(SP)
+	MOVQ 120(SP),AX
+	MULQ 88(SP)
 	MOVQ AX,R8
 	MOVQ DX,R9
-	MOVQ 176(SP),AX
-	MULQ 152(SP)
+	MOVQ 120(SP),AX
+	MULQ 96(SP)
 	MOVQ AX,R10
 	MOVQ DX,R11
-	MOVQ 176(SP),AX
-	MULQ 160(SP)
+	MOVQ 120(SP),AX
+	MULQ 104(SP)
 	MOVQ AX,R12
 	MOVQ DX,R13
-	MOVQ 176(SP),AX
-	MULQ 168(SP)
+	MOVQ 120(SP),AX
+	MULQ 112(SP)
 	MOVQ AX,R14
 	MOVQ DX,R15
-	MOVQ 184(SP),AX
-	MULQ 136(SP)
+	MOVQ 128(SP),AX
+	MULQ 80(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 184(SP),AX
-	MULQ 144(SP)
+	MOVQ 128(SP),AX
+	MULQ 88(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 184(SP),AX
-	MULQ 152(SP)
+	MOVQ 128(SP),AX
+	MULQ 96(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ 184(SP),AX
-	MULQ 160(SP)
+	MOVQ 128(SP),AX
+	MULQ 104(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 184(SP),DX
+	MOVQ 128(SP),DX
 	IMUL3Q $19,DX,AX
-	MULQ 168(SP)
+	MULQ 112(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 192(SP),AX
-	MULQ 136(SP)
+	MOVQ 136(SP),AX
+	MULQ 80(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 192(SP),AX
-	MULQ 144(SP)
+	MOVQ 136(SP),AX
+	MULQ 88(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ 192(SP),AX
-	MULQ 152(SP)
+	MOVQ 136(SP),AX
+	MULQ 96(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 192(SP),DX
+	MOVQ 136(SP),DX
 	IMUL3Q $19,DX,AX
-	MULQ 160(SP)
+	MULQ 104(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
-	MOVQ 192(SP),DX
+	MOVQ 136(SP),DX
 	IMUL3Q $19,DX,AX
-	MULQ 168(SP)
+	MULQ 112(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 200(SP),AX
-	MULQ 136(SP)
+	MOVQ 144(SP),AX
+	MULQ 80(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ 200(SP),AX
-	MULQ 144(SP)
+	MOVQ 144(SP),AX
+	MULQ 88(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 56(SP),AX
-	MULQ 160(SP)
+	MOVQ 0(SP),AX
+	MULQ 104(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 56(SP),AX
-	MULQ 168(SP)
+	MOVQ 0(SP),AX
+	MULQ 112(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 208(SP),AX
-	MULQ 136(SP)
+	MOVQ 152(SP),AX
+	MULQ 80(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 64(SP),AX
-	MULQ 152(SP)
+	MOVQ 8(SP),AX
+	MULQ 96(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 64(SP),AX
-	MULQ 160(SP)
+	MOVQ 8(SP),AX
+	MULQ 104(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 64(SP),AX
-	MULQ 168(SP)
+	MOVQ 8(SP),AX
+	MULQ 112(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -1199,37 +1188,37 @@
 	MOVQ R9,56(DI)
 	MOVQ AX,64(DI)
 	MOVQ R10,72(DI)
-	MOVQ 216(SP),AX
+	MOVQ 160(SP),AX
 	MULQ ·_121666_213(SB)
 	SHRQ $13,AX
 	MOVQ AX,SI
 	MOVQ DX,CX
-	MOVQ 224(SP),AX
+	MOVQ 168(SP),AX
 	MULQ ·_121666_213(SB)
 	SHRQ $13,AX
 	ADDQ AX,CX
 	MOVQ DX,R8
-	MOVQ 232(SP),AX
+	MOVQ 176(SP),AX
 	MULQ ·_121666_213(SB)
 	SHRQ $13,AX
 	ADDQ AX,R8
 	MOVQ DX,R9
-	MOVQ 240(SP),AX
+	MOVQ 184(SP),AX
 	MULQ ·_121666_213(SB)
 	SHRQ $13,AX
 	ADDQ AX,R9
 	MOVQ DX,R10
-	MOVQ 248(SP),AX
+	MOVQ 192(SP),AX
 	MULQ ·_121666_213(SB)
 	SHRQ $13,AX
 	ADDQ AX,R10
 	IMUL3Q $19,DX,DX
 	ADDQ DX,SI
-	ADDQ 136(SP),SI
-	ADDQ 144(SP),CX
-	ADDQ 152(SP),R8
-	ADDQ 160(SP),R9
-	ADDQ 168(SP),R10
+	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)
@@ -1237,112 +1226,112 @@
 	MOVQ R10,112(DI)
 	MOVQ 104(DI),SI
 	IMUL3Q $19,SI,AX
-	MOVQ AX,56(SP)
-	MULQ 232(SP)
+	MOVQ AX,0(SP)
+	MULQ 176(SP)
 	MOVQ AX,SI
 	MOVQ DX,CX
 	MOVQ 112(DI),DX
 	IMUL3Q $19,DX,AX
-	MOVQ AX,64(SP)
-	MULQ 224(SP)
+	MOVQ AX,8(SP)
+	MULQ 168(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
 	MOVQ 80(DI),AX
-	MULQ 216(SP)
+	MULQ 160(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
 	MOVQ 80(DI),AX
-	MULQ 224(SP)
+	MULQ 168(SP)
 	MOVQ AX,R8
 	MOVQ DX,R9
 	MOVQ 80(DI),AX
-	MULQ 232(SP)
+	MULQ 176(SP)
 	MOVQ AX,R10
 	MOVQ DX,R11
 	MOVQ 80(DI),AX
-	MULQ 240(SP)
+	MULQ 184(SP)
 	MOVQ AX,R12
 	MOVQ DX,R13
 	MOVQ 80(DI),AX
-	MULQ 248(SP)
+	MULQ 192(SP)
 	MOVQ AX,R14
 	MOVQ DX,R15
 	MOVQ 88(DI),AX
-	MULQ 216(SP)
+	MULQ 160(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
 	MOVQ 88(DI),AX
-	MULQ 224(SP)
+	MULQ 168(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
 	MOVQ 88(DI),AX
-	MULQ 232(SP)
+	MULQ 176(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
 	MOVQ 88(DI),AX
-	MULQ 240(SP)
+	MULQ 184(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
 	MOVQ 88(DI),DX
 	IMUL3Q $19,DX,AX
-	MULQ 248(SP)
+	MULQ 192(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
 	MOVQ 96(DI),AX
-	MULQ 216(SP)
+	MULQ 160(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
 	MOVQ 96(DI),AX
-	MULQ 224(SP)
+	MULQ 168(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
 	MOVQ 96(DI),AX
-	MULQ 232(SP)
+	MULQ 176(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
 	MOVQ 96(DI),DX
 	IMUL3Q $19,DX,AX
-	MULQ 240(SP)
+	MULQ 184(SP)
 	ADDQ AX,SI
 	ADCQ DX,CX
 	MOVQ 96(DI),DX
 	IMUL3Q $19,DX,AX
-	MULQ 248(SP)
+	MULQ 192(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
 	MOVQ 104(DI),AX
-	MULQ 216(SP)
+	MULQ 160(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
 	MOVQ 104(DI),AX
-	MULQ 224(SP)
+	MULQ 168(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 56(SP),AX
-	MULQ 240(SP)
+	MOVQ 0(SP),AX
+	MULQ 184(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 56(SP),AX
-	MULQ 248(SP)
+	MOVQ 0(SP),AX
+	MULQ 192(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
 	MOVQ 112(DI),AX
-	MULQ 216(SP)
+	MULQ 160(SP)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ 64(SP),AX
-	MULQ 232(SP)
+	MOVQ 8(SP),AX
+	MULQ 176(SP)
 	ADDQ AX,R8
 	ADCQ DX,R9
-	MOVQ 64(SP),AX
-	MULQ 240(SP)
+	MOVQ 8(SP),AX
+	MULQ 184(SP)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 64(SP),AX
-	MULQ 248(SP)
+	MOVQ 8(SP),AX
+	MULQ 192(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -1385,14 +1374,4 @@
 	MOVQ R9,96(DI)
 	MOVQ AX,104(DI)
 	MOVQ R10,112(DI)
-	MOVQ 0(SP),R11
-	MOVQ 8(SP),R12
-	MOVQ 16(SP),R13
-	MOVQ 24(SP),R14
-	MOVQ 32(SP),R15
-	MOVQ 40(SP),BX
-	MOVQ 48(SP),BP
-	MOVQ R11,SP
-	MOVQ DI,AX
-	MOVQ SI,DX
 	RET
diff --git a/src/ssl/test/runner/curve25519/mul_amd64.s b/src/ssl/test/runner/curve25519/mul_amd64.s
index e48d183..b162e65 100644
--- a/src/ssl/test/runner/curve25519/mul_amd64.s
+++ b/src/ssl/test/runner/curve25519/mul_amd64.s
@@ -7,36 +7,24 @@
 
 // +build amd64,!gccgo,!appengine
 
+#include "const_amd64.h"
+
 // func mul(dest, a, b *[5]uint64)
-TEXT ·mul(SB),0,$128-24
+TEXT ·mul(SB),0,$16-24
 	MOVQ dest+0(FP), DI
 	MOVQ a+8(FP), SI
 	MOVQ b+16(FP), DX
 
-	MOVQ SP,R11
-	MOVQ $31,CX
-	NOTQ CX
-	ANDQ CX,SP
-	ADDQ $32,SP
-
-	MOVQ R11,0(SP)
-	MOVQ R12,8(SP)
-	MOVQ R13,16(SP)
-	MOVQ R14,24(SP)
-	MOVQ R15,32(SP)
-	MOVQ BX,40(SP)
-	MOVQ BP,48(SP)
-	MOVQ DI,56(SP)
 	MOVQ DX,CX
 	MOVQ 24(SI),DX
 	IMUL3Q $19,DX,AX
-	MOVQ AX,64(SP)
+	MOVQ AX,0(SP)
 	MULQ 16(CX)
 	MOVQ AX,R8
 	MOVQ DX,R9
 	MOVQ 32(SI),DX
 	IMUL3Q $19,DX,AX
-	MOVQ AX,72(SP)
+	MOVQ AX,8(SP)
 	MULQ 8(CX)
 	ADDQ AX,R8
 	ADCQ DX,R9
@@ -111,11 +99,11 @@
 	MULQ 8(CX)
 	ADDQ AX,BX
 	ADCQ DX,BP
-	MOVQ 64(SP),AX
+	MOVQ 0(SP),AX
 	MULQ 24(CX)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 64(SP),AX
+	MOVQ 0(SP),AX
 	MULQ 32(CX)
 	ADDQ AX,R12
 	ADCQ DX,R13
@@ -123,19 +111,19 @@
 	MULQ 0(CX)
 	ADDQ AX,BX
 	ADCQ DX,BP
-	MOVQ 72(SP),AX
+	MOVQ 8(SP),AX
 	MULQ 16(CX)
 	ADDQ AX,R10
 	ADCQ DX,R11
-	MOVQ 72(SP),AX
+	MOVQ 8(SP),AX
 	MULQ 24(CX)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ 72(SP),AX
+	MOVQ 8(SP),AX
 	MULQ 32(CX)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ ·REDMASK51(SB),SI
+	MOVQ $REDMASK51,SI
 	SHLQ $13,R9:R8
 	ANDQ SI,R8
 	SHLQ $13,R11:R10
@@ -178,14 +166,4 @@
 	MOVQ R9,16(DI)
 	MOVQ AX,24(DI)
 	MOVQ R10,32(DI)
-	MOVQ 0(SP),R11
-	MOVQ 8(SP),R12
-	MOVQ 16(SP),R13
-	MOVQ 24(SP),R14
-	MOVQ 32(SP),R15
-	MOVQ 40(SP),BX
-	MOVQ 48(SP),BP
-	MOVQ R11,SP
-	MOVQ DI,AX
-	MOVQ SI,DX
 	RET
diff --git a/src/ssl/test/runner/curve25519/square_amd64.s b/src/ssl/test/runner/curve25519/square_amd64.s
index 78d1a50..4e864a8 100644
--- a/src/ssl/test/runner/curve25519/square_amd64.s
+++ b/src/ssl/test/runner/curve25519/square_amd64.s
@@ -7,24 +7,13 @@
 
 // +build amd64,!gccgo,!appengine
 
+#include "const_amd64.h"
+
 // func square(out, in *[5]uint64)
-TEXT ·square(SB),7,$96-16
+TEXT ·square(SB),7,$0-16
 	MOVQ out+0(FP), DI
 	MOVQ in+8(FP), SI
 
-	MOVQ SP,R11
-	MOVQ $31,CX
-	NOTQ CX
-	ANDQ CX,SP
-	ADDQ $32, SP
-
-	MOVQ R11,0(SP)
-	MOVQ R12,8(SP)
-	MOVQ R13,16(SP)
-	MOVQ R14,24(SP)
-	MOVQ R15,32(SP)
-	MOVQ BX,40(SP)
-	MOVQ BP,48(SP)
 	MOVQ 0(SI),AX
 	MULQ 0(SI)
 	MOVQ AX,CX
@@ -97,7 +86,7 @@
 	MULQ 32(SI)
 	ADDQ AX,R13
 	ADCQ DX,R14
-	MOVQ ·REDMASK51(SB),SI
+	MOVQ $REDMASK51,SI
 	SHLQ $13,R8:CX
 	ANDQ SI,CX
 	SHLQ $13,R10:R9
@@ -140,14 +129,4 @@
 	MOVQ R9,16(DI)
 	MOVQ AX,24(DI)
 	MOVQ R10,32(DI)
-	MOVQ 0(SP),R11
-	MOVQ 8(SP),R12
-	MOVQ 16(SP),R13
-	MOVQ 24(SP),R14
-	MOVQ 32(SP),R15
-	MOVQ 40(SP),BX
-	MOVQ 48(SP),BP
-	MOVQ R11,SP
-	MOVQ DI,AX
-	MOVQ SI,DX
 	RET
diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json
index 80a9bf1..603ca24 100644
--- a/src/ssl/test/runner/fuzzer_mode.json
+++ b/src/ssl/test/runner/fuzzer_mode.json
@@ -21,6 +21,7 @@
     "*-InvalidSignature-*": "Fuzzer mode always accepts a signature.",
     "*Auth-Verify-RSA-PKCS1-*-TLS13": "Fuzzer mode always accepts a signature.",
     "*Auth-Verify-ECDSA-SHA1-TLS13": "Fuzzer mode always accepts a signature.",
+    "*Auth-Verify-ECDSA-P224-*-TLS13": "Fuzzer mode always accepts a signature.",
     "Verify-*Auth-SignatureType*": "Fuzzer mode always accepts a signature.",
     "ECDSACurveMismatch-Verify-TLS13": "Fuzzer mode always accepts a signature.",
     "InvalidChannelIDSignature-*": "Fuzzer mode always accepts a signature.",
@@ -34,6 +35,12 @@
 
     "Resume-Server-*Binder*": "Fuzzer mode does not check binders.",
 
-    "SkipEarlyData*": "Trial decryption does not work with the NULL cipher."
+    "SkipEarlyData*": "Trial decryption does not work with the NULL cipher.",
+    "TLS13-EarlyDataChannelID-OfferBoth-Server": "Trial decryption does not work with the NULL cipher.",
+    "TLS13-EarlyData-NonZeroRTTSession-Server": "Trial decryption does not work with the NULL cipher.",
+    "TLS13-EarlyData-SkipEndOfEarlyData": "Trial decryption does not work with the NULL cipher.",
+    "TLS13-EarlyData-ALPNMismatch-Server": "Trial decryption does not work with the NULL cipher.",
+    "TLS13-EarlyData-ALPNOmitted1-Server": "Trial decryption does not work with the NULL cipher.",
+    "TLS13-EarlyData-ALPNOmitted2-Server": "Trial decryption does not work with the NULL cipher."
   }
 }
diff --git a/src/ssl/test/runner/poly1305/const_amd64.s b/src/ssl/test/runner/poly1305/const_amd64.s
deleted file mode 100644
index 8e861f3..0000000
--- a/src/ssl/test/runner/poly1305/const_amd64.s
+++ /dev/null
@@ -1,45 +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
-
-DATA ·SCALE(SB)/8, $0x37F4000000000000
-GLOBL ·SCALE(SB), 8, $8
-DATA ·TWO32(SB)/8, $0x41F0000000000000
-GLOBL ·TWO32(SB), 8, $8
-DATA ·TWO64(SB)/8, $0x43F0000000000000
-GLOBL ·TWO64(SB), 8, $8
-DATA ·TWO96(SB)/8, $0x45F0000000000000
-GLOBL ·TWO96(SB), 8, $8
-DATA ·ALPHA32(SB)/8, $0x45E8000000000000
-GLOBL ·ALPHA32(SB), 8, $8
-DATA ·ALPHA64(SB)/8, $0x47E8000000000000
-GLOBL ·ALPHA64(SB), 8, $8
-DATA ·ALPHA96(SB)/8, $0x49E8000000000000
-GLOBL ·ALPHA96(SB), 8, $8
-DATA ·ALPHA130(SB)/8, $0x4C08000000000000
-GLOBL ·ALPHA130(SB), 8, $8
-DATA ·DOFFSET0(SB)/8, $0x4330000000000000
-GLOBL ·DOFFSET0(SB), 8, $8
-DATA ·DOFFSET1(SB)/8, $0x4530000000000000
-GLOBL ·DOFFSET1(SB), 8, $8
-DATA ·DOFFSET2(SB)/8, $0x4730000000000000
-GLOBL ·DOFFSET2(SB), 8, $8
-DATA ·DOFFSET3(SB)/8, $0x4930000000000000
-GLOBL ·DOFFSET3(SB), 8, $8
-DATA ·DOFFSET3MINUSTWO128(SB)/8, $0x492FFFFE00000000
-GLOBL ·DOFFSET3MINUSTWO128(SB), 8, $8
-DATA ·HOFFSET0(SB)/8, $0x43300001FFFFFFFB
-GLOBL ·HOFFSET0(SB), 8, $8
-DATA ·HOFFSET1(SB)/8, $0x45300001FFFFFFFE
-GLOBL ·HOFFSET1(SB), 8, $8
-DATA ·HOFFSET2(SB)/8, $0x47300001FFFFFFFE
-GLOBL ·HOFFSET2(SB), 8, $8
-DATA ·HOFFSET3(SB)/8, $0x49300003FFFFFFFE
-GLOBL ·HOFFSET3(SB), 8, $8
-DATA ·ROUNDING(SB)/2, $0x137f
-GLOBL ·ROUNDING(SB), 8, $2
diff --git a/src/ssl/test/runner/poly1305/poly1305_amd64.s b/src/ssl/test/runner/poly1305/poly1305_amd64.s
deleted file mode 100644
index f8d4ee9..0000000
--- a/src/ssl/test/runner/poly1305/poly1305_amd64.s
+++ /dev/null
@@ -1,497 +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 poly1305(out *[16]byte, m *byte, mlen uint64, key *[32]key)
-TEXT ·poly1305(SB),0,$224-32
-	MOVQ out+0(FP),DI
-	MOVQ m+8(FP),SI
-	MOVQ mlen+16(FP),DX
-	MOVQ key+24(FP),CX
-
-	MOVQ SP,R11
-	MOVQ $31,R9
-	NOTQ R9
-	ANDQ R9,SP
-	ADDQ $32,SP
-
-	MOVQ R11,32(SP)
-	MOVQ R12,40(SP)
-	MOVQ R13,48(SP)
-	MOVQ R14,56(SP)
-	MOVQ R15,64(SP)
-	MOVQ BX,72(SP)
-	MOVQ BP,80(SP)
-	FLDCW ·ROUNDING(SB)
-	MOVL 0(CX),R8
-	MOVL 4(CX),R9
-	MOVL 8(CX),AX
-	MOVL 12(CX),R10
-	MOVQ DI,88(SP)
-	MOVQ CX,96(SP)
-	MOVL $0X43300000,108(SP)
-	MOVL $0X45300000,116(SP)
-	MOVL $0X47300000,124(SP)
-	MOVL $0X49300000,132(SP)
-	ANDL $0X0FFFFFFF,R8
-	ANDL $0X0FFFFFFC,R9
-	ANDL $0X0FFFFFFC,AX
-	ANDL $0X0FFFFFFC,R10
-	MOVL R8,104(SP)
-	MOVL R9,112(SP)
-	MOVL AX,120(SP)
-	MOVL R10,128(SP)
-	FMOVD 104(SP), F0
-	FSUBD ·DOFFSET0(SB), F0
-	FMOVD 112(SP), F0
-	FSUBD ·DOFFSET1(SB), F0
-	FMOVD 120(SP), F0
-	FSUBD ·DOFFSET2(SB), F0
-	FMOVD 128(SP), F0
-	FSUBD ·DOFFSET3(SB), F0
-	FXCHD F0, F3
-	FMOVDP F0, 136(SP)
-	FXCHD F0, F1
-	FMOVD F0, 144(SP)
-	FMULD ·SCALE(SB), F0
-	FMOVDP F0, 152(SP)
-	FMOVD F0, 160(SP)
-	FMULD ·SCALE(SB), F0
-	FMOVDP F0, 168(SP)
-	FMOVD F0, 176(SP)
-	FMULD ·SCALE(SB), F0
-	FMOVDP F0, 184(SP)
-	FLDZ
-	FLDZ
-	FLDZ
-	FLDZ
-	CMPQ DX,$16
-	JB ADDATMOST15BYTES
-	INITIALATLEAST16BYTES:
-	MOVL 12(SI),DI
-	MOVL 8(SI),CX
-	MOVL 4(SI),R8
-	MOVL 0(SI),R9
-	MOVL DI,128(SP)
-	MOVL CX,120(SP)
-	MOVL R8,112(SP)
-	MOVL R9,104(SP)
-	ADDQ $16,SI
-	SUBQ $16,DX
-	FXCHD F0, F3
-	FADDD 128(SP), F0
-	FSUBD ·DOFFSET3MINUSTWO128(SB), F0
-	FXCHD F0, F1
-	FADDD 112(SP), F0
-	FSUBD ·DOFFSET1(SB), F0
-	FXCHD F0, F2
-	FADDD 120(SP), F0
-	FSUBD ·DOFFSET2(SB), F0
-	FXCHD F0, F3
-	FADDD 104(SP), F0
-	FSUBD ·DOFFSET0(SB), F0
-	CMPQ DX,$16
-	JB MULTIPLYADDATMOST15BYTES
-	MULTIPLYADDATLEAST16BYTES:
-	MOVL 12(SI),DI
-	MOVL 8(SI),CX
-	MOVL 4(SI),R8
-	MOVL 0(SI),R9
-	MOVL DI,128(SP)
-	MOVL CX,120(SP)
-	MOVL R8,112(SP)
-	MOVL R9,104(SP)
-	ADDQ $16,SI
-	SUBQ $16,DX
-	FMOVD ·ALPHA130(SB), F0
-	FADDD F2,F0
-	FSUBD ·ALPHA130(SB), F0
-	FSUBD F0,F2
-	FMULD ·SCALE(SB), F0
-	FMOVD ·ALPHA32(SB), F0
-	FADDD F2,F0
-	FSUBD ·ALPHA32(SB), F0
-	FSUBD F0,F2
-	FXCHD F0, F2
-	FADDDP F0,F1
-	FMOVD ·ALPHA64(SB), F0
-	FADDD F4,F0
-	FSUBD ·ALPHA64(SB), F0
-	FSUBD F0,F4
-	FMOVD ·ALPHA96(SB), F0
-	FADDD F6,F0
-	FSUBD ·ALPHA96(SB), F0
-	FSUBD F0,F6
-	FXCHD F0, F6
-	FADDDP F0,F1
-	FXCHD F0, F3
-	FADDDP F0,F5
-	FXCHD F0, F3
-	FADDDP F0,F1
-	FMOVD 176(SP), F0
-	FMULD F3,F0
-	FMOVD 160(SP), F0
-	FMULD F4,F0
-	FMOVD 144(SP), F0
-	FMULD F5,F0
-	FMOVD 136(SP), F0
-	FMULDP F0,F6
-	FMOVD 160(SP), F0
-	FMULD F4,F0
-	FADDDP F0,F3
-	FMOVD 144(SP), F0
-	FMULD F4,F0
-	FADDDP F0,F2
-	FMOVD 136(SP), F0
-	FMULD F4,F0
-	FADDDP F0,F1
-	FMOVD 184(SP), F0
-	FMULDP F0,F4
-	FXCHD F0, F3
-	FADDDP F0,F5
-	FMOVD 144(SP), F0
-	FMULD F4,F0
-	FADDDP F0,F2
-	FMOVD 136(SP), F0
-	FMULD F4,F0
-	FADDDP F0,F1
-	FMOVD 184(SP), F0
-	FMULD F4,F0
-	FADDDP F0,F3
-	FMOVD 168(SP), F0
-	FMULDP F0,F4
-	FXCHD F0, F3
-	FADDDP F0,F4
-	FMOVD 136(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F1
-	FXCHD F0, F3
-	FMOVD 184(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F3
-	FXCHD F0, F1
-	FMOVD 168(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F1
-	FMOVD 152(SP), F0
-	FMULDP F0,F5
-	FXCHD F0, F4
-	FADDDP F0,F1
-	CMPQ DX,$16
-	FXCHD F0, F2
-	FMOVD 128(SP), F0
-	FSUBD ·DOFFSET3MINUSTWO128(SB), F0
-	FADDDP F0,F1
-	FXCHD F0, F1
-	FMOVD 120(SP), F0
-	FSUBD ·DOFFSET2(SB), F0
-	FADDDP F0,F1
-	FXCHD F0, F3
-	FMOVD 112(SP), F0
-	FSUBD ·DOFFSET1(SB), F0
-	FADDDP F0,F1
-	FXCHD F0, F2
-	FMOVD 104(SP), F0
-	FSUBD ·DOFFSET0(SB), F0
-	FADDDP F0,F1
-	JAE MULTIPLYADDATLEAST16BYTES
-	MULTIPLYADDATMOST15BYTES:
-	FMOVD ·ALPHA130(SB), F0
-	FADDD F2,F0
-	FSUBD ·ALPHA130(SB), F0
-	FSUBD F0,F2
-	FMULD ·SCALE(SB), F0
-	FMOVD ·ALPHA32(SB), F0
-	FADDD F2,F0
-	FSUBD ·ALPHA32(SB), F0
-	FSUBD F0,F2
-	FMOVD ·ALPHA64(SB), F0
-	FADDD F5,F0
-	FSUBD ·ALPHA64(SB), F0
-	FSUBD F0,F5
-	FMOVD ·ALPHA96(SB), F0
-	FADDD F7,F0
-	FSUBD ·ALPHA96(SB), F0
-	FSUBD F0,F7
-	FXCHD F0, F7
-	FADDDP F0,F1
-	FXCHD F0, F5
-	FADDDP F0,F1
-	FXCHD F0, F3
-	FADDDP F0,F5
-	FADDDP F0,F1
-	FMOVD 176(SP), F0
-	FMULD F1,F0
-	FMOVD 160(SP), F0
-	FMULD F2,F0
-	FMOVD 144(SP), F0
-	FMULD F3,F0
-	FMOVD 136(SP), F0
-	FMULDP F0,F4
-	FMOVD 160(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F3
-	FMOVD 144(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F2
-	FMOVD 136(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F1
-	FMOVD 184(SP), F0
-	FMULDP F0,F5
-	FXCHD F0, F4
-	FADDDP F0,F3
-	FMOVD 144(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F2
-	FMOVD 136(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F1
-	FMOVD 184(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F4
-	FMOVD 168(SP), F0
-	FMULDP F0,F5
-	FXCHD F0, F4
-	FADDDP F0,F2
-	FMOVD 136(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F1
-	FMOVD 184(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F4
-	FMOVD 168(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F3
-	FMOVD 152(SP), F0
-	FMULDP F0,F5
-	FXCHD F0, F4
-	FADDDP F0,F1
-	ADDATMOST15BYTES:
-	CMPQ DX,$0
-	JE NOMOREBYTES
-	MOVL $0,0(SP)
-	MOVL $0, 4 (SP)
-	MOVL $0, 8 (SP)
-	MOVL $0, 12 (SP)
-	LEAQ 0(SP),DI
-	MOVQ DX,CX
-	REP; MOVSB
-	MOVB $1,0(DI)
-	MOVL  12 (SP),DI
-	MOVL  8 (SP),SI
-	MOVL  4 (SP),DX
-	MOVL 0(SP),CX
-	MOVL DI,128(SP)
-	MOVL SI,120(SP)
-	MOVL DX,112(SP)
-	MOVL CX,104(SP)
-	FXCHD F0, F3
-	FADDD 128(SP), F0
-	FSUBD ·DOFFSET3(SB), F0
-	FXCHD F0, F2
-	FADDD 120(SP), F0
-	FSUBD ·DOFFSET2(SB), F0
-	FXCHD F0, F1
-	FADDD 112(SP), F0
-	FSUBD ·DOFFSET1(SB), F0
-	FXCHD F0, F3
-	FADDD 104(SP), F0
-	FSUBD ·DOFFSET0(SB), F0
-	FMOVD ·ALPHA130(SB), F0
-	FADDD F3,F0
-	FSUBD ·ALPHA130(SB), F0
-	FSUBD F0,F3
-	FMULD ·SCALE(SB), F0
-	FMOVD ·ALPHA32(SB), F0
-	FADDD F2,F0
-	FSUBD ·ALPHA32(SB), F0
-	FSUBD F0,F2
-	FMOVD ·ALPHA64(SB), F0
-	FADDD F6,F0
-	FSUBD ·ALPHA64(SB), F0
-	FSUBD F0,F6
-	FMOVD ·ALPHA96(SB), F0
-	FADDD F5,F0
-	FSUBD ·ALPHA96(SB), F0
-	FSUBD F0,F5
-	FXCHD F0, F4
-	FADDDP F0,F3
-	FXCHD F0, F6
-	FADDDP F0,F1
-	FXCHD F0, F3
-	FADDDP F0,F5
-	FXCHD F0, F3
-	FADDDP F0,F1
-	FMOVD 176(SP), F0
-	FMULD F3,F0
-	FMOVD 160(SP), F0
-	FMULD F4,F0
-	FMOVD 144(SP), F0
-	FMULD F5,F0
-	FMOVD 136(SP), F0
-	FMULDP F0,F6
-	FMOVD 160(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F3
-	FMOVD 144(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F2
-	FMOVD 136(SP), F0
-	FMULD F5,F0
-	FADDDP F0,F1
-	FMOVD 184(SP), F0
-	FMULDP F0,F5
-	FXCHD F0, F4
-	FADDDP F0,F5
-	FMOVD 144(SP), F0
-	FMULD F6,F0
-	FADDDP F0,F2
-	FMOVD 136(SP), F0
-	FMULD F6,F0
-	FADDDP F0,F1
-	FMOVD 184(SP), F0
-	FMULD F6,F0
-	FADDDP F0,F4
-	FMOVD 168(SP), F0
-	FMULDP F0,F6
-	FXCHD F0, F5
-	FADDDP F0,F4
-	FMOVD 136(SP), F0
-	FMULD F2,F0
-	FADDDP F0,F1
-	FMOVD 184(SP), F0
-	FMULD F2,F0
-	FADDDP F0,F5
-	FMOVD 168(SP), F0
-	FMULD F2,F0
-	FADDDP F0,F3
-	FMOVD 152(SP), F0
-	FMULDP F0,F2
-	FXCHD F0, F1
-	FADDDP F0,F3
-	FXCHD F0, F3
-	FXCHD F0, F2
-	NOMOREBYTES:
-	MOVL $0,R10
-	FMOVD ·ALPHA130(SB), F0
-	FADDD F4,F0
-	FSUBD ·ALPHA130(SB), F0
-	FSUBD F0,F4
-	FMULD ·SCALE(SB), F0
-	FMOVD ·ALPHA32(SB), F0
-	FADDD F2,F0
-	FSUBD ·ALPHA32(SB), F0
-	FSUBD F0,F2
-	FMOVD ·ALPHA64(SB), F0
-	FADDD F4,F0
-	FSUBD ·ALPHA64(SB), F0
-	FSUBD F0,F4
-	FMOVD ·ALPHA96(SB), F0
-	FADDD F6,F0
-	FSUBD ·ALPHA96(SB), F0
-	FXCHD F0, F6
-	FSUBD F6,F0
-	FXCHD F0, F4
-	FADDDP F0,F3
-	FXCHD F0, F4
-	FADDDP F0,F1
-	FXCHD F0, F2
-	FADDDP F0,F3
-	FXCHD F0, F4
-	FADDDP F0,F3
-	FXCHD F0, F3
-	FADDD ·HOFFSET0(SB), F0
-	FXCHD F0, F3
-	FADDD ·HOFFSET1(SB), F0
-	FXCHD F0, F1
-	FADDD ·HOFFSET2(SB), F0
-	FXCHD F0, F2
-	FADDD ·HOFFSET3(SB), F0
-	FXCHD F0, F3
-	FMOVDP F0, 104(SP)
-	FMOVDP F0, 112(SP)
-	FMOVDP F0, 120(SP)
-	FMOVDP F0, 128(SP)
-	MOVL 108(SP),DI
-	ANDL $63,DI
-	MOVL 116(SP),SI
-	ANDL $63,SI
-	MOVL 124(SP),DX
-	ANDL $63,DX
-	MOVL 132(SP),CX
-	ANDL $63,CX
-	MOVL 112(SP),R8
-	ADDL DI,R8
-	MOVQ R8,112(SP)
-	MOVL 120(SP),DI
-	ADCL SI,DI
-	MOVQ DI,120(SP)
-	MOVL 128(SP),DI
-	ADCL DX,DI
-	MOVQ DI,128(SP)
-	MOVL R10,DI
-	ADCL CX,DI
-	MOVQ DI,136(SP)
-	MOVQ $5,DI
-	MOVL 104(SP),SI
-	ADDL SI,DI
-	MOVQ DI,104(SP)
-	MOVL R10,DI
-	MOVQ 112(SP),DX
-	ADCL DX,DI
-	MOVQ DI,112(SP)
-	MOVL R10,DI
-	MOVQ 120(SP),CX
-	ADCL CX,DI
-	MOVQ DI,120(SP)
-	MOVL R10,DI
-	MOVQ 128(SP),R8
-	ADCL R8,DI
-	MOVQ DI,128(SP)
-	MOVQ $0XFFFFFFFC,DI
-	MOVQ 136(SP),R9
-	ADCL R9,DI
-	SARL $16,DI
-	MOVQ DI,R9
-	XORL $0XFFFFFFFF,R9
-	ANDQ DI,SI
-	MOVQ 104(SP),AX
-	ANDQ R9,AX
-	ORQ AX,SI
-	ANDQ DI,DX
-	MOVQ 112(SP),AX
-	ANDQ R9,AX
-	ORQ AX,DX
-	ANDQ DI,CX
-	MOVQ 120(SP),AX
-	ANDQ R9,AX
-	ORQ AX,CX
-	ANDQ DI,R8
-	MOVQ 128(SP),DI
-	ANDQ R9,DI
-	ORQ DI,R8
-	MOVQ 88(SP),DI
-	MOVQ 96(SP),R9
-	ADDL 16(R9),SI
-	ADCL 20(R9),DX
-	ADCL 24(R9),CX
-	ADCL 28(R9),R8
-	MOVL SI,0(DI)
-	MOVL DX,4(DI)
-	MOVL CX,8(DI)
-	MOVL R8,12(DI)
-	MOVQ 32(SP),R11
-	MOVQ 40(SP),R12
-	MOVQ 48(SP),R13
-	MOVQ 56(SP),R14
-	MOVQ 64(SP),R15
-	MOVQ 72(SP),BX
-	MOVQ 80(SP),BP
-	MOVQ R11,SP
-	RET
diff --git a/src/ssl/test/runner/poly1305/poly1305_arm.s b/src/ssl/test/runner/poly1305/poly1305_arm.s
deleted file mode 100644
index c153867..0000000
--- a/src/ssl/test/runner/poly1305/poly1305_arm.s
+++ /dev/null
@@ -1,379 +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.
-
-// 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.
-
-// +build arm,!gccgo,!appengine
-
-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),4,$-4
-  MOVM.DB.W [R4-R11], (R13)
-  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)
-  MOVM.IA.W (R13), [R4-R11]
-  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),4,$-4
-  MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13)
-  SUB $128, R13
-  MOVW R0, 36(R13)
-  MOVW R1, 40(R13)
-  MOVW R2, 44(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, 32(R13)
-  ADD $64, 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 $48, 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, 40(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 32(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 $64, 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, 24(R13)
-  MOVW R11, 28(R13)
-  MOVW R12, 16(R13)
-  MOVW R14, 20(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, 8(R13)
-  MOVW R11, 12(R13)
-  MOVW R12, 0(R13)
-  MOVW R14, w+4(SP)
-  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)
-  MOVM.IA (R13), [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 w+44(SP), R12
-  MOVW w+40(SP), R14
-  MOVW R0, R6
-  CMP $32, R12
-  SUB $16, R12, R12
-  MOVW R12, 44(R13)
-  BHS poly1305_blocks_armv6_mainloop
-poly1305_blocks_armv6_done:
-  MOVW 36(R13), R12
-  MOVW R5, 20(R12)
-  MOVW R6, 24(R12)
-  MOVW R7, 28(R12)
-  MOVW R8, 32(R12)
-  MOVW R9, 36(R12)
-  ADD $128, R13, R13
-  MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, 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)
-
-TEXT poly1305_finish_ext_armv6<>(SB),4,$-4
-  MOVM.DB.W [R4, R5, R6, R7, R8, R9, g, R11, R14], (R13)
-  SUB $16, R13, R13
-  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
-  MOVW R13, R9
-  MOVW R0, 0(R13)
-  MOVW R0, 4(R13)
-  MOVW R0, 8(R13)
-  MOVW R0, 12(R13)
-  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
-  MOVW 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, R14
-  MOVW R14>>31, R12
-  SUB $1, R12
-  AND R12, R6, R6
-  AND R12, R7, R7
-  AND R12, g, g
-  AND R12, R11, R11
-  AND R12, R14, R14
-  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 R14, 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)
-  ADD $16, R13, R13
-  MOVM.IA.W (R13), [R4, R5, R6, R7, R8, R9, g, R11, R14]
-  RET
-
-// func poly1305_auth_armv6(out *[16]byte, m *byte, mlen uint32, key *[32]key)
-TEXT ·poly1305_auth_armv6(SB),0,$280-16
-  MOVW  out+0(FP), R4
-  MOVW  m+4(FP), R5
-  MOVW  mlen+8(FP), R6
-  MOVW  key+12(FP), R7
-
-  MOVW R13, R8
-  BIC $63, R13
-  SUB $64, R13, R13
-  MOVW  R13, R0
-  MOVW  R7, R1
-  BL poly1305_init_ext_armv6<>(SB)
-  BIC.S $15, R6, R2
-  BEQ poly1305_auth_armv6_noblocks
-  MOVW R13, R0
-  MOVW R5, R1
-  ADD R2, R5, R5
-  SUB R2, R6, R6
-  BL poly1305_blocks_armv6<>(SB)
-poly1305_auth_armv6_noblocks:
-  MOVW R13, R0
-  MOVW R5, R1
-  MOVW R6, R2
-  MOVW R4, R3
-  BL poly1305_finish_ext_armv6<>(SB)
-  MOVW R8, R13
-  RET
diff --git a/src/ssl/test/runner/poly1305/poly1305_test.go b/src/ssl/test/runner/poly1305/poly1305_test.go
index b3e9231..017027f 100644
--- a/src/ssl/test/runner/poly1305/poly1305_test.go
+++ b/src/ssl/test/runner/poly1305/poly1305_test.go
@@ -6,10 +6,14 @@
 
 import (
 	"bytes"
+	"encoding/hex"
+	"flag"
 	"testing"
 	"unsafe"
 )
 
+var stressFlag = flag.Bool("stress", false, "run slow stress tests")
+
 var testData = []struct {
 	in, k, correct []byte
 }{
@@ -33,6 +37,42 @@
 		make([]byte, 32),
 		make([]byte, 16),
 	},
+	{
+		// This test triggers an edge-case. See https://go-review.googlesource.com/#/c/30101/.
+		[]byte{0x81, 0xd8, 0xb2, 0xe4, 0x6a, 0x25, 0x21, 0x3b, 0x58, 0xfe, 0xe4, 0x21, 0x3a, 0x2a, 0x28, 0xe9, 0x21, 0xc1, 0x2a, 0x96, 0x32, 0x51, 0x6d, 0x3b, 0x73, 0x27, 0x27, 0x27, 0xbe, 0xcf, 0x21, 0x29},
+		[]byte{0x3b, 0x3a, 0x29, 0xe9, 0x3b, 0x21, 0x3a, 0x5c, 0x5c, 0x3b, 0x3b, 0x05, 0x3a, 0x3a, 0x8c, 0x0d},
+		[]byte{0x6d, 0xc1, 0x8b, 0x8c, 0x34, 0x4c, 0xd7, 0x99, 0x27, 0x11, 0x8b, 0xbe, 0x84, 0xb7, 0xf3, 0x14},
+	},
+	{
+		// This test generates a result of (2^130-1) % (2^130-5).
+		[]byte{
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		[]byte{1, 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},
+		[]byte{4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	},
+	{
+		// This test generates a result of (2^130-6) % (2^130-5).
+		[]byte{
+			0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		[]byte{1, 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},
+		[]byte{0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
+	},
+	{
+		// This test generates a result of (2^130-5) % (2^130-5).
+		[]byte{
+			0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		},
+		[]byte{1, 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},
+		[]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+	},
 }
 
 func testSum(t *testing.T, unaligned bool) {
@@ -52,6 +92,39 @@
 	}
 }
 
+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) }
 func TestSumUnaligned(t *testing.T) { testSum(t, true) }
 
diff --git a/src/ssl/test/runner/poly1305/sum_amd64.go b/src/ssl/test/runner/poly1305/sum_amd64.go
index 6775c70..4dd72fe 100644
--- a/src/ssl/test/runner/poly1305/sum_amd64.go
+++ b/src/ssl/test/runner/poly1305/sum_amd64.go
@@ -6,10 +6,8 @@
 
 package poly1305
 
-// This function is implemented in poly1305_amd64.s
-
+// 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
diff --git a/src/ssl/test/runner/poly1305/sum_amd64.s b/src/ssl/test/runner/poly1305/sum_amd64.s
new file mode 100644
index 0000000..2edae63
--- /dev/null
+++ b/src/ssl/test/runner/poly1305/sum_amd64.s
@@ -0,0 +1,125 @@
+// 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
index 50b979c..5dc321c 100644
--- a/src/ssl/test/runner/poly1305/sum_arm.go
+++ b/src/ssl/test/runner/poly1305/sum_arm.go
@@ -2,14 +2,12 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build arm,!gccgo,!appengine
+// +build arm,!gccgo,!appengine,!nacl
 
 package poly1305
 
-// This function is implemented in poly1305_arm.s
-
+// 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
diff --git a/src/ssl/test/runner/poly1305/sum_arm.s b/src/ssl/test/runner/poly1305/sum_arm.s
new file mode 100644
index 0000000..f70b4ac
--- /dev/null
+++ b/src/ssl/test/runner/poly1305/sum_arm.s
@@ -0,0 +1,427 @@
+// 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_ref.go b/src/ssl/test/runner/poly1305/sum_ref.go
index 0b24fc7..b2805a5 100644
--- a/src/ssl/test/runner/poly1305/sum_ref.go
+++ b/src/ssl/test/runner/poly1305/sum_ref.go
@@ -2,1530 +2,140 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !amd64,!arm gccgo appengine
+// +build !amd64,!arm gccgo appengine nacl
 
 package poly1305
 
-// Based on original, public domain implementation from NaCl by D. J.
-// Bernstein.
+import "encoding/binary"
 
-import "math"
-
-const (
-	alpham80 = 0.00000000558793544769287109375
-	alpham48 = 24.0
-	alpham16 = 103079215104.0
-	alpha0   = 6755399441055744.0
-	alpha18  = 1770887431076116955136.0
-	alpha32  = 29014219670751100192948224.0
-	alpha50  = 7605903601369376408980219232256.0
-	alpha64  = 124615124604835863084731911901282304.0
-	alpha82  = 32667107224410092492483962313449748299776.0
-	alpha96  = 535217884764734955396857238543560676143529984.0
-	alpha112 = 35076039295941670036888435985190792471742381031424.0
-	alpha130 = 9194973245195333150150082162901855101712434733101613056.0
-	scale    = 0.0000000000000000000000000000000000000036734198463196484624023016788195177431833298649127735047148490821200539357960224151611328125
-	offset0  = 6755408030990331.0
-	offset1  = 29014256564239239022116864.0
-	offset2  = 124615283061160854719918951570079744.0
-	offset3  = 535219245894202480694386063513315216128475136.0
-)
-
-// Sum generates an authenticator for m using a one-time key and puts the
+// 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 *[16]byte, m []byte, key *[32]byte) {
-	r := key
-	s := key[16:]
+func Sum(out *[TagSize]byte, msg []byte, key *[32]byte) {
 	var (
-		y7        float64
-		y6        float64
-		y1        float64
-		y0        float64
-		y5        float64
-		y4        float64
-		x7        float64
-		x6        float64
-		x1        float64
-		x0        float64
-		y3        float64
-		y2        float64
-		x5        float64
-		r3lowx0   float64
-		x4        float64
-		r0lowx6   float64
-		x3        float64
-		r3highx0  float64
-		x2        float64
-		r0highx6  float64
-		r0lowx0   float64
-		sr1lowx6  float64
-		r0highx0  float64
-		sr1highx6 float64
-		sr3low    float64
-		r1lowx0   float64
-		sr2lowx6  float64
-		r1highx0  float64
-		sr2highx6 float64
-		r2lowx0   float64
-		sr3lowx6  float64
-		r2highx0  float64
-		sr3highx6 float64
-		r1highx4  float64
-		r1lowx4   float64
-		r0highx4  float64
-		r0lowx4   float64
-		sr3highx4 float64
-		sr3lowx4  float64
-		sr2highx4 float64
-		sr2lowx4  float64
-		r0lowx2   float64
-		r0highx2  float64
-		r1lowx2   float64
-		r1highx2  float64
-		r2lowx2   float64
-		r2highx2  float64
-		sr3lowx2  float64
-		sr3highx2 float64
-		z0        float64
-		z1        float64
-		z2        float64
-		z3        float64
-		m0        int64
-		m1        int64
-		m2        int64
-		m3        int64
-		m00       uint32
-		m01       uint32
-		m02       uint32
-		m03       uint32
-		m10       uint32
-		m11       uint32
-		m12       uint32
-		m13       uint32
-		m20       uint32
-		m21       uint32
-		m22       uint32
-		m23       uint32
-		m30       uint32
-		m31       uint32
-		m32       uint32
-		m33       uint64
-		lbelow2   int32
-		lbelow3   int32
-		lbelow4   int32
-		lbelow5   int32
-		lbelow6   int32
-		lbelow7   int32
-		lbelow8   int32
-		lbelow9   int32
-		lbelow10  int32
-		lbelow11  int32
-		lbelow12  int32
-		lbelow13  int32
-		lbelow14  int32
-		lbelow15  int32
-		s00       uint32
-		s01       uint32
-		s02       uint32
-		s03       uint32
-		s10       uint32
-		s11       uint32
-		s12       uint32
-		s13       uint32
-		s20       uint32
-		s21       uint32
-		s22       uint32
-		s23       uint32
-		s30       uint32
-		s31       uint32
-		s32       uint32
-		s33       uint32
-		bits32    uint64
-		f         uint64
-		f0        uint64
-		f1        uint64
-		f2        uint64
-		f3        uint64
-		f4        uint64
-		g         uint64
-		g0        uint64
-		g1        uint64
-		g2        uint64
-		g3        uint64
-		g4        uint64
+		h0, h1, h2, h3, h4 uint32 // the hash accumulators
+		r0, r1, r2, r3, r4 uint64 // the r part of the key
 	)
 
-	var p int32
+	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)
 
-	l := int32(len(m))
+	R1, R2, R3, R4 := r1*5, r2*5, r3*5, r4*5
 
-	r00 := uint32(r[0])
+	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)
 
-	r01 := uint32(r[1])
+		// 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)
 
-	r02 := uint32(r[2])
-	r0 := int64(2151)
+		// h %= p
+		h0 = uint32(d0) & 0x3ffffff
+		h1 = uint32(d1) & 0x3ffffff
+		h2 = uint32(d2) & 0x3ffffff
+		h3 = uint32(d3) & 0x3ffffff
+		h4 = uint32(d4) & 0x3ffffff
 
-	r03 := uint32(r[3])
-	r03 &= 15
-	r0 <<= 51
+		h0 += uint32(d4>>26) * 5
+		h1 += h0 >> 26
+		h0 = h0 & 0x3ffffff
 
-	r10 := uint32(r[4])
-	r10 &= 252
-	r01 <<= 8
-	r0 += int64(r00)
-
-	r11 := uint32(r[5])
-	r02 <<= 16
-	r0 += int64(r01)
-
-	r12 := uint32(r[6])
-	r03 <<= 24
-	r0 += int64(r02)
-
-	r13 := uint32(r[7])
-	r13 &= 15
-	r1 := int64(2215)
-	r0 += int64(r03)
-
-	d0 := r0
-	r1 <<= 51
-	r2 := int64(2279)
-
-	r20 := uint32(r[8])
-	r20 &= 252
-	r11 <<= 8
-	r1 += int64(r10)
-
-	r21 := uint32(r[9])
-	r12 <<= 16
-	r1 += int64(r11)
-
-	r22 := uint32(r[10])
-	r13 <<= 24
-	r1 += int64(r12)
-
-	r23 := uint32(r[11])
-	r23 &= 15
-	r2 <<= 51
-	r1 += int64(r13)
-
-	d1 := r1
-	r21 <<= 8
-	r2 += int64(r20)
-
-	r30 := uint32(r[12])
-	r30 &= 252
-	r22 <<= 16
-	r2 += int64(r21)
-
-	r31 := uint32(r[13])
-	r23 <<= 24
-	r2 += int64(r22)
-
-	r32 := uint32(r[14])
-	r2 += int64(r23)
-	r3 := int64(2343)
-
-	d2 := r2
-	r3 <<= 51
-
-	r33 := uint32(r[15])
-	r33 &= 15
-	r31 <<= 8
-	r3 += int64(r30)
-
-	r32 <<= 16
-	r3 += int64(r31)
-
-	r33 <<= 24
-	r3 += int64(r32)
-
-	r3 += int64(r33)
-	h0 := alpha32 - alpha32
-
-	d3 := r3
-	h1 := alpha32 - alpha32
-
-	h2 := alpha32 - alpha32
-
-	h3 := alpha32 - alpha32
-
-	h4 := alpha32 - alpha32
-
-	r0low := math.Float64frombits(uint64(d0))
-	h5 := alpha32 - alpha32
-
-	r1low := math.Float64frombits(uint64(d1))
-	h6 := alpha32 - alpha32
-
-	r2low := math.Float64frombits(uint64(d2))
-	h7 := alpha32 - alpha32
-
-	r0low -= alpha0
-
-	r1low -= alpha32
-
-	r2low -= alpha64
-
-	r0high := r0low + alpha18
-
-	r3low := math.Float64frombits(uint64(d3))
-
-	r1high := r1low + alpha50
-	sr1low := scale * r1low
-
-	r2high := r2low + alpha82
-	sr2low := scale * r2low
-
-	r0high -= alpha18
-	r0high_stack := r0high
-
-	r3low -= alpha96
-
-	r1high -= alpha50
-	r1high_stack := r1high
-
-	sr1high := sr1low + alpham80
-
-	r0low -= r0high
-
-	r2high -= alpha82
-	sr3low = scale * r3low
-
-	sr2high := sr2low + alpham48
-
-	r1low -= r1high
-	r1low_stack := r1low
-
-	sr1high -= alpham80
-	sr1high_stack := sr1high
-
-	r2low -= r2high
-	r2low_stack := r2low
-
-	sr2high -= alpham48
-	sr2high_stack := sr2high
-
-	r3high := r3low + alpha112
-	r0low_stack := r0low
-
-	sr1low -= sr1high
-	sr1low_stack := sr1low
-
-	sr3high := sr3low + alpham16
-	r2high_stack := r2high
-
-	sr2low -= sr2high
-	sr2low_stack := sr2low
-
-	r3high -= alpha112
-	r3high_stack := r3high
-
-	sr3high -= alpham16
-	sr3high_stack := sr3high
-
-	r3low -= r3high
-	r3low_stack := r3low
-
-	sr3low -= sr3high
-	sr3low_stack := sr3low
-
-	if l < 16 {
-		goto addatmost15bytes
+		msg = msg[TagSize:]
 	}
 
-	m00 = uint32(m[p+0])
-	m0 = 2151
+	if len(msg) > 0 {
+		var block [TagSize]byte
+		off := copy(block[:], msg)
+		block[off] = 0x01
 
-	m0 <<= 51
-	m1 = 2215
-	m01 = uint32(m[p+1])
+		// 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)
 
-	m1 <<= 51
-	m2 = 2279
-	m02 = uint32(m[p+2])
+		// 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)
 
-	m2 <<= 51
-	m3 = 2343
-	m03 = uint32(m[p+3])
+		// h %= p
+		h0 = uint32(d0) & 0x3ffffff
+		h1 = uint32(d1) & 0x3ffffff
+		h2 = uint32(d2) & 0x3ffffff
+		h3 = uint32(d3) & 0x3ffffff
+		h4 = uint32(d4) & 0x3ffffff
 
-	m10 = uint32(m[p+4])
-	m01 <<= 8
-	m0 += int64(m00)
-
-	m11 = uint32(m[p+5])
-	m02 <<= 16
-	m0 += int64(m01)
-
-	m12 = uint32(m[p+6])
-	m03 <<= 24
-	m0 += int64(m02)
-
-	m13 = uint32(m[p+7])
-	m3 <<= 51
-	m0 += int64(m03)
-
-	m20 = uint32(m[p+8])
-	m11 <<= 8
-	m1 += int64(m10)
-
-	m21 = uint32(m[p+9])
-	m12 <<= 16
-	m1 += int64(m11)
-
-	m22 = uint32(m[p+10])
-	m13 <<= 24
-	m1 += int64(m12)
-
-	m23 = uint32(m[p+11])
-	m1 += int64(m13)
-
-	m30 = uint32(m[p+12])
-	m21 <<= 8
-	m2 += int64(m20)
-
-	m31 = uint32(m[p+13])
-	m22 <<= 16
-	m2 += int64(m21)
-
-	m32 = uint32(m[p+14])
-	m23 <<= 24
-	m2 += int64(m22)
-
-	m33 = uint64(m[p+15])
-	m2 += int64(m23)
-
-	d0 = m0
-	m31 <<= 8
-	m3 += int64(m30)
-
-	d1 = m1
-	m32 <<= 16
-	m3 += int64(m31)
-
-	d2 = m2
-	m33 += 256
-
-	m33 <<= 24
-	m3 += int64(m32)
-
-	m3 += int64(m33)
-	d3 = m3
-
-	p += 16
-	l -= 16
-
-	z0 = math.Float64frombits(uint64(d0))
-
-	z1 = math.Float64frombits(uint64(d1))
-
-	z2 = math.Float64frombits(uint64(d2))
-
-	z3 = math.Float64frombits(uint64(d3))
-
-	z0 -= alpha0
-
-	z1 -= alpha32
-
-	z2 -= alpha64
-
-	z3 -= alpha96
-
-	h0 += z0
-
-	h1 += z1
-
-	h3 += z2
-
-	h5 += z3
-
-	if l < 16 {
-		goto multiplyaddatmost15bytes
+		h0 += uint32(d4>>26) * 5
+		h1 += h0 >> 26
+		h0 = h0 & 0x3ffffff
 	}
 
-multiplyaddatleast16bytes:
+	// 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
 
-	m2 = 2279
-	m20 = uint32(m[p+8])
-	y7 = h7 + alpha130
+	// 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
 
-	m2 <<= 51
-	m3 = 2343
-	m21 = uint32(m[p+9])
-	y6 = h6 + alpha130
+	// 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)
 
-	m3 <<= 51
-	m0 = 2151
-	m22 = uint32(m[p+10])
-	y1 = h1 + alpha32
+	// h %= 2^128
+	h0 |= h1 << 26
+	h1 = ((h1 >> 6) | (h2 << 20))
+	h2 = ((h2 >> 12) | (h3 << 14))
+	h3 = ((h3 >> 18) | (h4 << 8))
 
-	m0 <<= 51
-	m1 = 2215
-	m23 = uint32(m[p+11])
-	y0 = h0 + alpha32
+	// 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)
 
-	m1 <<= 51
-	m30 = uint32(m[p+12])
-	y7 -= alpha130
-
-	m21 <<= 8
-	m2 += int64(m20)
-	m31 = uint32(m[p+13])
-	y6 -= alpha130
-
-	m22 <<= 16
-	m2 += int64(m21)
-	m32 = uint32(m[p+14])
-	y1 -= alpha32
-
-	m23 <<= 24
-	m2 += int64(m22)
-	m33 = uint64(m[p+15])
-	y0 -= alpha32
-
-	m2 += int64(m23)
-	m00 = uint32(m[p+0])
-	y5 = h5 + alpha96
-
-	m31 <<= 8
-	m3 += int64(m30)
-	m01 = uint32(m[p+1])
-	y4 = h4 + alpha96
-
-	m32 <<= 16
-	m02 = uint32(m[p+2])
-	x7 = h7 - y7
-	y7 *= scale
-
-	m33 += 256
-	m03 = uint32(m[p+3])
-	x6 = h6 - y6
-	y6 *= scale
-
-	m33 <<= 24
-	m3 += int64(m31)
-	m10 = uint32(m[p+4])
-	x1 = h1 - y1
-
-	m01 <<= 8
-	m3 += int64(m32)
-	m11 = uint32(m[p+5])
-	x0 = h0 - y0
-
-	m3 += int64(m33)
-	m0 += int64(m00)
-	m12 = uint32(m[p+6])
-	y5 -= alpha96
-
-	m02 <<= 16
-	m0 += int64(m01)
-	m13 = uint32(m[p+7])
-	y4 -= alpha96
-
-	m03 <<= 24
-	m0 += int64(m02)
-	d2 = m2
-	x1 += y7
-
-	m0 += int64(m03)
-	d3 = m3
-	x0 += y6
-
-	m11 <<= 8
-	m1 += int64(m10)
-	d0 = m0
-	x7 += y5
-
-	m12 <<= 16
-	m1 += int64(m11)
-	x6 += y4
-
-	m13 <<= 24
-	m1 += int64(m12)
-	y3 = h3 + alpha64
-
-	m1 += int64(m13)
-	d1 = m1
-	y2 = h2 + alpha64
-
-	x0 += x1
-
-	x6 += x7
-
-	y3 -= alpha64
-	r3low = r3low_stack
-
-	y2 -= alpha64
-	r0low = r0low_stack
-
-	x5 = h5 - y5
-	r3lowx0 = r3low * x0
-	r3high = r3high_stack
-
-	x4 = h4 - y4
-	r0lowx6 = r0low * x6
-	r0high = r0high_stack
-
-	x3 = h3 - y3
-	r3highx0 = r3high * x0
-	sr1low = sr1low_stack
-
-	x2 = h2 - y2
-	r0highx6 = r0high * x6
-	sr1high = sr1high_stack
-
-	x5 += y3
-	r0lowx0 = r0low * x0
-	r1low = r1low_stack
-
-	h6 = r3lowx0 + r0lowx6
-	sr1lowx6 = sr1low * x6
-	r1high = r1high_stack
-
-	x4 += y2
-	r0highx0 = r0high * x0
-	sr2low = sr2low_stack
-
-	h7 = r3highx0 + r0highx6
-	sr1highx6 = sr1high * x6
-	sr2high = sr2high_stack
-
-	x3 += y1
-	r1lowx0 = r1low * x0
-	r2low = r2low_stack
-
-	h0 = r0lowx0 + sr1lowx6
-	sr2lowx6 = sr2low * x6
-	r2high = r2high_stack
-
-	x2 += y0
-	r1highx0 = r1high * x0
-	sr3low = sr3low_stack
-
-	h1 = r0highx0 + sr1highx6
-	sr2highx6 = sr2high * x6
-	sr3high = sr3high_stack
-
-	x4 += x5
-	r2lowx0 = r2low * x0
-	z2 = math.Float64frombits(uint64(d2))
-
-	h2 = r1lowx0 + sr2lowx6
-	sr3lowx6 = sr3low * x6
-
-	x2 += x3
-	r2highx0 = r2high * x0
-	z3 = math.Float64frombits(uint64(d3))
-
-	h3 = r1highx0 + sr2highx6
-	sr3highx6 = sr3high * x6
-
-	r1highx4 = r1high * x4
-	z2 -= alpha64
-
-	h4 = r2lowx0 + sr3lowx6
-	r1lowx4 = r1low * x4
-
-	r0highx4 = r0high * x4
-	z3 -= alpha96
-
-	h5 = r2highx0 + sr3highx6
-	r0lowx4 = r0low * x4
-
-	h7 += r1highx4
-	sr3highx4 = sr3high * x4
-
-	h6 += r1lowx4
-	sr3lowx4 = sr3low * x4
-
-	h5 += r0highx4
-	sr2highx4 = sr2high * x4
-
-	h4 += r0lowx4
-	sr2lowx4 = sr2low * x4
-
-	h3 += sr3highx4
-	r0lowx2 = r0low * x2
-
-	h2 += sr3lowx4
-	r0highx2 = r0high * x2
-
-	h1 += sr2highx4
-	r1lowx2 = r1low * x2
-
-	h0 += sr2lowx4
-	r1highx2 = r1high * x2
-
-	h2 += r0lowx2
-	r2lowx2 = r2low * x2
-
-	h3 += r0highx2
-	r2highx2 = r2high * x2
-
-	h4 += r1lowx2
-	sr3lowx2 = sr3low * x2
-
-	h5 += r1highx2
-	sr3highx2 = sr3high * x2
-
-	p += 16
-	l -= 16
-	h6 += r2lowx2
-
-	h7 += r2highx2
-
-	z1 = math.Float64frombits(uint64(d1))
-	h0 += sr3lowx2
-
-	z0 = math.Float64frombits(uint64(d0))
-	h1 += sr3highx2
-
-	z1 -= alpha32
-
-	z0 -= alpha0
-
-	h5 += z3
-
-	h3 += z2
-
-	h1 += z1
-
-	h0 += z0
-
-	if l >= 16 {
-		goto multiplyaddatleast16bytes
-	}
-
-multiplyaddatmost15bytes:
-
-	y7 = h7 + alpha130
-
-	y6 = h6 + alpha130
-
-	y1 = h1 + alpha32
-
-	y0 = h0 + alpha32
-
-	y7 -= alpha130
-
-	y6 -= alpha130
-
-	y1 -= alpha32
-
-	y0 -= alpha32
-
-	y5 = h5 + alpha96
-
-	y4 = h4 + alpha96
-
-	x7 = h7 - y7
-	y7 *= scale
-
-	x6 = h6 - y6
-	y6 *= scale
-
-	x1 = h1 - y1
-
-	x0 = h0 - y0
-
-	y5 -= alpha96
-
-	y4 -= alpha96
-
-	x1 += y7
-
-	x0 += y6
-
-	x7 += y5
-
-	x6 += y4
-
-	y3 = h3 + alpha64
-
-	y2 = h2 + alpha64
-
-	x0 += x1
-
-	x6 += x7
-
-	y3 -= alpha64
-	r3low = r3low_stack
-
-	y2 -= alpha64
-	r0low = r0low_stack
-
-	x5 = h5 - y5
-	r3lowx0 = r3low * x0
-	r3high = r3high_stack
-
-	x4 = h4 - y4
-	r0lowx6 = r0low * x6
-	r0high = r0high_stack
-
-	x3 = h3 - y3
-	r3highx0 = r3high * x0
-	sr1low = sr1low_stack
-
-	x2 = h2 - y2
-	r0highx6 = r0high * x6
-	sr1high = sr1high_stack
-
-	x5 += y3
-	r0lowx0 = r0low * x0
-	r1low = r1low_stack
-
-	h6 = r3lowx0 + r0lowx6
-	sr1lowx6 = sr1low * x6
-	r1high = r1high_stack
-
-	x4 += y2
-	r0highx0 = r0high * x0
-	sr2low = sr2low_stack
-
-	h7 = r3highx0 + r0highx6
-	sr1highx6 = sr1high * x6
-	sr2high = sr2high_stack
-
-	x3 += y1
-	r1lowx0 = r1low * x0
-	r2low = r2low_stack
-
-	h0 = r0lowx0 + sr1lowx6
-	sr2lowx6 = sr2low * x6
-	r2high = r2high_stack
-
-	x2 += y0
-	r1highx0 = r1high * x0
-	sr3low = sr3low_stack
-
-	h1 = r0highx0 + sr1highx6
-	sr2highx6 = sr2high * x6
-	sr3high = sr3high_stack
-
-	x4 += x5
-	r2lowx0 = r2low * x0
-
-	h2 = r1lowx0 + sr2lowx6
-	sr3lowx6 = sr3low * x6
-
-	x2 += x3
-	r2highx0 = r2high * x0
-
-	h3 = r1highx0 + sr2highx6
-	sr3highx6 = sr3high * x6
-
-	r1highx4 = r1high * x4
-
-	h4 = r2lowx0 + sr3lowx6
-	r1lowx4 = r1low * x4
-
-	r0highx4 = r0high * x4
-
-	h5 = r2highx0 + sr3highx6
-	r0lowx4 = r0low * x4
-
-	h7 += r1highx4
-	sr3highx4 = sr3high * x4
-
-	h6 += r1lowx4
-	sr3lowx4 = sr3low * x4
-
-	h5 += r0highx4
-	sr2highx4 = sr2high * x4
-
-	h4 += r0lowx4
-	sr2lowx4 = sr2low * x4
-
-	h3 += sr3highx4
-	r0lowx2 = r0low * x2
-
-	h2 += sr3lowx4
-	r0highx2 = r0high * x2
-
-	h1 += sr2highx4
-	r1lowx2 = r1low * x2
-
-	h0 += sr2lowx4
-	r1highx2 = r1high * x2
-
-	h2 += r0lowx2
-	r2lowx2 = r2low * x2
-
-	h3 += r0highx2
-	r2highx2 = r2high * x2
-
-	h4 += r1lowx2
-	sr3lowx2 = sr3low * x2
-
-	h5 += r1highx2
-	sr3highx2 = sr3high * x2
-
-	h6 += r2lowx2
-
-	h7 += r2highx2
-
-	h0 += sr3lowx2
-
-	h1 += sr3highx2
-
-addatmost15bytes:
-
-	if l == 0 {
-		goto nomorebytes
-	}
-
-	lbelow2 = l - 2
-
-	lbelow3 = l - 3
-
-	lbelow2 >>= 31
-	lbelow4 = l - 4
-
-	m00 = uint32(m[p+0])
-	lbelow3 >>= 31
-	p += lbelow2
-
-	m01 = uint32(m[p+1])
-	lbelow4 >>= 31
-	p += lbelow3
-
-	m02 = uint32(m[p+2])
-	p += lbelow4
-	m0 = 2151
-
-	m03 = uint32(m[p+3])
-	m0 <<= 51
-	m1 = 2215
-
-	m0 += int64(m00)
-	m01 &^= uint32(lbelow2)
-
-	m02 &^= uint32(lbelow3)
-	m01 -= uint32(lbelow2)
-
-	m01 <<= 8
-	m03 &^= uint32(lbelow4)
-
-	m0 += int64(m01)
-	lbelow2 -= lbelow3
-
-	m02 += uint32(lbelow2)
-	lbelow3 -= lbelow4
-
-	m02 <<= 16
-	m03 += uint32(lbelow3)
-
-	m03 <<= 24
-	m0 += int64(m02)
-
-	m0 += int64(m03)
-	lbelow5 = l - 5
-
-	lbelow6 = l - 6
-	lbelow7 = l - 7
-
-	lbelow5 >>= 31
-	lbelow8 = l - 8
-
-	lbelow6 >>= 31
-	p += lbelow5
-
-	m10 = uint32(m[p+4])
-	lbelow7 >>= 31
-	p += lbelow6
-
-	m11 = uint32(m[p+5])
-	lbelow8 >>= 31
-	p += lbelow7
-
-	m12 = uint32(m[p+6])
-	m1 <<= 51
-	p += lbelow8
-
-	m13 = uint32(m[p+7])
-	m10 &^= uint32(lbelow5)
-	lbelow4 -= lbelow5
-
-	m10 += uint32(lbelow4)
-	lbelow5 -= lbelow6
-
-	m11 &^= uint32(lbelow6)
-	m11 += uint32(lbelow5)
-
-	m11 <<= 8
-	m1 += int64(m10)
-
-	m1 += int64(m11)
-	m12 &^= uint32(lbelow7)
-
-	lbelow6 -= lbelow7
-	m13 &^= uint32(lbelow8)
-
-	m12 += uint32(lbelow6)
-	lbelow7 -= lbelow8
-
-	m12 <<= 16
-	m13 += uint32(lbelow7)
-
-	m13 <<= 24
-	m1 += int64(m12)
-
-	m1 += int64(m13)
-	m2 = 2279
-
-	lbelow9 = l - 9
-	m3 = 2343
-
-	lbelow10 = l - 10
-	lbelow11 = l - 11
-
-	lbelow9 >>= 31
-	lbelow12 = l - 12
-
-	lbelow10 >>= 31
-	p += lbelow9
-
-	m20 = uint32(m[p+8])
-	lbelow11 >>= 31
-	p += lbelow10
-
-	m21 = uint32(m[p+9])
-	lbelow12 >>= 31
-	p += lbelow11
-
-	m22 = uint32(m[p+10])
-	m2 <<= 51
-	p += lbelow12
-
-	m23 = uint32(m[p+11])
-	m20 &^= uint32(lbelow9)
-	lbelow8 -= lbelow9
-
-	m20 += uint32(lbelow8)
-	lbelow9 -= lbelow10
-
-	m21 &^= uint32(lbelow10)
-	m21 += uint32(lbelow9)
-
-	m21 <<= 8
-	m2 += int64(m20)
-
-	m2 += int64(m21)
-	m22 &^= uint32(lbelow11)
-
-	lbelow10 -= lbelow11
-	m23 &^= uint32(lbelow12)
-
-	m22 += uint32(lbelow10)
-	lbelow11 -= lbelow12
-
-	m22 <<= 16
-	m23 += uint32(lbelow11)
-
-	m23 <<= 24
-	m2 += int64(m22)
-
-	m3 <<= 51
-	lbelow13 = l - 13
-
-	lbelow13 >>= 31
-	lbelow14 = l - 14
-
-	lbelow14 >>= 31
-	p += lbelow13
-	lbelow15 = l - 15
-
-	m30 = uint32(m[p+12])
-	lbelow15 >>= 31
-	p += lbelow14
-
-	m31 = uint32(m[p+13])
-	p += lbelow15
-	m2 += int64(m23)
-
-	m32 = uint32(m[p+14])
-	m30 &^= uint32(lbelow13)
-	lbelow12 -= lbelow13
-
-	m30 += uint32(lbelow12)
-	lbelow13 -= lbelow14
-
-	m3 += int64(m30)
-	m31 &^= uint32(lbelow14)
-
-	m31 += uint32(lbelow13)
-	m32 &^= uint32(lbelow15)
-
-	m31 <<= 8
-	lbelow14 -= lbelow15
-
-	m3 += int64(m31)
-	m32 += uint32(lbelow14)
-	d0 = m0
-
-	m32 <<= 16
-	m33 = uint64(lbelow15 + 1)
-	d1 = m1
-
-	m33 <<= 24
-	m3 += int64(m32)
-	d2 = m2
-
-	m3 += int64(m33)
-	d3 = m3
-
-	z3 = math.Float64frombits(uint64(d3))
-
-	z2 = math.Float64frombits(uint64(d2))
-
-	z1 = math.Float64frombits(uint64(d1))
-
-	z0 = math.Float64frombits(uint64(d0))
-
-	z3 -= alpha96
-
-	z2 -= alpha64
-
-	z1 -= alpha32
-
-	z0 -= alpha0
-
-	h5 += z3
-
-	h3 += z2
-
-	h1 += z1
-
-	h0 += z0
-
-	y7 = h7 + alpha130
-
-	y6 = h6 + alpha130
-
-	y1 = h1 + alpha32
-
-	y0 = h0 + alpha32
-
-	y7 -= alpha130
-
-	y6 -= alpha130
-
-	y1 -= alpha32
-
-	y0 -= alpha32
-
-	y5 = h5 + alpha96
-
-	y4 = h4 + alpha96
-
-	x7 = h7 - y7
-	y7 *= scale
-
-	x6 = h6 - y6
-	y6 *= scale
-
-	x1 = h1 - y1
-
-	x0 = h0 - y0
-
-	y5 -= alpha96
-
-	y4 -= alpha96
-
-	x1 += y7
-
-	x0 += y6
-
-	x7 += y5
-
-	x6 += y4
-
-	y3 = h3 + alpha64
-
-	y2 = h2 + alpha64
-
-	x0 += x1
-
-	x6 += x7
-
-	y3 -= alpha64
-	r3low = r3low_stack
-
-	y2 -= alpha64
-	r0low = r0low_stack
-
-	x5 = h5 - y5
-	r3lowx0 = r3low * x0
-	r3high = r3high_stack
-
-	x4 = h4 - y4
-	r0lowx6 = r0low * x6
-	r0high = r0high_stack
-
-	x3 = h3 - y3
-	r3highx0 = r3high * x0
-	sr1low = sr1low_stack
-
-	x2 = h2 - y2
-	r0highx6 = r0high * x6
-	sr1high = sr1high_stack
-
-	x5 += y3
-	r0lowx0 = r0low * x0
-	r1low = r1low_stack
-
-	h6 = r3lowx0 + r0lowx6
-	sr1lowx6 = sr1low * x6
-	r1high = r1high_stack
-
-	x4 += y2
-	r0highx0 = r0high * x0
-	sr2low = sr2low_stack
-
-	h7 = r3highx0 + r0highx6
-	sr1highx6 = sr1high * x6
-	sr2high = sr2high_stack
-
-	x3 += y1
-	r1lowx0 = r1low * x0
-	r2low = r2low_stack
-
-	h0 = r0lowx0 + sr1lowx6
-	sr2lowx6 = sr2low * x6
-	r2high = r2high_stack
-
-	x2 += y0
-	r1highx0 = r1high * x0
-	sr3low = sr3low_stack
-
-	h1 = r0highx0 + sr1highx6
-	sr2highx6 = sr2high * x6
-	sr3high = sr3high_stack
-
-	x4 += x5
-	r2lowx0 = r2low * x0
-
-	h2 = r1lowx0 + sr2lowx6
-	sr3lowx6 = sr3low * x6
-
-	x2 += x3
-	r2highx0 = r2high * x0
-
-	h3 = r1highx0 + sr2highx6
-	sr3highx6 = sr3high * x6
-
-	r1highx4 = r1high * x4
-
-	h4 = r2lowx0 + sr3lowx6
-	r1lowx4 = r1low * x4
-
-	r0highx4 = r0high * x4
-
-	h5 = r2highx0 + sr3highx6
-	r0lowx4 = r0low * x4
-
-	h7 += r1highx4
-	sr3highx4 = sr3high * x4
-
-	h6 += r1lowx4
-	sr3lowx4 = sr3low * x4
-
-	h5 += r0highx4
-	sr2highx4 = sr2high * x4
-
-	h4 += r0lowx4
-	sr2lowx4 = sr2low * x4
-
-	h3 += sr3highx4
-	r0lowx2 = r0low * x2
-
-	h2 += sr3lowx4
-	r0highx2 = r0high * x2
-
-	h1 += sr2highx4
-	r1lowx2 = r1low * x2
-
-	h0 += sr2lowx4
-	r1highx2 = r1high * x2
-
-	h2 += r0lowx2
-	r2lowx2 = r2low * x2
-
-	h3 += r0highx2
-	r2highx2 = r2high * x2
-
-	h4 += r1lowx2
-	sr3lowx2 = sr3low * x2
-
-	h5 += r1highx2
-	sr3highx2 = sr3high * x2
-
-	h6 += r2lowx2
-
-	h7 += r2highx2
-
-	h0 += sr3lowx2
-
-	h1 += sr3highx2
-
-nomorebytes:
-
-	y7 = h7 + alpha130
-
-	y0 = h0 + alpha32
-
-	y1 = h1 + alpha32
-
-	y2 = h2 + alpha64
-
-	y7 -= alpha130
-
-	y3 = h3 + alpha64
-
-	y4 = h4 + alpha96
-
-	y5 = h5 + alpha96
-
-	x7 = h7 - y7
-	y7 *= scale
-
-	y0 -= alpha32
-
-	y1 -= alpha32
-
-	y2 -= alpha64
-
-	h6 += x7
-
-	y3 -= alpha64
-
-	y4 -= alpha96
-
-	y5 -= alpha96
-
-	y6 = h6 + alpha130
-
-	x0 = h0 - y0
-
-	x1 = h1 - y1
-
-	x2 = h2 - y2
-
-	y6 -= alpha130
-
-	x0 += y7
-
-	x3 = h3 - y3
-
-	x4 = h4 - y4
-
-	x5 = h5 - y5
-
-	x6 = h6 - y6
-
-	y6 *= scale
-
-	x2 += y0
-
-	x3 += y1
-
-	x4 += y2
-
-	x0 += y6
-
-	x5 += y3
-
-	x6 += y4
-
-	x2 += x3
-
-	x0 += x1
-
-	x4 += x5
-
-	x6 += y5
-
-	x2 += offset1
-	d1 = int64(math.Float64bits(x2))
-
-	x0 += offset0
-	d0 = int64(math.Float64bits(x0))
-
-	x4 += offset2
-	d2 = int64(math.Float64bits(x4))
-
-	x6 += offset3
-	d3 = int64(math.Float64bits(x6))
-
-	f0 = uint64(d0)
-
-	f1 = uint64(d1)
-	bits32 = math.MaxUint64
-
-	f2 = uint64(d2)
-	bits32 >>= 32
-
-	f3 = uint64(d3)
-	f = f0 >> 32
-
-	f0 &= bits32
-	f &= 255
-
-	f1 += f
-	g0 = f0 + 5
-
-	g = g0 >> 32
-	g0 &= bits32
-
-	f = f1 >> 32
-	f1 &= bits32
-
-	f &= 255
-	g1 = f1 + g
-
-	g = g1 >> 32
-	f2 += f
-
-	f = f2 >> 32
-	g1 &= bits32
-
-	f2 &= bits32
-	f &= 255
-
-	f3 += f
-	g2 = f2 + g
-
-	g = g2 >> 32
-	g2 &= bits32
-
-	f4 = f3 >> 32
-	f3 &= bits32
-
-	f4 &= 255
-	g3 = f3 + g
-
-	g = g3 >> 32
-	g3 &= bits32
-
-	g4 = f4 + g
-
-	g4 = g4 - 4
-	s00 = uint32(s[0])
-
-	f = uint64(int64(g4) >> 63)
-	s01 = uint32(s[1])
-
-	f0 &= f
-	g0 &^= f
-	s02 = uint32(s[2])
-
-	f1 &= f
-	f0 |= g0
-	s03 = uint32(s[3])
-
-	g1 &^= f
-	f2 &= f
-	s10 = uint32(s[4])
-
-	f3 &= f
-	g2 &^= f
-	s11 = uint32(s[5])
-
-	g3 &^= f
-	f1 |= g1
-	s12 = uint32(s[6])
-
-	f2 |= g2
-	f3 |= g3
-	s13 = uint32(s[7])
-
-	s01 <<= 8
-	f0 += uint64(s00)
-	s20 = uint32(s[8])
-
-	s02 <<= 16
-	f0 += uint64(s01)
-	s21 = uint32(s[9])
-
-	s03 <<= 24
-	f0 += uint64(s02)
-	s22 = uint32(s[10])
-
-	s11 <<= 8
-	f1 += uint64(s10)
-	s23 = uint32(s[11])
-
-	s12 <<= 16
-	f1 += uint64(s11)
-	s30 = uint32(s[12])
-
-	s13 <<= 24
-	f1 += uint64(s12)
-	s31 = uint32(s[13])
-
-	f0 += uint64(s03)
-	f1 += uint64(s13)
-	s32 = uint32(s[14])
-
-	s21 <<= 8
-	f2 += uint64(s20)
-	s33 = uint32(s[15])
-
-	s22 <<= 16
-	f2 += uint64(s21)
-
-	s23 <<= 24
-	f2 += uint64(s22)
-
-	s31 <<= 8
-	f3 += uint64(s30)
-
-	s32 <<= 16
-	f3 += uint64(s31)
-
-	s33 <<= 24
-	f3 += uint64(s32)
-
-	f2 += uint64(s23)
-	f3 += uint64(s33)
-
-	out[0] = byte(f0)
-	f0 >>= 8
-	out[1] = byte(f0)
-	f0 >>= 8
-	out[2] = byte(f0)
-	f0 >>= 8
-	out[3] = byte(f0)
-	f0 >>= 8
-	f1 += f0
-
-	out[4] = byte(f1)
-	f1 >>= 8
-	out[5] = byte(f1)
-	f1 >>= 8
-	out[6] = byte(f1)
-	f1 >>= 8
-	out[7] = byte(f1)
-	f1 >>= 8
-	f2 += f1
-
-	out[8] = byte(f2)
-	f2 >>= 8
-	out[9] = byte(f2)
-	f2 >>= 8
-	out[10] = byte(f2)
-	f2 >>= 8
-	out[11] = byte(f2)
-	f2 >>= 8
-	f3 += f2
-
-	out[12] = byte(f3)
-	f3 >>= 8
-	out[13] = byte(f3)
-	f3 >>= 8
-	out[14] = byte(f3)
-	f3 >>= 8
-	out[15] = byte(f3)
+	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/runner.go b/src/ssl/test/runner/runner.go
index 3aa2c46..8444c21 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -6662,6 +6662,10 @@
 	{"RSA-PKCS1-SHA384", signatureRSAPKCS1WithSHA384, testCertRSA},
 	{"RSA-PKCS1-SHA512", signatureRSAPKCS1WithSHA512, testCertRSA},
 	{"ECDSA-SHA1", signatureECDSAWithSHA1, testCertECDSAP256},
+	// The “P256” in the following line is not a mistake. In TLS 1.2 the
+	// hash function doesn't have to match the curve and so the same
+	// signature algorithm works with P-224.
+	{"ECDSA-P224-SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP224},
 	{"ECDSA-P256-SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP256},
 	{"ECDSA-P384-SHA384", signatureECDSAWithP384AndSHA384, testCertECDSAP384},
 	{"ECDSA-P521-SHA512", signatureECDSAWithP521AndSHA512, testCertECDSAP521},
@@ -6718,7 +6722,13 @@
 				shouldVerifyFail = true
 			}
 			// RSA-PKCS1 does not exist in TLS 1.3.
-			if ver.version == VersionTLS13 && hasComponent(alg.name, "PKCS1") {
+			if ver.version >= VersionTLS13 && hasComponent(alg.name, "PKCS1") {
+				shouldSignFail = true
+				shouldVerifyFail = true
+			}
+			// SHA-224 has been removed from TLS 1.3 and, in 1.3,
+			// the curve has to match the hash size.
+			if ver.version >= VersionTLS13 && alg.cert == testCertECDSAP224 {
 				shouldSignFail = true
 				shouldVerifyFail = true
 			}
@@ -7486,31 +7496,6 @@
 		},
 		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
 	})
-
-	// A server certificate with a P-224 key will only work up to TLS 1.2
-	// and we only test it with BoringSSL acting as a server because that's
-	// all Alphabet requires with it.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "P224-Server",
-		config: Config{
-			VerifySignatureAlgorithms: []signatureAlgorithm{
-				// TLS 1.2 does not require that the curve
-				// match the hash, thus P-256 with SHA-256 is
-				// the same signature algorithm value as P-224
-				// with SHA-256.
-				signatureECDSAWithP256AndSHA256,
-			},
-			// P-256 must be offered as well because ECDHE requires
-			// it.
-			CurvePreferences: []CurveID{CurveP224, CurveP256},
-		},
-		flags: []string{
-			"-max-version", strconv.Itoa(VersionTLS12),
-			"-cert-file", path.Join(*resourceDir, ecdsaP224CertificateFile),
-			"-key-file", path.Join(*resourceDir, ecdsaP224KeyFile),
-		},
-	})
 }
 
 // timeouts is the retransmit schedule for BoringSSL. It doubles and
@@ -8146,6 +8131,7 @@
 	name string
 	id   CurveID
 }{
+	{"P-224", CurveP224},
 	{"P-256", CurveP256},
 	{"P-384", CurveP384},
 	{"P-521", CurveP521},
@@ -10309,10 +10295,11 @@
 		},
 	})
 
-	// Test that we fail on early data with Channel ID.
+	// Test that the client offering 0-RTT and Channel ID forbids the server
+	// from accepting both.
 	testCases = append(testCases, testCase{
 		testType: clientTest,
-		name:     "TLS13-EarlyData-ChannelID-Client",
+		name:     "TLS13-EarlyDataChannelID-AcceptBoth-Client",
 		config: Config{
 			MaxVersion:       VersionTLS13,
 			MaxEarlyDataSize: 16384,
@@ -10329,14 +10316,57 @@
 		},
 	})
 
+	// Test that the client offering Channel ID and 0-RTT allows the server
+	// to decline 0-RTT.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-EarlyDataChannelID-AcceptChannelID-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			RequestChannelID: true,
+			Bugs: ProtocolBugs{
+				AlwaysRejectEarlyData: true,
+			},
+		},
+		resumeSession:   true,
+		expectChannelID: true,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-info",
+			"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
+			"-expect-reject-early-data",
+		},
+	})
+
+	// Test that the client offering Channel ID and 0-RTT allows the server
+	// to decline Channel ID.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-EarlyDataChannelID-AcceptEarlyData-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-info",
+			"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
+			"-expect-accept-early-data",
+		},
+	})
+
+	// Test that the server supporting Channel ID and 0-RTT declines 0-RTT
+	// if it would negotiate Channel ID.
 	testCases = append(testCases, testCase{
 		testType: serverTest,
-		name:     "TLS13-EarlyData-ChannelID-Server",
+		name:     "TLS13-EarlyDataChannelID-OfferBoth-Server",
 		config: Config{
 			MaxVersion: VersionTLS13,
 			ChannelID:  channelIDKey,
 			Bugs: ProtocolBugs{
-				SendEarlyData:           [][]byte{{}},
+				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
 				ExpectEarlyDataAccepted: false,
 			},
 		},
@@ -10350,6 +10380,28 @@
 		},
 	})
 
+	// Test that the server supporting Channel ID and 0-RTT accepts 0-RTT
+	// if not offered Channel ID.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-EarlyDataChannelID-OfferEarlyData-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+				ExpectEarlyDataAccepted: true,
+				ExpectHalfRTTData:       [][]byte{{254, 253, 252, 251}},
+			},
+		},
+		resumeSession:   true,
+		expectChannelID: false,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-accept-early-data",
+			"-enable-channel-id",
+		},
+	})
+
 	// Test that the server rejects 0-RTT streams without end_of_early_data.
 	// The subsequent records should fail to decrypt.
 	testCases = append(testCases, testCase{
@@ -10740,6 +10792,109 @@
 	}
 }
 
+func addExtraHandshakeTests() {
+	// An extra SSL_do_handshake is normally a no-op. These tests use -async
+	// to ensure there is no transport I/O.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ExtraHandshake-Client-TLS12",
+		config: Config{
+			MinVersion: VersionTLS12,
+			MaxVersion: VersionTLS12,
+		},
+		flags: []string{
+			"-async",
+			"-no-op-extra-handshake",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ExtraHandshake-Server-TLS12",
+		config: Config{
+			MinVersion: VersionTLS12,
+			MaxVersion: VersionTLS12,
+		},
+		flags: []string{
+			"-async",
+			"-no-op-extra-handshake",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ExtraHandshake-Client-TLS13",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+		},
+		flags: []string{
+			"-async",
+			"-no-op-extra-handshake",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ExtraHandshake-Server-TLS13",
+		config: Config{
+			MinVersion: VersionTLS13,
+			MaxVersion: VersionTLS13,
+		},
+		flags: []string{
+			"-async",
+			"-no-op-extra-handshake",
+		},
+	})
+
+	// An extra SSL_do_handshake is a no-op in server 0-RTT.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ExtraHandshake-Server-EarlyData-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+				ExpectEarlyDataAccepted: true,
+				ExpectHalfRTTData:       [][]byte{{254, 253, 252, 251}},
+			},
+		},
+		messageCount:  2,
+		resumeSession: true,
+		flags: []string{
+			"-async",
+			"-enable-early-data",
+			"-expect-accept-early-data",
+			"-no-op-extra-handshake",
+		},
+	})
+
+	// An extra SSL_do_handshake drives the handshake to completion in False
+	// Start. We test this by handshaking twice and asserting the False
+	// Start does not appear to happen. See AlertBeforeFalseStartTest for
+	// how the test works.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ExtraHandshake-FalseStart",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			NextProtos:   []string{"foo"},
+			Bugs: ProtocolBugs{
+				ExpectFalseStart:          true,
+				AlertBeforeFalseStartTest: alertAccessDenied,
+			},
+		},
+		flags: []string{
+			"-handshake-twice",
+			"-false-start",
+			"-advertise-alpn", "\x03foo",
+		},
+		shimWritesFirst:    true,
+		shouldFail:         true,
+		expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
+		expectedLocalError: "tls: peer did not false start: EOF",
+	})
+}
+
 func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
 	defer wg.Done()
 
@@ -10866,6 +11021,7 @@
 	addCertificateTests()
 	addRetainOnlySHA256ClientCertTests()
 	addECDSAKeyUsageTests()
+	addExtraHandshakeTests()
 
 	var wg sync.WaitGroup
 
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 7e57543..a8cf755 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -128,6 +128,8 @@
   { "-expect-reject-early-data", &TestConfig::expect_reject_early_data },
   { "-expect-no-alpn", &TestConfig::expect_no_alpn },
   { "-expect-no-resume-alpn", &TestConfig::expect_no_resume_alpn },
+  { "-no-op-extra-handshake", &TestConfig::no_op_extra_handshake },
+  { "-handshake-twice", &TestConfig::handshake_twice },
 };
 
 const Flag<std::string> kStringFlags[] = {
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index fadd05e..ef14f15 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -141,6 +141,8 @@
   bool expect_session_id = false;
   bool expect_no_session_id = false;
   int expect_ticket_age_skew = 0;
+  bool no_op_extra_handshake = false;
+  bool handshake_twice = false;
 };
 
 bool ParseConfig(int argc, char **argv, TestConfig *out_config);
diff --git a/src/util/diff_asm.go b/src/util/diff_asm.go
index 0a0888b..bc9363f 100644
--- a/src/util/diff_asm.go
+++ b/src/util/diff_asm.go
@@ -31,7 +31,7 @@
 
 func mapName(path string) string {
 	switch filepath.ToSlash(path) {
-	case "crypto/rand/asm/rdrand-x86_64.pl":
+	case "crypto/cipher/asm/chacha20_poly1305_x86_64.pl", "crypto/rand/asm/rdrand-x86_64.pl":
 		return ""
 	case "crypto/ec/asm/p256-x86_64-asm.pl":
 		return filepath.FromSlash("crypto/ec/asm/ecp_nistz256-x86_64.pl")