external/boringssl: Sync to 3ef7697ed30f28367395a5aafb57a12a19906d96.
am: 95add82835

Change-Id: I479f3ead51ffd6fb4cc326a31409a38928f51b34
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index dff0ac7..9fe48a4 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-3cbdc34619daafb9f8527fb9dd27afc8ee7dcf19
+3ef7697ed30f28367395a5aafb57a12a19906d96
diff --git a/UPDATING b/UPDATING
old mode 100644
new mode 100755
index c7019e4..f818987
--- a/UPDATING
+++ b/UPDATING
@@ -1,9 +1,24 @@
+#!/bin/sh
+
+set -xe
+
+old_revision=$(cat BORINGSSL_REVISION)
 rm -Rf src
 git clone https://boringssl.googlesource.com/boringssl src
 cd src
-git show -s --pretty=%H > ../BORINGSSL_REVISION
+new_revision=$(git show -s --pretty=%H)
 cd ..
+echo ${new_revision} > BORINGSSL_REVISION
+
 rm -Rf src/.git
 rm -Rf src/fuzz
 rm -Rf linux-aarch64/ linux-arm/ linux-x86/ linux-x86_64/ mac-x86/ mac-x86_64/ win-x86_64/ win-x86/
 python src/util/generate_build_files.py android
+
+git add .
+git commit -m "external/boringssl: Sync to ${new_revision}.
+
+This includes the following changes:
+
+https://boringssl.googlesource.com/boringssl/+log/${old_revision}..${new_revision}
+"
diff --git a/err_data.c b/err_data.c
index 6b0b8cc..001145d 100644
--- a/err_data.c
+++ b/err_data.c
@@ -178,42 +178,42 @@
     0x28340c19,
     0x283480ac,
     0x283500ea,
-    0x2c3228da,
-    0x2c32a8e8,
-    0x2c3328fa,
-    0x2c33a90c,
-    0x2c342920,
-    0x2c34a932,
-    0x2c35294d,
-    0x2c35a95f,
-    0x2c362972,
+    0x2c322910,
+    0x2c32a91e,
+    0x2c332930,
+    0x2c33a942,
+    0x2c342956,
+    0x2c34a968,
+    0x2c352983,
+    0x2c35a995,
+    0x2c3629a8,
     0x2c36832d,
-    0x2c37297f,
-    0x2c37a991,
-    0x2c3829a4,
-    0x2c38a9bb,
-    0x2c3929c9,
-    0x2c39a9d9,
-    0x2c3a29eb,
-    0x2c3aa9ff,
-    0x2c3b2a10,
-    0x2c3baa2f,
-    0x2c3c2a43,
-    0x2c3caa59,
-    0x2c3d2a72,
-    0x2c3daa8f,
-    0x2c3e2aa0,
-    0x2c3eaaae,
-    0x2c3f2ac6,
-    0x2c3faade,
-    0x2c402aeb,
+    0x2c3729b5,
+    0x2c37a9c7,
+    0x2c3829da,
+    0x2c38a9f1,
+    0x2c3929ff,
+    0x2c39aa0f,
+    0x2c3a2a21,
+    0x2c3aaa35,
+    0x2c3b2a46,
+    0x2c3baa65,
+    0x2c3c2a79,
+    0x2c3caa8f,
+    0x2c3d2aa8,
+    0x2c3daac5,
+    0x2c3e2ad6,
+    0x2c3eaae4,
+    0x2c3f2afc,
+    0x2c3fab14,
+    0x2c402b21,
     0x2c4090e7,
-    0x2c412afc,
-    0x2c41ab0f,
+    0x2c412b32,
+    0x2c41ab45,
     0x2c4210c0,
-    0x2c42ab20,
+    0x2c42ab56,
     0x2c430720,
-    0x2c43aa21,
+    0x2c43aa57,
     0x30320000,
     0x30328015,
     0x3033001f,
@@ -461,42 +461,42 @@
     0x406b2370,
     0x406ba393,
     0x406c23a9,
-    0x406ca5d5,
-    0x406d2604,
-    0x406da62c,
-    0x406e265a,
-    0x406ea672,
-    0x406f2691,
-    0x406fa6a6,
-    0x407026b9,
-    0x4070a6d6,
+    0x406ca60b,
+    0x406d263a,
+    0x406da662,
+    0x406e2690,
+    0x406ea6a8,
+    0x406f26c7,
+    0x406fa6dc,
+    0x407026ef,
+    0x4070a70c,
     0x40710800,
-    0x4071a6e8,
-    0x407226fb,
-    0x4072a714,
-    0x4073272c,
+    0x4071a71e,
+    0x40722731,
+    0x4072a74a,
+    0x40732762,
     0x4073936d,
-    0x40742740,
-    0x4074a75a,
-    0x4075276b,
-    0x4075a77f,
-    0x4076278d,
+    0x40742776,
+    0x4074a790,
+    0x407527a1,
+    0x4075a7b5,
+    0x407627c3,
     0x407691aa,
-    0x407727b2,
-    0x4077a7d4,
-    0x407827ef,
-    0x4078a828,
-    0x4079283f,
-    0x4079a855,
-    0x407a2861,
-    0x407aa874,
-    0x407b2889,
-    0x407ba89b,
-    0x407c28b0,
-    0x407ca8b9,
+    0x407727e8,
+    0x4077a80a,
+    0x40782825,
+    0x4078a85e,
+    0x40792875,
+    0x4079a88b,
+    0x407a2897,
+    0x407aa8aa,
+    0x407b28bf,
+    0x407ba8d1,
+    0x407c28e6,
+    0x407ca8ef,
     0x407d2162,
     0x407d9c57,
-    0x407e2804,
+    0x407e283a,
     0x407e9e16,
     0x407f1a67,
     0x407f9887,
@@ -504,7 +504,7 @@
     0x40809a8f,
     0x40811cd9,
     0x40819c08,
-    0x40822645,
+    0x4082267b,
     0x4082986d,
     0x40831df1,
     0x4083a038,
@@ -536,11 +536,13 @@
     0x421f2453,
     0x42212520,
     0x422624b3,
-    0x422b25b9,
-    0x422ba582,
-    0x422c25a1,
+    0x422b25ef,
+    0x422ba59d,
+    0x422c25d7,
     0x422ca55c,
     0x422d253b,
+    0x422da5bc,
+    0x422e2582,
     0x4432072b,
     0x4432873a,
     0x44330746,
@@ -583,69 +585,69 @@
     0x4c3d136d,
     0x4c3d937c,
     0x4c3e1389,
-    0x50322b32,
-    0x5032ab41,
-    0x50332b4c,
-    0x5033ab5c,
-    0x50342b75,
-    0x5034ab8f,
-    0x50352b9d,
-    0x5035abb3,
-    0x50362bc5,
-    0x5036abdb,
-    0x50372bf4,
-    0x5037ac07,
-    0x50382c1f,
-    0x5038ac30,
-    0x50392c45,
-    0x5039ac59,
-    0x503a2c79,
-    0x503aac8f,
-    0x503b2ca7,
-    0x503bacb9,
-    0x503c2cd5,
-    0x503cacec,
-    0x503d2d05,
-    0x503dad1b,
-    0x503e2d28,
-    0x503ead3e,
-    0x503f2d50,
+    0x50322b68,
+    0x5032ab77,
+    0x50332b82,
+    0x5033ab92,
+    0x50342bab,
+    0x5034abc5,
+    0x50352bd3,
+    0x5035abe9,
+    0x50362bfb,
+    0x5036ac11,
+    0x50372c2a,
+    0x5037ac3d,
+    0x50382c55,
+    0x5038ac66,
+    0x50392c7b,
+    0x5039ac8f,
+    0x503a2caf,
+    0x503aacc5,
+    0x503b2cdd,
+    0x503bacef,
+    0x503c2d0b,
+    0x503cad22,
+    0x503d2d3b,
+    0x503dad51,
+    0x503e2d5e,
+    0x503ead74,
+    0x503f2d86,
     0x503f8382,
-    0x50402d63,
-    0x5040ad73,
-    0x50412d8d,
-    0x5041ad9c,
-    0x50422db6,
-    0x5042add3,
-    0x50432de3,
-    0x5043adf3,
-    0x50442e02,
+    0x50402d99,
+    0x5040ada9,
+    0x50412dc3,
+    0x5041add2,
+    0x50422dec,
+    0x5042ae09,
+    0x50432e19,
+    0x5043ae29,
+    0x50442e38,
     0x5044843f,
-    0x50452e16,
-    0x5045ae34,
-    0x50462e47,
-    0x5046ae5d,
-    0x50472e6f,
-    0x5047ae84,
-    0x50482eaa,
-    0x5048aeb8,
-    0x50492ecb,
-    0x5049aee0,
-    0x504a2ef6,
-    0x504aaf06,
-    0x504b2f26,
-    0x504baf39,
-    0x504c2f5c,
-    0x504caf8a,
-    0x504d2f9c,
-    0x504dafb9,
-    0x504e2fd4,
-    0x504eaff0,
-    0x504f3002,
-    0x504fb019,
-    0x50503028,
+    0x50452e4c,
+    0x5045ae6a,
+    0x50462e7d,
+    0x5046ae93,
+    0x50472ea5,
+    0x5047aeba,
+    0x50482ee0,
+    0x5048aeee,
+    0x50492f01,
+    0x5049af16,
+    0x504a2f2c,
+    0x504aaf3c,
+    0x504b2f5c,
+    0x504baf6f,
+    0x504c2f92,
+    0x504cafc0,
+    0x504d2fd2,
+    0x504dafef,
+    0x504e300a,
+    0x504eb026,
+    0x504f3038,
+    0x504fb04f,
+    0x5050305e,
     0x505086ef,
-    0x5051303b,
+    0x50513071,
     0x58320ec9,
     0x68320e8b,
     0x68328c25,
@@ -1141,7 +1143,9 @@
     "TLSV1_ALERT_USER_CANCELLED\0"
     "TLSV1_BAD_CERTIFICATE_HASH_VALUE\0"
     "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\0"
+    "TLSV1_CERTIFICATE_REQUIRED\0"
     "TLSV1_CERTIFICATE_UNOBTAINABLE\0"
+    "TLSV1_UNKNOWN_PSK_IDENTITY\0"
     "TLSV1_UNRECOGNIZED_NAME\0"
     "TLSV1_UNSUPPORTED_EXTENSION\0"
     "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3d1ea78..8ab4066 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -126,7 +126,7 @@
   endif()
 
   add_definitions(-DBORINGSSL_UNSAFE_FUZZER_MODE)
-  set(RUNNER_ARGS "-fuzzer")
+  set(RUNNER_ARGS "-fuzzer" "-deterministic" "-shim-config" "fuzzer_mode.json")
 
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters")
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters")
diff --git a/src/crypto/asn1/tasn_utl.c b/src/crypto/asn1/tasn_utl.c
index 55037a1..d409cfa 100644
--- a/src/crypto/asn1/tasn_utl.c
+++ b/src/crypto/asn1/tasn_utl.c
@@ -70,7 +70,7 @@
 /* Utility functions for manipulating fields and offsets */
 
 /* Add 'offset' to 'addr' */
-#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset)
+#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset))
 
 /* Given an ASN1_ITEM CHOICE type return the selector value */
 int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) {
diff --git a/src/crypto/bio/socket.c b/src/crypto/bio/socket.c
index 0520c3e..f70ea92 100644
--- a/src/crypto/bio/socket.c
+++ b/src/crypto/bio/socket.c
@@ -67,7 +67,7 @@
 #include <winsock2.h>
 OPENSSL_MSVC_PRAGMA(warning(pop))
 
-#pragma comment(lib, "Ws2_32.lib")
+OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
 #endif
 
 #include "internal.h"
diff --git a/src/crypto/bn/asm/x86_64-gcc.c b/src/crypto/bn/asm/x86_64-gcc.c
index 214c12a..177d335 100644
--- a/src/crypto/bn/asm/x86_64-gcc.c
+++ b/src/crypto/bn/asm/x86_64-gcc.c
@@ -80,7 +80,7 @@
         : "+m"(r), "+d"(high)                                          \
         : "r"(carry), "g"(0)                                           \
         : "cc");                                                       \
-    carry = high;                                                      \
+    (carry) = high;                                                    \
   } while (0)
 
 #define mul(r, a, word, carry)                                         \
@@ -91,7 +91,8 @@
         : "+r"(carry), "+d"(high)                                      \
         : "a"(low), "g"(0)                                             \
         : "cc");                                                       \
-    (r) = carry, carry = high;                                         \
+    (r) = (carry);                                                     \
+    (carry) = high;                                                    \
   } while (0)
 #undef sqr
 #define sqr(r0, r1, a) asm("mulq %2" : "=a"(r0), "=d"(r1) : "a"(a) : "cc");
@@ -256,14 +257,14 @@
         : "cc");                             \
   } while (0)
 
-#define sqr_add_c(a, i, c0, c1, c2)          \
-  do {                                       \
-    BN_ULONG t1, t2;                         \
-    asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"(a[i]) : "cc"); \
-    asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
-        : "+r"(c0), "+r"(c1), "+r"(c2)       \
-        : "r"(t1), "r"(t2), "g"(0)           \
-        : "cc");                             \
+#define sqr_add_c(a, i, c0, c1, c2)                           \
+  do {                                                        \
+    BN_ULONG t1, t2;                                          \
+    asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"((a)[i]) : "cc"); \
+    asm("addq %3,%0; adcq %4,%1; adcq %5,%2"                  \
+        : "+r"(c0), "+r"(c1), "+r"(c2)                        \
+        : "r"(t1), "r"(t2), "g"(0)                            \
+        : "cc");                                              \
   } while (0)
 
 #define mul_add_c2(a, b, c0, c1, c2)         \
diff --git a/src/crypto/bn/generic.c b/src/crypto/bn/generic.c
index f552d99..de77cc5 100644
--- a/src/crypto/bn/generic.c
+++ b/src/crypto/bn/generic.c
@@ -67,34 +67,34 @@
     !(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__)))
 
 #ifdef BN_ULLONG
-#define mul_add(r, a, w, c)             \
-  {                                     \
-    BN_ULLONG t;                        \
-    t = (BN_ULLONG)w * (a) + (r) + (c); \
-    (r) = Lw(t);                        \
-    (c) = Hw(t);                        \
-  }
+#define mul_add(r, a, w, c)               \
+  do {                                    \
+    BN_ULLONG t;                          \
+    t = (BN_ULLONG)(w) * (a) + (r) + (c); \
+    (r) = Lw(t);                          \
+    (c) = Hw(t);                          \
+  } while (0)
 
-#define mul(r, a, w, c)           \
-  {                               \
-    BN_ULLONG t;                  \
-    t = (BN_ULLONG)w * (a) + (c); \
-    (r) = Lw(t);                  \
-    (c) = Hw(t);                  \
-  }
+#define mul(r, a, w, c)             \
+  do {                              \
+    BN_ULLONG t;                    \
+    t = (BN_ULLONG)(w) * (a) + (c); \
+    (r) = Lw(t);                    \
+    (c) = Hw(t);                    \
+  } while (0)
 
 #define sqr(r0, r1, a)        \
-  {                           \
+  do {                        \
     BN_ULLONG t;              \
     t = (BN_ULLONG)(a) * (a); \
     (r0) = Lw(t);             \
     (r1) = Hw(t);             \
-  }
+  } while (0)
 
 #else
 
 #define mul_add(r, a, w, c)             \
-  {                                     \
+  do {                                  \
     BN_ULONG high, low, ret, tmp = (a); \
     ret = (r);                          \
     BN_UMULT_LOHI(low, high, w, tmp);   \
@@ -104,23 +104,23 @@
     ret += low;                         \
     (c) += (ret < low) ? 1 : 0;         \
     (r) = ret;                          \
-  }
+  } while (0)
 
 #define mul(r, a, w, c)                \
-  {                                    \
+  do {                                 \
     BN_ULONG high, low, ret, ta = (a); \
     BN_UMULT_LOHI(low, high, w, ta);   \
     ret = low + (c);                   \
     (c) = high;                        \
     (c) += (ret < low) ? 1 : 0;        \
     (r) = ret;                         \
-  }
+  } while (0)
 
 #define sqr(r0, r1, a)               \
-  {                                  \
+  do {                               \
     BN_ULONG tmp = (a);              \
     BN_UMULT_LOHI(r0, r1, tmp, tmp); \
-  }
+  } while (0)
 
 #endif /* !BN_ULLONG */
 
@@ -369,42 +369,46 @@
   do {                                  \
     BN_ULONG hi;                        \
     BN_ULLONG t = (BN_ULLONG)(a) * (b); \
-    t += c0; /* no carry */             \
-    c0 = (BN_ULONG)Lw(t);               \
+    t += (c0); /* no carry */           \
+    (c0) = (BN_ULONG)Lw(t);             \
     hi = (BN_ULONG)Hw(t);               \
-    c1 = (c1 + hi) & BN_MASK2;          \
-    if (c1 < hi)                        \
-      c2++;                             \
+    (c1) = ((c1) + (hi)) & BN_MASK2;    \
+    if ((c1) < hi) {                    \
+      (c2)++;                           \
+    }                                   \
   } while (0)
 
-#define mul_add_c2(a, b, c0, c1, c2)      \
-  do {                                    \
-    BN_ULONG hi;                          \
-    BN_ULLONG t = (BN_ULLONG)(a) * (b);   \
-    BN_ULLONG tt = t + c0; /* no carry */ \
-    c0 = (BN_ULONG)Lw(tt);                \
-    hi = (BN_ULONG)Hw(tt);                \
-    c1 = (c1 + hi) & BN_MASK2;            \
-    if (c1 < hi)                          \
-      c2++;                               \
-    t += c0; /* no carry */               \
-    c0 = (BN_ULONG)Lw(t);                 \
-    hi = (BN_ULONG)Hw(t);                 \
-    c1 = (c1 + hi) & BN_MASK2;            \
-    if (c1 < hi)                          \
-      c2++;                               \
+#define mul_add_c2(a, b, c0, c1, c2)        \
+  do {                                      \
+    BN_ULONG hi;                            \
+    BN_ULLONG t = (BN_ULLONG)(a) * (b);     \
+    BN_ULLONG tt = t + (c0); /* no carry */ \
+    (c0) = (BN_ULONG)Lw(tt);                \
+    hi = (BN_ULONG)Hw(tt);                  \
+    (c1) = ((c1) + hi) & BN_MASK2;          \
+    if ((c1) < hi) {                        \
+      (c2)++;                               \
+    }                                       \
+    t += (c0); /* no carry */               \
+    (c0) = (BN_ULONG)Lw(t);                 \
+    hi = (BN_ULONG)Hw(t);                   \
+    (c1) = ((c1) + hi) & BN_MASK2;          \
+    if ((c1) < hi) {                        \
+      (c2)++;                               \
+    }                                       \
   } while (0)
 
-#define sqr_add_c(a, i, c0, c1, c2)       \
-  do {                                    \
-    BN_ULONG hi;                          \
-    BN_ULLONG t = (BN_ULLONG)a[i] * a[i]; \
-    t += c0; /* no carry */               \
-    c0 = (BN_ULONG)Lw(t);                 \
-    hi = (BN_ULONG)Hw(t);                 \
-    c1 = (c1 + hi) & BN_MASK2;            \
-    if (c1 < hi)                          \
-      c2++;                               \
+#define sqr_add_c(a, i, c0, c1, c2)           \
+  do {                                        \
+    BN_ULONG hi;                              \
+    BN_ULLONG t = (BN_ULLONG)(a)[i] * (a)[i]; \
+    t += (c0); /* no carry */                 \
+    (c0) = (BN_ULONG)Lw(t);                   \
+    hi = (BN_ULONG)Hw(t);                     \
+    (c1) = ((c1) + hi) & BN_MASK2;            \
+    if ((c1) < hi) {                          \
+      (c2)++;                                 \
+    }                                         \
   } while (0)
 
 #define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
@@ -418,10 +422,10 @@
     BN_ULONG ta = (a), tb = (b);    \
     BN_ULONG lo, hi;                \
     BN_UMULT_LOHI(lo, hi, ta, tb);  \
-    c0 += lo;                       \
-    hi += (c0 < lo) ? 1 : 0;        \
-    c1 += hi;                       \
-    c2 += (c1 < hi) ? 1 : 0;        \
+    (c0) += lo;                     \
+    hi += ((c0) < lo) ? 1 : 0;      \
+    (c1) += hi;                     \
+    (c2) += ((c1) < hi) ? 1 : 0;    \
   } while (0)
 
 #define mul_add_c2(a, b, c0, c1, c2) \
@@ -429,14 +433,14 @@
     BN_ULONG ta = (a), tb = (b);     \
     BN_ULONG lo, hi, tt;             \
     BN_UMULT_LOHI(lo, hi, ta, tb);   \
-    c0 += lo;                        \
-    tt = hi + ((c0 < lo) ? 1 : 0);   \
-    c1 += tt;                        \
-    c2 += (c1 < tt) ? 1 : 0;         \
-    c0 += lo;                        \
+    (c0) += lo;                      \
+    tt = hi + (((c0) < lo) ? 1 : 0); \
+    (c1) += tt;                      \
+    (c2) += ((c1) < tt) ? 1 : 0;     \
+    (c0) += lo;                      \
     hi += (c0 < lo) ? 1 : 0;         \
-    c1 += hi;                        \
-    c2 += (c1 < hi) ? 1 : 0;         \
+    (c1) += hi;                      \
+    (c2) += ((c1) < hi) ? 1 : 0;     \
   } while (0)
 
 #define sqr_add_c(a, i, c0, c1, c2) \
@@ -444,10 +448,10 @@
     BN_ULONG ta = (a)[i];           \
     BN_ULONG lo, hi;                \
     BN_UMULT_LOHI(lo, hi, ta, ta);  \
-    c0 += lo;                       \
+    (c0) += lo;                     \
     hi += (c0 < lo) ? 1 : 0;        \
-    c1 += hi;                       \
-    c2 += (c1 < hi) ? 1 : 0;        \
+    (c1) += hi;                     \
+    (c2) += ((c1) < hi) ? 1 : 0;    \
   } while (0)
 
 #define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
diff --git a/src/crypto/bn/internal.h b/src/crypto/bn/internal.h
index aafd175..99fc306 100644
--- a/src/crypto/bn/internal.h
+++ b/src/crypto/bn/internal.h
@@ -188,10 +188,10 @@
 #endif
 
 
-#define STATIC_BIGNUM(x)                                \
-  {                                                     \
-    (BN_ULONG *)x, sizeof(x) / sizeof(BN_ULONG),        \
-    sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
+#define STATIC_BIGNUM(x)                                    \
+  {                                                         \
+    (BN_ULONG *)(x), sizeof(x) / sizeof(BN_ULONG),          \
+        sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
   }
 
 #if defined(BN_ULLONG)
diff --git a/src/crypto/cipher/e_rc2.c b/src/crypto/cipher/e_rc2.c
index 67418d5..e1b4301 100644
--- a/src/crypto/cipher/e_rc2.c
+++ b/src/crypto/cipher/e_rc2.c
@@ -60,63 +60,68 @@
 #include "internal.h"
 
 
-#define c2l(c, l)                                                           \
-  (l = ((uint32_t)(*((c)++))), l |= ((uint32_t)(*((c)++))) << 8L, \
-   l |= ((uint32_t)(*((c)++))) << 16L,                                 \
-   l |= ((uint32_t)(*((c)++))) << 24L)
+#define c2l(c, l)                         \
+  do {                                    \
+    (l) = ((uint32_t)(*((c)++)));         \
+    (l) |= ((uint32_t)(*((c)++))) << 8L;  \
+    (l) |= ((uint32_t)(*((c)++))) << 16L; \
+    (l) |= ((uint32_t)(*((c)++))) << 24L; \
+  } while (0)
 
-#define c2ln(c, l1, l2, n)                        \
-  {                                               \
-    c += n;                                       \
-    l1 = l2 = 0;                                  \
-    switch (n) {                                  \
-      case 8:                                     \
-        l2 = ((uint32_t)(*(--(c)))) << 24L;  \
-      case 7:                                     \
-        l2 |= ((uint32_t)(*(--(c)))) << 16L; \
-      case 6:                                     \
-        l2 |= ((uint32_t)(*(--(c)))) << 8L;  \
-      case 5:                                     \
-        l2 |= ((uint32_t)(*(--(c))));        \
-      case 4:                                     \
-        l1 = ((uint32_t)(*(--(c)))) << 24L;  \
-      case 3:                                     \
-        l1 |= ((uint32_t)(*(--(c)))) << 16L; \
-      case 2:                                     \
-        l1 |= ((uint32_t)(*(--(c)))) << 8L;  \
-      case 1:                                     \
-        l1 |= ((uint32_t)(*(--(c))));        \
-    }                                             \
-  }
+#define c2ln(c, l1, l2, n)                     \
+  do {                                         \
+    (c) += (n);                                \
+    (l1) = (l2) = 0;                           \
+    switch (n) {                               \
+      case 8:                                  \
+        (l2) = ((uint32_t)(*(--(c)))) << 24L;  \
+      case 7:                                  \
+        (l2) |= ((uint32_t)(*(--(c)))) << 16L; \
+      case 6:                                  \
+        (l2) |= ((uint32_t)(*(--(c)))) << 8L;  \
+      case 5:                                  \
+        (l2) |= ((uint32_t)(*(--(c))));        \
+      case 4:                                  \
+        (l1) = ((uint32_t)(*(--(c)))) << 24L;  \
+      case 3:                                  \
+        (l1) |= ((uint32_t)(*(--(c)))) << 16L; \
+      case 2:                                  \
+        (l1) |= ((uint32_t)(*(--(c)))) << 8L;  \
+      case 1:                                  \
+        (l1) |= ((uint32_t)(*(--(c))));        \
+    }                                          \
+  } while (0)
 
-#define l2c(l, c)                                   \
-  (*((c)++) = (uint8_t)(((l)) & 0xff),        \
-   *((c)++) = (uint8_t)(((l) >> 8L) & 0xff),  \
-   *((c)++) = (uint8_t)(((l) >> 16L) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 24L) & 0xff))
+#define l2c(l, c)                              \
+  do {                                         \
+    *((c)++) = (uint8_t)(((l)) & 0xff);        \
+    *((c)++) = (uint8_t)(((l) >> 8L) & 0xff);  \
+    *((c)++) = (uint8_t)(((l) >> 16L) & 0xff); \
+    *((c)++) = (uint8_t)(((l) >> 24L) & 0xff); \
+  } while (0)
 
-#define l2cn(l1, l2, c, n)                                \
-  {                                                       \
-    c += n;                                               \
-    switch (n) {                                          \
-      case 8:                                             \
+#define l2cn(l1, l2, c, n)                          \
+  do {                                              \
+    (c) += (n);                                     \
+    switch (n) {                                    \
+      case 8:                                       \
         *(--(c)) = (uint8_t)(((l2) >> 24L) & 0xff); \
-      case 7:                                             \
+      case 7:                                       \
         *(--(c)) = (uint8_t)(((l2) >> 16L) & 0xff); \
-      case 6:                                             \
+      case 6:                                       \
         *(--(c)) = (uint8_t)(((l2) >> 8L) & 0xff);  \
-      case 5:                                             \
+      case 5:                                       \
         *(--(c)) = (uint8_t)(((l2)) & 0xff);        \
-      case 4:                                             \
+      case 4:                                       \
         *(--(c)) = (uint8_t)(((l1) >> 24L) & 0xff); \
-      case 3:                                             \
+      case 3:                                       \
         *(--(c)) = (uint8_t)(((l1) >> 16L) & 0xff); \
-      case 2:                                             \
+      case 2:                                       \
         *(--(c)) = (uint8_t)(((l1) >> 8L) & 0xff);  \
-      case 1:                                             \
+      case 1:                                       \
         *(--(c)) = (uint8_t)(((l1)) & 0xff);        \
-    }                                                     \
-  }
+    }                                               \
+  } while (0)
 
 typedef struct rc2_key_st { uint16_t data[64]; } RC2_KEY;
 
diff --git a/src/crypto/cipher/tls_cbc.c b/src/crypto/cipher/tls_cbc.c
index 02d6745..dd6ab8c 100644
--- a/src/crypto/cipher/tls_cbc.c
+++ b/src/crypto/cipher/tls_cbc.c
@@ -264,23 +264,27 @@
 
 /* u32toBE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
  * big-endian order. The value of p is advanced by four. */
-#define u32toBE(n, p) \
-  (*((p)++)=(uint8_t)(n>>24), \
-   *((p)++)=(uint8_t)(n>>16), \
-   *((p)++)=(uint8_t)(n>>8), \
-   *((p)++)=(uint8_t)(n))
+#define u32toBE(n, p)                \
+  do {                               \
+    *((p)++) = (uint8_t)((n) >> 24); \
+    *((p)++) = (uint8_t)((n) >> 16); \
+    *((p)++) = (uint8_t)((n) >> 8);  \
+    *((p)++) = (uint8_t)((n));       \
+  } while (0)
 
 /* u64toBE serialises an unsigned, 64-bit number (n) as eight bytes at (p) in
  * big-endian order. The value of p is advanced by eight. */
-#define u64toBE(n, p) \
-  (*((p)++)=(uint8_t)(n>>56), \
-   *((p)++)=(uint8_t)(n>>48), \
-   *((p)++)=(uint8_t)(n>>40), \
-   *((p)++)=(uint8_t)(n>>32), \
-   *((p)++)=(uint8_t)(n>>24), \
-   *((p)++)=(uint8_t)(n>>16), \
-   *((p)++)=(uint8_t)(n>>8), \
-   *((p)++)=(uint8_t)(n))
+#define u64toBE(n, p)                \
+  do {                               \
+    *((p)++) = (uint8_t)((n) >> 56); \
+    *((p)++) = (uint8_t)((n) >> 48); \
+    *((p)++) = (uint8_t)((n) >> 40); \
+    *((p)++) = (uint8_t)((n) >> 32); \
+    *((p)++) = (uint8_t)((n) >> 24); \
+    *((p)++) = (uint8_t)((n) >> 16); \
+    *((p)++) = (uint8_t)((n) >> 8);  \
+    *((p)++) = (uint8_t)((n));       \
+  } while (0)
 
 /* 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
diff --git a/src/crypto/des/des.c b/src/crypto/des/des.c
index 1d27ebe..cada7d1 100644
--- a/src/crypto/des/des.c
+++ b/src/crypto/des/des.c
@@ -291,7 +291,7 @@
 
 #define HPERM_OP(a, t, n, m)                  \
   ((t) = ((((a) << (16 - (n))) ^ (a)) & (m)), \
-   (a) = (a) ^ (t) ^ (t >> (16 - (n))))
+   (a) = (a) ^ (t) ^ ((t) >> (16 - (n))))
 
 void DES_set_key(const DES_cblock *key, DES_key_schedule *schedule) {
   static const int shifts2[16] = {0, 0, 1, 1, 1, 1, 1, 1,
diff --git a/src/crypto/des/internal.h b/src/crypto/des/internal.h
index 00b4558..21eb933 100644
--- a/src/crypto/des/internal.h
+++ b/src/crypto/des/internal.h
@@ -64,45 +64,51 @@
 #endif
 
 
-#define c2l(c, l)                                                 \
-  (l = ((uint32_t)(*((c)++))), l |= ((uint32_t)(*((c)++))) << 8L, \
-   l |= ((uint32_t)(*((c)++))) << 16L, l |= ((uint32_t)(*((c)++))) << 24L)
+#define c2l(c, l)                         \
+  do {                                    \
+    (l) = ((uint32_t)(*((c)++)));         \
+    (l) |= ((uint32_t)(*((c)++))) << 8L;  \
+    (l) |= ((uint32_t)(*((c)++))) << 16L; \
+    (l) |= ((uint32_t)(*((c)++))) << 24L; \
+  } while (0)
 
-#define l2c(l, c)                                   \
-  (*((c)++) = (unsigned char)(((l)) & 0xff),        \
-   *((c)++) = (unsigned char)(((l) >> 8L) & 0xff),  \
-   *((c)++) = (unsigned char)(((l) >> 16L) & 0xff), \
-   *((c)++) = (unsigned char)(((l) >> 24L) & 0xff))
+#define l2c(l, c)                                    \
+  do {                                               \
+    *((c)++) = (unsigned char)(((l)) & 0xff);        \
+    *((c)++) = (unsigned char)(((l) >> 8L) & 0xff);  \
+    *((c)++) = (unsigned char)(((l) >> 16L) & 0xff); \
+    *((c)++) = (unsigned char)(((l) >> 24L) & 0xff); \
+  } while (0)
 
 /* NOTE - c is not incremented as per c2l */
-#define c2ln(c, l1, l2, n)                   \
-  {                                          \
-    c += n;                                  \
-    l1 = l2 = 0;                             \
-    switch (n) {                             \
-      case 8:                                \
-        l2 = ((uint32_t)(*(--(c)))) << 24L;  \
-      case 7:                                \
-        l2 |= ((uint32_t)(*(--(c)))) << 16L; \
-      case 6:                                \
-        l2 |= ((uint32_t)(*(--(c)))) << 8L;  \
-      case 5:                                \
-        l2 |= ((uint32_t)(*(--(c))));        \
-      case 4:                                \
-        l1 = ((uint32_t)(*(--(c)))) << 24L;  \
-      case 3:                                \
-        l1 |= ((uint32_t)(*(--(c)))) << 16L; \
-      case 2:                                \
-        l1 |= ((uint32_t)(*(--(c)))) << 8L;  \
-      case 1:                                \
-        l1 |= ((uint32_t)(*(--(c))));        \
-    }                                        \
-  }
+#define c2ln(c, l1, l2, n)                     \
+  do {                                         \
+    (c) += (n);                                \
+    (l1) = (l2) = 0;                           \
+    switch (n) {                               \
+      case 8:                                  \
+        (l2) = ((uint32_t)(*(--(c)))) << 24L;  \
+      case 7:                                  \
+        (l2) |= ((uint32_t)(*(--(c)))) << 16L; \
+      case 6:                                  \
+        (l2) |= ((uint32_t)(*(--(c)))) << 8L;  \
+      case 5:                                  \
+        (l2) |= ((uint32_t)(*(--(c))));        \
+      case 4:                                  \
+        (l1) = ((uint32_t)(*(--(c)))) << 24L;  \
+      case 3:                                  \
+        (l1) |= ((uint32_t)(*(--(c)))) << 16L; \
+      case 2:                                  \
+        (l1) |= ((uint32_t)(*(--(c)))) << 8L;  \
+      case 1:                                  \
+        (l1) |= ((uint32_t)(*(--(c))));        \
+    }                                          \
+  } while (0)
 
 /* NOTE - c is not incremented as per l2c */
 #define l2cn(l1, l2, c, n)                                \
-  {                                                       \
-    c += n;                                               \
+  do {                                                    \
+    (c) += (n);                                           \
     switch (n) {                                          \
       case 8:                                             \
         *(--(c)) = (unsigned char)(((l2) >> 24L) & 0xff); \
@@ -121,7 +127,7 @@
       case 1:                                             \
         *(--(c)) = (unsigned char)(((l1)) & 0xff);        \
     }                                                     \
-  }
+  } while (0)
 
 /* IP and FP
  * The problem is more of a geometric problem that random bit fiddling.
@@ -160,44 +166,50 @@
 I first got ~42 operations without xors.  When I remembered
 how to use xors :-) I got it to its final state.
 */
-#define PERM_OP(a, b, t, n, m) \
-  ((t) = ((((a) >> (n)) ^ (b)) & (m)), (b) ^= (t), (a) ^= ((t) << (n)))
+#define PERM_OP(a, b, t, n, m)          \
+  do {                                  \
+    (t) = ((((a) >> (n)) ^ (b)) & (m)); \
+    (b) ^= (t);                         \
+    (a) ^= ((t) << (n));                \
+  } while (0)
 
 #define IP(l, r)                        \
-  {                                     \
+  do {                                  \
     uint32_t tt;                        \
     PERM_OP(r, l, tt, 4, 0x0f0f0f0fL);  \
     PERM_OP(l, r, tt, 16, 0x0000ffffL); \
     PERM_OP(r, l, tt, 2, 0x33333333L);  \
     PERM_OP(l, r, tt, 8, 0x00ff00ffL);  \
     PERM_OP(r, l, tt, 1, 0x55555555L);  \
-  }
+  } while (0)
 
 #define FP(l, r)                        \
-  {                                     \
+  do {                                  \
     uint32_t tt;                        \
     PERM_OP(l, r, tt, 1, 0x55555555L);  \
     PERM_OP(r, l, tt, 8, 0x00ff00ffL);  \
     PERM_OP(l, r, tt, 2, 0x33333333L);  \
     PERM_OP(r, l, tt, 16, 0x0000ffffL); \
     PERM_OP(l, r, tt, 4, 0x0f0f0f0fL);  \
-  }
+  } while (0)
 
 #define LOAD_DATA(ks, R, S, u, t, E0, E1) \
-  u = R ^ ks->subkeys[S][0];              \
-  t = R ^ ks->subkeys[S][1]
+  do {                                    \
+    (u) = (R) ^ (ks)->subkeys[S][0];      \
+    (t) = (R) ^ (ks)->subkeys[S][1];      \
+  } while (0)
 
 #define D_ENCRYPT(ks, LL, R, S)                                                \
-  {                                                                            \
+  do {                                                                         \
     LOAD_DATA(ks, R, S, u, t, E0, E1);                                         \
     t = ROTATE(t, 4);                                                          \
-    LL ^=                                                                      \
+    (LL) ^=                                                                    \
         DES_SPtrans[0][(u >> 2L) & 0x3f] ^ DES_SPtrans[2][(u >> 10L) & 0x3f] ^ \
         DES_SPtrans[4][(u >> 18L) & 0x3f] ^                                    \
         DES_SPtrans[6][(u >> 26L) & 0x3f] ^ DES_SPtrans[1][(t >> 2L) & 0x3f] ^ \
         DES_SPtrans[3][(t >> 10L) & 0x3f] ^                                    \
         DES_SPtrans[5][(t >> 18L) & 0x3f] ^ DES_SPtrans[7][(t >> 26L) & 0x3f]; \
-  }
+  } while (0)
 
 #define ITERATIONS 16
 #define HALF_ITERATIONS 8
diff --git a/src/crypto/digest/md32_common.h b/src/crypto/digest/md32_common.h
index 4cf050c..818eb63 100644
--- a/src/crypto/digest/md32_common.h
+++ b/src/crypto/digest/md32_common.h
@@ -140,29 +140,39 @@
 
 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
 
-#define HOST_c2l(c, l)                        \
-  (void)(l = (((uint32_t)(*((c)++))) << 24),  \
-         l |= (((uint32_t)(*((c)++))) << 16), \
-         l |= (((uint32_t)(*((c)++))) << 8), l |= (((uint32_t)(*((c)++)))))
+#define HOST_c2l(c, l)                     \
+  do {                                     \
+    (l) = (((uint32_t)(*((c)++))) << 24);  \
+    (l) |= (((uint32_t)(*((c)++))) << 16); \
+    (l) |= (((uint32_t)(*((c)++))) << 8);  \
+    (l) |= (((uint32_t)(*((c)++))));       \
+  } while (0)
 
-#define HOST_l2c(l, c)                             \
-  (void)(*((c)++) = (uint8_t)(((l) >> 24) & 0xff), \
-         *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
-         *((c)++) = (uint8_t)(((l) >> 8) & 0xff),  \
-         *((c)++) = (uint8_t)(((l)) & 0xff))
+#define HOST_l2c(l, c)                        \
+  do {                                        \
+    *((c)++) = (uint8_t)(((l) >> 24) & 0xff); \
+    *((c)++) = (uint8_t)(((l) >> 16) & 0xff); \
+    *((c)++) = (uint8_t)(((l) >> 8) & 0xff);  \
+    *((c)++) = (uint8_t)(((l)) & 0xff);       \
+  } while (0)
 
 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
 
-#define HOST_c2l(c, l)                                                     \
-  (void)(l = (((uint32_t)(*((c)++)))), l |= (((uint32_t)(*((c)++))) << 8), \
-         l |= (((uint32_t)(*((c)++))) << 16),                              \
-         l |= (((uint32_t)(*((c)++))) << 24))
+#define HOST_c2l(c, l)                     \
+  do {                                     \
+    (l) = (((uint32_t)(*((c)++))));        \
+    (l) |= (((uint32_t)(*((c)++))) << 8);  \
+    (l) |= (((uint32_t)(*((c)++))) << 16); \
+    (l) |= (((uint32_t)(*((c)++))) << 24); \
+  } while (0)
 
-#define HOST_l2c(l, c)                             \
-  (void)(*((c)++) = (uint8_t)(((l)) & 0xff),       \
-         *((c)++) = (uint8_t)(((l) >> 8) & 0xff),  \
-         *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
-         *((c)++) = (uint8_t)(((l) >> 24) & 0xff))
+#define HOST_l2c(l, c)                        \
+  do {                                        \
+    *((c)++) = (uint8_t)(((l)) & 0xff);       \
+    *((c)++) = (uint8_t)(((l) >> 8) & 0xff);  \
+    *((c)++) = (uint8_t)(((l) >> 16) & 0xff); \
+    *((c)++) = (uint8_t)(((l) >> 24) & 0xff); \
+  } while (0)
 
 #endif /* DATA_ORDER */
 
diff --git a/src/crypto/ec/p256-64.c b/src/crypto/ec/p256-64.c
index a0e4df5..6a54200 100644
--- a/src/crypto/ec/p256-64.c
+++ b/src/crypto/ec/p256-64.c
@@ -175,9 +175,9 @@
   out[7] *= scalar;
 }
 
-#define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9)
+#define two105m41m9 ((((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9))
 #define two105 (((limb)1) << 105)
-#define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9)
+#define two105m41p9 ((((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9))
 
 /* zero105 is 0 mod p */
 static const felem zero105 = {two105m41m9, two105, two105m41p9, two105m41p9};
@@ -211,9 +211,11 @@
   out[3] -= in[3];
 }
 
-#define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11)
+#define two107m43m11 \
+  ((((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11))
 #define two107 (((limb)1) << 107)
-#define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11)
+#define two107m43p11 \
+  ((((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11))
 
 /* zero107 is 0 mod p */
 static const felem zero107 = {two107m43m11, two107, two107m43p11, two107m43p11};
@@ -272,10 +274,10 @@
   out[7] -= in[7];
 }
 
-#define two64m0 (((limb)1) << 64) - 1
-#define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1
-#define two64m46 (((limb)1) << 64) - (((limb)1) << 46)
-#define two64m32 (((limb)1) << 64) - (((limb)1) << 32)
+#define two64m0 ((((limb)1) << 64) - 1)
+#define two110p32m0 ((((limb)1) << 110) + (((limb)1) << 32) - 1)
+#define two64m46 ((((limb)1) << 64) - (((limb)1) << 46))
+#define two64m32 ((((limb)1) << 64) - (((limb)1) << 32))
 
 /* zero110 is 0 mod p. */
 static const felem zero110 = {two64m0, two110p32m0, two64m46, two64m32};
@@ -594,9 +596,9 @@
   smallfelem_mul(out, small1, small2);
 }
 
-#define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4)
+#define two100m36m4 ((((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4))
 #define two100 (((limb)1) << 100)
-#define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4)
+#define two100m36p4 ((((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4))
 
 /* zero100 is 0 mod p */
 static const felem zero100 = {two100m36m4, two100, two100m36p4, two100m36p4};
diff --git a/src/crypto/ecdh/ecdh.c b/src/crypto/ecdh/ecdh.c
index 37a67b2..50a844e 100644
--- a/src/crypto/ecdh/ecdh.c
+++ b/src/crypto/ecdh/ecdh.c
@@ -76,7 +76,7 @@
 
 
 int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
-                     EC_KEY *priv_key,
+                     const EC_KEY *priv_key,
                      void *(*kdf)(const void *in, size_t inlen, void *out,
                                   size_t *outlen)) {
   const BIGNUM *const priv = EC_KEY_get0_private_key(priv_key);
diff --git a/src/crypto/err/ssl.errordata b/src/crypto/err/ssl.errordata
index 9045e9a..c25683e 100644
--- a/src/crypto/err/ssl.errordata
+++ b/src/crypto/err/ssl.errordata
@@ -157,7 +157,9 @@
 SSL,1090,TLSV1_ALERT_USER_CANCELLED
 SSL,1114,TLSV1_BAD_CERTIFICATE_HASH_VALUE
 SSL,1113,TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE
+SSL,1116,TLSV1_CERTIFICATE_REQUIRED
 SSL,1111,TLSV1_CERTIFICATE_UNOBTAINABLE
+SSL,1115,TLSV1_UNKNOWN_PSK_IDENTITY
 SSL,1112,TLSV1_UNRECOGNIZED_NAME
 SSL,1110,TLSV1_UNSUPPORTED_EXTENSION
 SSL,217,TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST
diff --git a/src/crypto/md4/md4.c b/src/crypto/md4/md4.c
index f79da9f..7da3ec8 100644
--- a/src/crypto/md4/md4.c
+++ b/src/crypto/md4/md4.c
@@ -114,23 +114,23 @@
 
 #define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n))))
 
-#define R0(a, b, c, d, k, s, t)        \
-  {                                    \
-    a += ((k) + (t)+F((b), (c), (d))); \
-    a = ROTATE(a, s);                  \
-  };
+#define R0(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + F((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+  } while (0)
 
-#define R1(a, b, c, d, k, s, t)        \
-  {                                    \
-    a += ((k) + (t)+G((b), (c), (d))); \
-    a = ROTATE(a, s);                  \
-  };
+#define R1(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + G((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+  } while (0)
 
-#define R2(a, b, c, d, k, s, t)        \
-  {                                    \
-    a += ((k) + (t)+H((b), (c), (d))); \
-    a = ROTATE(a, s);                  \
-  };
+#define R2(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + H((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+  } while (0)
 
 void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num) {
   uint32_t A, B, C, D, l;
diff --git a/src/crypto/md5/md5.c b/src/crypto/md5/md5.c
index 66483b8..a66fa7f 100644
--- a/src/crypto/md5/md5.c
+++ b/src/crypto/md5/md5.c
@@ -122,32 +122,40 @@
  * simplified to the code below.  Wei attributes these optimizations
  * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
  */
-#define	F(b,c,d)	((((c) ^ (d)) & (b)) ^ (d))
-#define	G(b,c,d)	((((b) ^ (c)) & (d)) ^ (c))
-#define	H(b,c,d)	((b) ^ (c) ^ (d))
-#define	I(b,c,d)	(((~(d)) | (b)) ^ (c))
+#define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d))
+#define G(b, c, d) ((((b) ^ (c)) & (d)) ^ (c))
+#define H(b, c, d) ((b) ^ (c) ^ (d))
+#define I(b, c, d) (((~(d)) | (b)) ^ (c))
 
 #define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n))))
 
-#define R0(a,b,c,d,k,s,t) { \
-	a+=((k)+(t)+F((b),(c),(d))); \
-	a=ROTATE(a,s); \
-	a+=b; };\
+#define R0(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + F((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+    (a) += (b);                            \
+  } while (0)
 
-#define R1(a,b,c,d,k,s,t) { \
-	a+=((k)+(t)+G((b),(c),(d))); \
-	a=ROTATE(a,s); \
-	a+=b; };
+#define R1(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + G((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+    (a) += (b);                            \
+  } while (0)
 
-#define R2(a,b,c,d,k,s,t) { \
-	a+=((k)+(t)+H((b),(c),(d))); \
-	a=ROTATE(a,s); \
-	a+=b; };
+#define R2(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + H((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+    (a) += (b);                            \
+  } while (0)
 
-#define R3(a,b,c,d,k,s,t) { \
-	a+=((k)+(t)+I((b),(c),(d))); \
-	a=ROTATE(a,s); \
-	a+=b; };
+#define R3(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + I((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+    (a) += (b);                            \
+  } while (0)
 
 #ifndef md5_block_data_order
 #ifdef X
diff --git a/src/crypto/modes/gcm.c b/src/crypto/modes/gcm.c
index 69bdfdc..eb63aa0 100644
--- a/src/crypto/modes/gcm.c
+++ b/src/crypto/modes/gcm.c
@@ -74,17 +74,17 @@
 #endif
 
 #define PACK(s) ((size_t)(s) << (sizeof(size_t) * 8 - 16))
-#define REDUCE1BIT(V)                                                  \
-  do {                                                                 \
-    if (sizeof(size_t) == 8) {                                         \
-      uint64_t T = UINT64_C(0xe100000000000000) & (0 - (V.lo & 1)); \
-      V.lo = (V.hi << 63) | (V.lo >> 1);                               \
-      V.hi = (V.hi >> 1) ^ T;                                          \
-    } else {                                                           \
-      uint32_t T = 0xe1000000U & (0 - (uint32_t)(V.lo & 1));           \
-      V.lo = (V.hi << 63) | (V.lo >> 1);                               \
-      V.hi = (V.hi >> 1) ^ ((uint64_t)T << 32);                        \
-    }                                                                  \
+#define REDUCE1BIT(V)                                                 \
+  do {                                                                \
+    if (sizeof(size_t) == 8) {                                        \
+      uint64_t T = UINT64_C(0xe100000000000000) & (0 - ((V).lo & 1)); \
+      (V).lo = ((V).hi << 63) | ((V).lo >> 1);                        \
+      (V).hi = ((V).hi >> 1) ^ T;                                     \
+    } else {                                                          \
+      uint32_t T = 0xe1000000U & (0 - (uint32_t)((V).lo & 1));        \
+      (V).lo = ((V).hi << 63) | ((V).lo >> 1);                        \
+      (V).hi = ((V).hi >> 1) ^ ((uint64_t)T << 32);                   \
+    }                                                                 \
   } while (0)
 
 // kSizeTWithoutLower4Bits is a mask that can be used to zero the lower four
@@ -313,7 +313,7 @@
                     size_t len);
 #endif
 
-#define GCM_MUL(ctx, Xi) gcm_gmult_4bit(ctx->Xi.u, ctx->Htable)
+#define GCM_MUL(ctx, Xi) gcm_gmult_4bit((ctx)->Xi.u, (ctx)->Htable)
 #if defined(GHASH_ASM)
 #define GHASH(ctx, in, len) gcm_ghash_4bit((ctx)->Xi.u, (ctx)->Htable, in, len)
 /* GHASH_CHUNK is "stride parameter" missioned to mitigate cache
@@ -418,10 +418,10 @@
 
 #ifdef GCM_FUNCREF_4BIT
 #undef GCM_MUL
-#define GCM_MUL(ctx, Xi) (*gcm_gmult_p)(ctx->Xi.u, ctx->Htable)
+#define GCM_MUL(ctx, Xi) (*gcm_gmult_p)((ctx)->Xi.u, (ctx)->Htable)
 #ifdef GHASH
 #undef GHASH
-#define GHASH(ctx, in, len) (*gcm_ghash_p)(ctx->Xi.u, ctx->Htable, in, len)
+#define GHASH(ctx, in, len) (*gcm_ghash_p)((ctx)->Xi.u, (ctx)->Htable, in, len)
 #endif
 #endif
 
diff --git a/src/crypto/sha/sha1.c b/src/crypto/sha/sha1.c
index 74e841c..0ebed99 100644
--- a/src/crypto/sha/sha1.c
+++ b/src/crypto/sha/sha1.c
@@ -119,7 +119,10 @@
 #define HASH_BLOCK_DATA_ORDER sha1_block_data_order
 #define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n))))
 #define Xupdate(a, ix, ia, ib, ic, id) \
-  ((a) = (ia ^ ib ^ ic ^ id), ix = (a) = ROTATE((a), 1))
+  do {                                 \
+    (a) = ((ia) ^ (ib) ^ (ic) ^ (id)); \
+    (ix) = (a) = ROTATE((a), 1);       \
+  } while (0)
 
 #ifndef SHA1_ASM
 static
@@ -143,34 +146,46 @@
 #define F_40_59(b, c, d) (((b) & (c)) | (((b) | (c)) & (d)))
 #define F_60_79(b, c, d) F_20_39(b, c, d)
 
-#define BODY_00_15(i, a, b, c, d, e, f, xi)                           \
-  (f) = xi + (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_00_15(i, a, b, c, d, e, f, xi)                               \
+  do {                                                                    \
+    (f) = (xi) + (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                                \
+  } while (0)
 
-#define BODY_16_19(i, a, b, c, d, e, f, xi, xa, xb, xc, xd)       \
-  Xupdate(f, xi, xa, xb, xc, xd);                                 \
-  (f) += (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_16_19(i, a, b, c, d, e, f, xi, xa, xb, xc, xd)         \
+  do {                                                              \
+    Xupdate(f, xi, xa, xb, xc, xd);                                 \
+    (f) += (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                          \
+  } while (0)
 
-#define BODY_20_31(i, a, b, c, d, e, f, xi, xa, xb, xc, xd)       \
-  Xupdate(f, xi, xa, xb, xc, xd);                                 \
-  (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_20_31(i, a, b, c, d, e, f, xi, xa, xb, xc, xd)         \
+  do {                                                              \
+    Xupdate(f, xi, xa, xb, xc, xd);                                 \
+    (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                          \
+  } while (0)
 
-#define BODY_32_39(i, a, b, c, d, e, f, xa, xb, xc, xd)           \
-  Xupdate(f, xa, xa, xb, xc, xd);                                 \
-  (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_32_39(i, a, b, c, d, e, f, xa, xb, xc, xd)             \
+  do {                                                              \
+    Xupdate(f, xa, xa, xb, xc, xd);                                 \
+    (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                          \
+  } while (0)
 
-#define BODY_40_59(i, a, b, c, d, e, f, xa, xb, xc, xd)           \
-  Xupdate(f, xa, xa, xb, xc, xd);                                 \
-  (f) += (e) + K_40_59 + ROTATE((a), 5) + F_40_59((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_40_59(i, a, b, c, d, e, f, xa, xb, xc, xd)             \
+  do {                                                              \
+    Xupdate(f, xa, xa, xb, xc, xd);                                 \
+    (f) += (e) + K_40_59 + ROTATE((a), 5) + F_40_59((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                          \
+  } while (0)
 
-#define BODY_60_79(i, a, b, c, d, e, f, xa, xb, xc, xd)               \
-  Xupdate(f, xa, xa, xb, xc, xd);                                     \
-  (f) = xa + (e) + K_60_79 + ROTATE((a), 5) + F_60_79((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_60_79(i, a, b, c, d, e, f, xa, xb, xc, xd)                   \
+  do {                                                                    \
+    Xupdate(f, xa, xa, xb, xc, xd);                                       \
+    (f) = (xa) + (e) + K_60_79 + ROTATE((a), 5) + F_60_79((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                                \
+  } while (0)
 
 #ifdef X
 #undef X
@@ -199,51 +214,51 @@
   E = state[4];
 
   for (;;) {
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(0) = l;
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(1) = l;
     BODY_00_15(0, A, B, C, D, E, T, X(0));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(2) = l;
     BODY_00_15(1, T, A, B, C, D, E, X(1));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(3) = l;
     BODY_00_15(2, E, T, A, B, C, D, X(2));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(4) = l;
     BODY_00_15(3, D, E, T, A, B, C, X(3));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(5) = l;
     BODY_00_15(4, C, D, E, T, A, B, X(4));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(6) = l;
     BODY_00_15(5, B, C, D, E, T, A, X(5));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(7) = l;
     BODY_00_15(6, A, B, C, D, E, T, X(6));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(8) = l;
     BODY_00_15(7, T, A, B, C, D, E, X(7));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(9) = l;
     BODY_00_15(8, E, T, A, B, C, D, X(8));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(10) = l;
     BODY_00_15(9, D, E, T, A, B, C, X(9));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(11) = l;
     BODY_00_15(10, C, D, E, T, A, B, X(10));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(12) = l;
     BODY_00_15(11, B, C, D, E, T, A, X(11));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(13) = l;
     BODY_00_15(12, A, B, C, D, E, T, X(12));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(14) = l;
     BODY_00_15(13, T, A, B, C, D, E, X(13));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(15) = l;
     BODY_00_15(14, E, T, A, B, C, D, X(14));
     BODY_00_15(15, D, E, T, A, B, C, X(15));
diff --git a/src/crypto/test/malloc.cc b/src/crypto/test/malloc.cc
index 47ee6da..33f0972 100644
--- a/src/crypto/test/malloc.cc
+++ b/src/crypto/test/malloc.cc
@@ -26,9 +26,13 @@
 
 // This file isn't built on ARM or Aarch64 because we link statically in those
 // builds and trying to override malloc in a static link doesn't work. It also
-// requires glibc.
+// requires glibc. It's also disabled on ASan builds as this interferes with
+// ASan's malloc interceptor.
+//
+// TODO(davidben): See if this and ASan's and MSan's interceptors can be made to
+// coexist.
 #if defined(__linux__) && defined(OPENSSL_GLIBC) && !defined(OPENSSL_ARM) && \
-    !defined(OPENSSL_AARCH64)
+    !defined(OPENSSL_AARCH64) && !defined(OPENSSL_ASAN)
 
 #include <errno.h>
 #include <signal.h>
@@ -40,38 +44,23 @@
 #include <new>
 
 
-/* This file defines overrides for the standard allocation functions that allow
- * a given allocation to be made to fail for testing. If the program is run
- * with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will
- * return NULL. If MALLOC_BREAK_ON_FAIL is also defined then the allocation
- * will signal SIGTRAP rather than return NULL.
- *
- * This code is not thread safe. */
+// This file defines overrides for the standard allocation functions that allow
+// a given allocation to be made to fail for testing. If the program is run
+// with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will
+// return NULL. If MALLOC_BREAK_ON_FAIL is also defined then the allocation
+// will signal SIGTRAP rather than return NULL.
+//
+// This code is not thread safe.
 
 static uint64_t current_malloc_count = 0;
 static uint64_t malloc_number_to_fail = 0;
-static char failure_enabled = 0, break_on_fail = 0;
-static int in_call = 0;
+static bool failure_enabled = false, break_on_fail = false, in_call = false;
 
 extern "C" {
-
-#if defined(OPENSSL_ASAN)
-#define REAL_MALLOC __interceptor_malloc
-#define REAL_CALLOC __interceptor_calloc
-#define REAL_REALLOC __interceptor_realloc
-#define REAL_FREE __interceptor_free
-#else
-#define REAL_MALLOC __libc_malloc
-#define REAL_CALLOC __libc_calloc
-#define REAL_REALLOC __libc_realloc
-#define REAL_FREE __libc_free
-#endif
-
-/* These are other names for the standard allocation functions. */
-extern void *REAL_MALLOC(size_t size);
-extern void *REAL_CALLOC(size_t num_elems, size_t size);
-extern void *REAL_REALLOC(void *ptr, size_t size);
-extern void REAL_FREE(void *ptr);
+// These are other names for the standard allocation functions.
+extern void *__libc_malloc(size_t size);
+extern void *__libc_calloc(size_t num_elems, size_t size);
+extern void *__libc_realloc(void *ptr, size_t size);
 }
 
 static void exit_handler(void) {
@@ -85,16 +74,15 @@
   return;
 }
 
-/* should_fail_allocation returns true if the current allocation should fail. */
-static int should_fail_allocation() {
-  static int init = 0;
-  char should_fail;
+// should_fail_allocation returns true if the current allocation should fail.
+static bool should_fail_allocation() {
+  static bool init = false;
 
   if (in_call) {
-    return 0;
+    return false;
   }
 
-  in_call = 1;
+  in_call = true;
 
   if (!init) {
     const char *env = getenv("MALLOC_NUMBER_TO_FAIL");
@@ -102,22 +90,22 @@
       char *endptr;
       malloc_number_to_fail = strtoull(env, &endptr, 10);
       if (*endptr == 0) {
-        failure_enabled = 1;
+        failure_enabled = true;
         atexit(exit_handler);
         std::set_new_handler(cpp_new_handler);
       }
     }
     break_on_fail = (NULL != getenv("MALLOC_BREAK_ON_FAIL"));
-    init = 1;
+    init = true;
   }
 
-  in_call = 0;
+  in_call = false;
 
   if (!failure_enabled) {
-    return 0;
+    return false;
   }
 
-  should_fail = (current_malloc_count == malloc_number_to_fail);
+  bool should_fail = (current_malloc_count == malloc_number_to_fail);
   current_malloc_count++;
 
   if (should_fail && break_on_fail) {
@@ -134,7 +122,7 @@
     return NULL;
   }
 
-  return REAL_MALLOC(size);
+  return __libc_malloc(size);
 }
 
 void *calloc(size_t num_elems, size_t size) {
@@ -143,7 +131,7 @@
     return NULL;
   }
 
-  return REAL_CALLOC(num_elems, size);
+  return __libc_calloc(num_elems, size);
 }
 
 void *realloc(void *ptr, size_t size) {
@@ -152,11 +140,7 @@
     return NULL;
   }
 
-  return REAL_REALLOC(ptr, size);
-}
-
-void free(void *ptr) {
-  REAL_FREE(ptr);
+  return __libc_realloc(ptr, size);
 }
 
 }  // extern "C"
diff --git a/src/crypto/x509/x509_vpm.c b/src/crypto/x509/x509_vpm.c
index 9e9dbf5..924cfa7 100644
--- a/src/crypto/x509/x509_vpm.c
+++ b/src/crypto/x509/x509_vpm.c
@@ -227,8 +227,8 @@
 /* Macro to test if a field should be copied from src to dest */
 
 #define test_x509_verify_param_copy(field, def) \
-        (to_overwrite || \
-                ((src->field != def) && (to_default || (dest->field == def))))
+  (to_overwrite ||                              \
+   ((src->field != (def)) && (to_default || (dest->field == (def)))))
 
 /* As above but for ID fields */
 
@@ -513,7 +513,7 @@
 static const X509_VERIFY_PARAM_ID _empty_id =
     { NULL, 0U, NULL, NULL, 0, NULL, 0 };
 
-#define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
+#define vpm_empty_id ((X509_VERIFY_PARAM_ID *)&_empty_id)
 
 /*
  * Default verify parameters: these are used for various applications and can
diff --git a/src/crypto/x509v3/pcy_int.h b/src/crypto/x509v3/pcy_int.h
index b5075f9..1e76503 100644
--- a/src/crypto/x509v3/pcy_int.h
+++ b/src/crypto/x509v3/pcy_int.h
@@ -180,8 +180,8 @@
 
 /* Useful macros */
 
-#define node_data_critical(data) (data->flags & POLICY_DATA_FLAG_CRITICAL)
-#define node_critical(node) node_data_critical(node->data)
+#define node_data_critical(data) ((data)->flags & POLICY_DATA_FLAG_CRITICAL)
+#define node_critical(node) node_data_critical((node)->data)
 
 /* Internal functions */
 
diff --git a/src/crypto/x509v3/v3_purp.c b/src/crypto/x509v3/v3_purp.c
index f9324d4..9152444 100644
--- a/src/crypto/x509v3/v3_purp.c
+++ b/src/crypto/x509v3/v3_purp.c
@@ -647,7 +647,7 @@
  * key types.
  */
 #define KU_TLS \
-        KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT
+        (KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT)
 
 static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
                                     int ca)
diff --git a/src/decrepit/ripemd/internal.h b/src/decrepit/ripemd/internal.h
index c4db4b2..cbf7a8d 100644
--- a/src/decrepit/ripemd/internal.h
+++ b/src/decrepit/ripemd/internal.h
@@ -79,15 +79,15 @@
   do {                         \
     unsigned long ll;          \
     ll = (c)->h[0];            \
-    (void)HOST_l2c(ll, (s));   \
+    HOST_l2c(ll, (s));         \
     ll = (c)->h[1];            \
-    (void)HOST_l2c(ll, (s));   \
+    HOST_l2c(ll, (s));         \
     ll = (c)->h[2];            \
-    (void)HOST_l2c(ll, (s));   \
+    HOST_l2c(ll, (s));         \
     ll = (c)->h[3];            \
-    (void)HOST_l2c(ll, (s));   \
+    HOST_l2c(ll, (s));         \
     ll = (c)->h[4];            \
-    (void)HOST_l2c(ll, (s));   \
+    HOST_l2c(ll, (s));         \
   } while (0)
 #define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order
 
diff --git a/src/decrepit/ripemd/ripemd.c b/src/decrepit/ripemd/ripemd.c
index 6ed7816..ce47c28 100644
--- a/src/decrepit/ripemd/ripemd.c
+++ b/src/decrepit/ripemd/ripemd.c
@@ -86,51 +86,51 @@
     D = h[3];
     E = h[4];
 
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(0) = l;
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(1) = l;
     RIP1(A, B, C, D, E, WL00, SL00);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(2) = l;
     RIP1(E, A, B, C, D, WL01, SL01);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(3) = l;
     RIP1(D, E, A, B, C, WL02, SL02);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(4) = l;
     RIP1(C, D, E, A, B, WL03, SL03);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(5) = l;
     RIP1(B, C, D, E, A, WL04, SL04);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(6) = l;
     RIP1(A, B, C, D, E, WL05, SL05);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(7) = l;
     RIP1(E, A, B, C, D, WL06, SL06);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(8) = l;
     RIP1(D, E, A, B, C, WL07, SL07);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(9) = l;
     RIP1(C, D, E, A, B, WL08, SL08);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(10) = l;
     RIP1(B, C, D, E, A, WL09, SL09);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(11) = l;
     RIP1(A, B, C, D, E, WL10, SL10);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(12) = l;
     RIP1(E, A, B, C, D, WL11, SL11);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(13) = l;
     RIP1(D, E, A, B, C, WL12, SL12);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(14) = l;
     RIP1(C, D, E, A, B, WL13, SL13);
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(15) = l;
     RIP1(B, C, D, E, A, WL14, SL14);
     RIP1(A, B, C, D, E, WL15, SL15);
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
index 888b594..10a22ce 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -60,6 +60,11 @@
 #include <stdint.h>
 #include <sys/types.h>
 
+#if defined(__MINGW32__)
+/* stdio.h is needed on MinGW for __MINGW_PRINTF_FORMAT. */
+#include <stdio.h>
+#endif
+
 #include <openssl/opensslconf.h>
 
 #if defined(BORINGSSL_PREFIX)
@@ -158,8 +163,17 @@
 
 
 #if defined(__GNUC__)
+/* MinGW has two different printf implementations. Ensure the format macro
+ * matches the selected implementation. See
+ * https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/. */
+#if defined(__MINGW_PRINTF_FORMAT)
 #define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check) \
-        __attribute__((__format__(__printf__, string_index, first_to_check)))
+  __attribute__(                                                 \
+      (__format__(__MINGW_PRINTF_FORMAT, string_index, first_to_check)))
+#else
+#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check) \
+  __attribute__((__format__(__printf__, string_index, first_to_check)))
+#endif
 #else
 #define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check)
 #endif
diff --git a/src/include/openssl/ecdh.h b/src/include/openssl/ecdh.h
index 5fe3ae9..c167503 100644
--- a/src/include/openssl/ecdh.h
+++ b/src/include/openssl/ecdh.h
@@ -85,10 +85,9 @@
  * return value. Otherwise, as many bytes of the shared key as will fit are
  * copied directly to, at most, |outlen| bytes at |out|. It returns the number
  * of bytes written to |out|, or -1 on error. */
-OPENSSL_EXPORT int ECDH_compute_key(void *out, size_t outlen,
-                                    const EC_POINT *pub_key, EC_KEY *priv_key,
-                                    void *(*kdf)(const void *in, size_t inlen,
-                                                 void *out, size_t *outlen));
+OPENSSL_EXPORT int ECDH_compute_key(
+    void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *priv_key,
+    void *(*kdf)(const void *in, size_t inlen, void *out, size_t *outlen));
 
 
 #if defined(__cplusplus)
diff --git a/src/include/openssl/err.h b/src/include/openssl/err.h
index cac50e0..f6efa12 100644
--- a/src/include/openssl/err.h
+++ b/src/include/openssl/err.h
@@ -467,7 +467,7 @@
 #define ERR_R_OVERFLOW (5 | ERR_R_FATAL)
 
 #define ERR_PACK(lib, reason)                                              \
-  (((((uint32_t)lib) & 0xff) << 24) | ((((uint32_t)reason) & 0xfff)))
+  (((((uint32_t)(lib)) & 0xff) << 24) | ((((uint32_t)(reason)) & 0xfff)))
 
 #define ERR_GET_LIB(packed_error) ((int)(((packed_error) >> 24) & 0xff))
 #define ERR_GET_FUNC(packed_error) 0
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 88fe845..0d78754 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -562,7 +562,7 @@
 #define DTLS1_VERSION 0xfeff
 #define DTLS1_2_VERSION 0xfefd
 
-#define TLS1_3_DRAFT_VERSION 0x7f0f
+#define TLS1_3_DRAFT_VERSION 0x7f10
 
 /* SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to
  * |version|. If |version| is zero, the default minimum version is used. It
@@ -2708,6 +2708,7 @@
 #define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION
 #define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY
 #define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR
+#define SSL_AD_INAPPROPRIATE_FALLBACK SSL3_AD_INAPPROPRIATE_FALLBACK
 #define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
 #define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
 #define SSL_AD_MISSING_EXTENSION TLS1_AD_MISSING_EXTENSION
@@ -2718,7 +2719,7 @@
   TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
 #define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
 #define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY
-#define SSL_AD_INAPPROPRIATE_FALLBACK SSL3_AD_INAPPROPRIATE_FALLBACK
+#define SSL_AD_CERTIFICATE_REQUIRED TLS1_AD_CERTIFICATE_REQUIRED
 
 /* SSL_alert_type_string_long returns a string description of |value| as an
  * alert type (warning or fatal). */
@@ -2897,7 +2898,7 @@
 
 /* SSL_MAX_CERT_LIST_DEFAULT is the default maximum length, in bytes, of a peer
  * certificate chain. */
-#define SSL_MAX_CERT_LIST_DEFAULT 1024 * 100
+#define SSL_MAX_CERT_LIST_DEFAULT (1024 * 100)
 
 /* SSL_CTX_get_max_cert_list returns the maximum length, in bytes, of a peer
  * certificate chain accepted by |ctx|. */
@@ -3114,8 +3115,8 @@
 OPENSSL_EXPORT void SSL_CTX_set_retain_only_sha256_of_client_certs(SSL_CTX *ctx,
                                                                    int enable);
 
-/* SSL_CTX_set_grease_enabled configures whether client sockets on |ctx| should
- * enable GREASE. See draft-davidben-tls-grease-01. */
+/* SSL_CTX_set_grease_enabled configures whether sockets on |ctx| should enable
+ * GREASE. See draft-davidben-tls-grease-01. */
 OPENSSL_EXPORT void SSL_CTX_set_grease_enabled(SSL_CTX *ctx, int enabled);
 
 
@@ -3342,14 +3343,14 @@
 /* SSL_get_server_tmp_key returns zero. */
 OPENSSL_EXPORT int *SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key);
 
-#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
+#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)(arg)))
 #define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
 #define SSL_SESSION_set_app_data(s, a) \
-  (SSL_SESSION_set_ex_data(s, 0, (char *)a))
+  (SSL_SESSION_set_ex_data(s, 0, (char *)(a)))
 #define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s, 0))
 #define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx, 0))
 #define SSL_CTX_set_app_data(ctx, arg) \
-  (SSL_CTX_set_ex_data(ctx, 0, (char *)arg))
+  (SSL_CTX_set_ex_data(ctx, 0, (char *)(arg)))
 
 #define OpenSSL_add_ssl_algorithms() SSL_library_init()
 #define SSLeay_add_ssl_algorithms() SSL_library_init()
@@ -3471,14 +3472,15 @@
 
  /* SSL_get_finished writes up to |count| bytes of the Finished message sent by
   * |ssl| to |buf|. It returns the total untruncated length or zero if none has
-  * been sent yet.
+  * been sent yet. At SSL 3.0 or TLS 1.3 and later, it returns zero.
   *
   * Use |SSL_get_tls_unique| instead. */
 OPENSSL_EXPORT size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count);
 
  /* SSL_get_peer_finished writes up to |count| bytes of the Finished message
   * received from |ssl|'s peer to |buf|. It returns the total untruncated length
-  * or zero if none has been received yet.
+  * or zero if none has been received yet. At SSL 3.0 or TLS 1.3 and later, it
+  * returns zero.
   *
   * Use |SSL_get_tls_unique| instead. */
 OPENSSL_EXPORT size_t SSL_get_peer_finished(const SSL *ssl, void *buf,
@@ -4200,283 +4202,6 @@
   int tlsext_status_type;
 };
 
-typedef struct ssl3_record_st {
-  /* type is the record type. */
-  uint8_t type;
-  /* length is the number of unconsumed bytes in the record. */
-  uint16_t length;
-  /* data is a non-owning pointer to the first unconsumed byte of the record. */
-  uint8_t *data;
-} SSL3_RECORD;
-
-typedef struct ssl3_buffer_st {
-  /* buf is the memory allocated for this buffer. */
-  uint8_t *buf;
-  /* offset is the offset into |buf| which the buffer contents start at. */
-  uint16_t offset;
-  /* len is the length of the buffer contents from |buf| + |offset|. */
-  uint16_t len;
-  /* cap is how much memory beyond |buf| + |offset| is available. */
-  uint16_t cap;
-} SSL3_BUFFER;
-
-/* An ssl_shutdown_t describes the shutdown state of one end of the connection,
- * whether it is alive or has been shutdown via close_notify or fatal alert. */
-enum ssl_shutdown_t {
-  ssl_shutdown_none = 0,
-  ssl_shutdown_close_notify = 1,
-  ssl_shutdown_fatal_alert = 2,
-};
-
-typedef struct ssl3_state_st {
-  uint8_t read_sequence[8];
-  uint8_t write_sequence[8];
-
-  uint8_t server_random[SSL3_RANDOM_SIZE];
-  uint8_t client_random[SSL3_RANDOM_SIZE];
-
-  /* have_version is true if the connection's final version is known. Otherwise
-   * the version has not been negotiated yet. */
-  unsigned have_version:1;
-
-  /* v2_hello_done is true if the peer's V2ClientHello, if any, has been handled
-   * and future messages should use the record layer. */
-  unsigned v2_hello_done:1;
-
-  /* initial_handshake_complete is true if the initial handshake has
-   * completed. */
-  unsigned initial_handshake_complete:1;
-
-  /* read_buffer holds data from the transport to be processed. */
-  SSL3_BUFFER read_buffer;
-  /* write_buffer holds data to be written to the transport. */
-  SSL3_BUFFER write_buffer;
-
-  SSL3_RECORD rrec; /* each decoded record goes in here */
-
-  /* partial write - check the numbers match */
-  unsigned int wnum; /* number of bytes sent so far */
-  int wpend_tot;     /* number bytes written */
-  int wpend_type;
-  int wpend_ret; /* number of bytes submitted */
-  const uint8_t *wpend_buf;
-
-  /* handshake_buffer, if non-NULL, contains the handshake transcript. */
-  BUF_MEM *handshake_buffer;
-  /* handshake_hash, if initialized with an |EVP_MD|, maintains the handshake
-   * hash. For TLS 1.1 and below, it is the SHA-1 half. */
-  EVP_MD_CTX handshake_hash;
-  /* handshake_md5, if initialized with an |EVP_MD|, maintains the MD5 half of
-   * the handshake hash for TLS 1.1 and below. */
-  EVP_MD_CTX handshake_md5;
-
-  /* recv_shutdown is the shutdown state for the receive half of the
-   * connection. */
-  enum ssl_shutdown_t recv_shutdown;
-
-  /* recv_shutdown is the shutdown state for the send half of the connection. */
-  enum ssl_shutdown_t send_shutdown;
-
-  int alert_dispatch;
-  uint8_t send_alert[2];
-
-  int total_renegotiations;
-
-  /* empty_record_count is the number of consecutive empty records received. */
-  uint8_t empty_record_count;
-
-  /* warning_alert_count is the number of consecutive warning alerts
-   * received. */
-  uint8_t warning_alert_count;
-
-  /* key_update_count is the number of consecutive KeyUpdates received. */
-  uint8_t key_update_count;
-
-  /* aead_read_ctx is the current read cipher state. */
-  SSL_AEAD_CTX *aead_read_ctx;
-
-  /* aead_write_ctx is the current write cipher state. */
-  SSL_AEAD_CTX *aead_write_ctx;
-
-  /* enc_method is the method table corresponding to the current protocol
-   * version. */
-  const SSL3_ENC_METHOD *enc_method;
-
-  /* pending_message is the current outgoing handshake message. */
-  uint8_t *pending_message;
-  uint32_t pending_message_len;
-
-  /* hs is the handshake state for the current handshake or NULL if there isn't
-   * one. */
-  SSL_HANDSHAKE *hs;
-
-  uint8_t write_traffic_secret[EVP_MAX_MD_SIZE];
-  uint8_t write_traffic_secret_len;
-  uint8_t read_traffic_secret[EVP_MAX_MD_SIZE];
-  uint8_t read_traffic_secret_len;
-  uint8_t exporter_secret[EVP_MAX_MD_SIZE];
-  uint8_t exporter_secret_len;
-
-  /* State pertaining to the pending handshake.
-   *
-   * TODO(davidben): Move everything not needed after the handshake completes to
-   * |hs| and remove this. */
-  struct {
-    uint8_t finish_md[EVP_MAX_MD_SIZE];
-    uint8_t finish_md_len;
-    uint8_t peer_finish_md[EVP_MAX_MD_SIZE];
-    uint8_t peer_finish_md_len;
-
-    int message_type;
-
-    /* used to hold the new cipher we are going to use */
-    const SSL_CIPHER *new_cipher;
-
-    /* used when SSL_ST_FLUSH_DATA is entered */
-    int next_state;
-
-    int reuse_message;
-
-    union {
-      /* sent is a bitset where the bits correspond to elements of kExtensions
-       * in t1_lib.c. Each bit is set if that extension was sent in a
-       * ClientHello. It's not used by servers. */
-      uint32_t sent;
-      /* received is a bitset, like |sent|, but is used by servers to record
-       * which extensions were received from a client. */
-      uint32_t received;
-    } extensions;
-
-    union {
-      /* sent is a bitset where the bits correspond to elements of
-       * |client_custom_extensions| in the |SSL_CTX|. Each bit is set if that
-       * extension was sent in a ClientHello. It's not used by servers. */
-      uint16_t sent;
-      /* received is a bitset, like |sent|, but is used by servers to record
-       * which custom extensions were received from a client. The bits here
-       * correspond to |server_custom_extensions|. */
-      uint16_t received;
-    } custom_extensions;
-
-    /* should_ack_sni is used by a server and indicates that the SNI extension
-     * should be echoed in the ServerHello. */
-    unsigned should_ack_sni:1;
-
-    /* Client-only: ca_names contains the list of CAs received in a
-     * CertificateRequest message. */
-    STACK_OF(X509_NAME) *ca_names;
-
-    /* Client-only: certificate_types contains the set of certificate types
-     * received in a CertificateRequest message. */
-    uint8_t *certificate_types;
-    size_t num_certificate_types;
-
-    uint8_t *key_block;
-    uint8_t key_block_length;
-
-    uint8_t new_mac_secret_len;
-    uint8_t new_key_len;
-    uint8_t new_fixed_iv_len;
-
-    /* cert_request is true if a client certificate was requested and false
-     * otherwise. */
-    unsigned cert_request:1;
-
-    /* certificate_status_expected is true if OCSP stapling was negotiated and
-     * the server is expected to send a CertificateStatus message. (This is
-     * used on both the client and server sides.) */
-    unsigned certificate_status_expected:1;
-
-    /* ocsp_stapling_requested is true if a client requested OCSP stapling. */
-    unsigned ocsp_stapling_requested:1;
-
-    /* Server-only: peer_supported_group_list contains the supported group IDs
-     * advertised by the peer. This is only set on the server's end. The server
-     * does not advertise this extension to the client. */
-    uint16_t *peer_supported_group_list;
-    size_t peer_supported_group_list_len;
-
-    /* extended_master_secret indicates whether the extended master secret
-     * computation is used in this handshake. Note that this is different from
-     * whether it was used for the current session. If this is a resumption
-     * handshake then EMS might be negotiated in the client and server hello
-     * messages, but it doesn't matter if the session that's being resumed
-     * didn't use it to create the master secret initially. */
-    char extended_master_secret;
-
-    /* Client-only: in_false_start is one if there is a pending handshake in
-     * False Start. The client may write data at this point. */
-    char in_false_start;
-
-    /* peer_signature_algorithm is the signature algorithm used to authenticate
-     * the peer, or zero if not applicable. */
-    uint16_t peer_signature_algorithm;
-
-    /* ecdh_ctx is the current ECDH instance. */
-    SSL_ECDH_CTX ecdh_ctx;
-
-    /* peer_key is the peer's ECDH key. */
-    uint8_t *peer_key;
-    uint16_t peer_key_len;
-
-    /* server_params stores the ServerKeyExchange parameters to be signed while
-     * the signature is being computed. */
-    uint8_t *server_params;
-    uint32_t server_params_len;
-  } tmp;
-
-  /* new_session is the new mutable session being established by the current
-   * handshake. It should not be cached. */
-  SSL_SESSION *new_session;
-
-  /* established_session is the session established by the connection. This
-   * session is only filled upon the completion of the handshake and is
-   * immutable. */
-  SSL_SESSION *established_session;
-
-  /* session_reused indicates whether a session was resumed. */
-  unsigned session_reused:1;
-
-  /* Connection binding to prevent renegotiation attacks */
-  uint8_t previous_client_finished[EVP_MAX_MD_SIZE];
-  uint8_t previous_client_finished_len;
-  uint8_t previous_server_finished[EVP_MAX_MD_SIZE];
-  uint8_t previous_server_finished_len;
-  int send_connection_binding;
-
-  /* Set if we saw the Next Protocol Negotiation extension from our peer. */
-  int next_proto_neg_seen;
-
-  /* Next protocol negotiation. For the client, this is the protocol that we
-   * sent in NextProtocol and is set when handling ServerHello extensions.
-   *
-   * For a server, this is the client's selected_protocol from NextProtocol and
-   * is set when handling the NextProtocol message, before the Finished
-   * message. */
-  uint8_t *next_proto_negotiated;
-  size_t next_proto_negotiated_len;
-
-  /* ALPN information
-   * (we are in the process of transitioning from NPN to ALPN.) */
-
-  /* In a server these point to the selected ALPN protocol after the
-   * ClientHello has been processed. In a client these contain the protocol
-   * that the server selected once the ServerHello has been processed. */
-  uint8_t *alpn_selected;
-  size_t alpn_selected_len;
-
-  /* In a client, this means that the server supported Channel ID and that a
-   * Channel ID was sent. In a server it means that we echoed support for
-   * Channel IDs and that tlsext_channel_id will be valid after the
-   * handshake. */
-  char tlsext_channel_id_valid;
-  /* For a server:
-   *     If |tlsext_channel_id_valid| is true, then this contains the
-   *     verified Channel ID from the client: a P256 point, (x,y), where
-   *     each are big-endian values. */
-  uint8_t tlsext_channel_id[64];
-} SSL3_STATE;
-
 
 /* Nodejs compatibility section (hidden).
  *
@@ -4839,5 +4564,7 @@
 #define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112
 #define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113
 #define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114
+#define SSL_R_TLSV1_UNKNOWN_PSK_IDENTITY 1115
+#define SSL_R_TLSV1_CERTIFICATE_REQUIRED 1116
 
 #endif /* OPENSSL_HEADER_SSL_H */
diff --git a/src/include/openssl/tls1.h b/src/include/openssl/tls1.h
index c1db7ab..35d3145 100644
--- a/src/include/openssl/tls1.h
+++ b/src/include/openssl/tls1.h
@@ -160,14 +160,14 @@
 #define TLS1_AD_END_OF_EARLY_DATA 1
 #define TLS1_AD_DECRYPTION_FAILED 21
 #define TLS1_AD_RECORD_OVERFLOW 22
-#define TLS1_AD_UNKNOWN_CA 48    /* fatal */
-#define TLS1_AD_ACCESS_DENIED 49 /* fatal */
-#define TLS1_AD_DECODE_ERROR 50  /* fatal */
+#define TLS1_AD_UNKNOWN_CA 48
+#define TLS1_AD_ACCESS_DENIED 49
+#define TLS1_AD_DECODE_ERROR 50
 #define TLS1_AD_DECRYPT_ERROR 51
-#define TLS1_AD_EXPORT_RESTRICTION 60    /* fatal */
-#define TLS1_AD_PROTOCOL_VERSION 70      /* fatal */
-#define TLS1_AD_INSUFFICIENT_SECURITY 71 /* fatal */
-#define TLS1_AD_INTERNAL_ERROR 80        /* fatal */
+#define TLS1_AD_EXPORT_RESTRICTION 60
+#define TLS1_AD_PROTOCOL_VERSION 70
+#define TLS1_AD_INSUFFICIENT_SECURITY 71
+#define TLS1_AD_INTERNAL_ERROR 80
 #define TLS1_AD_USER_CANCELLED 90
 #define TLS1_AD_NO_RENEGOTIATION 100
 #define TLS1_AD_MISSING_EXTENSION 109
@@ -177,7 +177,8 @@
 #define TLS1_AD_UNRECOGNIZED_NAME 112
 #define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
 #define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
-#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115 /* fatal */
+#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115
+#define TLS1_AD_CERTIFICATE_REQUIRED 116
 
 /* ExtensionType values from RFC6066 */
 #define TLSEXT_TYPE_server_name 0
@@ -204,7 +205,7 @@
 /* ExtensionType value from RFC4507 */
 #define TLSEXT_TYPE_session_ticket 35
 
-/* ExtensionType values from draft-ietf-tls-tls13-13 */
+/* ExtensionType values from draft-ietf-tls-tls13-16 */
 #define TLSEXT_TYPE_supported_groups 10
 #define TLSEXT_TYPE_key_share 40
 #define TLSEXT_TYPE_pre_shared_key 41
@@ -418,7 +419,7 @@
 #define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305 \
   TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
 
-/* TLS 1.3 ciphersuites from draft-ietf-tls-tls13-15 */
+/* TLS 1.3 ciphersuites from draft-ietf-tls-tls13-16 */
 #define TLS1_CK_AES_128_GCM_SHA256 0x03001301
 #define TLS1_CK_AES_256_GCM_SHA384 0x03001302
 #define TLS1_CK_CHACHA20_POLY1305_SHA256 0x03001303
@@ -609,7 +610,7 @@
 #define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 \
   TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
 
-/* TLS 1.3 ciphersuites from draft-ietf-tls-tls13-15 */
+/* TLS 1.3 ciphersuites from draft-ietf-tls-tls13-16 */
 #define TLS1_TXT_AES_128_GCM_SHA256 "AEAD-AES128-GCM-SHA256"
 #define TLS1_TXT_AES_256_GCM_SHA384 "AEAD-AES256-GCM-SHA384"
 #define TLS1_TXT_CHACHA20_POLY1305_SHA256 "AEAD-CHACHA20-POLY1305-SHA256"
diff --git a/src/include/openssl/x509.h b/src/include/openssl/x509.h
index 51be320..8204486 100644
--- a/src/include/openssl/x509.h
+++ b/src/include/openssl/x509.h
@@ -286,7 +286,7 @@
 
 /* standard trust ids */
 
-#define X509_TRUST_DEFAULT	-1	/* Only valid in purpose settings */
+#define X509_TRUST_DEFAULT	(-1)	/* Only valid in purpose settings */
 
 #define X509_TRUST_COMPAT	1
 #define X509_TRUST_SSL_CLIENT	2
diff --git a/src/include/openssl/x509_vfy.h b/src/include/openssl/x509_vfy.h
index 0a45aad..1182bc2 100644
--- a/src/include/openssl/x509_vfy.h
+++ b/src/include/openssl/x509_vfy.h
@@ -110,7 +110,7 @@
 */
 
 /* The following are legacy constants that should not be used. */
-#define X509_LU_RETRY		-1
+#define X509_LU_RETRY		(-1)
 #define X509_LU_FAIL		0
 
 #define X509_LU_X509		1
diff --git a/src/include/openssl/x509v3.h b/src/include/openssl/x509v3.h
index d25a125..4754f71 100644
--- a/src/include/openssl/x509v3.h
+++ b/src/include/openssl/x509v3.h
@@ -230,7 +230,7 @@
 /* All existing reasons */
 #define CRLDP_ALL_REASONS	0x807f
 
-#define CRL_REASON_NONE				-1
+#define CRL_REASON_NONE				(-1)
 #define CRL_REASON_UNSPECIFIED			0
 #define CRL_REASON_KEY_COMPROMISE		1
 #define CRL_REASON_CA_COMPROMISE		2
@@ -376,8 +376,8 @@
 /* onlysomereasons present */
 #define IDP_REASONS	0x40
 
-#define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \
-",name:", val->name, ",value:", val->value);
+#define X509V3_conf_err(val) ERR_add_error_data(6, "section:", (val)->section, \
+",name:", (val)->name, ",value:", (val)->value);
 
 #define X509V3_set_ctx_test(ctx) \
 			X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST)
@@ -389,7 +389,7 @@
 			(X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \
 			(X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \
 			NULL, NULL, \
-			(void *)table}
+			(void *)(table)}
 
 #define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \
 			0,0,0,0, \
diff --git a/src/ssl/custom_extensions.c b/src/ssl/custom_extensions.c
index ed802ee..780cdc6 100644
--- a/src/ssl/custom_extensions.c
+++ b/src/ssl/custom_extensions.c
@@ -72,7 +72,7 @@
     const SSL_CUSTOM_EXTENSION *ext = sk_SSL_CUSTOM_EXTENSION_value(stack, i);
 
     if (ssl->server &&
-        !(ssl->s3->tmp.custom_extensions.received & (1u << i))) {
+        !(ssl->s3->hs->custom_extensions.received & (1u << i))) {
       /* Servers cannot echo extensions that the client didn't send. */
       continue;
     }
@@ -102,8 +102,8 @@
         }
 
         if (!ssl->server) {
-          assert((ssl->s3->tmp.custom_extensions.sent & (1u << i)) == 0);
-          ssl->s3->tmp.custom_extensions.sent |= (1u << i);
+          assert((ssl->s3->hs->custom_extensions.sent & (1u << i)) == 0);
+          ssl->s3->hs->custom_extensions.sent |= (1u << i);
         }
         break;
 
@@ -134,7 +134,7 @@
   if (/* Unknown extensions are not allowed in a ServerHello. */
       ext == NULL ||
       /* Also, if we didn't send the extension, that's also unacceptable. */
-      !(ssl->s3->tmp.custom_extensions.sent & (1u << index))) {
+      !(ssl->s3->hs->custom_extensions.sent & (1u << index))) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
     ERR_add_error_dataf("extension: %u", (unsigned)value);
     *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
@@ -162,8 +162,8 @@
     return 1;
   }
 
-  assert((ssl->s3->tmp.custom_extensions.received & (1u << index)) == 0);
-  ssl->s3->tmp.custom_extensions.received |= (1u << index);
+  assert((ssl->s3->hs->custom_extensions.received & (1u << index)) == 0);
+  ssl->s3->hs->custom_extensions.received |= (1u << index);
 
   if (ext->parse_callback &&
       !ext->parse_callback(ssl, value, CBS_data(extension), CBS_len(extension),
@@ -184,7 +184,7 @@
  * can be set on an |SSL_CTX|. It's determined by the size of the bitset used
  * to track when an extension has been sent. */
 #define MAX_NUM_CUSTOM_EXTENSIONS \
-  (sizeof(((struct ssl3_state_st *)NULL)->tmp.custom_extensions.sent) * 8)
+  (sizeof(((SSL_HANDSHAKE *)NULL)->custom_extensions.sent) * 8)
 
 static int custom_ext_append(STACK_OF(SSL_CUSTOM_EXTENSION) **stack,
                              unsigned extension_value,
diff --git a/src/ssl/handshake_client.c b/src/ssl/handshake_client.c
index 31394c0..a917e02 100644
--- a/src/ssl/handshake_client.c
+++ b/src/ssl/handshake_client.c
@@ -276,7 +276,7 @@
         break;
 
       case SSL3_ST_CR_CERT_STATUS_A:
-        if (ssl->s3->tmp.certificate_status_expected) {
+        if (ssl->s3->hs->certificate_status_expected) {
           ret = ssl3_get_cert_status(ssl);
           if (ret <= 0) {
             goto end;
@@ -331,7 +331,7 @@
       case SSL3_ST_CW_CERT_A:
       case SSL3_ST_CW_CERT_B:
       case SSL3_ST_CW_CERT_C:
-        if (ssl->s3->tmp.cert_request) {
+        if (ssl->s3->hs->cert_request) {
           ret = ssl3_send_client_certificate(ssl);
           if (ret <= 0) {
             goto end;
@@ -354,7 +354,7 @@
       case SSL3_ST_CW_CERT_VRFY_A:
       case SSL3_ST_CW_CERT_VRFY_B:
       case SSL3_ST_CW_CERT_VRFY_C:
-        if (ssl->s3->tmp.cert_request) {
+        if (ssl->s3->hs->cert_request) {
           ret = ssl3_send_cert_verify(ssl);
           if (ret <= 0) {
             goto end;
@@ -382,7 +382,7 @@
 
       case SSL3_ST_CW_NEXT_PROTO_A:
       case SSL3_ST_CW_NEXT_PROTO_B:
-        if (ssl->s3->next_proto_neg_seen) {
+        if (ssl->s3->hs->next_proto_neg_seen) {
           ret = ssl3_send_next_proto(ssl);
           if (ret <= 0) {
             goto end;
@@ -440,7 +440,7 @@
 
       case SSL3_ST_FALSE_START:
         ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
-        ssl->s3->tmp.in_false_start = 1;
+        ssl->s3->hs->in_false_start = 1;
 
         ssl_free_wbio_buffer(ssl);
         ret = 1;
@@ -541,10 +541,7 @@
         ssl->s3->hs = NULL;
 
         const int is_initial_handshake = !ssl->s3->initial_handshake_complete;
-
-        ssl->s3->tmp.in_false_start = 0;
         ssl->s3->initial_handshake_complete = 1;
-
         if (is_initial_handshake) {
           /* Renegotiations do not participate in session resumption. */
           ssl_update_cache(ssl, SSL_SESS_CACHE_CLIENT);
@@ -1216,18 +1213,13 @@
       goto err;
     }
 
-    SSL_ECDH_CTX_init_for_dhe(&ssl->s3->tmp.ecdh_ctx, dh);
+    SSL_ECDH_CTX_init_for_dhe(&ssl->s3->hs->ecdh_ctx, dh);
     dh = NULL;
 
     /* Save the peer public key for later. */
-    size_t peer_key_len;
-    if (!CBS_stow(&dh_Ys, &ssl->s3->tmp.peer_key, &peer_key_len)) {
+    if (!CBS_stow(&dh_Ys, &ssl->s3->hs->peer_key, &ssl->s3->hs->peer_key_len)) {
       goto err;
     }
-    /* |dh_Ys| was initialized with CBS_get_u16_length_prefixed, so peer_key_len
-     * fits in a uint16_t. */
-    assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
-    ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
   } else if (alg_k & SSL_kECDHE) {
     /* Parse the server parameters. */
     uint8_t group_type;
@@ -1251,17 +1243,12 @@
     }
 
     /* Initialize ECDH and save the peer public key for later. */
-    size_t peer_key_len;
-    if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id) ||
-        !CBS_stow(&point, &ssl->s3->tmp.peer_key, &peer_key_len)) {
+    if (!SSL_ECDH_CTX_init(&ssl->s3->hs->ecdh_ctx, group_id) ||
+        !CBS_stow(&point, &ssl->s3->hs->peer_key, &ssl->s3->hs->peer_key_len)) {
       goto err;
     }
-    /* |point| was initialized with CBS_get_u8_length_prefixed, so peer_key_len
-     * fits in a uint16_t. */
-    assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
-    ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
   } else if (alg_k & SSL_kCECPQ1) {
-    SSL_ECDH_CTX_init_for_cecpq1(&ssl->s3->tmp.ecdh_ctx);
+    SSL_ECDH_CTX_init_for_cecpq1(&ssl->s3->hs->ecdh_ctx);
     CBS key;
     if (!CBS_get_u16_length_prefixed(&server_key_exchange, &key)) {
       al = SSL_AD_DECODE_ERROR;
@@ -1269,14 +1256,9 @@
       goto f_err;
     }
 
-    size_t peer_key_len;
-    if (!CBS_stow(&key, &ssl->s3->tmp.peer_key, &peer_key_len)) {
+    if (!CBS_stow(&key, &ssl->s3->hs->peer_key, &ssl->s3->hs->peer_key_len)) {
       goto err;
     }
-    /* |key| was initialized with CBS_get_u16_length_prefixed, so peer_key_len
-     * fits in a uint16_t. */
-    assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
-    ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
   } else if (!(alg_k & SSL_kPSK)) {
     al = SSL_AD_UNEXPECTED_MESSAGE;
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
@@ -1385,8 +1367,6 @@
     return msg_ret;
   }
 
-  ssl->s3->tmp.cert_request = 0;
-
   if (ssl->s3->tmp.message_type == SSL3_MT_SERVER_HELLO_DONE) {
     ssl->s3->tmp.reuse_message = 1;
     /* If we get here we don't need the handshake buffer as we won't be doing
@@ -1412,8 +1392,8 @@
     return -1;
   }
 
-  if (!CBS_stow(&certificate_types, &ssl->s3->tmp.certificate_types,
-                &ssl->s3->tmp.num_certificate_types)) {
+  if (!CBS_stow(&certificate_types, &ssl->s3->hs->certificate_types,
+                &ssl->s3->hs->num_certificate_types)) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
     return -1;
   }
@@ -1442,9 +1422,9 @@
     return -1;
   }
 
-  ssl->s3->tmp.cert_request = 1;
-  sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free);
-  ssl->s3->tmp.ca_names = ca_sk;
+  ssl->s3->hs->cert_request = 1;
+  sk_X509_NAME_pop_free(ssl->s3->hs->ca_names, X509_NAME_free);
+  ssl->s3->hs->ca_names = ca_sk;
   return 1;
 }
 
@@ -1494,7 +1474,7 @@
     }
 
     if (!ssl_has_certificate(ssl)) {
-      ssl->s3->tmp.cert_request = 0;
+      ssl->s3->hs->cert_request = 0;
       /* Without a client certificate, the handshake buffer may be released. */
       ssl3_free_handshake_buffer(ssl);
 
@@ -1625,15 +1605,15 @@
   } else if (alg_k & (SSL_kECDHE|SSL_kDHE|SSL_kCECPQ1)) {
     /* Generate a keypair and serialize the public half. */
     CBB child;
-    if (!SSL_ECDH_CTX_add_key(&ssl->s3->tmp.ecdh_ctx, &body, &child)) {
+    if (!SSL_ECDH_CTX_add_key(&ssl->s3->hs->ecdh_ctx, &body, &child)) {
       goto err;
     }
 
     /* Compute the premaster. */
     uint8_t alert;
-    if (!SSL_ECDH_CTX_accept(&ssl->s3->tmp.ecdh_ctx, &child, &pms, &pms_len,
-                             &alert, ssl->s3->tmp.peer_key,
-                             ssl->s3->tmp.peer_key_len)) {
+    if (!SSL_ECDH_CTX_accept(&ssl->s3->hs->ecdh_ctx, &child, &pms, &pms_len,
+                             &alert, ssl->s3->hs->peer_key,
+                             ssl->s3->hs->peer_key_len)) {
       ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
       goto err;
     }
@@ -1642,9 +1622,10 @@
     }
 
     /* The key exchange state may now be discarded. */
-    SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx);
-    OPENSSL_free(ssl->s3->tmp.peer_key);
-    ssl->s3->tmp.peer_key = NULL;
+    SSL_ECDH_CTX_cleanup(&ssl->s3->hs->ecdh_ctx);
+    OPENSSL_free(ssl->s3->hs->peer_key);
+    ssl->s3->hs->peer_key = NULL;
+    ssl->s3->hs->peer_key_len = 0;
   } else if (alg_k & SSL_kPSK) {
     /* For plain PSK, other_secret is a block of 0s with the same length as
      * the pre-shared key. */
diff --git a/src/ssl/handshake_server.c b/src/ssl/handshake_server.c
index fd0223f..e018680 100644
--- a/src/ssl/handshake_server.c
+++ b/src/ssl/handshake_server.c
@@ -270,7 +270,7 @@
 
       case SSL3_ST_SW_CERT_STATUS_A:
       case SSL3_ST_SW_CERT_STATUS_B:
-        if (ssl->s3->tmp.certificate_status_expected) {
+        if (ssl->s3->hs->certificate_status_expected) {
           ret = ssl3_send_certificate_status(ssl);
           if (ret <= 0) {
             goto end;
@@ -302,7 +302,7 @@
 
       case SSL3_ST_SW_CERT_REQ_A:
       case SSL3_ST_SW_CERT_REQ_B:
-        if (ssl->s3->tmp.cert_request) {
+        if (ssl->s3->hs->cert_request) {
           ret = ssl3_send_certificate_request(ssl);
           if (ret <= 0) {
             goto end;
@@ -324,7 +324,7 @@
         break;
 
       case SSL3_ST_SR_CERT_A:
-        if (ssl->s3->tmp.cert_request) {
+        if (ssl->s3->hs->cert_request) {
           ret = ssl3_get_client_certificate(ssl);
           if (ret <= 0) {
             goto end;
@@ -366,7 +366,7 @@
         break;
 
       case SSL3_ST_SR_NEXT_PROTO_A:
-        if (ssl->s3->next_proto_neg_seen) {
+        if (ssl->s3->hs->next_proto_neg_seen) {
           ret = ssl3_get_next_proto(ssl);
           if (ret <= 0) {
             goto end;
@@ -836,7 +836,6 @@
     }
 
     ssl->s3->tmp.new_cipher = ssl->session->cipher;
-    ssl->s3->tmp.cert_request = 0;
   } else {
     /* Call |cert_cb| to update server certificates if required. */
     if (ssl->cert->cert_cb != NULL) {
@@ -864,18 +863,18 @@
     ssl->s3->tmp.new_cipher = c;
 
     /* Determine whether to request a client certificate. */
-    ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+    ssl->s3->hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
     /* Only request a certificate if Channel ID isn't negotiated. */
     if ((ssl->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
         ssl->s3->tlsext_channel_id_valid) {
-      ssl->s3->tmp.cert_request = 0;
+      ssl->s3->hs->cert_request = 0;
     }
     /* CertificateRequest may only be sent in certificate-based ciphers. */
     if (!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
-      ssl->s3->tmp.cert_request = 0;
+      ssl->s3->hs->cert_request = 0;
     }
 
-    if (!ssl->s3->tmp.cert_request) {
+    if (!ssl->s3->hs->cert_request) {
       /* OpenSSL returns X509_V_OK when no certificates are requested. This is
        * classed by them as a bug, but it's assumed by at least NGINX. */
       ssl->s3->new_session->verify_result = X509_V_OK;
@@ -888,7 +887,7 @@
   }
 
   /* Release the handshake buffer if client authentication isn't required. */
-  if (!ssl->s3->tmp.cert_request) {
+  if (!ssl->s3->hs->cert_request) {
     ssl3_free_handshake_buffer(ssl);
   }
 
@@ -1051,13 +1050,13 @@
         goto err;
       }
 
-      SSL_ECDH_CTX_init_for_dhe(&ssl->s3->tmp.ecdh_ctx, dh);
+      SSL_ECDH_CTX_init_for_dhe(&ssl->s3->hs->ecdh_ctx, dh);
       if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
           !BN_bn2cbb_padded(&child, BN_num_bytes(params->p), params->p) ||
           !CBB_add_u16_length_prefixed(&cbb, &child) ||
           !BN_bn2cbb_padded(&child, BN_num_bytes(params->g), params->g) ||
           !CBB_add_u16_length_prefixed(&cbb, &child) ||
-          !SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) {
+          !SSL_ECDH_CTX_offer(&ssl->s3->hs->ecdh_ctx, &child)) {
         goto err;
       }
     } else if (alg_k & SSL_kECDHE) {
@@ -1071,39 +1070,35 @@
       ssl->s3->new_session->key_exchange_info = group_id;
 
       /* Set up ECDH, generate a key, and emit the public half. */
-      if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id) ||
+      if (!SSL_ECDH_CTX_init(&ssl->s3->hs->ecdh_ctx, group_id) ||
           !CBB_add_u8(&cbb, NAMED_CURVE_TYPE) ||
           !CBB_add_u16(&cbb, group_id) ||
           !CBB_add_u8_length_prefixed(&cbb, &child) ||
-          !SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) {
+          !SSL_ECDH_CTX_offer(&ssl->s3->hs->ecdh_ctx, &child)) {
         goto err;
       }
     } else if (alg_k & SSL_kCECPQ1) {
-      SSL_ECDH_CTX_init_for_cecpq1(&ssl->s3->tmp.ecdh_ctx);
+      SSL_ECDH_CTX_init_for_cecpq1(&ssl->s3->hs->ecdh_ctx);
       if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
-          !SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) {
+          !SSL_ECDH_CTX_offer(&ssl->s3->hs->ecdh_ctx, &child)) {
         goto err;
       }
     } else {
       assert(alg_k & SSL_kPSK);
     }
 
-    size_t len;
-    if (!CBB_finish(&cbb, &ssl->s3->tmp.server_params, &len) ||
-        len > 0xffffffffu) {
-      OPENSSL_free(ssl->s3->tmp.server_params);
-      ssl->s3->tmp.server_params = NULL;
+    if (!CBB_finish(&cbb, &ssl->s3->hs->server_params,
+                    &ssl->s3->hs->server_params_len)) {
       goto err;
     }
-    ssl->s3->tmp.server_params_len = (uint32_t)len;
   }
 
   /* Assemble the message. */
   CBB body;
   if (!ssl->method->init_message(ssl, &cbb, &body,
                                  SSL3_MT_SERVER_KEY_EXCHANGE) ||
-      !CBB_add_bytes(&body, ssl->s3->tmp.server_params,
-                     ssl->s3->tmp.server_params_len)) {
+      !CBB_add_bytes(&body, ssl->s3->hs->server_params,
+                     ssl->s3->hs->server_params_len)) {
     goto err;
   }
 
@@ -1142,11 +1137,11 @@
       uint8_t *transcript_data;
       size_t transcript_len;
       if (!CBB_init(&transcript,
-                    2*SSL3_RANDOM_SIZE + ssl->s3->tmp.server_params_len) ||
+                    2*SSL3_RANDOM_SIZE + ssl->s3->hs->server_params_len) ||
           !CBB_add_bytes(&transcript, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
           !CBB_add_bytes(&transcript, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
-          !CBB_add_bytes(&transcript, ssl->s3->tmp.server_params,
-                         ssl->s3->tmp.server_params_len) ||
+          !CBB_add_bytes(&transcript, ssl->s3->hs->server_params,
+                         ssl->s3->hs->server_params_len) ||
           !CBB_finish(&transcript, &transcript_data, &transcript_len)) {
         CBB_cleanup(&transcript);
         OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
@@ -1182,9 +1177,9 @@
     goto err;
   }
 
-  OPENSSL_free(ssl->s3->tmp.server_params);
-  ssl->s3->tmp.server_params = NULL;
-  ssl->s3->tmp.server_params_len = 0;
+  OPENSSL_free(ssl->s3->hs->server_params);
+  ssl->s3->hs->server_params = NULL;
+  ssl->s3->hs->server_params_len = 0;
 
   ssl->state = SSL3_ST_SW_KEY_EXCH_C;
   return ssl->method->write_message(ssl);
@@ -1199,8 +1194,8 @@
   int have_rsa_sign = 0;
   int have_ecdsa_sign = 0;
   const uint16_t *sig_algs;
-  size_t sig_algs_len = tls12_get_psigalgs(ssl, &sig_algs);
-  for (size_t i = 0; i < sig_algs_len; i++) {
+  size_t num_sig_algs = tls12_get_verify_sigalgs(ssl, &sig_algs);
+  for (size_t i = 0; i < num_sig_algs; i++) {
     switch (sig_algs[i]) {
       case SSL_SIGN_RSA_PKCS1_SHA512:
       case SSL_SIGN_RSA_PKCS1_SHA384:
@@ -1247,7 +1242,7 @@
 
   if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
     const uint16_t *sigalgs;
-    size_t num_sigalgs = tls12_get_psigalgs(ssl, &sigalgs);
+    size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
     if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
       goto err;
     }
@@ -1291,7 +1286,7 @@
 }
 
 static int ssl3_get_client_certificate(SSL *ssl) {
-  assert(ssl->s3->tmp.cert_request);
+  assert(ssl->s3->hs->cert_request);
 
   int msg_ret = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message);
   if (msg_ret <= 0) {
@@ -1572,7 +1567,7 @@
   } else if (alg_k & (SSL_kECDHE|SSL_kDHE|SSL_kCECPQ1)) {
     /* Parse the ClientKeyExchange. */
     CBS peer_key;
-    if (!SSL_ECDH_CTX_get_key(&ssl->s3->tmp.ecdh_ctx, &client_key_exchange,
+    if (!SSL_ECDH_CTX_get_key(&ssl->s3->hs->ecdh_ctx, &client_key_exchange,
                               &peer_key) ||
         CBS_len(&client_key_exchange) != 0) {
       al = SSL_AD_DECODE_ERROR;
@@ -1582,7 +1577,7 @@
 
     /* Compute the premaster. */
     uint8_t alert;
-    if (!SSL_ECDH_CTX_finish(&ssl->s3->tmp.ecdh_ctx, &premaster_secret,
+    if (!SSL_ECDH_CTX_finish(&ssl->s3->hs->ecdh_ctx, &premaster_secret,
                              &premaster_secret_len, &alert, CBS_data(&peer_key),
                              CBS_len(&peer_key))) {
       al = alert;
@@ -1590,7 +1585,7 @@
     }
 
     /* The key exchange state may now be discarded. */
-    SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx);
+    SSL_ECDH_CTX_cleanup(&ssl->s3->hs->ecdh_ctx);
   } else if (alg_k & SSL_kPSK) {
     /* For plain PSK, other_secret is a block of 0s with the same length as the
      * pre-shared key. */
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 3e7c053..7e9954d 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -896,15 +896,43 @@
   size_t hash_len;
   uint8_t resumption_hash[EVP_MAX_MD_SIZE];
   uint8_t secret[EVP_MAX_MD_SIZE];
-  uint8_t traffic_secret_0[EVP_MAX_MD_SIZE];
+  uint8_t client_traffic_secret_0[EVP_MAX_MD_SIZE];
+  uint8_t server_traffic_secret_0[EVP_MAX_MD_SIZE];
 
-  /* ecdh_ctx is the active client ECDH offer in TLS 1.3. */
+  union {
+    /* sent is a bitset where the bits correspond to elements of kExtensions
+     * in t1_lib.c. Each bit is set if that extension was sent in a
+     * ClientHello. It's not used by servers. */
+    uint32_t sent;
+    /* received is a bitset, like |sent|, but is used by servers to record
+     * which extensions were received from a client. */
+    uint32_t received;
+  } extensions;
+
+  union {
+    /* sent is a bitset where the bits correspond to elements of
+     * |client_custom_extensions| in the |SSL_CTX|. Each bit is set if that
+     * extension was sent in a ClientHello. It's not used by servers. */
+    uint16_t sent;
+    /* received is a bitset, like |sent|, but is used by servers to record
+     * which custom extensions were received from a client. The bits here
+     * correspond to |server_custom_extensions|. */
+    uint16_t received;
+  } custom_extensions;
+
+  /* ecdh_ctx is the current ECDH instance. */
   SSL_ECDH_CTX ecdh_ctx;
 
+  unsigned received_hello_retry_request:1;
+
   /* retry_group is the group ID selected by the server in HelloRetryRequest in
    * TLS 1.3. */
   uint16_t retry_group;
 
+  /* cookie is the value of the cookie received from the server, if any. */
+  uint8_t *cookie;
+  size_t cookie_len;
+
   /* key_share_bytes is the value of the previously sent KeyShare extension by
    * the client in TLS 1.3. */
   uint8_t *key_share_bytes;
@@ -922,11 +950,60 @@
   /* num_peer_sigalgs is the number of entries in |peer_sigalgs|. */
   size_t num_peer_sigalgs;
 
+  /* peer_supported_group_list contains the supported group IDs advertised by
+   * the peer. This is only set on the server's end. The server does not
+   * advertise this extension to the client. */
+  uint16_t *peer_supported_group_list;
+  size_t peer_supported_group_list_len;
+
+  /* peer_key is the peer's ECDH key for a TLS 1.2 client. */
+  uint8_t *peer_key;
+  size_t peer_key_len;
+
+  /* server_params, in TLS 1.2, stores the ServerKeyExchange parameters to be
+   * signed while the signature is being computed. */
+  uint8_t *server_params;
+  size_t server_params_len;
+
+  /* session_tickets_sent, in TLS 1.3, is the number of tickets the server has
+   * sent. */
   uint8_t session_tickets_sent;
 
+  /* cert_request is one if a client certificate was requested and zero
+   * otherwise. */
+  unsigned cert_request:1;
+
+  /* certificate_status_expected is one if OCSP stapling was negotiated and the
+   * server is expected to send a CertificateStatus message. (This is used on
+   * both the client and server sides.) */
+  unsigned certificate_status_expected:1;
+
+  /* ocsp_stapling_requested is one if a client requested OCSP stapling. */
+  unsigned ocsp_stapling_requested:1;
+
+  /* should_ack_sni is used by a server and indicates that the SNI extension
+   * should be echoed in the ServerHello. */
+  unsigned should_ack_sni:1;
+
+  /* in_false_start is one if there is a pending client handshake in False
+   * Start. The client may write data at this point. */
+  unsigned in_false_start:1;
+
+  /* next_proto_neg_seen is one of NPN was negotiated. */
+  unsigned next_proto_neg_seen:1;
+
   /* peer_psk_identity_hint, on the client, is the psk_identity_hint sent by the
    * server when using a TLS 1.2 PSK key exchange. */
   char *peer_psk_identity_hint;
+
+  /* ca_names, on the client, contains the list of CAs received in a
+   * CertificateRequest message. */
+  STACK_OF(X509_NAME) *ca_names;
+
+  /* certificate_types, on the client, contains the set of certificate types
+   * received in a CertificateRequest message. */
+  uint8_t *certificate_types;
+  size_t num_certificate_types;
 } /* SSL_HANDSHAKE */;
 
 SSL_HANDSHAKE *ssl_handshake_new(enum ssl_hs_wait_t (*do_handshake)(SSL *ssl));
@@ -1024,6 +1101,7 @@
   ssl_grease_extension1,
   ssl_grease_extension2,
   ssl_grease_version,
+  ssl_grease_ticket_extension,
 };
 
 /* ssl_get_grease_value returns a GREASE value for |ssl|. For a given
@@ -1033,6 +1111,27 @@
 uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index);
 
 
+/* Signature algorithms. */
+
+/* tls1_parse_peer_sigalgs parses |sigalgs| as the list of peer signature
+ * algorithms and them on |ssl|. It returns one on success and zero on error. */
+int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *sigalgs);
+
+/* tls1_choose_signature_algorithm sets |*out| to a signature algorithm for use
+ * with |ssl|'s private key based on the peer's preferences and the algorithms
+ * supported. It returns one on success and zero on error. */
+int tls1_choose_signature_algorithm(SSL *ssl, uint16_t *out);
+
+/* tls12_get_verify_sigalgs sets |*out| to the signature algorithms acceptable
+ * for the peer signature and returns the length of the list. */
+size_t tls12_get_verify_sigalgs(const SSL *ssl, const uint16_t **out);
+
+/* tls12_check_peer_sigalg checks if |sigalg| is acceptable for the peer
+ * signature. It returns one on success and zero on error, setting |*out_alert|
+ * to an alert to send. */
+int tls12_check_peer_sigalg(SSL *ssl, int *out_alert, uint16_t sigalg);
+
+
 /* Underdocumented functions.
  *
  * Functions below here haven't been touched up and may be underdocumented. */
@@ -1184,6 +1283,207 @@
   int (*final_finish_mac)(SSL *ssl, int from_server, uint8_t *out);
 };
 
+typedef struct ssl3_record_st {
+  /* type is the record type. */
+  uint8_t type;
+  /* length is the number of unconsumed bytes in the record. */
+  uint16_t length;
+  /* data is a non-owning pointer to the first unconsumed byte of the record. */
+  uint8_t *data;
+} SSL3_RECORD;
+
+typedef struct ssl3_buffer_st {
+  /* buf is the memory allocated for this buffer. */
+  uint8_t *buf;
+  /* offset is the offset into |buf| which the buffer contents start at. */
+  uint16_t offset;
+  /* len is the length of the buffer contents from |buf| + |offset|. */
+  uint16_t len;
+  /* cap is how much memory beyond |buf| + |offset| is available. */
+  uint16_t cap;
+} SSL3_BUFFER;
+
+/* An ssl_shutdown_t describes the shutdown state of one end of the connection,
+ * whether it is alive or has been shutdown via close_notify or fatal alert. */
+enum ssl_shutdown_t {
+  ssl_shutdown_none = 0,
+  ssl_shutdown_close_notify = 1,
+  ssl_shutdown_fatal_alert = 2,
+};
+
+typedef struct ssl3_state_st {
+  uint8_t read_sequence[8];
+  uint8_t write_sequence[8];
+
+  uint8_t server_random[SSL3_RANDOM_SIZE];
+  uint8_t client_random[SSL3_RANDOM_SIZE];
+
+  /* have_version is true if the connection's final version is known. Otherwise
+   * the version has not been negotiated yet. */
+  unsigned have_version:1;
+
+  /* v2_hello_done is true if the peer's V2ClientHello, if any, has been handled
+   * and future messages should use the record layer. */
+  unsigned v2_hello_done:1;
+
+  /* initial_handshake_complete is true if the initial handshake has
+   * completed. */
+  unsigned initial_handshake_complete:1;
+
+  /* read_buffer holds data from the transport to be processed. */
+  SSL3_BUFFER read_buffer;
+  /* write_buffer holds data to be written to the transport. */
+  SSL3_BUFFER write_buffer;
+
+  SSL3_RECORD rrec; /* each decoded record goes in here */
+
+  /* partial write - check the numbers match */
+  unsigned int wnum; /* number of bytes sent so far */
+  int wpend_tot;     /* number bytes written */
+  int wpend_type;
+  int wpend_ret; /* number of bytes submitted */
+  const uint8_t *wpend_buf;
+
+  /* handshake_buffer, if non-NULL, contains the handshake transcript. */
+  BUF_MEM *handshake_buffer;
+  /* handshake_hash, if initialized with an |EVP_MD|, maintains the handshake
+   * hash. For TLS 1.1 and below, it is the SHA-1 half. */
+  EVP_MD_CTX handshake_hash;
+  /* handshake_md5, if initialized with an |EVP_MD|, maintains the MD5 half of
+   * the handshake hash for TLS 1.1 and below. */
+  EVP_MD_CTX handshake_md5;
+
+  /* recv_shutdown is the shutdown state for the receive half of the
+   * connection. */
+  enum ssl_shutdown_t recv_shutdown;
+
+  /* recv_shutdown is the shutdown state for the send half of the connection. */
+  enum ssl_shutdown_t send_shutdown;
+
+  int alert_dispatch;
+  uint8_t send_alert[2];
+
+  int total_renegotiations;
+
+  /* empty_record_count is the number of consecutive empty records received. */
+  uint8_t empty_record_count;
+
+  /* warning_alert_count is the number of consecutive warning alerts
+   * received. */
+  uint8_t warning_alert_count;
+
+  /* key_update_count is the number of consecutive KeyUpdates received. */
+  uint8_t key_update_count;
+
+  /* aead_read_ctx is the current read cipher state. */
+  SSL_AEAD_CTX *aead_read_ctx;
+
+  /* aead_write_ctx is the current write cipher state. */
+  SSL_AEAD_CTX *aead_write_ctx;
+
+  /* enc_method is the method table corresponding to the current protocol
+   * version. */
+  const SSL3_ENC_METHOD *enc_method;
+
+  /* pending_message is the current outgoing handshake message. */
+  uint8_t *pending_message;
+  uint32_t pending_message_len;
+
+  /* hs is the handshake state for the current handshake or NULL if there isn't
+   * one. */
+  SSL_HANDSHAKE *hs;
+
+  uint8_t write_traffic_secret[EVP_MAX_MD_SIZE];
+  uint8_t write_traffic_secret_len;
+  uint8_t read_traffic_secret[EVP_MAX_MD_SIZE];
+  uint8_t read_traffic_secret_len;
+  uint8_t exporter_secret[EVP_MAX_MD_SIZE];
+  uint8_t exporter_secret_len;
+
+  /* State pertaining to the pending handshake.
+   *
+   * TODO(davidben): Move everything not needed after the handshake completes to
+   * |hs| and remove this. */
+  struct {
+    int message_type;
+
+    /* used to hold the new cipher we are going to use */
+    const SSL_CIPHER *new_cipher;
+
+    /* used when SSL_ST_FLUSH_DATA is entered */
+    int next_state;
+
+    int reuse_message;
+
+    uint8_t *key_block;
+    uint8_t key_block_length;
+
+    uint8_t new_mac_secret_len;
+    uint8_t new_key_len;
+    uint8_t new_fixed_iv_len;
+
+    /* extended_master_secret indicates whether the extended master secret
+     * computation is used in this handshake. Note that this is different from
+     * whether it was used for the current session. If this is a resumption
+     * handshake then EMS might be negotiated in the client and server hello
+     * messages, but it doesn't matter if the session that's being resumed
+     * didn't use it to create the master secret initially. */
+    char extended_master_secret;
+
+    /* peer_signature_algorithm is the signature algorithm used to authenticate
+     * the peer, or zero if not applicable. */
+    uint16_t peer_signature_algorithm;
+  } tmp;
+
+  /* new_session is the new mutable session being established by the current
+   * handshake. It should not be cached. */
+  SSL_SESSION *new_session;
+
+  /* established_session is the session established by the connection. This
+   * session is only filled upon the completion of the handshake and is
+   * immutable. */
+  SSL_SESSION *established_session;
+
+  /* session_reused indicates whether a session was resumed. */
+  unsigned session_reused:1;
+
+  /* Connection binding to prevent renegotiation attacks */
+  uint8_t previous_client_finished[12];
+  uint8_t previous_client_finished_len;
+  uint8_t previous_server_finished[12];
+  uint8_t previous_server_finished_len;
+  int send_connection_binding;
+
+  /* Next protocol negotiation. For the client, this is the protocol that we
+   * sent in NextProtocol and is set when handling ServerHello extensions.
+   *
+   * For a server, this is the client's selected_protocol from NextProtocol and
+   * is set when handling the NextProtocol message, before the Finished
+   * message. */
+  uint8_t *next_proto_negotiated;
+  size_t next_proto_negotiated_len;
+
+  /* ALPN information
+   * (we are in the process of transitioning from NPN to ALPN.) */
+
+  /* In a server these point to the selected ALPN protocol after the
+   * ClientHello has been processed. In a client these contain the protocol
+   * that the server selected once the ServerHello has been processed. */
+  uint8_t *alpn_selected;
+  size_t alpn_selected_len;
+
+  /* In a client, this means that the server supported Channel ID and that a
+   * Channel ID was sent. In a server it means that we echoed support for
+   * Channel IDs and that tlsext_channel_id will be valid after the
+   * handshake. */
+  char tlsext_channel_id_valid;
+  /* For a server:
+   *     If |tlsext_channel_id_valid| is true, then this contains the
+   *     verified Channel ID from the client: a P256 point, (x,y), where
+   *     each are big-endian values. */
+  uint8_t tlsext_channel_id[64];
+} SSL3_STATE;
+
 /* lengths of messages */
 #define DTLS1_COOKIE_LENGTH 256
 
@@ -1269,13 +1569,18 @@
 extern const SSL3_ENC_METHOD TLSv1_enc_data;
 extern const SSL3_ENC_METHOD SSLv3_enc_data;
 
-/* From draft-ietf-tls-tls13-15, used in determining PSK modes. */
+/* From draft-ietf-tls-tls13-16, used in determining PSK modes. */
 #define SSL_PSK_KE        0x0
 #define SSL_PSK_DHE_KE    0x1
 
 #define SSL_PSK_AUTH      0x0
 #define SSL_PSK_SIGN_AUTH 0x1
 
+/* From draft-ietf-tls-tls13-16, used in determining whether to respond with a
+ * KeyUpdate. */
+#define SSL_KEY_UPDATE_NOT_REQUESTED 0
+#define SSL_KEY_UPDATE_REQUESTED 1
+
 CERT *ssl_cert_new(void);
 CERT *ssl_cert_dup(CERT *cert);
 void ssl_cert_clear_certs(CERT *c);
@@ -1453,15 +1758,12 @@
                                 size_t premaster_len);
 
 /* tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the
- * list of allowed group IDs. If |get_peer_groups| is non-zero, return the
- * peer's group list. Otherwise, return the preferred list. */
-void tls1_get_grouplist(SSL *ssl, int get_peer_groups,
-                        const uint16_t **out_group_ids,
+ * locally-configured group preference list. */
+void tls1_get_grouplist(SSL *ssl, const uint16_t **out_group_ids,
                         size_t *out_group_ids_len);
 
-/* tls1_check_group_id returns one if |group_id| is consistent with both our
- * and the peer's group preferences. Note: if called as the client, only our
- * preferences are checked; the peer (the server) does not send preferences. */
+/* tls1_check_group_id returns one if |group_id| is consistent with
+ * locally-configured group preferences. */
 int tls1_check_group_id(SSL *ssl, uint16_t group_id);
 
 /* tls1_get_shared_group sets |*out_group_id| to the first preferred shared
@@ -1483,11 +1785,6 @@
 int tls1_set_curves_list(uint16_t **out_group_ids, size_t *out_group_ids_len,
                          const char *curves);
 
-/* tls1_check_ec_cert returns one if |x| is an ECC certificate with curve and
- * point format compatible with the client's preferences. Otherwise it returns
- * zero. */
-int tls1_check_ec_cert(SSL *ssl, X509 *x);
-
 /* ssl_add_clienthello_tlsext writes ClientHello extensions to |out|. It
  * returns one on success and zero on failure. The |header_len| argument is the
  * length of the ClientHello written so far and is used to compute the padding
@@ -1536,20 +1833,7 @@
 uint16_t ssl3_protocol_version(const SSL *ssl);
 
 uint32_t ssl_get_algorithm_prf(const SSL *ssl);
-int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *sigalgs);
 
-/* tls1_choose_signature_algorithm sets |*out| to a signature algorithm for use
- * with |ssl|'s private key based on the peer's preferences and the digests
- * supported. It returns one on success and zero on error. */
-int tls1_choose_signature_algorithm(SSL *ssl, uint16_t *out);
-
-size_t tls12_get_psigalgs(SSL *ssl, const uint16_t **psigs);
-
-/* tls12_check_peer_sigalg checks that |signature_algorithm| is consistent with
- * |ssl|'s sent, supported signature algorithms and returns 1. Otherwise it
- * returns 0 and writes an alert into |*out_alert|. */
-int tls12_check_peer_sigalg(SSL *ssl, int *out_alert,
-                            uint16_t signature_algorithm);
 void ssl_set_client_disabled(SSL *ssl);
 
 void ssl_get_current_time(const SSL *ssl, struct timeval *out_clock);
diff --git a/src/ssl/s3_both.c b/src/ssl/s3_both.c
index 52c93aa..1e7e4e1 100644
--- a/src/ssl/s3_both.c
+++ b/src/ssl/s3_both.c
@@ -148,12 +148,21 @@
   }
 
   OPENSSL_cleanse(hs->secret, sizeof(hs->secret));
-  OPENSSL_cleanse(hs->traffic_secret_0, sizeof(hs->traffic_secret_0));
+  OPENSSL_cleanse(hs->client_traffic_secret_0,
+                  sizeof(hs->client_traffic_secret_0));
+  OPENSSL_cleanse(hs->server_traffic_secret_0,
+                  sizeof(hs->server_traffic_secret_0));
   SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+  OPENSSL_free(hs->cookie);
   OPENSSL_free(hs->key_share_bytes);
   OPENSSL_free(hs->public_key);
   OPENSSL_free(hs->peer_sigalgs);
+  OPENSSL_free(hs->peer_supported_group_list);
+  OPENSSL_free(hs->peer_key);
+  OPENSSL_free(hs->server_params);
   OPENSSL_free(hs->peer_psk_identity_hint);
+  sk_X509_NAME_pop_free(hs->ca_names, X509_NAME_free);
+  OPENSSL_free(hs->certificate_types);
   OPENSSL_free(hs);
 }
 
@@ -235,12 +244,12 @@
     return ssl->method->write_message(ssl);
   }
 
-  int n = ssl->s3->enc_method->final_finish_mac(ssl, ssl->server,
-                                                ssl->s3->tmp.finish_md);
-  if (n == 0) {
+  uint8_t finished[EVP_MAX_MD_SIZE];
+  size_t finished_len =
+      ssl->s3->enc_method->final_finish_mac(ssl, ssl->server, finished);
+  if (finished_len == 0) {
     return 0;
   }
-  ssl->s3->tmp.finish_md_len = n;
 
   /* Log the master secret, if logging is enabled. */
   if (!ssl_log_secret(ssl, "CLIENT_RANDOM",
@@ -249,21 +258,26 @@
     return 0;
   }
 
-  /* Copy the finished so we can use it for renegotiation checks */
-  if (ssl->server) {
-    assert(n <= EVP_MAX_MD_SIZE);
-    memcpy(ssl->s3->previous_server_finished, ssl->s3->tmp.finish_md, n);
-    ssl->s3->previous_server_finished_len = n;
-  } else {
-    assert(n <= EVP_MAX_MD_SIZE);
-    memcpy(ssl->s3->previous_client_finished, ssl->s3->tmp.finish_md, n);
-    ssl->s3->previous_client_finished_len = n;
+  /* Copy the Finished so we can use it for renegotiation checks. */
+  if (ssl->version != SSL3_VERSION) {
+    if (finished_len > sizeof(ssl->s3->previous_client_finished) ||
+        finished_len > sizeof(ssl->s3->previous_server_finished)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return -1;
+    }
+
+    if (ssl->server) {
+      memcpy(ssl->s3->previous_server_finished, finished, finished_len);
+      ssl->s3->previous_server_finished_len = finished_len;
+    } else {
+      memcpy(ssl->s3->previous_client_finished, finished, finished_len);
+      ssl->s3->previous_client_finished_len = finished_len;
+    }
   }
 
   CBB cbb, body;
   if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_FINISHED) ||
-      !CBB_add_bytes(&body, ssl->s3->tmp.finish_md,
-                     ssl->s3->tmp.finish_md_len) ||
+      !CBB_add_bytes(&body, finished, finished_len) ||
       !ssl->method->finish_message(ssl, &cbb)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     CBB_cleanup(&cbb);
@@ -274,21 +288,7 @@
   return ssl->method->write_message(ssl);
 }
 
-/* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen
- * so far. */
-static void ssl3_take_mac(SSL *ssl) {
-  /* If no new cipher setup then return immediately: other functions will set
-   * the appropriate error. */
-  if (ssl->s3->tmp.new_cipher == NULL) {
-    return;
-  }
-
-  ssl->s3->tmp.peer_finish_md_len = ssl->s3->enc_method->final_finish_mac(
-      ssl, !ssl->server, ssl->s3->tmp.peer_finish_md);
-}
-
 int ssl3_get_finished(SSL *ssl) {
-  int al;
   int ret = ssl->method->ssl_get_message(ssl, SSL3_MT_FINISHED,
                                          ssl_dont_hash_message);
   if (ret <= 0) {
@@ -296,44 +296,43 @@
   }
 
   /* Snapshot the finished hash before incorporating the new message. */
-  ssl3_take_mac(ssl);
-  if (!ssl->method->hash_current_message(ssl)) {
-    goto err;
+  uint8_t finished[EVP_MAX_MD_SIZE];
+  size_t finished_len =
+      ssl->s3->enc_method->final_finish_mac(ssl, !ssl->server, finished);
+  if (finished_len == 0 ||
+      !ssl->method->hash_current_message(ssl)) {
+    return -1;
   }
 
-  size_t finished_len = ssl->s3->tmp.peer_finish_md_len;
-
   int finished_ok = ssl->init_num == finished_len &&
-                    CRYPTO_memcmp(ssl->init_msg, ssl->s3->tmp.peer_finish_md,
-                                  finished_len) == 0;
+                    CRYPTO_memcmp(ssl->init_msg, finished, finished_len) == 0;
 #if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
   finished_ok = 1;
 #endif
   if (!finished_ok) {
-    al = SSL_AD_DECRYPT_ERROR;
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
     OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
-    goto f_err;
+    return -1;
   }
 
-  /* Copy the finished so we can use it for renegotiation checks */
-  if (ssl->server) {
-    assert(finished_len <= EVP_MAX_MD_SIZE);
-    memcpy(ssl->s3->previous_client_finished, ssl->s3->tmp.peer_finish_md,
-           finished_len);
-    ssl->s3->previous_client_finished_len = finished_len;
-  } else {
-    assert(finished_len <= EVP_MAX_MD_SIZE);
-    memcpy(ssl->s3->previous_server_finished, ssl->s3->tmp.peer_finish_md,
-           finished_len);
-    ssl->s3->previous_server_finished_len = finished_len;
+  /* Copy the Finished so we can use it for renegotiation checks. */
+  if (ssl->version != SSL3_VERSION) {
+    if (finished_len > sizeof(ssl->s3->previous_client_finished) ||
+        finished_len > sizeof(ssl->s3->previous_server_finished)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return -1;
+    }
+
+    if (ssl->server) {
+      memcpy(ssl->s3->previous_client_finished, finished, finished_len);
+      ssl->s3->previous_client_finished_len = finished_len;
+    } else {
+      memcpy(ssl->s3->previous_server_finished, finished, finished_len);
+      ssl->s3->previous_server_finished_len = finished_len;
+    }
   }
 
   return 1;
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
-  return 0;
 }
 
 int ssl3_send_change_cipher_spec(SSL *ssl) {
diff --git a/src/ssl/s3_lib.c b/src/ssl/s3_lib.c
index 2a7bbae..69d3a9d 100644
--- a/src/ssl/s3_lib.c
+++ b/src/ssl/s3_lib.c
@@ -203,13 +203,7 @@
   ssl3_cleanup_key_block(ssl);
   ssl_read_buffer_clear(ssl);
   ssl_write_buffer_clear(ssl);
-  SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx);
-  OPENSSL_free(ssl->s3->tmp.peer_key);
-  OPENSSL_free(ssl->s3->tmp.server_params);
 
-  sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free);
-  OPENSSL_free(ssl->s3->tmp.certificate_types);
-  OPENSSL_free(ssl->s3->tmp.peer_supported_group_list);
   SSL_SESSION_free(ssl->s3->new_session);
   SSL_SESSION_free(ssl->s3->established_session);
   ssl3_free_handshake_buffer(ssl);
diff --git a/src/ssl/ssl_cert.c b/src/ssl/ssl_cert.c
index 0c5a7af..55b464f 100644
--- a/src/ssl/ssl_cert.c
+++ b/src/ssl/ssl_cert.c
@@ -395,7 +395,11 @@
    * |SSL_set_connect_state|. If |handshake_func| is NULL, |ssl| is in an
    * indeterminate mode and |ssl->server| is unset. */
   if (ssl->handshake_func != NULL && !ssl->server) {
-    return ssl->s3->tmp.ca_names;
+    if (ssl->s3->hs != NULL) {
+      return ssl->s3->hs->ca_names;
+    }
+
+    return NULL;
   }
 
   if (ssl->client_CA != NULL) {
@@ -774,6 +778,8 @@
 }
 
 int ssl_check_leaf_certificate(SSL *ssl, X509 *leaf) {
+  assert(ssl3_protocol_version(ssl) < TLS1_3_VERSION);
+
   int ret = 0;
   EVP_PKEY *pkey = X509_get_pubkey(leaf);
   if (pkey == NULL) {
@@ -800,7 +806,18 @@
       goto err;
     }
 
-    if (!tls1_check_ec_cert(ssl, leaf)) {
+    EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
+    if (ec_key == NULL) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
+      goto err;
+    }
+
+    /* Check the key's group and point format are acceptable. */
+    uint16_t group_id;
+    if (!ssl_nid_to_group_id(
+            &group_id, EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key))) ||
+        !tls1_check_group_id(ssl, group_id) ||
+        EC_KEY_get_conv_form(ec_key) != POINT_CONVERSION_UNCOMPRESSED) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
       goto err;
     }
diff --git a/src/ssl/ssl_lib.c b/src/ssl/ssl_lib.c
index f17dc0a..491c408 100644
--- a/src/ssl/ssl_lib.c
+++ b/src/ssl/ssl_lib.c
@@ -151,7 +151,6 @@
 #include <openssl/lhash.h>
 #include <openssl/mem.h>
 #include <openssl/rand.h>
-#include <openssl/x509v3.h>
 
 #include "internal.h"
 #include "../crypto/internal.h"
@@ -636,8 +635,10 @@
 }
 
 static int ssl_do_renegotiate(SSL *ssl) {
-  /* We do not accept renegotiations as a server. */
-  if (ssl->server) {
+  /* We do not accept renegotiations as a server or SSL 3.0. SSL 3.0 will be
+   * removed entirely in the future and requires retaining more data for
+   * renegotiation_info. */
+  if (ssl->server || ssl->version == SSL3_VERSION) {
     goto no_renegotiation;
   }
 
@@ -1065,6 +1066,13 @@
 
 int SSL_get_tls_unique(const SSL *ssl, uint8_t *out, size_t *out_len,
                        size_t max_out) {
+  /* tls-unique is not defined for SSL 3.0 or TLS 1.3. */
+  if (!ssl->s3->initial_handshake_complete ||
+      ssl3_protocol_version(ssl) < TLS1_VERSION ||
+      ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    goto err;
+  }
+
   /* The tls-unique value is the first Finished message in the handshake, which
    * is the client's in a full handshake and the server's for a resumption. See
    * https://tools.ietf.org/html/rfc5929#section-3.1. */
@@ -1079,11 +1087,6 @@
     finished_len = ssl->s3->previous_server_finished_len;
   }
 
-  if (!ssl->s3->initial_handshake_complete ||
-      ssl->version < TLS1_VERSION) {
-    goto err;
-  }
-
   *out_len = finished_len;
   if (finished_len > max_out) {
     *out_len = max_out;
@@ -1232,32 +1235,45 @@
   return 1;
 }
 
-size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count) {
-  size_t ret = 0;
+static size_t copy_finished(void *out, size_t out_len, const uint8_t *in,
+                            size_t in_len) {
+  if (out_len > in_len) {
+    out_len = in_len;
+  }
+  memcpy(out, in, out_len);
+  return in_len;
+}
 
-  if (ssl->s3 != NULL) {
-    ret = ssl->s3->tmp.finish_md_len;
-    if (count > ret) {
-      count = ret;
-    }
-    memcpy(buf, ssl->s3->tmp.finish_md, count);
+size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count) {
+  if (!ssl->s3->initial_handshake_complete ||
+      ssl3_protocol_version(ssl) < TLS1_VERSION ||
+      ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 0;
   }
 
-  return ret;
+  if (ssl->server) {
+    return copy_finished(buf, count, ssl->s3->previous_server_finished,
+                         ssl->s3->previous_server_finished_len);
+  }
+
+  return copy_finished(buf, count, ssl->s3->previous_client_finished,
+                       ssl->s3->previous_client_finished_len);
 }
 
 size_t SSL_get_peer_finished(const SSL *ssl, void *buf, size_t count) {
-  size_t ret = 0;
-
-  if (ssl->s3 != NULL) {
-    ret = ssl->s3->tmp.peer_finish_md_len;
-    if (count > ret) {
-      count = ret;
-    }
-    memcpy(buf, ssl->s3->tmp.peer_finish_md, count);
+  if (!ssl->s3->initial_handshake_complete ||
+      ssl3_protocol_version(ssl) < TLS1_VERSION ||
+      ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 0;
   }
 
-  return ret;
+  if (ssl->server) {
+    return copy_finished(buf, count, ssl->s3->previous_client_finished,
+                         ssl->s3->previous_client_finished_len);
+  }
+
+  return copy_finished(buf, count, ssl->s3->previous_server_finished,
+                       ssl->s3->previous_server_finished_len);
 }
 
 int SSL_get_verify_mode(const SSL *ssl) { return ssl->verify_mode; }
@@ -2021,12 +2037,12 @@
 }
 
 size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) {
-  if (ssl->server) {
+  if (ssl->server || ssl->s3->hs == NULL) {
     *out_types = NULL;
     return 0;
   }
-  *out_types = ssl->s3->tmp.certificate_types;
-  return ssl->s3->tmp.num_certificate_types;
+  *out_types = ssl->s3->hs->certificate_types;
+  return ssl->s3->hs->num_certificate_types;
 }
 
 void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k,
@@ -2046,17 +2062,7 @@
       mask_k |= SSL_kRSA;
       mask_a |= SSL_aRSA;
     } else if (ssl_is_ecdsa_key_type(type)) {
-      /* An ECC certificate may be usable for ECDSA cipher suites depending on
-       * the key usage extension and on the client's group preferences. */
-      X509 *x = ssl->cert->x509;
-      /* This call populates extension flags (ex_flags). */
-      X509_check_purpose(x, -1, 0);
-      int ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE)
-                         ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)
-                         : 1;
-      if (ecdsa_ok && tls1_check_ec_cert(ssl, x)) {
-        mask_a |= SSL_aECDSA;
-      }
+      mask_a |= SSL_aECDSA;
     }
   }
 
@@ -2674,7 +2680,10 @@
 }
 
 int SSL_in_false_start(const SSL *ssl) {
-  return ssl->s3->tmp.in_false_start;
+  if (ssl->s3->hs == NULL) {
+    return 0;
+  }
+  return ssl->s3->hs->in_false_start;
 }
 
 int SSL_cutthrough_complete(const SSL *ssl) {
@@ -2694,7 +2703,8 @@
   /* False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN. */
   return !SSL_is_dtls(ssl) &&
       SSL_version(ssl) == TLS1_2_VERSION &&
-      (ssl->s3->alpn_selected || ssl->s3->next_proto_neg_seen) &&
+      (ssl->s3->alpn_selected != NULL ||
+       ssl->s3->next_proto_negotiated != NULL) &&
       cipher != NULL &&
       (cipher->algorithm_mkey == SSL_kECDHE ||
        cipher->algorithm_mkey == SSL_kCECPQ1) &&
diff --git a/src/ssl/ssl_rsa.c b/src/ssl/ssl_rsa.c
index 6f8ceae..29e5f19 100644
--- a/src/ssl/ssl_rsa.c
+++ b/src/ssl/ssl_rsa.c
@@ -65,6 +65,7 @@
 #include <openssl/mem.h>
 #include <openssl/type_check.h>
 #include <openssl/x509.h>
+#include <openssl/x509v3.h>
 
 #include "internal.h"
 
@@ -217,6 +218,19 @@
     return 0;
   }
 
+  /* An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
+   * certificates, so sanity-check the key usage extension. */
+  if (pkey->type == EVP_PKEY_EC) {
+    /* This call populates extension flags (ex_flags). */
+    X509_check_purpose(x, -1, 0);
+    if ((x->ex_flags & EXFLAG_KUSAGE) &&
+        !(x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+      EVP_PKEY_free(pkey);
+      return 0;
+    }
+  }
+
   if (c->privatekey != NULL) {
     /* Sanity-check that the private key and the certificate match, unless the
      * key is opaque (in case of, say, a smartcard). */
@@ -338,6 +352,8 @@
 
 static int set_signing_algorithm_prefs(CERT *cert, const uint16_t *prefs,
                                        size_t num_prefs) {
+  OPENSSL_free(cert->sigalgs);
+
   cert->num_sigalgs = 0;
   cert->sigalgs = BUF_memdup(prefs, num_prefs * sizeof(prefs[0]));
   if (cert->sigalgs == NULL) {
diff --git a/src/ssl/ssl_stat.c b/src/ssl/ssl_stat.c
index 3fdc6e5..1ed0bdf 100644
--- a/src/ssl/ssl_stat.c
+++ b/src/ssl/ssl_stat.c
@@ -476,6 +476,9 @@
     case TLS1_AD_INTERNAL_ERROR:
       return "internal error";
 
+    case SSL3_AD_INAPPROPRIATE_FALLBACK:
+      return "inappropriate fallback";
+
     case TLS1_AD_USER_CANCELLED:
       return "user canceled";
 
@@ -500,8 +503,8 @@
     case TLS1_AD_UNKNOWN_PSK_IDENTITY:
       return "unknown PSK identity";
 
-    case SSL3_AD_INAPPROPRIATE_FALLBACK:
-      return "inappropriate fallback";
+    case TLS1_AD_CERTIFICATE_REQUIRED:
+      return "certificate required";
 
     default:
       return "unknown";
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 419cce5..cfce2d0 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -924,7 +924,10 @@
     return 0;
   }
   bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
-  if (!ssl || !SSL_set_session(ssl.get(), session.get())) {
+  // Test at TLS 1.2. TLS 1.3 adds enough extensions that the ClientHello is
+  // longer than our test vectors.
+  if (!ssl || !SSL_set_session(ssl.get(), session.get()) ||
+      !SSL_set_max_proto_version(ssl.get(), TLS1_2_VERSION)) {
     return 0;
   }
   std::vector<uint8_t> client_hello;
@@ -1270,70 +1273,100 @@
   return true;
 }
 
-static bool TestSequenceNumber(bool dtls) {
-  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
-  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(dtls ? DTLS_method() : TLS_method()));
-  if (!client_ctx || !server_ctx) {
-    return false;
-  }
+static uint16_t kTLSVersions[] = {
+    SSL3_VERSION, TLS1_VERSION, TLS1_1_VERSION, TLS1_2_VERSION, TLS1_3_VERSION,
+};
 
-  bssl::UniquePtr<X509> cert = GetTestCertificate();
-  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
-  if (!cert || !key ||
-      !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
-      !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
-    return false;
-  }
+static uint16_t kDTLSVersions[] = {
+    DTLS1_VERSION, DTLS1_2_VERSION,
+};
 
-  bssl::UniquePtr<SSL> client, server;
-  if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
-                              server_ctx.get(), nullptr /* no session */)) {
-    return false;
-  }
+static bool TestSequenceNumber() {
+  for (bool is_dtls : std::vector<bool>{false, true}) {
+    const SSL_METHOD *method = is_dtls ? DTLS_method() : TLS_method();
+    const uint16_t *versions = is_dtls ? kDTLSVersions : kTLSVersions;
+    size_t num_versions = is_dtls ? OPENSSL_ARRAY_SIZE(kDTLSVersions)
+                                  : OPENSSL_ARRAY_SIZE(kTLSVersions);
+    for (size_t i = 0; i < num_versions; i++) {
+      uint16_t version = versions[i];
+      bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
+      bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
+      if (!server_ctx || !client_ctx ||
+          !SSL_CTX_set_min_proto_version(client_ctx.get(), version) ||
+          !SSL_CTX_set_max_proto_version(client_ctx.get(), version) ||
+          !SSL_CTX_set_min_proto_version(server_ctx.get(), version) ||
+          !SSL_CTX_set_max_proto_version(server_ctx.get(), version)) {
+        return false;
+      }
 
-  uint64_t client_read_seq = SSL_get_read_sequence(client.get());
-  uint64_t client_write_seq = SSL_get_write_sequence(client.get());
-  uint64_t server_read_seq = SSL_get_read_sequence(server.get());
-  uint64_t server_write_seq = SSL_get_write_sequence(server.get());
+      bssl::UniquePtr<X509> cert = GetTestCertificate();
+      bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+      if (!cert || !key ||
+          !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+          !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
+        return false;
+      }
 
-  if (dtls) {
-    // Both client and server must be at epoch 1.
-    if (EpochFromSequence(client_read_seq) != 1 ||
-        EpochFromSequence(client_write_seq) != 1 ||
-        EpochFromSequence(server_read_seq) != 1 ||
-        EpochFromSequence(server_write_seq) != 1) {
-      fprintf(stderr, "Bad epochs.\n");
-      return false;
+      bssl::UniquePtr<SSL> client, server;
+      if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
+                                  server_ctx.get(), nullptr /* no session */)) {
+        return false;
+      }
+
+      // Drain any post-handshake messages to ensure there are no unread records
+      // on either end.
+      uint8_t byte = 0;
+      if (SSL_read(client.get(), &byte, 1) > 0 ||
+          SSL_read(server.get(), &byte, 1) > 0) {
+        fprintf(stderr, "Received unexpected data.\n");
+        return false;
+      }
+
+      uint64_t client_read_seq = SSL_get_read_sequence(client.get());
+      uint64_t client_write_seq = SSL_get_write_sequence(client.get());
+      uint64_t server_read_seq = SSL_get_read_sequence(server.get());
+      uint64_t server_write_seq = SSL_get_write_sequence(server.get());
+
+      if (is_dtls) {
+        // Both client and server must be at epoch 1.
+        if (EpochFromSequence(client_read_seq) != 1 ||
+            EpochFromSequence(client_write_seq) != 1 ||
+            EpochFromSequence(server_read_seq) != 1 ||
+            EpochFromSequence(server_write_seq) != 1) {
+          fprintf(stderr, "Bad epochs.\n");
+          return false;
+        }
+
+        // The next record to be written should exceed the largest received.
+        if (client_write_seq <= server_read_seq ||
+            server_write_seq <= client_read_seq) {
+          fprintf(stderr, "Inconsistent sequence numbers.\n");
+          return false;
+        }
+      } else {
+        // The next record to be written should equal the next to be received.
+        if (client_write_seq != server_read_seq ||
+            server_write_seq != client_read_seq) {
+          fprintf(stderr, "Inconsistent sequence numbers.\n");
+          return false;
+        }
+      }
+
+      // Send a record from client to server.
+      if (SSL_write(client.get(), &byte, 1) != 1 ||
+          SSL_read(server.get(), &byte, 1) != 1) {
+        fprintf(stderr, "Could not send byte.\n");
+        return false;
+      }
+
+      // The client write and server read sequence numbers should have
+      // incremented.
+      if (client_write_seq + 1 != SSL_get_write_sequence(client.get()) ||
+          server_read_seq + 1 != SSL_get_read_sequence(server.get())) {
+        fprintf(stderr, "Sequence numbers did not increment.\n");
+        return false;
+      }
     }
-
-    // The next record to be written should exceed the largest received.
-    if (client_write_seq <= server_read_seq ||
-        server_write_seq <= client_read_seq) {
-      fprintf(stderr, "Inconsistent sequence numbers.\n");
-      return false;
-    }
-  } else {
-    // The next record to be written should equal the next to be received.
-    if (client_write_seq != server_read_seq ||
-        server_write_seq != client_write_seq) {
-      fprintf(stderr, "Inconsistent sequence numbers.\n");
-      return false;
-    }
-  }
-
-  // Send a record from client to server.
-  uint8_t byte = 0;
-  if (SSL_write(client.get(), &byte, 1) != 1 ||
-      SSL_read(server.get(), &byte, 1) != 1) {
-    fprintf(stderr, "Could not send byte.\n");
-    return false;
-  }
-
-  // The client write and server read sequence numbers should have incremented.
-  if (client_write_seq + 1 != SSL_get_write_sequence(client.get()) ||
-      server_read_seq + 1 != SSL_get_read_sequence(server.get())) {
-    fprintf(stderr, "Sequence numbers did not increment.\n");\
-    return false;
   }
 
   return true;
@@ -1596,14 +1629,6 @@
   return true;
 }
 
-static uint16_t kTLSVersions[] = {
-    SSL3_VERSION, TLS1_VERSION, TLS1_1_VERSION, TLS1_2_VERSION, TLS1_3_VERSION,
-};
-
-static uint16_t kDTLSVersions[] = {
-    DTLS1_VERSION, DTLS1_2_VERSION,
-};
-
 static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) { return 1; }
 
 static bool TestGetPeerCertificate() {
@@ -1865,7 +1890,7 @@
   }
 
   static const uint8_t kTLS12ClientHello[] = {
-      0x16, 0x03, 0x01, 0x00, 0xa2, 0x01, 0x00, 0x00, 0x9e, 0x03, 0x03, 0x00,
+      0x16, 0x03, 0x01, 0x00, 0x9e, 0x01, 0x00, 0x00, 0x9a, 0x03, 0x03, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3a, 0xcc, 0xa9,
@@ -1873,12 +1898,12 @@
       0xc0, 0x2c, 0xc0, 0x30, 0x00, 0x9f, 0xc0, 0x09, 0xc0, 0x23, 0xc0, 0x13,
       0xc0, 0x27, 0x00, 0x33, 0x00, 0x67, 0xc0, 0x0a, 0xc0, 0x24, 0xc0, 0x14,
       0xc0, 0x28, 0x00, 0x39, 0x00, 0x6b, 0x00, 0x9c, 0x00, 0x9d, 0x00, 0x2f,
-      0x00, 0x3c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x3b,
+      0x00, 0x3c, 0x00, 0x35, 0x00, 0x3d, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x37,
       0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x23, 0x00,
-      0x00, 0x00, 0x0d, 0x00, 0x18, 0x00, 0x16, 0x08, 0x06, 0x06, 0x01, 0x06,
-      0x03, 0x08, 0x05, 0x05, 0x01, 0x05, 0x03, 0x08, 0x04, 0x04, 0x01, 0x04,
-      0x03, 0x02, 0x01, 0x02, 0x03, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
-      0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
+      0x00, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x12, 0x08, 0x06, 0x06, 0x01, 0x08,
+      0x05, 0x05, 0x01, 0x05, 0x03, 0x08, 0x04, 0x04, 0x01, 0x04, 0x03, 0x02,
+      0x01, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x00, 0x08, 0x00,
+      0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
   };
   if (!ClientHelloMatches(TLS1_2_VERSION, kTLS12ClientHello,
                           sizeof(kTLS12ClientHello))) {
@@ -2324,8 +2349,7 @@
       !TestPaddingExtension() ||
       !TestClientCAList() ||
       !TestInternalSessionCache() ||
-      !TestSequenceNumber(false /* TLS */) ||
-      !TestSequenceNumber(true /* DTLS */) ||
+      !TestSequenceNumber() ||
       !TestOneSidedShutdown() ||
       !TestSessionDuplication() ||
       !TestSetFD() ||
diff --git a/src/ssl/t1_lib.c b/src/ssl/t1_lib.c
index 2aca268..9655b83 100644
--- a/src/ssl/t1_lib.c
+++ b/src/ssl/t1_lib.c
@@ -312,18 +312,8 @@
 #endif
 };
 
-void tls1_get_grouplist(SSL *ssl, int get_peer_groups,
-                        const uint16_t **out_group_ids,
+void tls1_get_grouplist(SSL *ssl, const uint16_t **out_group_ids,
                         size_t *out_group_ids_len) {
-  if (get_peer_groups) {
-    /* Only clients send a supported group list, so this function is only
-     * called on the server. */
-    assert(ssl->server);
-    *out_group_ids = ssl->s3->tmp.peer_supported_group_list;
-    *out_group_ids_len = ssl->s3->tmp.peer_supported_group_list_len;
-    return;
-  }
-
   *out_group_ids = ssl->supported_group_list;
   *out_group_ids_len = ssl->supported_group_list_len;
   if (!*out_group_ids) {
@@ -333,42 +323,35 @@
 }
 
 int tls1_get_shared_group(SSL *ssl, uint16_t *out_group_id) {
-  const uint16_t *groups, *peer_groups, *pref, *supp;
-  size_t groups_len, peer_groups_len, pref_len, supp_len, i, j;
+  assert(ssl->server);
 
-  /* Can't do anything on client side */
-  if (ssl->server == 0) {
-    return 0;
-  }
+  const uint16_t *groups, *pref, *supp;
+  size_t groups_len, pref_len, supp_len;
+  tls1_get_grouplist(ssl, &groups, &groups_len);
 
-  tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
-  tls1_get_grouplist(ssl, 1 /* peer groups */, &peer_groups, &peer_groups_len);
-
-  if (peer_groups_len == 0) {
-    /* Clients are not required to send a supported_groups extension. In this
-     * case, the server is free to pick any group it likes. See RFC 4492,
-     * section 4, paragraph 3.
-     *
-     * However, in the interests of compatibility, we will skip ECDH if the
-     * client didn't send an extension because we can't be sure that they'll
-     * support our favoured group. */
-    return 0;
-  }
+  /* Clients are not required to send a supported_groups extension. In this
+   * case, the server is free to pick any group it likes. See RFC 4492,
+   * section 4, paragraph 3.
+   *
+   * However, in the interests of compatibility, we will skip ECDH if the
+   * client didn't send an extension because we can't be sure that they'll
+   * support our favoured group. Thus we do not special-case an emtpy
+   * |peer_supported_group_list|. */
 
   if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
     pref = groups;
     pref_len = groups_len;
-    supp = peer_groups;
-    supp_len = peer_groups_len;
+    supp = ssl->s3->hs->peer_supported_group_list;
+    supp_len = ssl->s3->hs->peer_supported_group_list_len;
   } else {
-    pref = peer_groups;
-    pref_len = peer_groups_len;
+    pref = ssl->s3->hs->peer_supported_group_list;
+    pref_len = ssl->s3->hs->peer_supported_group_list_len;
     supp = groups;
     supp_len = groups_len;
   }
 
-  for (i = 0; i < pref_len; i++) {
-    for (j = 0; j < supp_len; j++) {
+  for (size_t i = 0; i < pref_len; i++) {
+    for (size_t j = 0; j < supp_len; j++) {
       if (pref[i] == supp[j]) {
         *out_group_id = pref[i];
         return 1;
@@ -445,117 +428,54 @@
   return 0;
 }
 
-/* tls1_curve_params_from_ec_key sets |*out_group_id| and |*out_comp_id| to the
- * TLS group ID and point format, respectively, for |ec|. It returns one on
- * success and zero on failure. */
-static int tls1_curve_params_from_ec_key(uint16_t *out_group_id,
-                                         uint8_t *out_comp_id, EC_KEY *ec) {
-  int nid;
-  uint16_t id;
-  const EC_GROUP *grp;
-
-  if (ec == NULL) {
-    return 0;
-  }
-
-  grp = EC_KEY_get0_group(ec);
-  if (grp == NULL) {
-    return 0;
-  }
-
-  /* Determine group ID */
-  nid = EC_GROUP_get_curve_name(grp);
-  if (!ssl_nid_to_group_id(&id, nid)) {
-    return 0;
-  }
-
-  /* Set the named group ID. Arbitrary explicit groups are not supported. */
-  *out_group_id = id;
-
-  if (out_comp_id) {
-    if (EC_KEY_get0_public_key(ec) == NULL) {
-      return 0;
-    }
-    if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) {
-      *out_comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
-    } else {
-      *out_comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
-    }
-  }
-
-  return 1;
-}
-
-/* tls1_check_group_id returns one if |group_id| is consistent with both our
- * and the peer's group preferences. Note: if called as the client, only our
- * preferences are checked; the peer (the server) does not send preferences. */
 int tls1_check_group_id(SSL *ssl, uint16_t group_id) {
   const uint16_t *groups;
-  size_t groups_len, i, get_peer_groups;
-
-  /* Check against our list, then the peer's list. */
-  for (get_peer_groups = 0; get_peer_groups <= 1; get_peer_groups++) {
-    if (get_peer_groups && !ssl->server) {
-      /* Servers do not present a preference list so, if we are a client, only
-       * check our list. */
-      continue;
-    }
-
-    tls1_get_grouplist(ssl, get_peer_groups, &groups, &groups_len);
-    if (get_peer_groups && groups_len == 0) {
-      /* Clients are not required to send a supported_groups extension. In this
-       * case, the server is free to pick any group it likes. See RFC 4492,
-       * section 4, paragraph 3. */
-      continue;
-    }
-    for (i = 0; i < groups_len; i++) {
-      if (groups[i] == group_id) {
-        break;
-      }
-    }
-
-    if (i == groups_len) {
-      return 0;
+  size_t groups_len;
+  tls1_get_grouplist(ssl, &groups, &groups_len);
+  for (size_t i = 0; i < groups_len; i++) {
+    if (groups[i] == group_id) {
+      return 1;
     }
   }
 
-  return 1;
+  return 0;
 }
 
-int tls1_check_ec_cert(SSL *ssl, X509 *x) {
-  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
-    /* In TLS 1.3, the ECDSA curve is negotiated via signature algorithms. */
-    return 1;
-  }
+/* kVerifySignatureAlgorithms is the default list of accepted signature
+ * algorithms for verifying. */
+static const uint16_t kVerifySignatureAlgorithms[] = {
+    /* For now, do not enable RSA-PSS signature algorithms on Android's system
+     * BoringSSL. Once TLS 1.3 is finalized and the change in Chrome has stuck,
+     * restore them. */
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_RSA_PSS_SHA512,
+#endif
+    SSL_SIGN_RSA_PKCS1_SHA512,
+    /* TODO(davidben): Remove this entry and SSL_CURVE_SECP521R1 from
+     * kDefaultGroups. */
+#if defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_ECDSA_SECP521R1_SHA512,
+#endif
 
-  EVP_PKEY *pkey = X509_get_pubkey(x);
-  if (pkey == NULL) {
-    return 0;
-  }
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_RSA_PSS_SHA384,
+#endif
+    SSL_SIGN_RSA_PKCS1_SHA384,
+    SSL_SIGN_ECDSA_SECP384R1_SHA384,
 
-  int ret = 0;
-  uint16_t group_id;
-  uint8_t comp_id;
-  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
-  if (ec_key == NULL ||
-      !tls1_curve_params_from_ec_key(&group_id, &comp_id, ec_key) ||
-      !tls1_check_group_id(ssl, group_id) ||
-      comp_id != TLSEXT_ECPOINTFORMAT_uncompressed) {
-    goto done;
-  }
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_RSA_PSS_SHA256,
+#endif
+    SSL_SIGN_RSA_PKCS1_SHA256,
+    SSL_SIGN_ECDSA_SECP256R1_SHA256,
 
-  ret = 1;
+    SSL_SIGN_RSA_PKCS1_SHA1,
+};
 
-done:
-  EVP_PKEY_free(pkey);
-  return ret;
-}
-
-/* List of supported signature algorithms and hashes. Should make this
- * customisable at some point, for now include everything we support. */
-
-static const uint16_t kDefaultSignatureAlgorithms[] = {
-    /* For now, do not ship RSA-PSS signature algorithms on Android's system
+/* kSignSignatureAlgorithms is the default list of supported signature
+ * algorithms for signing. */
+static const uint16_t kSignSignatureAlgorithms[] = {
+    /* For now, do not enable RSA-PSS signature algorithms on Android's system
      * BoringSSL. Once TLS 1.3 is finalized and the change in Chrome has stuck,
      * restore them. */
 #if !defined(BORINGSSL_ANDROID_SYSTEM)
@@ -580,30 +500,23 @@
     SSL_SIGN_ECDSA_SHA1,
 };
 
-size_t tls12_get_psigalgs(SSL *ssl, const uint16_t **psigs) {
-  *psigs = kDefaultSignatureAlgorithms;
-  return OPENSSL_ARRAY_SIZE(kDefaultSignatureAlgorithms);
+size_t tls12_get_verify_sigalgs(const SSL *ssl, const uint16_t **out) {
+  *out = kVerifySignatureAlgorithms;
+  return OPENSSL_ARRAY_SIZE(kVerifySignatureAlgorithms);
 }
 
 int tls12_check_peer_sigalg(SSL *ssl, int *out_alert, uint16_t sigalg) {
-  const uint16_t *sent_sigs;
-  size_t sent_sigslen, i;
-
-  /* Check signature matches a type we sent */
-  sent_sigslen = tls12_get_psigalgs(ssl, &sent_sigs);
-  for (i = 0; i < sent_sigslen; i++) {
-    if (sigalg == sent_sigs[i]) {
-      break;
+  const uint16_t *verify_sigalgs;
+  size_t num_verify_sigalgs = tls12_get_verify_sigalgs(ssl, &verify_sigalgs);
+  for (size_t i = 0; i < num_verify_sigalgs; i++) {
+    if (sigalg == verify_sigalgs[i]) {
+      return 1;
     }
   }
 
-  if (i == sent_sigslen) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
-    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
-    return 0;
-  }
-
-  return 1;
+  OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+  *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+  return 0;
 }
 
 /* Get a mask of disabled algorithms: an algorithm is disabled if it isn't
@@ -616,10 +529,10 @@
   c->mask_a = 0;
   c->mask_k = 0;
 
-  /* Now go through all signature algorithms seeing if we support any for RSA,
-   * DSA, ECDSA. Do this for all versions not just TLS 1.2. */
+  /* Now go through all signature algorithms seeing if we support any for RSA or
+   * ECDSA. Do this for all versions not just TLS 1.2. */
   const uint16_t *sigalgs;
-  size_t num_sigalgs = tls12_get_psigalgs(ssl, &sigalgs);
+  size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
   for (size_t i = 0; i < num_sigalgs; i++) {
     switch (sigalgs[i]) {
       case SSL_SIGN_RSA_PSS_SHA512:
@@ -706,10 +619,6 @@
  *
  * https://tools.ietf.org/html/rfc6066#section-3. */
 
-static void ext_sni_init(SSL *ssl) {
-  ssl->s3->tmp.should_ack_sni = 0;
-}
-
 static int ext_sni_add_clienthello(SSL *ssl, CBB *out) {
   if (ssl->tlsext_hostname == NULL) {
     return 1;
@@ -797,7 +706,7 @@
       return 0;
     }
 
-    ssl->s3->tmp.should_ack_sni = 1;
+    ssl->s3->hs->should_ack_sni = 1;
   }
 
   return 1;
@@ -805,7 +714,7 @@
 
 static int ext_sni_add_serverhello(SSL *ssl, CBB *out) {
   if (ssl->session != NULL ||
-      !ssl->s3->tmp.should_ack_sni ||
+      !ssl->s3->hs->should_ack_sni ||
       ssl->s3->new_session->tlsext_hostname == NULL) {
     return 1;
   }
@@ -834,6 +743,9 @@
     return 1;
   }
 
+  assert(ssl->s3->initial_handshake_complete ==
+         (ssl->s3->previous_client_finished_len != 0));
+
   CBB contents, prev_finished;
   if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
       !CBB_add_u16_length_prefixed(out, &contents) ||
@@ -879,6 +791,10 @@
   /* Check for logic errors */
   assert(!expected_len || ssl->s3->previous_client_finished_len);
   assert(!expected_len || ssl->s3->previous_server_finished_len);
+  assert(ssl->s3->initial_handshake_complete ==
+         (ssl->s3->previous_client_finished_len != 0));
+  assert(ssl->s3->initial_handshake_complete ==
+         (ssl->s3->previous_server_finished_len != 0));
 
   /* Parse out the extension contents. */
   CBS renegotiated_connection;
@@ -937,10 +853,9 @@
     return 0;
   }
 
-  /* Check that the extension matches */
-  if (!CBS_mem_equal(&renegotiated_connection,
-                     ssl->s3->previous_client_finished,
-                     ssl->s3->previous_client_finished_len)) {
+  /* Check that the extension matches. We do not support renegotiation as a
+   * server, so this must be empty. */
+  if (CBS_len(&renegotiated_connection) != 0) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
     *out_alert = SSL_AD_HANDSHAKE_FAILURE;
     return 0;
@@ -952,19 +867,17 @@
 }
 
 static int ext_ri_add_serverhello(SSL *ssl, CBB *out) {
+  /* Renegotiation isn't supported as a server so this function should never be
+   * called after the initial handshake. */
+  assert(!ssl->s3->initial_handshake_complete);
+
   if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
     return 1;
   }
 
-  CBB contents, prev_finished;
   if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
-      !CBB_add_u16_length_prefixed(out, &contents) ||
-      !CBB_add_u8_length_prefixed(&contents, &prev_finished) ||
-      !CBB_add_bytes(&prev_finished, ssl->s3->previous_client_finished,
-                     ssl->s3->previous_client_finished_len) ||
-      !CBB_add_bytes(&prev_finished, ssl->s3->previous_server_finished,
-                     ssl->s3->previous_server_finished_len) ||
-      !CBB_flush(out)) {
+      !CBB_add_u16(out, 1 /* length */) ||
+      !CBB_add_u8(out, 0 /* empty renegotiation info */)) {
     return 0;
   }
 
@@ -1162,7 +1075,7 @@
   }
 
   const uint16_t *sigalgs;
-  const size_t num_sigalgs = tls12_get_psigalgs(ssl, &sigalgs);
+  const size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
 
   CBB contents, sigalgs_cbb;
   if (!CBB_add_u16(out, TLSEXT_TYPE_signature_algorithms) ||
@@ -1211,7 +1124,6 @@
  * https://tools.ietf.org/html/rfc6066#section-8 */
 
 static void ext_ocsp_init(SSL *ssl) {
-  ssl->s3->tmp.certificate_status_expected = 0;
   ssl->tlsext_status_type = -1;
 }
 
@@ -1251,7 +1163,7 @@
      * status_request here does not make sense, but OpenSSL does so and the
      * specification does not say anything. Tolerate it but ignore it. */
 
-    ssl->s3->tmp.certificate_status_expected = 1;
+    ssl->s3->hs->certificate_status_expected = 1;
     return 1;
   }
 
@@ -1292,13 +1204,13 @@
 
   /* We cannot decide whether OCSP stapling will occur yet because the correct
    * SSL_CTX might not have been selected. */
-  ssl->s3->tmp.ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp;
+  ssl->s3->hs->ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp;
 
   return 1;
 }
 
 static int ext_ocsp_add_serverhello(SSL *ssl, CBB *out) {
-  if (!ssl->s3->tmp.ocsp_stapling_requested ||
+  if (!ssl->s3->hs->ocsp_stapling_requested ||
       ssl->ctx->ocsp_response_length == 0 ||
       ssl->s3->session_reused ||
       (ssl3_protocol_version(ssl) < TLS1_3_VERSION &&
@@ -1312,7 +1224,7 @@
       return 1;
     }
 
-    ssl->s3->tmp.certificate_status_expected = 1;
+    ssl->s3->hs->certificate_status_expected = 1;
 
     return CBB_add_u16(out, TLSEXT_TYPE_status_request) &&
            CBB_add_u16(out, 0 /* length */);
@@ -1333,10 +1245,6 @@
  *
  * https://htmlpreview.github.io/?https://github.com/agl/technotes/blob/master/nextprotoneg.html */
 
-static void ext_npn_init(SSL *ssl) {
-  ssl->s3->next_proto_neg_seen = 0;
-}
-
 static int ext_npn_add_clienthello(SSL *ssl, CBB *out) {
   if (ssl->s3->initial_handshake_complete ||
       ssl->ctx->next_proto_select_cb == NULL ||
@@ -1406,7 +1314,7 @@
   }
 
   ssl->s3->next_proto_negotiated_len = selected_len;
-  ssl->s3->next_proto_neg_seen = 1;
+  ssl->s3->hs->next_proto_neg_seen = 1;
 
   return 1;
 }
@@ -1432,14 +1340,14 @@
     return 1;
   }
 
-  ssl->s3->next_proto_neg_seen = 1;
+  ssl->s3->hs->next_proto_neg_seen = 1;
   return 1;
 }
 
 static int ext_npn_add_serverhello(SSL *ssl, CBB *out) {
   /* |next_proto_neg_seen| might have been cleared when an ALPN extension was
    * parsed. */
-  if (!ssl->s3->next_proto_neg_seen) {
+  if (!ssl->s3->hs->next_proto_neg_seen) {
     return 1;
   }
 
@@ -1449,7 +1357,7 @@
   if (ssl->ctx->next_protos_advertised_cb(
           ssl, &npa, &npa_len, ssl->ctx->next_protos_advertised_cb_arg) !=
       SSL_TLSEXT_ERR_OK) {
-    ssl->s3->next_proto_neg_seen = 0;
+    ssl->s3->hs->next_proto_neg_seen = 0;
     return 1;
   }
 
@@ -1572,7 +1480,7 @@
   assert(!ssl->s3->initial_handshake_complete);
   assert(ssl->alpn_client_proto_list != NULL);
 
-  if (ssl->s3->next_proto_neg_seen) {
+  if (ssl->s3->hs->next_proto_neg_seen) {
     /* NPN and ALPN may not be negotiated in the same connection. */
     *out_alert = SSL_AD_ILLEGAL_PARAMETER;
     OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
@@ -1638,7 +1546,7 @@
   }
 
   /* ALPN takes precedence over NPN. */
-  ssl->s3->next_proto_neg_seen = 0;
+  ssl->s3->hs->next_proto_neg_seen = 0;
 
   CBS protocol_name_list;
   if (!CBS_get_u16_length_prefixed(contents, &protocol_name_list) ||
@@ -2023,7 +1931,7 @@
 
 /* Pre Shared Key
  *
- * https://tools.ietf.org/html/draft-ietf-tls-tls13-15 */
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.6 */
 
 static int ext_pre_shared_key_add_clienthello(SSL *ssl, CBB *out) {
   uint16_t min_version, max_version;
@@ -2125,7 +2033,7 @@
 
 /* Key Share
  *
- * https://tools.ietf.org/html/draft-ietf-tls-tls13-12 */
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.5 */
 
 static int ext_key_share_add_clienthello(SSL *ssl, CBB *out) {
   uint16_t min_version, max_version;
@@ -2133,7 +2041,7 @@
     return 0;
   }
 
-  if (max_version < TLS1_3_VERSION || !ssl_any_ec_cipher_suites_enabled(ssl)) {
+  if (max_version < TLS1_3_VERSION) {
     return 1;
   }
 
@@ -2145,8 +2053,8 @@
   }
 
   uint16_t group_id;
-  if (ssl->s3->hs->retry_group) {
-    /* Append the new key share to the old list. */
+  if (ssl->s3->hs->received_hello_retry_request) {
+    /* Replay the old key shares. */
     if (!CBB_add_bytes(&kse_bytes, ssl->s3->hs->key_share_bytes,
                        ssl->s3->hs->key_share_bytes_len)) {
       return 0;
@@ -2156,6 +2064,12 @@
     ssl->s3->hs->key_share_bytes_len = 0;
 
     group_id = ssl->s3->hs->retry_group;
+
+    /* We received a HelloRetryRequest without a new curve, so there is no new
+     * share to append. Leave |ecdh_ctx| as-is. */
+    if (group_id == 0) {
+      return CBB_flush(out);
+    }
   } else {
     /* Add a fake group. See draft-davidben-tls-grease-01. */
     if (ssl->ctx->grease_enabled &&
@@ -2169,7 +2083,7 @@
     /* Predict the most preferred group. */
     const uint16_t *groups;
     size_t groups_len;
-    tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
+    tls1_get_grouplist(ssl, &groups, &groups_len);
     if (groups_len == 0) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_NO_GROUPS_SPECIFIED);
       return 0;
@@ -2187,7 +2101,7 @@
     return 0;
   }
 
-  if (!ssl->s3->hs->retry_group) {
+  if (!ssl->s3->hs->received_hello_retry_request) {
     /* Save the contents of the extension to repeat it in the second
      * ClientHello. */
     ssl->s3->hs->key_share_bytes_len = CBB_len(&kse_bytes);
@@ -2373,16 +2287,36 @@
 }
 
 
+/* Cookie
+ *
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.2 */
+
+static int ext_cookie_add_clienthello(SSL *ssl, CBB *out) {
+  if (ssl->s3->hs->cookie == NULL) {
+    return 1;
+  }
+
+  CBB contents, cookie;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_cookie) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u16_length_prefixed(&contents, &cookie) ||
+      !CBB_add_bytes(&cookie, ssl->s3->hs->cookie, ssl->s3->hs->cookie_len) ||
+      !CBB_flush(out)) {
+    return 0;
+  }
+
+  /* The cookie is no longer needed in memory. */
+  OPENSSL_free(ssl->s3->hs->cookie);
+  ssl->s3->hs->cookie = NULL;
+  ssl->s3->hs->cookie_len = 0;
+  return 1;
+}
+
+
 /* Negotiated Groups
  *
  * https://tools.ietf.org/html/rfc4492#section-5.1.2
- * https://tools.ietf.org/html/draft-ietf-tls-tls13-12#section-6.3.2.2 */
-
-static void ext_supported_groups_init(SSL *ssl) {
-  OPENSSL_free(ssl->s3->tmp.peer_supported_group_list);
-  ssl->s3->tmp.peer_supported_group_list = NULL;
-  ssl->s3->tmp.peer_supported_group_list_len = 0;
-}
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.4 */
 
 static int ext_supported_groups_add_clienthello(SSL *ssl, CBB *out) {
   if (!ssl_any_ec_cipher_suites_enabled(ssl)) {
@@ -2405,7 +2339,7 @@
 
   const uint16_t *groups;
   size_t groups_len;
-  tls1_get_grouplist(ssl, 0, &groups, &groups_len);
+  tls1_get_grouplist(ssl, &groups, &groups_len);
 
   for (size_t i = 0; i < groups_len; i++) {
     if (!CBB_add_u16(&groups_bytes, groups[i])) {
@@ -2437,9 +2371,9 @@
     return 0;
   }
 
-  ssl->s3->tmp.peer_supported_group_list = OPENSSL_malloc(
+  ssl->s3->hs->peer_supported_group_list = OPENSSL_malloc(
       CBS_len(&supported_group_list));
-  if (ssl->s3->tmp.peer_supported_group_list == NULL) {
+  if (ssl->s3->hs->peer_supported_group_list == NULL) {
     *out_alert = SSL_AD_INTERNAL_ERROR;
     return 0;
   }
@@ -2447,19 +2381,19 @@
   const size_t num_groups = CBS_len(&supported_group_list) / 2;
   for (size_t i = 0; i < num_groups; i++) {
     if (!CBS_get_u16(&supported_group_list,
-                     &ssl->s3->tmp.peer_supported_group_list[i])) {
+                     &ssl->s3->hs->peer_supported_group_list[i])) {
       goto err;
     }
   }
 
   assert(CBS_len(&supported_group_list) == 0);
-  ssl->s3->tmp.peer_supported_group_list_len = num_groups;
+  ssl->s3->hs->peer_supported_group_list_len = num_groups;
 
   return 1;
 
 err:
-  OPENSSL_free(ssl->s3->tmp.peer_supported_group_list);
-  ssl->s3->tmp.peer_supported_group_list = NULL;
+  OPENSSL_free(ssl->s3->hs->peer_supported_group_list);
+  ssl->s3->hs->peer_supported_group_list = NULL;
   *out_alert = SSL_AD_INTERNAL_ERROR;
   return 0;
 }
@@ -2482,7 +2416,7 @@
   },
   {
     TLSEXT_TYPE_server_name,
-    ext_sni_init,
+    NULL,
     ext_sni_add_clienthello,
     ext_sni_parse_serverhello,
     ext_sni_parse_clienthello,
@@ -2523,7 +2457,7 @@
   },
   {
     TLSEXT_TYPE_next_proto_neg,
-    ext_npn_init,
+    NULL,
     ext_npn_add_clienthello,
     ext_npn_parse_serverhello,
     ext_npn_parse_clienthello,
@@ -2593,12 +2527,20 @@
     ignore_parse_clienthello,
     dont_add_serverhello,
   },
+  {
+    TLSEXT_TYPE_cookie,
+    NULL,
+    ext_cookie_add_clienthello,
+    forbid_parse_serverhello,
+    ignore_parse_clienthello,
+    dont_add_serverhello,
+  },
   /* The final extension must be non-empty. WebSphere Application Server 7.0 is
    * intolerant to the last extension being zero-length. See
    * https://crbug.com/363583. */
   {
     TLSEXT_TYPE_supported_groups,
-    ext_supported_groups_init,
+    NULL,
     ext_supported_groups_add_clienthello,
     ext_supported_groups_parse_serverhello,
     ext_supported_groups_parse_clienthello,
@@ -2609,12 +2551,11 @@
 #define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
 
 OPENSSL_COMPILE_ASSERT(kNumExtensions <=
-                           sizeof(((SSL *)NULL)->s3->tmp.extensions.sent) * 8,
+                           sizeof(((SSL_HANDSHAKE *)NULL)->extensions.sent) * 8,
                        too_many_extensions_for_sent_bitset);
-OPENSSL_COMPILE_ASSERT(kNumExtensions <=
-                           sizeof(((SSL *)NULL)->s3->tmp.extensions.received) *
-                               8,
-                       too_many_extensions_for_received_bitset);
+OPENSSL_COMPILE_ASSERT(
+    kNumExtensions <= sizeof(((SSL_HANDSHAKE *)NULL)->extensions.received) * 8,
+    too_many_extensions_for_received_bitset);
 
 static const struct tls_extension *tls_extension_find(uint32_t *out_index,
                                                       uint16_t value) {
@@ -2647,8 +2588,8 @@
     goto err;
   }
 
-  ssl->s3->tmp.extensions.sent = 0;
-  ssl->s3->tmp.custom_extensions.sent = 0;
+  ssl->s3->hs->extensions.sent = 0;
+  ssl->s3->hs->custom_extensions.sent = 0;
 
   for (size_t i = 0; i < kNumExtensions; i++) {
     if (kExtensions[i].init != NULL) {
@@ -2675,7 +2616,7 @@
     }
 
     if (CBB_len(&extensions) != len_before) {
-      ssl->s3->tmp.extensions.sent |= (1u << i);
+      ssl->s3->hs->extensions.sent |= (1u << i);
     }
   }
 
@@ -2750,7 +2691,7 @@
 
   unsigned i;
   for (i = 0; i < kNumExtensions; i++) {
-    if (!(ssl->s3->tmp.extensions.received & (1u << i))) {
+    if (!(ssl->s3->hs->extensions.received & (1u << i))) {
       /* Don't send extensions that were not received. */
       continue;
     }
@@ -2788,8 +2729,8 @@
     }
   }
 
-  ssl->s3->tmp.extensions.received = 0;
-  ssl->s3->tmp.custom_extensions.received = 0;
+  ssl->s3->hs->extensions.received = 0;
+  ssl->s3->hs->custom_extensions.received = 0;
 
   CBS extensions;
   CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
@@ -2822,7 +2763,7 @@
       continue;
     }
 
-    ssl->s3->tmp.extensions.received |= (1u << ext_index);
+    ssl->s3->hs->extensions.received |= (1u << ext_index);
     uint8_t alert = SSL_AD_DECODE_ERROR;
     if (!ext->parse_clienthello(ssl, &alert, &extension)) {
       *out_alert = alert;
@@ -2833,7 +2774,7 @@
   }
 
   for (size_t i = 0; i < kNumExtensions; i++) {
-    if (ssl->s3->tmp.extensions.received & (1u << i)) {
+    if (ssl->s3->hs->extensions.received & (1u << i)) {
       continue;
     }
 
@@ -2847,7 +2788,7 @@
       CBS_init(&fake_contents, kFakeRenegotiateExtension,
                sizeof(kFakeRenegotiateExtension));
       contents = &fake_contents;
-      ssl->s3->tmp.extensions.received |= (1u << i);
+      ssl->s3->hs->extensions.received |= (1u << i);
     }
 
     /* Extension wasn't observed so call the callback with a NULL
@@ -2919,7 +2860,7 @@
       continue;
     }
 
-    if (!(ssl->s3->tmp.extensions.sent & (1u << ext_index)) &&
+    if (!(ssl->s3->hs->extensions.sent & (1u << ext_index)) &&
         type != TLSEXT_TYPE_renegotiate) {
       /* If the extension was never sent then it is illegal, except for the
        * renegotiation extension which, in SSL 3.0, is signaled via SCSV. */
@@ -2979,7 +2920,7 @@
       return 1;
 
     case SSL_TLSEXT_ERR_NOACK:
-      ssl->s3->tmp.should_ack_sni = 0;
+      ssl->s3->hs->should_ack_sni = 0;
       return 1;
 
     default:
@@ -3226,11 +3167,11 @@
     return 0;
   }
 
-  const uint16_t *sigalgs;
-  size_t num_sigalgs = tls12_get_psigalgs(ssl, &sigalgs);
-  if (cert->sigalgs != NULL) {
-    sigalgs = cert->sigalgs;
-    num_sigalgs = cert->num_sigalgs;
+  const uint16_t *sigalgs = cert->sigalgs;
+  size_t num_sigalgs = cert->num_sigalgs;
+  if (sigalgs == NULL) {
+    sigalgs = kSignSignatureAlgorithms;
+    num_sigalgs = OPENSSL_ARRAY_SIZE(kSignSignatureAlgorithms);
   }
 
   const uint16_t *peer_sigalgs = hs->peer_sigalgs;
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index c4407da..76caa4e 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -33,7 +33,7 @@
 #include <ws2tcpip.h>
 OPENSSL_MSVC_PRAGMA(warning(pop))
 
-#pragma comment(lib, "Ws2_32.lib")
+OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
 #endif
 
 #include <assert.h>
@@ -603,6 +603,31 @@
 }
 
 static int CertCallback(SSL *ssl, void *arg) {
+  const TestConfig *config = GetTestConfig(ssl);
+
+  // Check the CertificateRequest metadata is as expected.
+  //
+  // TODO(davidben): Test |SSL_get_client_CA_list|.
+  if (!SSL_is_server(ssl) &&
+      !config->expected_certificate_types.empty()) {
+    const uint8_t *certificate_types;
+    size_t certificate_types_len =
+        SSL_get0_certificate_types(ssl, &certificate_types);
+    if (certificate_types_len != config->expected_certificate_types.size() ||
+        memcmp(certificate_types,
+               config->expected_certificate_types.data(),
+               certificate_types_len) != 0) {
+      fprintf(stderr, "certificate types mismatch\n");
+      return 0;
+    }
+  }
+
+  // The certificate will be installed via other means.
+  if (!config->async || config->use_early_callback ||
+      config->use_old_client_cert_callback) {
+    return 1;
+  }
+
   if (!GetTestState(ssl)->cert_ready) {
     return -1;
   }
@@ -1153,19 +1178,6 @@
     }
   }
 
-  if (!config->expected_certificate_types.empty()) {
-    const uint8_t *certificate_types;
-    size_t certificate_types_len =
-        SSL_get0_certificate_types(ssl, &certificate_types);
-    if (certificate_types_len != config->expected_certificate_types.size() ||
-        memcmp(certificate_types,
-               config->expected_certificate_types.data(),
-               certificate_types_len) != 0) {
-      fprintf(stderr, "certificate types mismatch\n");
-      return false;
-    }
-  }
-
   if (!config->expected_next_proto.empty()) {
     const uint8_t *next_proto;
     unsigned next_proto_len;
@@ -1309,13 +1321,14 @@
       !SSL_set_mode(ssl.get(), SSL_MODE_SEND_FALLBACK_SCSV)) {
     return false;
   }
-  if (!config->use_early_callback && !config->use_old_client_cert_callback) {
-    if (config->async) {
-      SSL_set_cert_cb(ssl.get(), CertCallback, NULL);
-    } else if (!InstallCertificate(ssl.get())) {
-      return false;
-    }
+  // Install the certificate synchronously if nothing else will handle it.
+  if (!config->use_early_callback &&
+      !config->use_old_client_cert_callback &&
+      !config->async &&
+      !InstallCertificate(ssl.get())) {
+    return false;
   }
+  SSL_set_cert_cb(ssl.get(), CertCallback, nullptr);
   if (config->require_any_client_certificate) {
     SSL_set_verify(ssl.get(), SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
                    NULL);
diff --git a/src/ssl/test/runner/alert.go b/src/ssl/test/runner/alert.go
index b690c6f..8320b7e 100644
--- a/src/ssl/test/runner/alert.go
+++ b/src/ssl/test/runner/alert.go
@@ -43,6 +43,7 @@
 	alertUnsupportedExtension   alert = 110
 	alertUnrecognizedName       alert = 112
 	alertUnknownPSKIdentity     alert = 115
+	alertCertificateRequired    alert = 116
 )
 
 var alertText = map[alert]string{
@@ -73,6 +74,7 @@
 	alertUnsupportedExtension:   "unsupported extension",
 	alertUnrecognizedName:       "unrecognized name",
 	alertUnknownPSKIdentity:     "unknown PSK identity",
+	alertCertificateRequired:    "certificate required",
 }
 
 func (e alert) String() string {
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 309cd82..62c8dd3 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -27,7 +27,7 @@
 )
 
 // A draft version of TLS 1.3 that is sent over the wire for the current draft.
-const tls13DraftVersion = 0x7f0f
+const tls13DraftVersion = 0x7f10
 
 const (
 	maxPlaintext        = 16384        // maximum plaintext payload length
@@ -57,8 +57,8 @@
 	typeServerHello         uint8 = 2
 	typeHelloVerifyRequest  uint8 = 3
 	typeNewSessionTicket    uint8 = 4
-	typeHelloRetryRequest   uint8 = 6 // draft-ietf-tls-tls13-13
-	typeEncryptedExtensions uint8 = 8 // draft-ietf-tls-tls13-13
+	typeHelloRetryRequest   uint8 = 6 // draft-ietf-tls-tls13-16
+	typeEncryptedExtensions uint8 = 8 // draft-ietf-tls-tls13-16
 	typeCertificate         uint8 = 11
 	typeServerKeyExchange   uint8 = 12
 	typeCertificateRequest  uint8 = 13
@@ -67,7 +67,7 @@
 	typeClientKeyExchange   uint8 = 16
 	typeFinished            uint8 = 20
 	typeCertificateStatus   uint8 = 22
-	typeKeyUpdate           uint8 = 24  // draft-ietf-tls-tls13-13
+	typeKeyUpdate           uint8 = 24  // draft-ietf-tls-tls13-16
 	typeNextProtocol        uint8 = 67  // Not IANA assigned
 	typeChannelID           uint8 = 203 // Not IANA assigned
 )
@@ -89,17 +89,22 @@
 	extensionSignedCertificateTimestamp uint16 = 18
 	extensionExtendedMasterSecret       uint16 = 23
 	extensionSessionTicket              uint16 = 35
-	extensionKeyShare                   uint16 = 40    // draft-ietf-tls-tls13-13
-	extensionPreSharedKey               uint16 = 41    // draft-ietf-tls-tls13-13
-	extensionEarlyData                  uint16 = 42    // draft-ietf-tls-tls13-13
+	extensionKeyShare                   uint16 = 40    // draft-ietf-tls-tls13-16
+	extensionPreSharedKey               uint16 = 41    // draft-ietf-tls-tls13-16
+	extensionEarlyData                  uint16 = 42    // draft-ietf-tls-tls13-16
 	extensionSupportedVersions          uint16 = 43    // draft-ietf-tls-tls13-16
-	extensionCookie                     uint16 = 44    // draft-ietf-tls-tls13-13
+	extensionCookie                     uint16 = 44    // draft-ietf-tls-tls13-16
 	extensionCustom                     uint16 = 1234  // not IANA assigned
 	extensionNextProtoNeg               uint16 = 13172 // not IANA assigned
 	extensionRenegotiationInfo          uint16 = 0xff01
 	extensionChannelID                  uint16 = 30032 // not IANA assigned
 )
 
+// TLS ticket extension numbers
+const (
+	ticketExtensionCustom uint16 = 1234 // not IANA assigned
+)
+
 // TLS signaling cipher suite values
 const (
 	scsvRenegotiation uint16 = 0x00ff
@@ -189,18 +194,24 @@
 	SRTP_AES128_CM_HMAC_SHA1_32        = 0x0002
 )
 
-// PskKeyExchangeMode values (see draft-ietf-tls-tls13-15)
+// PskKeyExchangeMode values (see draft-ietf-tls-tls13-16)
 const (
 	pskKEMode    = 0
 	pskDHEKEMode = 1
 )
 
-// PskAuthenticationMode values (see draft-ietf-tls-tls13-15)
+// PskAuthenticationMode values (see draft-ietf-tls-tls13-16)
 const (
 	pskAuthMode     = 0
 	pskSignAuthMode = 1
 )
 
+// KeyUpdateRequest values (see draft-ietf-tls-tls13-16, section 4.5.3)
+const (
+	keyUpdateNotRequested = 0
+	keyUpdateRequested    = 1
+)
+
 // ConnectionState records basic TLS details about the connection.
 type ConnectionState struct {
 	Version                    uint16                // TLS version used by the connection (e.g. VersionTLS12)
@@ -458,11 +469,6 @@
 	// than the negotiated one.
 	SendCurve CurveID
 
-	// SendHelloRetryRequestCurve, if non-zero, causes the server to send
-	// the specified curve in HelloRetryRequest rather than the negotiated
-	// one.
-	SendHelloRetryRequestCurve CurveID
-
 	// InvalidECDHPoint, if true, causes the ECC points in
 	// ServerKeyExchange or ClientKeyExchange messages to be invalid.
 	InvalidECDHPoint bool
@@ -883,10 +889,22 @@
 	// that will be added to client/server hellos.
 	CustomExtension string
 
+	// CustomUnencryptedExtension, if not empty, contains the contents of
+	// an extension that will be added to ServerHello in TLS 1.3.
+	CustomUnencryptedExtension string
+
 	// ExpectedCustomExtension, if not nil, contains the expected contents
 	// of a custom extension.
 	ExpectedCustomExtension *string
 
+	// CustomTicketExtension, if not empty, contains the contents of an
+	// extension what will be added to NewSessionTicket in TLS 1.3.
+	CustomTicketExtension string
+
+	// CustomTicketExtension, if not empty, contains the contents of an
+	// extension what will be added to HelloRetryRequest in TLS 1.3.
+	CustomHelloRetryRequestExtension string
+
 	// NoCloseNotify, if true, causes the close_notify alert to be skipped
 	// on connection shutdown.
 	NoCloseNotify bool
@@ -913,6 +931,10 @@
 	// the client offer.
 	SendALPN string
 
+	// SendUnencryptedALPN, if non-empty, causes the server to send the
+	// specified string in a ServerHello ALPN extension in TLS 1.3.
+	SendUnencryptedALPN string
+
 	// SendEmptySessionTicket, if true, causes the server to send an empty
 	// session ticket.
 	SendEmptySessionTicket bool
@@ -939,10 +961,6 @@
 	// message. This only makes sense for a server.
 	SendHelloRequestBeforeEveryHandshakeMessage bool
 
-	// SendKeyUpdateBeforeEveryAppDataRecord, if true, causes a KeyUpdate
-	// handshake message to be sent before each application data record.
-	SendKeyUpdateBeforeEveryAppDataRecord bool
-
 	// RequireDHPublicValueLen causes a fatal error if the length (in
 	// bytes) of the server's Diffie-Hellman public value is not equal to
 	// this.
@@ -1073,14 +1091,26 @@
 	// include the KeyShare extension in the EncryptedExtensions block.
 	EncryptedExtensionsWithKeyShare bool
 
-	// UnnecessaryHelloRetryRequest, if true, causes the TLS 1.3 server to
-	// send a HelloRetryRequest regardless of whether it needs to.
-	UnnecessaryHelloRetryRequest bool
+	// AlwaysSendHelloRetryRequest, if true, causes a HelloRetryRequest to
+	// be sent by the server, even if empty.
+	AlwaysSendHelloRetryRequest bool
 
 	// SecondHelloRetryRequest, if true, causes the TLS 1.3 server to send
 	// two HelloRetryRequests instead of one.
 	SecondHelloRetryRequest bool
 
+	// SendHelloRetryRequestCurve, if non-zero, causes the server to send
+	// the specified curve in a HelloRetryRequest.
+	SendHelloRetryRequestCurve CurveID
+
+	// SendHelloRetryRequestCookie, if not nil, contains a cookie to be
+	// sent by the server in HelloRetryRequest.
+	SendHelloRetryRequestCookie []byte
+
+	// DuplicateHelloRetryRequestExtensions, if true, causes all
+	// HelloRetryRequest extensions to be sent twice.
+	DuplicateHelloRetryRequestExtensions bool
+
 	// SendServerHelloVersion, if non-zero, causes the server to send the
 	// specified value in ServerHello version field.
 	SendServerHelloVersion uint16
@@ -1127,8 +1157,8 @@
 	// invalid Channel ID signature.
 	InvalidChannelIDSignature bool
 
-	// ExpectGREASE, if true, causes the server to reject a ClientHello
-	// unless it contains GREASE values. See draft-davidben-tls-grease-01.
+	// ExpectGREASE, if true, causes messages without GREASE values to be
+	// rejected. See draft-davidben-tls-grease-01.
 	ExpectGREASE bool
 }
 
@@ -1505,7 +1535,7 @@
 }
 
 var (
-	// See draft-ietf-tls-tls13-13, section 6.3.1.2.
+	// See draft-ietf-tls-tls13-16, section 6.3.1.2.
 	downgradeTLS13 = []byte{0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01}
 	downgradeTLS12 = []byte{0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x00}
 )
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index 84e1eb8..f5014d4 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -92,6 +92,8 @@
 	handMsgLen       int      // handshake message length, not including the header
 	pendingFragments [][]byte // pending outgoing handshake fragments.
 
+	keyUpdateRequested bool
+
 	tmp [16]byte
 }
 
@@ -159,8 +161,7 @@
 	// used to save allocating a new buffer for each MAC.
 	inDigestBuf, outDigestBuf []byte
 
-	trafficSecret       []byte
-	keyUpdateGeneration int
+	trafficSecret []byte
 
 	config *Config
 }
@@ -223,7 +224,6 @@
 		side = clientWrite
 	}
 	hc.useTrafficSecret(hc.version, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), hc.trafficSecret), applicationPhase, side)
-	hc.keyUpdateGeneration++
 }
 
 // incSeq increments the sequence number.
@@ -1328,11 +1328,11 @@
 		return 0, alertInternalError
 	}
 
-	// Catch up with KeyUpdates from the peer.
-	for c.out.keyUpdateGeneration < c.in.keyUpdateGeneration {
-		if err := c.sendKeyUpdateLocked(); err != nil {
+	if c.keyUpdateRequested {
+		if err := c.sendKeyUpdateLocked(keyUpdateNotRequested); err != nil {
 			return 0, err
 		}
+		c.keyUpdateRequested = false
 	}
 
 	if c.config.Bugs.SendSpuriousAlert != 0 {
@@ -1344,12 +1344,6 @@
 		c.flushHandshake()
 	}
 
-	if c.config.Bugs.SendKeyUpdateBeforeEveryAppDataRecord {
-		if err := c.sendKeyUpdateLocked(); err != nil {
-			return 0, err
-		}
-	}
-
 	// SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
 	// attack when using block mode ciphers due to predictable IVs.
 	// This can be prevented by splitting each Application Data
@@ -1398,6 +1392,10 @@
 
 	if c.isClient {
 		if newSessionTicket, ok := msg.(*newSessionTicketMsg); ok {
+			if c.config.Bugs.ExpectGREASE && !newSessionTicket.hasGREASEExtension {
+				return errors.New("tls: no GREASE ticket extension found")
+			}
+
 			if c.config.ClientSessionCache == nil || newSessionTicket.ticketLifetime == 0 {
 				return nil
 			}
@@ -1437,8 +1435,11 @@
 		}
 	}
 
-	if _, ok := msg.(*keyUpdateMsg); ok {
+	if keyUpdate, ok := msg.(*keyUpdateMsg); ok {
 		c.in.doKeyUpdate(c, false)
+		if keyUpdate.keyUpdateRequest == keyUpdateRequested {
+			c.keyUpdateRequested = true
+		}
 		return nil
 	}
 
@@ -1710,10 +1711,11 @@
 
 	// TODO(davidben): Allow configuring these values.
 	m := &newSessionTicketMsg{
-		version:        c.vers,
-		ticketLifetime: uint32(24 * time.Hour / time.Second),
-		keModes:        []byte{pskDHEKEMode},
-		authModes:      []byte{pskAuthMode},
+		version:         c.vers,
+		ticketLifetime:  uint32(24 * time.Hour / time.Second),
+		keModes:         []byte{pskDHEKEMode},
+		authModes:       []byte{pskAuthMode},
+		customExtension: c.config.Bugs.CustomTicketExtension,
 	}
 
 	if len(c.config.Bugs.SendPSKKeyExchangeModes) != 0 {
@@ -1746,18 +1748,20 @@
 	return err
 }
 
-func (c *Conn) SendKeyUpdate() error {
+func (c *Conn) SendKeyUpdate(keyUpdateRequest byte) error {
 	c.out.Lock()
 	defer c.out.Unlock()
-	return c.sendKeyUpdateLocked()
+	return c.sendKeyUpdateLocked(keyUpdateRequest)
 }
 
-func (c *Conn) sendKeyUpdateLocked() error {
+func (c *Conn) sendKeyUpdateLocked(keyUpdateRequest byte) error {
 	if c.vers < VersionTLS13 {
 		return errors.New("tls: attempted to send KeyUpdate before TLS 1.3")
 	}
 
-	m := new(keyUpdateMsg)
+	m := keyUpdateMsg{
+		keyUpdateRequest: keyUpdateRequest,
+	}
 	if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
 		return err
 	}
diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json
index 94903c5..8fc1a56 100644
--- a/src/ssl/test/runner/fuzzer_mode.json
+++ b/src/ssl/test/runner/fuzzer_mode.json
@@ -15,6 +15,8 @@
     "CECPQ1-*-BadX25519Part": "Fuzzer mode does not notice a bad premaster secret.",
 
     "TrailingMessageData-TLS13-ServerHello": "Fuzzer mode will not read the peer's alert as a MAC error",
+    "UnexpectedUnencryptedExtension-Client-TLS13": "Fuzzer mode will not read the peer's alert as a MAC error",
+    "UnknownUnencryptedExtension-Client-TLS13": "Fuzzer mode will not read the peer's alert as a MAC error",
     "WrongMessageType-TLS13-ServerHello": "Fuzzer mode will not read the peer's alert as a MAC error",
 
     "*Auth-Verify-RSA-PKCS1-*-TLS13": "Fuzzer mode always accepts a signature.",
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index c5be2b7..ae3228a 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -389,34 +389,41 @@
 	helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
 	var secondHelloBytes []byte
 	if haveHelloRetryRequest {
-		var hrrCurveFound bool
+		if len(helloRetryRequest.cookie) > 0 {
+			hello.tls13Cookie = helloRetryRequest.cookie
+		}
+
 		if c.config.Bugs.MisinterpretHelloRetryRequestCurve != 0 {
+			helloRetryRequest.hasSelectedGroup = true
 			helloRetryRequest.selectedGroup = c.config.Bugs.MisinterpretHelloRetryRequestCurve
 		}
-		group := helloRetryRequest.selectedGroup
-		for _, curveID := range hello.supportedCurves {
-			if group == curveID {
-				hrrCurveFound = true
-				break
+		if helloRetryRequest.hasSelectedGroup {
+			var hrrCurveFound bool
+			group := helloRetryRequest.selectedGroup
+			for _, curveID := range hello.supportedCurves {
+				if group == curveID {
+					hrrCurveFound = true
+					break
+				}
 			}
+			if !hrrCurveFound || keyShares[group] != nil {
+				c.sendAlert(alertHandshakeFailure)
+				return errors.New("tls: received invalid HelloRetryRequest")
+			}
+			curve, ok := curveForCurveID(group)
+			if !ok {
+				return errors.New("tls: Unable to get curve requested in HelloRetryRequest")
+			}
+			publicKey, err := curve.offer(c.config.rand())
+			if err != nil {
+				return err
+			}
+			keyShares[group] = curve
+			hello.keyShares = append(hello.keyShares, keyShareEntry{
+				group:       group,
+				keyExchange: publicKey,
+			})
 		}
-		if !hrrCurveFound || keyShares[group] != nil {
-			c.sendAlert(alertHandshakeFailure)
-			return errors.New("tls: received invalid HelloRetryRequest")
-		}
-		curve, ok := curveForCurveID(group)
-		if !ok {
-			return errors.New("tls: Unable to get curve requested in HelloRetryRequest")
-		}
-		publicKey, err := curve.offer(c.config.rand())
-		if err != nil {
-			return err
-		}
-		keyShares[group] = curve
-		hello.keyShares = append(hello.keyShares, keyShareEntry{
-			group:       group,
-			keyExchange: publicKey,
-		})
 
 		if c.config.Bugs.SecondClientHelloMissingKeyShare {
 			hello.hasKeyShares = false
@@ -448,7 +455,7 @@
 	}
 
 	// Check for downgrade signals in the server random, per
-	// draft-ietf-tls-tls13-14, section 6.3.1.2.
+	// draft-ietf-tls-tls13-16, section 4.1.3.
 	if c.vers <= VersionTLS12 && c.config.maxVersion(c.isDTLS) >= VersionTLS13 {
 		if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS13) {
 			c.sendAlert(alertProtocolVersion)
@@ -468,7 +475,7 @@
 		return fmt.Errorf("tls: server selected an unsupported cipher suite")
 	}
 
-	if haveHelloRetryRequest && (helloRetryRequest.cipherSuite != serverHello.cipherSuite || helloRetryRequest.selectedGroup != serverHello.keyShare.group) {
+	if haveHelloRetryRequest && helloRetryRequest.hasSelectedGroup && helloRetryRequest.selectedGroup != serverHello.keyShare.group {
 		c.sendAlert(alertHandshakeFailure)
 		return errors.New("tls: ServerHello parameters did not match HelloRetryRequest")
 	}
@@ -644,9 +651,10 @@
 	handshakeSecret := hs.finishedHash.extractKey(earlySecret, ecdheSecret)
 
 	// Switch to handshake traffic keys.
-	handshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, handshakeTrafficLabel)
-	c.out.useTrafficSecret(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, clientWrite)
-	c.in.useTrafficSecret(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, serverWrite)
+	clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, clientHandshakeTrafficLabel)
+	c.out.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, handshakePhase, clientWrite)
+	serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, serverHandshakeTrafficLabel)
+	c.in.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, handshakePhase, serverWrite)
 
 	msg, err := c.readHandshake()
 	if err != nil {
@@ -756,7 +764,7 @@
 		return unexpectedMessageError(serverFinished, msg)
 	}
 
-	verify := hs.finishedHash.serverSum(handshakeTrafficSecret)
+	verify := hs.finishedHash.serverSum(serverHandshakeTrafficSecret)
 	if len(verify) != len(serverFinished.verifyData) ||
 		subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
 		c.sendAlert(alertHandshakeFailure)
@@ -768,7 +776,8 @@
 	// The various secrets do not incorporate the client's final leg, so
 	// derive them now before updating the handshake context.
 	masterSecret := hs.finishedHash.extractKey(handshakeSecret, zeroSecret)
-	trafficSecret := hs.finishedHash.deriveSecret(masterSecret, applicationTrafficLabel)
+	clientTrafficSecret := hs.finishedHash.deriveSecret(masterSecret, clientApplicationTrafficLabel)
+	serverTrafficSecret := hs.finishedHash.deriveSecret(masterSecret, serverApplicationTrafficLabel)
 
 	if certReq != nil && !c.config.Bugs.SkipClientCertificate {
 		certMsg := &certificateMsg{
@@ -813,7 +822,7 @@
 
 	// Send a client Finished message.
 	finished := new(finishedMsg)
-	finished.verifyData = hs.finishedHash.clientSum(handshakeTrafficSecret)
+	finished.verifyData = hs.finishedHash.clientSum(clientHandshakeTrafficSecret)
 	if c.config.Bugs.BadFinished {
 		finished.verifyData[0]++
 	}
@@ -830,8 +839,8 @@
 	c.flushHandshake()
 
 	// Switch to application data keys.
-	c.out.useTrafficSecret(c.vers, hs.suite, trafficSecret, applicationPhase, clientWrite)
-	c.in.useTrafficSecret(c.vers, hs.suite, trafficSecret, applicationPhase, serverWrite)
+	c.out.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, applicationPhase, clientWrite)
+	c.in.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, applicationPhase, serverWrite)
 
 	c.exporterSecret = hs.finishedHash.deriveSecret(masterSecret, exporterLabel)
 	c.resumptionSecret = hs.finishedHash.deriveSecret(masterSecret, resumptionLabel)
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index 19578e8..285587e 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -131,13 +131,11 @@
 }
 
 type clientHelloMsg struct {
-	raw       []byte
-	isDTLS    bool
-	vers      uint16
-	random    []byte
-	sessionId []byte
-	// TODO(davidben): Add support for TLS 1.3 cookies which are larger and
-	// use an extension.
+	raw                     []byte
+	isDTLS                  bool
+	vers                    uint16
+	random                  []byte
+	sessionId               []byte
 	cookie                  []byte
 	cipherSuites            []uint16
 	compressionMethods      []uint8
@@ -152,6 +150,7 @@
 	pskIdentities           []pskIdentity
 	hasEarlyData            bool
 	earlyDataContext        []byte
+	tls13Cookie             []byte
 	ticketSupported         bool
 	sessionTicket           []uint8
 	signatureAlgorithms     []signatureAlgorithm
@@ -194,6 +193,7 @@
 		eqPSKIdentityLists(m.pskIdentities, m1.pskIdentities) &&
 		m.hasEarlyData == m1.hasEarlyData &&
 		bytes.Equal(m.earlyDataContext, m1.earlyDataContext) &&
+		bytes.Equal(m.tls13Cookie, m1.tls13Cookie) &&
 		m.ticketSupported == m1.ticketSupported &&
 		bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
 		eqSignatureAlgorithms(m.signatureAlgorithms, m1.signatureAlgorithms) &&
@@ -334,6 +334,11 @@
 		context := earlyDataIndication.addU8LengthPrefixed()
 		context.addBytes(m.earlyDataContext)
 	}
+	if len(m.tls13Cookie) > 0 {
+		extensions.addU16(extensionCookie)
+		body := extensions.addU16LengthPrefixed()
+		body.addU16LengthPrefixed().addBytes(m.tls13Cookie)
+	}
 	if m.ticketSupported {
 		// http://tools.ietf.org/html/rfc5077#section-3.2
 		extensions.addU16(extensionSessionTicket)
@@ -666,6 +671,15 @@
 			}
 			m.hasEarlyData = true
 			m.earlyDataContext = data[1:length]
+		case extensionCookie:
+			if length < 2 {
+				return false
+			}
+			l := int(data[0])<<8 | int(data[1])
+			if l != length-2 || l == 0 {
+				return false
+			}
+			m.tls13Cookie = data[2 : 2+l]
 		case extensionSignatureAlgorithms:
 			// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
 			if length < 2 || length&1 != 0 {
@@ -782,6 +796,8 @@
 	useCertAuth         bool
 	earlyDataIndication bool
 	compressionMethod   uint8
+	customExtension     string
+	unencryptedALPN     string
 	extensions          serverExtensions
 }
 
@@ -840,6 +856,19 @@
 			extensions.addU16(extensionEarlyData)
 			extensions.addU16(0) // Length
 		}
+		if len(m.customExtension) > 0 {
+			extensions.addU16(extensionCustom)
+			customExt := extensions.addU16LengthPrefixed()
+			customExt.addBytes([]byte(m.customExtension))
+		}
+		if len(m.unencryptedALPN) > 0 {
+			extensions.addU16(extensionALPN)
+			extension := extensions.addU16LengthPrefixed()
+
+			protocolNameList := extension.addU16LengthPrefixed()
+			protocolName := protocolNameList.addU8LengthPrefixed()
+			protocolName.addBytes([]byte(m.unencryptedALPN))
+		}
 	} else {
 		m.extensions.marshal(extensions, vers)
 		if extensions.len() == 0 {
@@ -1255,10 +1284,13 @@
 }
 
 type helloRetryRequestMsg struct {
-	raw           []byte
-	vers          uint16
-	cipherSuite   uint16
-	selectedGroup CurveID
+	raw                 []byte
+	vers                uint16
+	hasSelectedGroup    bool
+	selectedGroup       CurveID
+	cookie              []byte
+	customExtension     string
+	duplicateExtensions bool
 }
 
 func (m *helloRetryRequestMsg) marshal() []byte {
@@ -1270,10 +1302,29 @@
 	retryRequestMsg.addU8(typeHelloRetryRequest)
 	retryRequest := retryRequestMsg.addU24LengthPrefixed()
 	retryRequest.addU16(m.vers)
-	retryRequest.addU16(m.cipherSuite)
-	retryRequest.addU16(uint16(m.selectedGroup))
-	// Extensions field. We have none to send.
-	retryRequest.addU16(0)
+	extensions := retryRequest.addU16LengthPrefixed()
+
+	count := 1
+	if m.duplicateExtensions {
+		count = 2
+	}
+
+	for i := 0; i < count; i++ {
+		if m.hasSelectedGroup {
+			extensions.addU16(extensionKeyShare)
+			extensions.addU16(2) // length
+			extensions.addU16(uint16(m.selectedGroup))
+		}
+		if len(m.cookie) > 0 {
+			extensions.addU16(extensionCookie)
+			body := extensions.addU16LengthPrefixed()
+			body.addU16LengthPrefixed().addBytes(m.cookie)
+		}
+		if len(m.customExtension) > 0 {
+			extensions.addU16(extensionCustom)
+			extensions.addU16LengthPrefixed().addBytes([]byte(m.customExtension))
+		}
+	}
 
 	m.raw = retryRequestMsg.finish()
 	return m.raw
@@ -1281,17 +1332,48 @@
 
 func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
 	m.raw = data
-	if len(data) < 12 {
+	if len(data) < 8 {
 		return false
 	}
 	m.vers = uint16(data[4])<<8 | uint16(data[5])
-	m.cipherSuite = uint16(data[6])<<8 | uint16(data[7])
-	m.selectedGroup = CurveID(data[8])<<8 | CurveID(data[9])
-	extLen := int(data[10])<<8 | int(data[11])
-	data = data[12:]
-	if len(data) != extLen {
+	extLen := int(data[6])<<8 | int(data[7])
+	data = data[8:]
+	if len(data) != extLen || len(data) == 0 {
 		return false
 	}
+	for len(data) > 0 {
+		if len(data) < 4 {
+			return false
+		}
+		extension := uint16(data[0])<<8 | uint16(data[1])
+		length := int(data[2])<<8 | int(data[3])
+		data = data[4:]
+		if len(data) < length {
+			return false
+		}
+
+		switch extension {
+		case extensionKeyShare:
+			if length != 2 {
+				return false
+			}
+			m.hasSelectedGroup = true
+			m.selectedGroup = CurveID(data[0])<<8 | CurveID(data[1])
+		case extensionCookie:
+			if length < 2 {
+				return false
+			}
+			cookieLen := int(data[0])<<8 | int(data[1])
+			if 2+cookieLen != length {
+				return false
+			}
+			m.cookie = data[2 : 2+cookieLen]
+		default:
+			// Unknown extensions are illegal from the server.
+			return false
+		}
+		data = data[length:]
+	}
 	return true
 }
 
@@ -1819,12 +1901,14 @@
 }
 
 type newSessionTicketMsg struct {
-	raw            []byte
-	version        uint16
-	ticketLifetime uint32
-	keModes        []byte
-	authModes      []byte
-	ticket         []byte
+	raw                []byte
+	version            uint16
+	ticketLifetime     uint32
+	keModes            []byte
+	authModes          []byte
+	ticket             []byte
+	customExtension    string
+	hasGREASEExtension bool
 }
 
 func (m *newSessionTicketMsg) marshal() []byte {
@@ -1846,11 +1930,11 @@
 	ticket.addBytes(m.ticket)
 
 	if m.version >= VersionTLS13 {
-		// Send no extensions.
-		//
-		// TODO(davidben): Add an option to send a custom extension to
-		// test we correctly ignore unknown ones.
-		body.addU16(0)
+		extensions := body.addU16LengthPrefixed()
+		if len(m.customExtension) > 0 {
+			extensions.addU16(ticketExtensionCustom)
+			extensions.addU16LengthPrefixed().addBytes([]byte(m.customExtension))
+		}
 	}
 
 	m.raw = ticketMsg.finish()
@@ -1913,7 +1997,24 @@
 		if len(data) < extsLength {
 			return false
 		}
+		extensions := data[:extsLength]
 		data = data[extsLength:]
+
+		for len(extensions) > 0 {
+			if len(extensions) < 4 {
+				return false
+			}
+			extValue := uint16(extensions[0])<<8 | uint16(extensions[1])
+			extLength := int(extensions[2])<<8 | int(extensions[3])
+			if len(extensions) < 4+extLength {
+				return false
+			}
+			extensions = extensions[4+extLength:]
+
+			if isGREASEValue(extValue) {
+				m.hasGREASEExtension = true
+			}
+		}
 	}
 
 	if len(data) > 0 {
@@ -2060,14 +2161,32 @@
 }
 
 type keyUpdateMsg struct {
+	raw              []byte
+	keyUpdateRequest byte
 }
 
-func (*keyUpdateMsg) marshal() []byte {
-	return []byte{typeKeyUpdate, 0, 0, 0}
+func (m *keyUpdateMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	return []byte{typeKeyUpdate, 0, 0, 1, m.keyUpdateRequest}
 }
 
-func (*keyUpdateMsg) unmarshal(data []byte) bool {
-	return len(data) == 4
+func (m *keyUpdateMsg) unmarshal(data []byte) bool {
+	m.raw = data
+
+	if len(data) != 5 {
+		return false
+	}
+
+	length := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+	if len(data)-4 != length {
+		return false
+	}
+
+	m.keyUpdateRequest = data[4]
+	return m.keyUpdateRequest == keyUpdateNotRequested || m.keyUpdateRequest == keyUpdateRequested
 }
 
 func eqUint16s(x, y []uint16) bool {
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 7c2fd17..9147134 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -359,9 +359,11 @@
 	config := c.config
 
 	hs.hello = &serverHelloMsg{
-		isDTLS:       c.isDTLS,
-		vers:         versionToWire(c.vers, c.isDTLS),
-		versOverride: config.Bugs.SendServerHelloVersion,
+		isDTLS:          c.isDTLS,
+		vers:            versionToWire(c.vers, c.isDTLS),
+		versOverride:    config.Bugs.SendServerHelloVersion,
+		customExtension: config.Bugs.CustomUnencryptedExtension,
+		unencryptedALPN: config.Bugs.SendUnencryptedALPN,
 	}
 
 	hs.hello.random = make([]byte, 32)
@@ -541,11 +543,32 @@
 		hs.hello.hasKeyShare = false
 	}
 
-	// Resolve ECDHE and compute the handshake secret.
-	var ecdheSecret []byte
+	firstHelloRetryRequest := true
+
+ResendHelloRetryRequest:
+	var sendHelloRetryRequest bool
+	helloRetryRequest := &helloRetryRequestMsg{
+		vers:                versionToWire(c.vers, c.isDTLS),
+		duplicateExtensions: config.Bugs.DuplicateHelloRetryRequestExtensions,
+	}
+
+	if config.Bugs.AlwaysSendHelloRetryRequest {
+		sendHelloRetryRequest = true
+	}
+
+	if config.Bugs.SendHelloRetryRequestCookie != nil {
+		sendHelloRetryRequest = true
+		helloRetryRequest.cookie = config.Bugs.SendHelloRetryRequestCookie
+	}
+
+	if len(config.Bugs.CustomHelloRetryRequestExtension) > 0 {
+		sendHelloRetryRequest = true
+		helloRetryRequest.customExtension = config.Bugs.CustomHelloRetryRequestExtension
+	}
+
+	var selectedKeyShare *keyShareEntry
 	if hs.hello.hasKeyShare {
 		// Look for the key share corresponding to our selected curve.
-		var selectedKeyShare *keyShareEntry
 		for i := range hs.clientHello.keyShares {
 			if hs.clientHello.keyShares[i].group == selectedCurve {
 				selectedKeyShare = &hs.clientHello.keyShares[i]
@@ -557,67 +580,80 @@
 			return errors.New("tls: expected missing key share")
 		}
 
-		sendHelloRetryRequest := selectedKeyShare == nil
-		if config.Bugs.UnnecessaryHelloRetryRequest {
+		if selectedKeyShare == nil {
+			helloRetryRequest.hasSelectedGroup = true
+			helloRetryRequest.selectedGroup = selectedCurve
 			sendHelloRetryRequest = true
 		}
-		if config.Bugs.SkipHelloRetryRequest {
-			sendHelloRetryRequest = false
+	}
+
+	if config.Bugs.SendHelloRetryRequestCurve != 0 {
+		helloRetryRequest.hasSelectedGroup = true
+		helloRetryRequest.selectedGroup = config.Bugs.SendHelloRetryRequestCurve
+		sendHelloRetryRequest = true
+	}
+
+	if config.Bugs.SkipHelloRetryRequest {
+		sendHelloRetryRequest = false
+	}
+
+	if sendHelloRetryRequest {
+		hs.writeServerHash(helloRetryRequest.marshal())
+		c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal())
+		c.flushHandshake()
+
+		// Read new ClientHello.
+		newMsg, err := c.readHandshake()
+		if err != nil {
+			return err
 		}
-		if sendHelloRetryRequest {
-			firstTime := true
-		ResendHelloRetryRequest:
-			// Send HelloRetryRequest.
-			helloRetryRequestMsg := helloRetryRequestMsg{
-				vers:          versionToWire(c.vers, c.isDTLS),
-				cipherSuite:   hs.hello.cipherSuite,
-				selectedGroup: selectedCurve,
-			}
-			if config.Bugs.SendHelloRetryRequestCurve != 0 {
-				helloRetryRequestMsg.selectedGroup = config.Bugs.SendHelloRetryRequestCurve
-			}
-			hs.writeServerHash(helloRetryRequestMsg.marshal())
-			c.writeRecord(recordTypeHandshake, helloRetryRequestMsg.marshal())
-			c.flushHandshake()
+		newClientHello, ok := newMsg.(*clientHelloMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(newClientHello, newMsg)
+		}
+		hs.writeClientHash(newClientHello.marshal())
 
-			// Read new ClientHello.
-			newMsg, err := c.readHandshake()
-			if err != nil {
-				return err
-			}
-			newClientHello, ok := newMsg.(*clientHelloMsg)
-			if !ok {
-				c.sendAlert(alertUnexpectedMessage)
-				return unexpectedMessageError(newClientHello, newMsg)
-			}
-			hs.writeClientHash(newClientHello.marshal())
+		// Check that the new ClientHello matches the old ClientHello,
+		// except for relevant modifications.
+		//
+		// TODO(davidben): Make this check more precise.
+		oldClientHelloCopy := *hs.clientHello
+		oldClientHelloCopy.raw = nil
+		oldClientHelloCopy.hasEarlyData = false
+		oldClientHelloCopy.earlyDataContext = nil
+		newClientHelloCopy := *newClientHello
+		newClientHelloCopy.raw = nil
 
-			// Check that the new ClientHello matches the old ClientHello, except for
-			// the addition of the new KeyShareEntry at the end of the list, and
-			// removing the EarlyDataIndication extension (if present).
-			newKeyShares := newClientHello.keyShares
-			if len(newKeyShares) == 0 || newKeyShares[len(newKeyShares)-1].group != selectedCurve {
+		if helloRetryRequest.hasSelectedGroup {
+			newKeyShares := newClientHelloCopy.keyShares
+			if len(newKeyShares) == 0 || newKeyShares[len(newKeyShares)-1].group != helloRetryRequest.selectedGroup {
 				return errors.New("tls: KeyShare from HelloRetryRequest not present in new ClientHello")
 			}
-			oldClientHelloCopy := *hs.clientHello
-			oldClientHelloCopy.raw = nil
-			oldClientHelloCopy.hasEarlyData = false
-			oldClientHelloCopy.earlyDataContext = nil
-			newClientHelloCopy := *newClientHello
-			newClientHelloCopy.raw = nil
-			newClientHelloCopy.keyShares = newKeyShares[:len(newKeyShares)-1]
-			if !oldClientHelloCopy.equal(&newClientHelloCopy) {
-				return errors.New("tls: new ClientHello does not match")
-			}
-
-			if firstTime && config.Bugs.SecondHelloRetryRequest {
-				firstTime = false
-				goto ResendHelloRetryRequest
-			}
-
 			selectedKeyShare = &newKeyShares[len(newKeyShares)-1]
+			newClientHelloCopy.keyShares = newKeyShares[:len(newKeyShares)-1]
 		}
 
+		if len(helloRetryRequest.cookie) > 0 {
+			if !bytes.Equal(newClientHelloCopy.tls13Cookie, helloRetryRequest.cookie) {
+				return errors.New("tls: cookie from HelloRetryRequest not present in new ClientHello")
+			}
+			newClientHelloCopy.tls13Cookie = nil
+		}
+
+		if !oldClientHelloCopy.equal(&newClientHelloCopy) {
+			return errors.New("tls: new ClientHello does not match")
+		}
+
+		if firstHelloRetryRequest && config.Bugs.SecondHelloRetryRequest {
+			firstHelloRetryRequest = false
+			goto ResendHelloRetryRequest
+		}
+	}
+
+	// Resolve ECDHE and compute the handshake secret.
+	var ecdheSecret []byte
+	if hs.hello.hasKeyShare {
 		// Once a curve has been selected and a key share identified,
 		// the server needs to generate a public value and send it in
 		// the ServerHello.
@@ -691,9 +727,10 @@
 	handshakeSecret := hs.finishedHash.extractKey(earlySecret, ecdheSecret)
 
 	// Switch to handshake traffic keys.
-	handshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, handshakeTrafficLabel)
-	c.out.useTrafficSecret(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, serverWrite)
-	c.in.useTrafficSecret(c.vers, hs.suite, handshakeTrafficSecret, handshakePhase, clientWrite)
+	serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, serverHandshakeTrafficLabel)
+	c.out.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, handshakePhase, serverWrite)
+	clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, clientHandshakeTrafficLabel)
+	c.in.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, handshakePhase, clientWrite)
 
 	if hs.hello.useCertAuth {
 		if hs.clientHello.ocspStapling {
@@ -791,7 +828,7 @@
 	}
 
 	finished := new(finishedMsg)
-	finished.verifyData = hs.finishedHash.serverSum(handshakeTrafficSecret)
+	finished.verifyData = hs.finishedHash.serverSum(serverHandshakeTrafficSecret)
 	if config.Bugs.BadFinished {
 		finished.verifyData[0]++
 	}
@@ -805,11 +842,12 @@
 	// The various secrets do not incorporate the client's final leg, so
 	// derive them now before updating the handshake context.
 	masterSecret := hs.finishedHash.extractKey(handshakeSecret, hs.finishedHash.zeroSecret())
-	trafficSecret := hs.finishedHash.deriveSecret(masterSecret, applicationTrafficLabel)
+	clientTrafficSecret := hs.finishedHash.deriveSecret(masterSecret, clientApplicationTrafficLabel)
+	serverTrafficSecret := hs.finishedHash.deriveSecret(masterSecret, serverApplicationTrafficLabel)
 
 	// Switch to application data keys on write. In particular, any alerts
 	// from the client certificate are sent over these keys.
-	c.out.useTrafficSecret(c.vers, hs.suite, trafficSecret, applicationPhase, serverWrite)
+	c.out.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, applicationPhase, serverWrite)
 
 	// If we requested a client certificate, then the client must send a
 	// certificate message, even if it's empty.
@@ -830,7 +868,7 @@
 			// The client didn't actually send a certificate
 			switch config.ClientAuth {
 			case RequireAnyClientCert, RequireAndVerifyClientCert:
-				c.sendAlert(alertBadCertificate)
+				c.sendAlert(alertCertificateRequired)
 				return errors.New("tls: client didn't provide a certificate")
 			}
 		}
@@ -873,7 +911,7 @@
 		return unexpectedMessageError(clientFinished, msg)
 	}
 
-	verify := hs.finishedHash.clientSum(handshakeTrafficSecret)
+	verify := hs.finishedHash.clientSum(clientHandshakeTrafficSecret)
 	if len(verify) != len(clientFinished.verifyData) ||
 		subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
 		c.sendAlert(alertHandshakeFailure)
@@ -882,7 +920,7 @@
 	hs.writeClientHash(clientFinished.marshal())
 
 	// Switch to application data keys on read.
-	c.in.useTrafficSecret(c.vers, hs.suite, trafficSecret, applicationPhase, clientWrite)
+	c.in.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, applicationPhase, clientWrite)
 
 	c.cipherSuite = hs.suite
 	c.exporterSecret = hs.finishedHash.deriveSecret(masterSecret, exporterLabel)
@@ -918,8 +956,8 @@
 		c.sendAlert(alertInternalError)
 		return false, err
 	}
-	// Signal downgrades in the server random, per draft-ietf-tls-tls13-14,
-	// section 6.3.1.2.
+	// Signal downgrades in the server random, per draft-ietf-tls-tls13-16,
+	// section 4.1.3.
 	if c.vers <= VersionTLS12 && config.maxVersion(c.isDTLS) >= VersionTLS13 {
 		copy(hs.hello.random[len(hs.hello.random)-8:], downgradeTLS13)
 	}
diff --git a/src/ssl/test/runner/prf.go b/src/ssl/test/runner/prf.go
index 5c7b3ab..ffa68e9 100644
--- a/src/ssl/test/runner/prf.go
+++ b/src/ssl/test/runner/prf.go
@@ -119,6 +119,7 @@
 var keyExpansionLabel = []byte("key expansion")
 var clientFinishedLabel = []byte("client finished")
 var serverFinishedLabel = []byte("server finished")
+var finishedLabel = []byte("finished")
 var channelIDLabel = []byte("TLS Channel ID signature\x00")
 var channelIDResumeLabel = []byte("Resumption\x00")
 
@@ -311,7 +312,7 @@
 		return out
 	}
 
-	clientFinishedKey := hkdfExpandLabel(h.hash, baseKey, clientFinishedLabel, nil, h.hash.Size())
+	clientFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size())
 	finishedHMAC := hmac.New(h.hash.New, clientFinishedKey)
 	finishedHMAC.Write(h.appendContextHashes(nil))
 	return finishedHMAC.Sum(nil)
@@ -330,7 +331,7 @@
 		return out
 	}
 
-	serverFinishedKey := hkdfExpandLabel(h.hash, baseKey, serverFinishedLabel, nil, h.hash.Size())
+	serverFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size())
 	finishedHMAC := hmac.New(h.hash.New, serverFinishedKey)
 	finishedHMAC.Write(h.appendContextHashes(nil))
 	return finishedHMAC.Sum(nil)
@@ -367,7 +368,7 @@
 }
 
 // zeroSecretTLS13 returns the default all zeros secret for TLS 1.3, used when a
-// given secret is not available in the handshake. See draft-ietf-tls-tls13-13,
+// given secret is not available in the handshake. See draft-ietf-tls-tls13-16,
 // section 7.1.
 func (h *finishedHash) zeroSecret() []byte {
 	return make([]byte, h.hash.Size())
@@ -387,7 +388,7 @@
 }
 
 // hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined
-// in section 7.1 of draft-ietf-tls-tls13-13.
+// in section 7.1 of draft-ietf-tls-tls13-16.
 func hkdfExpandLabel(hash crypto.Hash, secret, label, hashValue []byte, length int) []byte {
 	if len(label) > 255 || len(hashValue) > 255 {
 		panic("hkdfExpandLabel: label or hashValue too long")
@@ -417,15 +418,18 @@
 
 // The following are labels for traffic secret derivation in TLS 1.3.
 var (
-	earlyTrafficLabel       = []byte("early traffic secret")
-	handshakeTrafficLabel   = []byte("handshake traffic secret")
-	applicationTrafficLabel = []byte("application traffic secret")
-	exporterLabel           = []byte("exporter master secret")
-	resumptionLabel         = []byte("resumption master secret")
+	earlyTrafficLabel             = []byte("client early traffic secret")
+	clientHandshakeTrafficLabel   = []byte("client handshake traffic secret")
+	serverHandshakeTrafficLabel   = []byte("server handshake traffic secret")
+	clientApplicationTrafficLabel = []byte("client application traffic secret")
+	serverApplicationTrafficLabel = []byte("server application traffic secret")
+	applicationTrafficLabel       = []byte("application traffic secret")
+	exporterLabel                 = []byte("exporter master secret")
+	resumptionLabel               = []byte("resumption master secret")
 )
 
 // deriveSecret implements TLS 1.3's Derive-Secret function, as defined in
-// section 7.1 of draft ietf-tls-tls13-13.
+// section 7.1 of draft ietf-tls-tls13-16.
 func (h *finishedHash) deriveSecret(secret, label []byte) []byte {
 	if h.resumptionContextHash == nil {
 		panic("Resumption context not set.")
@@ -474,11 +478,7 @@
 func deriveTrafficAEAD(version uint16, suite *cipherSuite, secret, phase []byte, side trafficDirection) interface{} {
 	label := make([]byte, 0, len(phase)+2+16)
 	label = append(label, phase...)
-	if side == clientWrite {
-		label = append(label, []byte(", client write key")...)
-	} else {
-		label = append(label, []byte(", server write key")...)
-	}
+	label = append(label, []byte(", key")...)
 	key := hkdfExpandLabel(suite.hash(), secret, label, nil, suite.keyLen)
 
 	label = label[:len(label)-3] // Remove "key" from the end.
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 248c6eb..367fef1 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -359,6 +359,8 @@
 	// sendKeyUpdates is the number of consecutive key updates to send
 	// before and after the test message.
 	sendKeyUpdates int
+	// keyUpdateRequest is the KeyUpdateRequest value to send in KeyUpdate messages.
+	keyUpdateRequest byte
 	// expectMessageDropped, if true, means the test message is expected to
 	// be dropped by the client rather than echoed back.
 	expectMessageDropped bool
@@ -616,7 +618,7 @@
 	}
 
 	for i := 0; i < test.sendKeyUpdates; i++ {
-		if err := tlsConn.SendKeyUpdate(); err != nil {
+		if err := tlsConn.SendKeyUpdate(test.keyUpdateRequest); err != nil {
 			return err
 		}
 	}
@@ -678,7 +680,7 @@
 		tlsConn.Write(testMessage)
 
 		for i := 0; i < test.sendKeyUpdates; i++ {
-			tlsConn.SendKeyUpdate()
+			tlsConn.SendKeyUpdate(test.keyUpdateRequest)
 		}
 
 		for i := 0; i < test.sendEmptyRecords; i++ {
@@ -1981,13 +1983,14 @@
 			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
 		},
 		{
-			name: "SendKeyUpdates",
+			name: "TooManyKeyUpdates",
 			config: Config{
 				MaxVersion: VersionTLS13,
 			},
-			sendKeyUpdates: 33,
-			shouldFail:     true,
-			expectedError:  ":TOO_MANY_KEY_UPDATES:",
+			sendKeyUpdates:   33,
+			keyUpdateRequest: keyUpdateNotRequested,
+			shouldFail:       true,
+			expectedError:    ":TOO_MANY_KEY_UPDATES:",
 		},
 		{
 			name: "EmptySessionID",
@@ -2195,14 +2198,22 @@
 			expectedError: ":WRONG_VERSION_NUMBER:",
 		},
 		{
-			testType: clientTest,
-			name:     "KeyUpdate",
+			name: "KeyUpdate",
 			config: Config{
 				MaxVersion: VersionTLS13,
-				Bugs: ProtocolBugs{
-					SendKeyUpdateBeforeEveryAppDataRecord: true,
-				},
 			},
+			sendKeyUpdates:   1,
+			keyUpdateRequest: keyUpdateNotRequested,
+		},
+		{
+			name: "KeyUpdate-InvalidRequestMode",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			sendKeyUpdates:   1,
+			keyUpdateRequest: 42,
+			shouldFail:       true,
+			expectedError:    ":DECODE_ERROR:",
 		},
 		{
 			name: "SendSNIWarningAlert",
@@ -2263,7 +2274,7 @@
 			expectedLocalError: "remote error: illegal parameter",
 		},
 		{
-			name: "GREASE-TLS12",
+			name: "GREASE-Client-TLS12",
 			config: Config{
 				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
@@ -2273,7 +2284,18 @@
 			flags: []string{"-enable-grease"},
 		},
 		{
-			name: "GREASE-TLS13",
+			name: "GREASE-Client-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					ExpectGREASE: true,
+				},
+			},
+			flags: []string{"-enable-grease"},
+		},
+		{
+			testType: serverTest,
+			name:     "GREASE-Server-TLS13",
 			config: Config{
 				MaxVersion: VersionTLS13,
 				Bugs: ProtocolBugs{
@@ -2920,9 +2942,7 @@
 			flags: []string{
 				"-expect-verify-result",
 			},
-			// TODO(davidben): Switch this to true when TLS 1.3
-			// supports session resumption.
-			resumeSession: ver.version < VersionTLS13,
+			resumeSession: true,
 		})
 
 		testCases = append(testCases, testCase{
@@ -2938,11 +2958,15 @@
 				"-expect-verify-result",
 				"-verify-peer",
 			},
-			// TODO(davidben): Switch this to true when TLS 1.3
-			// supports session resumption.
-			resumeSession: ver.version < VersionTLS13,
+			resumeSession: true,
 		})
 
+		certificateRequired := "remote error: certificate required"
+		if ver.version < VersionTLS13 {
+			// Prior to TLS 1.3, the generic handshake_failure alert
+			// was used.
+			certificateRequired = "remote error: handshake failure"
+		}
 		testCases = append(testCases, testCase{
 			testType: serverTest,
 			name:     "RequireAnyClientCertificate-" + ver.name,
@@ -2950,9 +2974,10 @@
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
 			},
-			flags:         []string{"-require-any-client-certificate"},
-			shouldFail:    true,
-			expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
+			flags:              []string{"-require-any-client-certificate"},
+			shouldFail:         true,
+			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
+			expectedLocalError: certificateRequired,
 		})
 
 		if ver.version != VersionSSL30 {
@@ -3356,10 +3381,8 @@
 			config: Config{
 				MaxVersion: VersionTLS13,
 				MinVersion: VersionTLS13,
-				// P-384 requires a HelloRetryRequest against
-				// BoringSSL's default configuration. Assert
-				// that we do indeed test this with
-				// ExpectMissingKeyShare.
+				// P-384 requires a HelloRetryRequest against BoringSSL's default
+				// configuration. Assert this with ExpectMissingKeyShare.
 				CurvePreferences: []CurveID{CurveP384},
 				Bugs: ProtocolBugs{
 					ExpectMissingKeyShare: true,
@@ -5678,6 +5701,22 @@
 		},
 	})
 
+	// Renegotiation is not allowed at SSL 3.0.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-SSL3",
+		config: Config{
+			MaxVersion: VersionSSL30,
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shouldFail:         true,
+		expectedError:      ":NO_RENEGOTIATION:",
+		expectedLocalError: "remote error: no renegotiation",
+	})
+
 	// Stray HelloRequests during the handshake are ignored in TLS 1.2.
 	testCases = append(testCases, testCase{
 		name: "StrayHelloRequest",
@@ -5845,19 +5884,28 @@
 				continue
 			}
 
-			var shouldFail bool
+			var shouldSignFail, shouldVerifyFail bool
 			// ecdsa_sha1 does not exist in TLS 1.3.
 			if ver.version >= VersionTLS13 && alg.id == signatureECDSAWithSHA1 {
-				shouldFail = true
+				shouldSignFail = true
+				shouldVerifyFail = true
 			}
 			// RSA-PKCS1 does not exist in TLS 1.3.
 			if ver.version == VersionTLS13 && hasComponent(alg.name, "PKCS1") {
-				shouldFail = true
+				shouldSignFail = true
+				shouldVerifyFail = true
+			}
+
+			// BoringSSL will sign SHA-1 and SHA-512 with ECDSA but not accept them.
+			if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 {
+				shouldVerifyFail = true
 			}
 
 			var signError, verifyError string
-			if shouldFail {
+			if shouldSignFail {
 				signError = ":NO_COMMON_SIGNATURE_ALGORITHMS:"
+			}
+			if shouldVerifyFail {
 				verifyError = ":WRONG_SIGNATURE_TYPE:"
 			}
 
@@ -5879,7 +5927,7 @@
 					"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
 					"-enable-all-curves",
 				},
-				shouldFail:                     shouldFail,
+				shouldFail:                     shouldSignFail,
 				expectedError:                  signError,
 				expectedPeerSignatureAlgorithm: alg.id,
 			})
@@ -5894,11 +5942,10 @@
 						alg.id,
 					},
 					Bugs: ProtocolBugs{
-						SkipECDSACurveCheck:          shouldFail,
-						IgnoreSignatureVersionChecks: shouldFail,
-						// The client won't advertise 1.3-only algorithms after
-						// version negotiation.
-						IgnorePeerSignatureAlgorithmPreferences: shouldFail,
+						SkipECDSACurveCheck:          shouldVerifyFail,
+						IgnoreSignatureVersionChecks: shouldVerifyFail,
+						// Some signature algorithms may not be advertised.
+						IgnorePeerSignatureAlgorithmPreferences: shouldVerifyFail,
 					},
 				},
 				flags: []string{
@@ -5906,7 +5953,7 @@
 					"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)),
 					"-enable-all-curves",
 				},
-				shouldFail:    shouldFail,
+				shouldFail:    shouldVerifyFail,
 				expectedError: verifyError,
 			})
 
@@ -5927,7 +5974,7 @@
 					"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
 					"-enable-all-curves",
 				},
-				shouldFail:                     shouldFail,
+				shouldFail:                     shouldSignFail,
 				expectedError:                  signError,
 				expectedPeerSignatureAlgorithm: alg.id,
 			})
@@ -5942,19 +5989,21 @@
 						alg.id,
 					},
 					Bugs: ProtocolBugs{
-						SkipECDSACurveCheck:          shouldFail,
-						IgnoreSignatureVersionChecks: shouldFail,
+						SkipECDSACurveCheck:          shouldVerifyFail,
+						IgnoreSignatureVersionChecks: shouldVerifyFail,
+						// Some signature algorithms may not be advertised.
+						IgnorePeerSignatureAlgorithmPreferences: shouldVerifyFail,
 					},
 				},
 				flags: []string{
 					"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)),
 					"-enable-all-curves",
 				},
-				shouldFail:    shouldFail,
+				shouldFail:    shouldVerifyFail,
 				expectedError: verifyError,
 			})
 
-			if !shouldFail {
+			if !shouldVerifyFail {
 				testCases = append(testCases, testCase{
 					testType: serverTest,
 					name:     "ClientAuth-InvalidSignature" + suffix,
@@ -5995,7 +6044,7 @@
 				})
 			}
 
-			if ver.version >= VersionTLS12 && !shouldFail {
+			if ver.version >= VersionTLS12 && !shouldSignFail {
 				testCases = append(testCases, testCase{
 					name: "ClientAuth-Sign-Negotiate" + suffix,
 					config: Config{
@@ -7080,6 +7129,39 @@
 		expectedError:      ":UNEXPECTED_EXTENSION:",
 		expectedLocalError: "remote error: unsupported extension",
 	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnknownUnencryptedExtension-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomUnencryptedExtension: expectedContents,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+		// The shim must send an alert, but alerts at this point do not
+		// get successfully decrypted by the runner.
+		expectedLocalError: "local error: bad record MAC",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnexpectedUnencryptedExtension-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendUnencryptedALPN: "foo",
+			},
+		},
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+		// The shim must send an alert, but alerts at this point do not
+		// get successfully decrypted by the runner.
+		expectedLocalError: "local error: bad record MAC",
+	})
 
 	// Test a known but unoffered extension from the server.
 	testCases = append(testCases, testCase{
@@ -8431,9 +8513,10 @@
 	testCases = append(testCases, testCase{
 		name: "UnnecessaryHelloRetryRequest",
 		config: Config{
-			MaxVersion: VersionTLS13,
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveX25519},
 			Bugs: ProtocolBugs{
-				UnnecessaryHelloRetryRequest: true,
+				SendHelloRetryRequestCurve: CurveX25519,
 			},
 		},
 		shouldFail:    true,
@@ -8455,6 +8538,97 @@
 	})
 
 	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Empty",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AlwaysSendHelloRetryRequest: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-DuplicateCurve",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires a HelloRetryRequest against BoringSSL's default
+			// configuration. Assert this ExpectMissingKeyShare.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				ExpectMissingKeyShare:                true,
+				DuplicateHelloRetryRequestExtensions: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":DUPLICATE_EXTENSION:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Cookie",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte("cookie"),
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-DuplicateCookie",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie:          []byte("cookie"),
+				DuplicateHelloRetryRequestExtensions: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":DUPLICATE_EXTENSION:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-EmptyCookie",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte{},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Cookie-Curve",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte("cookie"),
+				ExpectMissingKeyShare:       true,
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Unknown",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomHelloRetryRequestExtension: "extension",
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+
+	testCases = append(testCases, testCase{
 		testType: serverTest,
 		name:     "SecondClientHelloMissingKeyShare",
 		config: Config{
@@ -8584,6 +8758,17 @@
 		shouldFail:    true,
 		expectedError: ":PSK_IDENTITY_NOT_FOUND:",
 	})
+
+	// Test that unknown NewSessionTicket extensions are tolerated.
+	testCases = append(testCases, testCase{
+		name: "TLS13-CustomTicketExtension",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomTicketExtension: "1234",
+			},
+		},
+	})
 }
 
 func addPeekTests() {
@@ -8649,11 +8834,10 @@
 		name: "Peek-KeyUpdate",
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Bugs: ProtocolBugs{
-				SendKeyUpdateBeforeEveryAppDataRecord: true,
-			},
 		},
-		flags: []string{"-peek-then-read"},
+		sendKeyUpdates:   1,
+		keyUpdateRequest: keyUpdateNotRequested,
+		flags:            []string{"-peek-then-read"},
 	})
 }
 
diff --git a/src/ssl/tls13_both.c b/src/ssl/tls13_both.c
index e634790..e32464d 100644
--- a/src/ssl/tls13_both.c
+++ b/src/ssl/tls13_both.c
@@ -178,7 +178,7 @@
   if (sk_X509_num(chain) == 0) {
     if (!allow_anonymous) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED);
       goto err;
     }
 
@@ -403,13 +403,20 @@
 }
 
 static int tls13_receive_key_update(SSL *ssl) {
-  if (ssl->init_num != 0) {
+  CBS cbs;
+  uint8_t key_update_request;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u8(&cbs, &key_update_request) ||
+      CBS_len(&cbs) != 0 ||
+      (key_update_request != SSL_KEY_UPDATE_NOT_REQUESTED &&
+       key_update_request != SSL_KEY_UPDATE_REQUESTED)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
     return 0;
   }
 
-  // TODO(svaldez): Send KeyUpdate.
+  /* TODO(svaldez): Send KeyUpdate if |key_update_request| is
+   * |SSL_KEY_UPDATE_REQUESTED|. */
   return tls13_rotate_traffic_key(ssl, evp_aead_open);
 }
 
diff --git a/src/ssl/tls13_client.c b/src/ssl/tls13_client.c
index 8f1b516..87ccdc4 100644
--- a/src/ssl/tls13_client.c
+++ b/src/ssl/tls13_client.c
@@ -54,48 +54,110 @@
   }
 
   CBS cbs, extensions;
-  uint16_t server_wire_version, cipher_suite, group_id;
+  uint16_t server_wire_version;
   CBS_init(&cbs, ssl->init_msg, ssl->init_num);
   if (!CBS_get_u16(&cbs, &server_wire_version) ||
-      !CBS_get_u16(&cbs, &cipher_suite) ||
-      !CBS_get_u16(&cbs, &group_id) ||
-      /* We do not currently parse any HelloRetryRequest extensions. */
       !CBS_get_u16_length_prefixed(&cbs, &extensions) ||
+      /* HelloRetryRequest may not be empty. */
+      CBS_len(&extensions) == 0 ||
       CBS_len(&cbs) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
     ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
     return ssl_hs_error;
   }
 
-  /* TODO(svaldez): Don't do early_data on HelloRetryRequest. */
+  while (CBS_len(&extensions) != 0) {
+    uint16_t type;
+    CBS extension;
+    if (!CBS_get_u16(&extensions, &type) ||
+        !CBS_get_u16_length_prefixed(&extensions, &extension)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+      return ssl_hs_error;
+    }
 
-  const uint16_t *groups;
-  size_t groups_len;
-  tls1_get_grouplist(ssl, 0 /* local groups */, &groups, &groups_len);
-  int found = 0;
-  for (size_t i = 0; i < groups_len; i++) {
-    if (groups[i] == group_id) {
-      found = 1;
-      break;
+    switch (type) {
+      case TLSEXT_TYPE_cookie: {
+        if (hs->cookie != NULL) {
+          OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION);
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+          return ssl_hs_error;
+        }
+
+        /* Cookies may be requested whether or not advertised, so no need to
+         * check. */
+
+        CBS cookie;
+        if (!CBS_get_u16_length_prefixed(&extension, &cookie) ||
+            CBS_len(&cookie) == 0 ||
+            CBS_len(&extension) != 0) {
+          OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+          return ssl_hs_error;
+        }
+
+        if (!CBS_stow(&cookie, &hs->cookie, &hs->cookie_len)) {
+          return ssl_hs_error;
+        }
+        break;
+      }
+
+      case TLSEXT_TYPE_key_share: {
+        if (hs->retry_group != 0) {
+          OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION);
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+          return ssl_hs_error;
+        }
+
+        /* key_share is always advertised, so no need to check. */
+
+        uint16_t group_id;
+        if (!CBS_get_u16(&extension, &group_id) ||
+            CBS_len(&extension) != 0) {
+          OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+          return ssl_hs_error;
+        }
+
+        /* The group must be supported. */
+        const uint16_t *groups;
+        size_t groups_len;
+        tls1_get_grouplist(ssl, &groups, &groups_len);
+        int found = 0;
+        for (size_t i = 0; i < groups_len; i++) {
+          if (groups[i] == group_id) {
+            found = 1;
+            break;
+          }
+        }
+
+        if (!found) {
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+          OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
+          return ssl_hs_error;
+        }
+
+        /* Check that the HelloRetryRequest does not request the key share that
+         * was provided in the initial ClientHello. */
+        if (SSL_ECDH_CTX_get_id(&hs->ecdh_ctx) == group_id) {
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+          OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
+          return ssl_hs_error;
+        }
+
+        SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+        hs->retry_group = group_id;
+        break;
+      }
+
+      default:
+        OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
+        return ssl_hs_error;
     }
   }
 
-  if (!found) {
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
-    return ssl_hs_error;
-  }
-
-  /* Check that the HelloRetryRequest does not request the key share that was
-   * provided in the initial ClientHello. */
-  if (SSL_ECDH_CTX_get_id(&ssl->s3->hs->ecdh_ctx) == group_id) {
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
-    return ssl_hs_error;
-  }
-
-  SSL_ECDH_CTX_cleanup(&ssl->s3->hs->ecdh_ctx);
-  ssl->s3->hs->retry_group = group_id;
-
+  hs->received_hello_retry_request = 1;
   hs->state = state_send_second_client_hello;
   return ssl_hs_ok;
 }
@@ -183,7 +245,7 @@
       case TLSEXT_TYPE_key_share:
         if (have_key_share) {
           OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION);
-          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
           return ssl_hs_error;
         }
         key_share = extension;
@@ -192,7 +254,7 @@
       case TLSEXT_TYPE_pre_shared_key:
         if (have_pre_shared_key) {
           OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION);
-          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
           return ssl_hs_error;
         }
         pre_shared_key = extension;
@@ -201,7 +263,7 @@
       case TLSEXT_TYPE_signature_algorithms:
         if (have_sigalgs) {
           OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION);
-          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
           return ssl_hs_error;
         }
         sigalgs = extension;
@@ -318,7 +380,7 @@
 
   /* If there was no HelloRetryRequest, the version negotiation logic has
    * already hashed the message. */
-  if (ssl->s3->hs->retry_group != 0 &&
+  if (hs->received_hello_retry_request &&
       !ssl->method->hash_current_message(ssl)) {
     return ssl_hs_error;
   }
@@ -359,8 +421,6 @@
 
 static enum ssl_hs_wait_t do_process_certificate_request(SSL *ssl,
                                                          SSL_HANDSHAKE *hs) {
-  ssl->s3->tmp.cert_request = 0;
-
   /* CertificateRequest may only be sent in non-resumption handshakes. */
   if (ssl->s3->session_reused) {
     hs->state = state_process_server_finished;
@@ -403,9 +463,9 @@
     return ssl_hs_error;
   }
 
-  ssl->s3->tmp.cert_request = 1;
-  sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free);
-  ssl->s3->tmp.ca_names = ca_sk;
+  ssl->s3->hs->cert_request = 1;
+  sk_X509_NAME_pop_free(ssl->s3->hs->ca_names, X509_NAME_free);
+  ssl->s3->hs->ca_names = ca_sk;
 
   if (!ssl->method->hash_current_message(ssl)) {
     return ssl_hs_error;
@@ -458,7 +518,7 @@
 
 static enum ssl_hs_wait_t do_certificate_callback(SSL *ssl, SSL_HANDSHAKE *hs) {
   /* The peer didn't request a certificate. */
-  if (!ssl->s3->tmp.cert_request) {
+  if (!ssl->s3->hs->cert_request) {
     hs->state = state_send_client_finished;
     return ssl_hs_ok;
   }
@@ -538,9 +598,9 @@
 
 static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
   if (!tls13_set_traffic_key(ssl, type_data, evp_aead_open,
-                             hs->traffic_secret_0, hs->hash_len) ||
+                             hs->server_traffic_secret_0, hs->hash_len) ||
       !tls13_set_traffic_key(ssl, type_data, evp_aead_seal,
-                             hs->traffic_secret_0, hs->hash_len) ||
+                             hs->client_traffic_secret_0, hs->hash_len) ||
       !tls13_finalize_keys(ssl)) {
     return ssl_hs_error;
   }
diff --git a/src/ssl/tls13_enc.c b/src/ssl/tls13_enc.c
index 88fe8f0..1fcde51 100644
--- a/src/ssl/tls13_enc.c
+++ b/src/ssl/tls13_enc.c
@@ -134,42 +134,27 @@
     return 0;
   }
 
-  const char *phase;
+  const char *key_label, *iv_label;
   switch (type) {
     case type_early_handshake:
-      phase = "early handshake key expansion, ";
+      key_label = "early handshake key expansion, key";
+      iv_label = "early handshake key expansion, iv";
       break;
     case type_early_data:
-      phase = "early application data key expansion, ";
+      key_label = "early application data key expansion, key";
+      iv_label = "early application data key expansion, iv";
       break;
     case type_handshake:
-      phase = "handshake key expansion, ";
+      key_label = "handshake key expansion, key";
+      iv_label = "handshake key expansion, iv";
       break;
     case type_data:
-      phase = "application data key expansion, ";
+      key_label = "application data key expansion, key";
+      iv_label = "application data key expansion, iv";
       break;
     default:
       return 0;
   }
-  size_t phase_len = strlen(phase);
-
-  const char *purpose = "client write key";
-  if ((ssl->server && direction == evp_aead_seal) ||
-      (!ssl->server && direction == evp_aead_open)) {
-    purpose = "server write key";
-  }
-  size_t purpose_len = strlen(purpose);
-
-  /* The longest label has length 38 (type_early_data) + 16 (either purpose
-   * value). */
-  uint8_t label[38 + 16];
-  size_t label_len = phase_len + purpose_len;
-  if (label_len > sizeof(label)) {
-    assert(0);
-    return 0;
-  }
-  memcpy(label, phase, phase_len);
-  memcpy(label + phase_len, purpose, purpose_len);
 
   /* Look up cipher suite properties. */
   const EVP_AEAD *aead;
@@ -184,25 +169,18 @@
   /* Derive the key. */
   size_t key_len = EVP_AEAD_key_length(aead);
   uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
-  if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, label,
-                         label_len, NULL, 0, key_len)) {
+  if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len,
+                         (const uint8_t *)key_label, strlen(key_label), NULL, 0,
+                         key_len)) {
     return 0;
   }
 
-  /* The IV's label ends in "iv" instead of "key". */
-  if (label_len < 3) {
-    assert(0);
-    return 0;
-  }
-  label_len--;
-  label[label_len - 2] = 'i';
-  label[label_len - 1] = 'v';
-
   /* Derive the IV. */
   size_t iv_len = EVP_AEAD_nonce_length(aead);
   uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH];
-  if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, label,
-                         label_len, NULL, 0, iv_len)) {
+  if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len,
+                         (const uint8_t *)iv_label, strlen(iv_label), NULL, 0,
+                         iv_len)) {
     return 0;
   }
 
@@ -235,38 +213,69 @@
   return 1;
 }
 
-static const char kTLS13LabelHandshakeTraffic[] = "handshake traffic secret";
-static const char kTLS13LabelApplicationTraffic[] =
-    "application traffic secret";
+static const char kTLS13LabelClientHandshakeTraffic[] =
+    "client handshake traffic secret";
+static const char kTLS13LabelServerHandshakeTraffic[] =
+    "server handshake traffic secret";
+static const char kTLS13LabelClientApplicationTraffic[] =
+    "client application traffic secret";
+static const char kTLS13LabelServerApplicationTraffic[] =
+    "server application traffic secret";
 
 int tls13_set_handshake_traffic(SSL *ssl) {
   SSL_HANDSHAKE *hs = ssl->s3->hs;
 
-  uint8_t traffic_secret[EVP_MAX_MD_SIZE];
-  if (!derive_secret(ssl, traffic_secret, hs->hash_len,
-                     (const uint8_t *)kTLS13LabelHandshakeTraffic,
-                     strlen(kTLS13LabelHandshakeTraffic)) ||
-      !ssl_log_secret(ssl, "HANDSHAKE_TRAFFIC_SECRET", traffic_secret,
-                      hs->hash_len) ||
-      !tls13_set_traffic_key(ssl, type_handshake, evp_aead_open, traffic_secret,
-                             hs->hash_len) ||
-      !tls13_set_traffic_key(ssl, type_handshake, evp_aead_seal, traffic_secret,
-                             hs->hash_len)) {
+  uint8_t client_traffic_secret[EVP_MAX_MD_SIZE];
+  uint8_t server_traffic_secret[EVP_MAX_MD_SIZE];
+  if (!derive_secret(ssl, client_traffic_secret, hs->hash_len,
+                     (const uint8_t *)kTLS13LabelClientHandshakeTraffic,
+                     strlen(kTLS13LabelClientHandshakeTraffic)) ||
+      !ssl_log_secret(ssl, "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
+                      client_traffic_secret, hs->hash_len) ||
+      !derive_secret(ssl, server_traffic_secret, hs->hash_len,
+                     (const uint8_t *)kTLS13LabelServerHandshakeTraffic,
+                     strlen(kTLS13LabelServerHandshakeTraffic)) ||
+      !ssl_log_secret(ssl, "SERVER_HANDSHAKE_TRAFFIC_SECRET",
+                      server_traffic_secret, hs->hash_len)) {
     return 0;
   }
+
+  if (ssl->server) {
+    if (!tls13_set_traffic_key(ssl, type_handshake, evp_aead_open,
+                               client_traffic_secret, hs->hash_len) ||
+        !tls13_set_traffic_key(ssl, type_handshake, evp_aead_seal,
+                               server_traffic_secret, hs->hash_len)) {
+      return 0;
+    }
+  } else {
+    if (!tls13_set_traffic_key(ssl, type_handshake, evp_aead_open,
+                               server_traffic_secret, hs->hash_len) ||
+        !tls13_set_traffic_key(ssl, type_handshake, evp_aead_seal,
+                               client_traffic_secret, hs->hash_len)) {
+      return 0;
+    }
+  }
   return 1;
 }
 
 int tls13_derive_traffic_secret_0(SSL *ssl) {
   SSL_HANDSHAKE *hs = ssl->s3->hs;
 
-  return derive_secret(ssl, hs->traffic_secret_0, hs->hash_len,
-                       (const uint8_t *)kTLS13LabelApplicationTraffic,
-                       strlen(kTLS13LabelApplicationTraffic)) &&
-         ssl_log_secret(ssl, "TRAFFIC_SECRET_0", hs->traffic_secret_0,
-                        hs->hash_len);
+  return derive_secret(ssl, hs->client_traffic_secret_0, hs->hash_len,
+                       (const uint8_t *)kTLS13LabelClientApplicationTraffic,
+                       strlen(kTLS13LabelClientApplicationTraffic)) &&
+         ssl_log_secret(ssl, "CLIENT_TRAFFIC_SECRET_0",
+                        hs->client_traffic_secret_0, hs->hash_len) &&
+         derive_secret(ssl, hs->server_traffic_secret_0, hs->hash_len,
+                       (const uint8_t *)kTLS13LabelServerApplicationTraffic,
+                       strlen(kTLS13LabelServerApplicationTraffic)) &&
+         ssl_log_secret(ssl, "SERVER_TRAFFIC_SECRET_0",
+                        hs->server_traffic_secret_0, hs->hash_len);
 }
 
+static const char kTLS13LabelApplicationTraffic[] =
+    "application traffic secret";
+
 int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) {
   const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
 
@@ -319,21 +328,11 @@
   size_t key_len = EVP_MD_size(digest);
 
   const uint8_t *traffic_secret;
-  const char *label;
-  if (is_server) {
-    label = "server finished";
-    if (ssl->server) {
-      traffic_secret = ssl->s3->write_traffic_secret;
-    } else {
-      traffic_secret = ssl->s3->read_traffic_secret;
-    }
+  const char *label = "finished";
+  if (is_server == ssl->server) {
+    traffic_secret = ssl->s3->write_traffic_secret;
   } else {
-    label = "client finished";
-    if (!ssl->server) {
-      traffic_secret = ssl->s3->write_traffic_secret;
-    } else {
-      traffic_secret = ssl->s3->read_traffic_secret;
-    }
+    traffic_secret = ssl->s3->read_traffic_secret;
   }
 
   uint8_t context_hashes[2 * EVP_MAX_MD_SIZE];
diff --git a/src/ssl/tls13_server.c b/src/ssl/tls13_server.c
index 984cc5c..2570069 100644
--- a/src/ssl/tls13_server.c
+++ b/src/ssl/tls13_server.c
@@ -254,10 +254,11 @@
   if (!ssl->method->init_message(ssl, &cbb, &body,
                                  SSL3_MT_HELLO_RETRY_REQUEST) ||
       !CBB_add_u16(&body, ssl->version) ||
-      !CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
       !tls1_get_shared_group(ssl, &group_id) ||
-      !CBB_add_u16(&body, group_id) ||
       !CBB_add_u16_length_prefixed(&body, &extensions) ||
+      !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
+      !CBB_add_u16(&extensions, 2 /* length */) ||
+      !CBB_add_u16(&extensions, group_id) ||
       !ssl->method->finish_message(ssl, &cbb)) {
     CBB_cleanup(&cbb);
     return ssl_hs_error;
@@ -360,13 +361,13 @@
 static enum ssl_hs_wait_t do_send_certificate_request(SSL *ssl,
                                                       SSL_HANDSHAKE *hs) {
   /* Determine whether to request a client certificate. */
-  ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+  ssl->s3->hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
   /* CertificateRequest may only be sent in non-resumption handshakes. */
   if (ssl->s3->session_reused) {
-    ssl->s3->tmp.cert_request = 0;
+    ssl->s3->hs->cert_request = 0;
   }
 
-  if (!ssl->s3->tmp.cert_request) {
+  if (!ssl->s3->hs->cert_request) {
     /* Skip this state. */
     hs->state = state_send_server_certificate;
     return ssl_hs_ok;
@@ -380,7 +381,7 @@
   }
 
   const uint16_t *sigalgs;
-  size_t num_sigalgs = tls12_get_psigalgs(ssl, &sigalgs);
+  size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
   if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
     goto err;
   }
@@ -459,7 +460,7 @@
   if (!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
       !tls13_derive_traffic_secret_0(ssl) ||
       !tls13_set_traffic_key(ssl, type_data, evp_aead_seal,
-                             hs->traffic_secret_0, hs->hash_len)) {
+                             hs->server_traffic_secret_0, hs->hash_len)) {
     return ssl_hs_error;
   }
 
@@ -469,7 +470,7 @@
 
 static enum ssl_hs_wait_t do_process_client_certificate(SSL *ssl,
                                                         SSL_HANDSHAKE *hs) {
-  if (!ssl->s3->tmp.cert_request) {
+  if (!ssl->s3->hs->cert_request) {
     /* OpenSSL returns X509_V_OK when no certificates are requested. This is
      * classed by them as a bug, but it's assumed by at least NGINX. */
     ssl->s3->new_session->verify_result = X509_V_OK;
@@ -523,7 +524,7 @@
       !ssl->method->hash_current_message(ssl) ||
       /* evp_aead_seal keys have already been switched. */
       !tls13_set_traffic_key(ssl, type_data, evp_aead_open,
-                             hs->traffic_secret_0, hs->hash_len) ||
+                             hs->client_traffic_secret_0, hs->hash_len) ||
       !tls13_finalize_keys(ssl)) {
     return ssl_hs_error;
   }
@@ -541,7 +542,7 @@
   /* TODO(svaldez): Add support for sending 0RTT through TicketEarlyDataInfo
    * extension. */
 
-  CBB cbb, body, ke_modes, auth_modes, ticket;
+  CBB cbb, body, ke_modes, auth_modes, ticket, extensions;
   if (!ssl->method->init_message(ssl, &cbb, &body,
                                  SSL3_MT_NEW_SESSION_TICKET) ||
       !CBB_add_u32(&body, session->tlsext_tick_lifetime_hint) ||
@@ -551,16 +552,31 @@
       !CBB_add_u8(&auth_modes, SSL_PSK_AUTH) ||
       !CBB_add_u16_length_prefixed(&body, &ticket) ||
       !ssl_encrypt_ticket(ssl, &ticket, session) ||
-      !CBB_add_u16(&body, 0 /* no ticket extensions */) ||
-      !ssl->method->finish_message(ssl, &cbb)) {
-    CBB_cleanup(&cbb);
-    return ssl_hs_error;
+      !CBB_add_u16_length_prefixed(&body, &extensions)) {
+    goto err;
+  }
+
+  /* Add a fake extension. See draft-davidben-tls-grease-01. */
+  if (ssl->ctx->grease_enabled) {
+    if (!CBB_add_u16(&extensions,
+                     ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
+        !CBB_add_u16(&extensions, 0 /* empty */)) {
+      goto err;
+    }
+  }
+
+  if (!ssl->method->finish_message(ssl, &cbb)) {
+    goto err;
   }
 
   hs->session_tickets_sent++;
 
   hs->state = state_flush_new_session_ticket;
   return ssl_hs_write_message;
+
+err:
+  CBB_cleanup(&cbb);
+  return ssl_hs_error;
 }
 
 /* TLS 1.3 recommends single-use tickets, so issue multiple tickets in case the
diff --git a/src/tool/transport_common.cc b/src/tool/transport_common.cc
index 9a3612c..d5326b5 100644
--- a/src/tool/transport_common.cc
+++ b/src/tool/transport_common.cc
@@ -40,7 +40,7 @@
 OPENSSL_MSVC_PRAGMA(warning(pop))
 
 typedef int ssize_t;
-#pragma comment(lib, "Ws2_32.lib")
+OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
 #endif
 
 #include <openssl/err.h>