external/boringssl: Sync to 56b6c714c9cae5963681ed9dd9f6cabf294e3f80.

This includes the following changes:

https://boringssl.googlesource.com/boringssl/+log/6e7255c17e1a7348a2377fbc804441dd284806e2..56b6c714c9cae5963681ed9dd9f6cabf294e3f80

Test: atest CtsLibcoreTestCases CtsLibcoreOkHttpTestCases
Change-Id: I9977c8fa204dd39e5b6c71abdb85d055e842bf4e
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index 6356531..b88723d 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-6e7255c17e1a7348a2377fbc804441dd284806e2
+56b6c714c9cae5963681ed9dd9f6cabf294e3f80
diff --git a/linux-aarch64/crypto/chacha/chacha-armv8.S b/linux-aarch64/crypto/chacha/chacha-armv8.S
index e05a265..3a39034 100644
--- a/linux-aarch64/crypto/chacha/chacha-armv8.S
+++ b/linux-aarch64/crypto/chacha/chacha-armv8.S
@@ -1980,5 +1980,6 @@
 	ldp	x29,x30,[sp],#96
 	ret
 .size	ChaCha20_512_neon,.-ChaCha20_512_neon
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S b/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S
index 1680444..4ab36b8 100644
--- a/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S
+++ b/linux-aarch64/crypto/fipsmodule/aesv8-armx64.S
@@ -770,5 +770,6 @@
 	ret
 .size	aes_hw_ctr32_encrypt_blocks,.-aes_hw_ctr32_encrypt_blocks
 #endif
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-aarch64/crypto/fipsmodule/armv8-mont.S b/linux-aarch64/crypto/fipsmodule/armv8-mont.S
index 1ea05ba..ccee888 100644
--- a/linux-aarch64/crypto/fipsmodule/armv8-mont.S
+++ b/linux-aarch64/crypto/fipsmodule/armv8-mont.S
@@ -1418,5 +1418,6 @@
 .byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	4
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S b/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S
index 3567683..9cd7351 100644
--- a/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S
+++ b/linux-aarch64/crypto/fipsmodule/ghash-neon-armv8.S
@@ -336,5 +336,6 @@
 .byte	71,72,65,83,72,32,102,111,114,32,65,82,77,118,56,44,32,100,101,114,105,118,101,100,32,102,114,111,109,32,65,82,77,118,52,32,118,101,114,115,105,111,110,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	2
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S b/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S
index 1267937..267cdd1 100644
--- a/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S
+++ b/linux-aarch64/crypto/fipsmodule/ghashv8-armx64.S
@@ -244,5 +244,6 @@
 .byte	71,72,65,83,72,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	2
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-aarch64/crypto/fipsmodule/sha1-armv8.S b/linux-aarch64/crypto/fipsmodule/sha1-armv8.S
index ecb4885..a378181 100644
--- a/linux-aarch64/crypto/fipsmodule/sha1-armv8.S
+++ b/linux-aarch64/crypto/fipsmodule/sha1-armv8.S
@@ -1230,5 +1230,6 @@
 .align	2
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-aarch64/crypto/fipsmodule/sha256-armv8.S b/linux-aarch64/crypto/fipsmodule/sha256-armv8.S
index b319688..c4d8871 100644
--- a/linux-aarch64/crypto/fipsmodule/sha256-armv8.S
+++ b/linux-aarch64/crypto/fipsmodule/sha256-armv8.S
@@ -1208,5 +1208,6 @@
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
 #endif
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-aarch64/crypto/fipsmodule/sha512-armv8.S b/linux-aarch64/crypto/fipsmodule/sha512-armv8.S
index 37e00d7..134f405 100644
--- a/linux-aarch64/crypto/fipsmodule/sha512-armv8.S
+++ b/linux-aarch64/crypto/fipsmodule/sha512-armv8.S
@@ -1080,5 +1080,6 @@
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
 #endif
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S b/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S
index 3a34209..bd46e53 100644
--- a/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S
+++ b/linux-aarch64/crypto/fipsmodule/vpaes-armv8.S
@@ -1211,5 +1211,6 @@
 	ldp	x29,x30,[sp],#16
 	ret
 .size	vpaes_ctr32_encrypt_blocks,.-vpaes_ctr32_encrypt_blocks
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-aarch64/crypto/test/trampoline-armv8.S b/linux-aarch64/crypto/test/trampoline-armv8.S
index f5296f6..df30630 100644
--- a/linux-aarch64/crypto/test/trampoline-armv8.S
+++ b/linux-aarch64/crypto/test/trampoline-armv8.S
@@ -683,5 +683,6 @@
 	fmov	v15.d[1], xzr
 	ret
 .size	abi_test_clobber_v15_upper,.-abi_test_clobber_v15_upper
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-aarch64/crypto/third_party/sike/asm/fp-armv8.S b/linux-aarch64/crypto/third_party/sike/asm/fp-armv8.S
index da49a40..02e5332 100644
--- a/linux-aarch64/crypto/third_party/sike/asm/fp-armv8.S
+++ b/linux-aarch64/crypto/third_party/sike/asm/fp-armv8.S
@@ -994,5 +994,6 @@
 
 	ldp	x29, x30, [sp],#16
 	ret
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/chacha/chacha-armv4.S b/linux-arm/crypto/chacha/chacha-armv4.S
index aed7ca6..f9202a3 100644
--- a/linux-arm/crypto/chacha/chacha-armv4.S
+++ b/linux-arm/crypto/chacha/chacha-armv4.S
@@ -1488,5 +1488,6 @@
 .size	ChaCha20_neon,.-ChaCha20_neon
 .comm	OPENSSL_armcap_P,4,4
 #endif
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/fipsmodule/aes-armv4.S b/linux-arm/crypto/fipsmodule/aes-armv4.S
index b2966b4..e4b09b3 100644
--- a/linux-arm/crypto/fipsmodule/aes-armv4.S
+++ b/linux-arm/crypto/fipsmodule/aes-armv4.S
@@ -1217,5 +1217,6 @@
 .byte	65,69,83,32,102,111,114,32,65,82,77,118,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	2
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/fipsmodule/aesv8-armx32.S b/linux-arm/crypto/fipsmodule/aesv8-armx32.S
index 3a2d2e4..b768742 100644
--- a/linux-arm/crypto/fipsmodule/aesv8-armx32.S
+++ b/linux-arm/crypto/fipsmodule/aesv8-armx32.S
@@ -776,5 +776,6 @@
 	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,pc}
 .size	aes_hw_ctr32_encrypt_blocks,.-aes_hw_ctr32_encrypt_blocks
 #endif
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/fipsmodule/armv4-mont.S b/linux-arm/crypto/fipsmodule/armv4-mont.S
index 12ebe40..ffbc2ef 100644
--- a/linux-arm/crypto/fipsmodule/armv4-mont.S
+++ b/linux-arm/crypto/fipsmodule/armv4-mont.S
@@ -972,5 +972,6 @@
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
 #endif
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/fipsmodule/bsaes-armv7.S b/linux-arm/crypto/fipsmodule/bsaes-armv7.S
index f6cec3d..6058d47 100644
--- a/linux-arm/crypto/fipsmodule/bsaes-armv7.S
+++ b/linux-arm/crypto/fipsmodule/bsaes-armv7.S
@@ -1524,5 +1524,6 @@
 	@ out to retain a constant-time implementation.
 .size	bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
 #endif
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/fipsmodule/ghash-armv4.S b/linux-arm/crypto/fipsmodule/ghash-armv4.S
index a0fa53c..800f450 100644
--- a/linux-arm/crypto/fipsmodule/ghash-armv4.S
+++ b/linux-arm/crypto/fipsmodule/ghash-armv4.S
@@ -586,5 +586,6 @@
 .byte	71,72,65,83,72,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	2
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/fipsmodule/ghashv8-armx32.S b/linux-arm/crypto/fipsmodule/ghashv8-armx32.S
index 65c9f22..50333c8 100644
--- a/linux-arm/crypto/fipsmodule/ghashv8-armx32.S
+++ b/linux-arm/crypto/fipsmodule/ghashv8-armx32.S
@@ -248,5 +248,6 @@
 .byte	71,72,65,83,72,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	2
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/fipsmodule/sha1-armv4-large.S b/linux-arm/crypto/fipsmodule/sha1-armv4-large.S
index 2b70a32..afb0a00 100644
--- a/linux-arm/crypto/fipsmodule/sha1-armv4-large.S
+++ b/linux-arm/crypto/fipsmodule/sha1-armv4-large.S
@@ -1506,5 +1506,6 @@
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
 #endif
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/fipsmodule/sha256-armv4.S b/linux-arm/crypto/fipsmodule/sha256-armv4.S
index 1928075..1cf4285 100644
--- a/linux-arm/crypto/fipsmodule/sha256-armv4.S
+++ b/linux-arm/crypto/fipsmodule/sha256-armv4.S
@@ -2834,5 +2834,6 @@
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
 #endif
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/fipsmodule/sha512-armv4.S b/linux-arm/crypto/fipsmodule/sha512-armv4.S
index c44fcc6..d59a389 100644
--- a/linux-arm/crypto/fipsmodule/sha512-armv4.S
+++ b/linux-arm/crypto/fipsmodule/sha512-armv4.S
@@ -1889,5 +1889,6 @@
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
 #endif
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/fipsmodule/vpaes-armv7.S b/linux-arm/crypto/fipsmodule/vpaes-armv7.S
index 9124ce2..a10e723 100644
--- a/linux-arm/crypto/fipsmodule/vpaes-armv7.S
+++ b/linux-arm/crypto/fipsmodule/vpaes-armv7.S
@@ -1231,5 +1231,6 @@
 	vldmia	sp!, {d8,d9,d10,d11,d12,d13,d14,d15}
 	ldmia	sp!, {r7,r8,r9,r10,r11, pc}	@ return
 .size	vpaes_ctr32_encrypt_blocks,.-vpaes_ctr32_encrypt_blocks
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-arm/crypto/test/trampoline-armv4.S b/linux-arm/crypto/test/trampoline-armv4.S
index e526e99..c184bb3 100644
--- a/linux-arm/crypto/test/trampoline-armv4.S
+++ b/linux-arm/crypto/test/trampoline-armv4.S
@@ -375,5 +375,6 @@
 	vmov	s31, r0
 	bx	lr
 .size	abi_test_clobber_d15,.-abi_test_clobber_d15
+.section	.note.GNU-stack,"",%progbits
 #endif
 #endif  // !OPENSSL_NO_ASM
diff --git a/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S b/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S
index 911d638..462afdf 100644
--- a/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S
+++ b/linux-ppc64le/crypto/fipsmodule/aesp8-ppc.S
@@ -3666,4 +3666,5 @@
 	blr	
 .long	0
 .byte	0,12,0x14,0,0,0,0,0
+.section	.note.GNU-stack,"",@progbits
 #endif  // !OPENSSL_NO_ASM && __powerpc64__
diff --git a/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S b/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S
index 88a8a25..50c5d80 100644
--- a/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S
+++ b/linux-ppc64le/crypto/fipsmodule/ghashp8-ppc.S
@@ -583,4 +583,5 @@
 .byte	71,72,65,83,72,32,102,111,114,32,80,111,119,101,114,73,83,65,32,50,46,48,55,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	2
+.section	.note.GNU-stack,"",@progbits
 #endif  // !OPENSSL_NO_ASM && __powerpc64__
diff --git a/linux-x86/crypto/chacha/chacha-x86.S b/linux-x86/crypto/chacha/chacha-x86.S
index 287b62a..389cecc 100644
--- a/linux-x86/crypto/chacha/chacha-x86.S
+++ b/linux-x86/crypto/chacha/chacha-x86.S
@@ -971,4 +971,5 @@
 .byte	44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32
 .byte	60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111
 .byte	114,103,62,0
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/aes-586.S b/linux-x86/crypto/fipsmodule/aes-586.S
index c8eeee5..d949f7d 100644
--- a/linux-x86/crypto/fipsmodule/aes-586.S
+++ b/linux-x86/crypto/fipsmodule/aes-586.S
@@ -3259,4 +3259,5 @@
 .byte	65,69,83,32,102,111,114,32,120,56,54,44,32,67,82,89
 .byte	80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114
 .byte	111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/aesni-x86.S b/linux-x86/crypto/fipsmodule/aesni-x86.S
index 671c79e..99410d9 100644
--- a/linux-x86/crypto/fipsmodule/aesni-x86.S
+++ b/linux-x86/crypto/fipsmodule/aesni-x86.S
@@ -2509,4 +2509,5 @@
 .byte	83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83
 .byte	32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115
 .byte	115,108,46,111,114,103,62,0
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/bn-586.S b/linux-x86/crypto/fipsmodule/bn-586.S
index 64e36ce..d2cd647 100644
--- a/linux-x86/crypto/fipsmodule/bn-586.S
+++ b/linux-x86/crypto/fipsmodule/bn-586.S
@@ -1540,4 +1540,5 @@
 	popl	%ebp
 	ret
 .size	bn_sub_part_words,.-.L_bn_sub_part_words_begin
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/co-586.S b/linux-x86/crypto/fipsmodule/co-586.S
index b617d81..3b77452 100644
--- a/linux-x86/crypto/fipsmodule/co-586.S
+++ b/linux-x86/crypto/fipsmodule/co-586.S
@@ -1262,4 +1262,5 @@
 	popl	%esi
 	ret
 .size	bn_sqr_comba4,.-.L_bn_sqr_comba4_begin
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S b/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S
index 7aa0ea5..4687715 100644
--- a/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S
+++ b/linux-x86/crypto/fipsmodule/ghash-ssse3-x86.S
@@ -290,4 +290,5 @@
 .align	16
 .Llow4_mask:
 .long	252645135,252645135,252645135,252645135
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/ghash-x86.S b/linux-x86/crypto/fipsmodule/ghash-x86.S
index e183078..c691f0a 100644
--- a/linux-x86/crypto/fipsmodule/ghash-x86.S
+++ b/linux-x86/crypto/fipsmodule/ghash-x86.S
@@ -1071,4 +1071,5 @@
 .byte	82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112
 .byte	112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62
 .byte	0
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/md5-586.S b/linux-x86/crypto/fipsmodule/md5-586.S
index cc0dcd8..22e0a29 100644
--- a/linux-x86/crypto/fipsmodule/md5-586.S
+++ b/linux-x86/crypto/fipsmodule/md5-586.S
@@ -684,4 +684,5 @@
 	popl	%esi
 	ret
 .size	md5_block_asm_data_order,.-.L_md5_block_asm_data_order_begin
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/sha1-586.S b/linux-x86/crypto/fipsmodule/sha1-586.S
index 4df4d06..4165f12 100644
--- a/linux-x86/crypto/fipsmodule/sha1-586.S
+++ b/linux-x86/crypto/fipsmodule/sha1-586.S
@@ -3804,4 +3804,5 @@
 .byte	102,111,114,109,32,102,111,114,32,120,56,54,44,32,67,82
 .byte	89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112
 .byte	114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/sha256-586.S b/linux-x86/crypto/fipsmodule/sha256-586.S
index 39d5778..f9cecb3 100644
--- a/linux-x86/crypto/fipsmodule/sha256-586.S
+++ b/linux-x86/crypto/fipsmodule/sha256-586.S
@@ -5563,4 +5563,5 @@
 	popl	%ebp
 	ret
 .size	sha256_block_data_order,.-.L_sha256_block_data_order_begin
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/sha512-586.S b/linux-x86/crypto/fipsmodule/sha512-586.S
index c8dd677..89fc8b5 100644
--- a/linux-x86/crypto/fipsmodule/sha512-586.S
+++ b/linux-x86/crypto/fipsmodule/sha512-586.S
@@ -2833,4 +2833,5 @@
 .byte	67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97
 .byte	112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103
 .byte	62,0
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/vpaes-x86.S b/linux-x86/crypto/fipsmodule/vpaes-x86.S
index 7200cfd..c36a8b8 100644
--- a/linux-x86/crypto/fipsmodule/vpaes-x86.S
+++ b/linux-x86/crypto/fipsmodule/vpaes-x86.S
@@ -704,4 +704,5 @@
 	popl	%ebp
 	ret
 .size	vpaes_cbc_encrypt,.-.L_vpaes_cbc_encrypt_begin
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/fipsmodule/x86-mont.S b/linux-x86/crypto/fipsmodule/x86-mont.S
index 9924c02..8b7dedd 100644
--- a/linux-x86/crypto/fipsmodule/x86-mont.S
+++ b/linux-x86/crypto/fipsmodule/x86-mont.S
@@ -480,4 +480,5 @@
 .byte	54,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121
 .byte	32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46
 .byte	111,114,103,62,0
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86/crypto/test/trampoline-x86.S b/linux-x86/crypto/test/trampoline-x86.S
index 2222347..56b9a90 100644
--- a/linux-x86/crypto/test/trampoline-x86.S
+++ b/linux-x86/crypto/test/trampoline-x86.S
@@ -202,4 +202,5 @@
 	pxor	%xmm7,%xmm7
 	ret
 .size	abi_test_clobber_xmm7,.-.L_abi_test_clobber_xmm7_begin
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/chacha/chacha-x86_64.S b/linux-x86_64/crypto/chacha/chacha-x86_64.S
index 4e2267b..2d8cd97 100644
--- a/linux-x86_64/crypto/chacha/chacha-x86_64.S
+++ b/linux-x86_64/crypto/chacha/chacha-x86_64.S
@@ -1629,4 +1629,5 @@
 	.byte	0xf3,0xc3
 .cfi_endproc	
 .size	ChaCha20_8x,.-ChaCha20_8x
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S b/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S
index 3eb1688..97fb817 100644
--- a/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S
+++ b/linux-x86_64/crypto/cipher_extra/aes128gcmsiv-x86_64.S
@@ -3075,4 +3075,5 @@
 	.byte	0xf3,0xc3
 .cfi_endproc	
 .size	aes256gcmsiv_kdf, .-aes256gcmsiv_kdf
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S b/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S
index 677335b..def3d5b 100644
--- a/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S
+++ b/linux-x86_64/crypto/cipher_extra/chacha20_poly1305_x86_64.S
@@ -8983,4 +8983,5 @@
 	vzeroupper
 	jmp	seal_sse_tail_16
 .cfi_endproc	
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/aes-x86_64.S b/linux-x86_64/crypto/fipsmodule/aes-x86_64.S
index f45e010..65de7b2 100644
--- a/linux-x86_64/crypto/fipsmodule/aes-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/aes-x86_64.S
@@ -2661,4 +2661,5 @@
 .long	0x1b1b1b1b, 0x1b1b1b1b, 0, 0
 .byte	65,69,83,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	64
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S b/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S
index 98365a8..c033966 100644
--- a/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/aesni-gcm-x86_64.S
@@ -848,4 +848,5 @@
 .byte	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 .byte	65,69,83,45,78,73,32,71,67,77,32,109,111,100,117,108,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	64
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S b/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S
index de30953..660564b 100644
--- a/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/aesni-x86_64.S
@@ -2502,4 +2502,5 @@
 
 .byte	65,69,83,32,102,111,114,32,73,110,116,101,108,32,65,69,83,45,78,73,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	64
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S b/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S
index ecf5b66..236df16 100644
--- a/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/ghash-ssse3-x86_64.S
@@ -423,4 +423,5 @@
 
 .Llow4_mask:
 .quad	0x0f0f0f0f0f0f0f0f, 0x0f0f0f0f0f0f0f0f
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S b/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S
index 0b36afa..6cdc8cd 100644
--- a/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/ghash-x86_64.S
@@ -1868,4 +1868,5 @@
 
 .byte	71,72,65,83,72,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	64
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/md5-x86_64.S b/linux-x86_64/crypto/fipsmodule/md5-x86_64.S
index 18e2e92..848f695 100644
--- a/linux-x86_64/crypto/fipsmodule/md5-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/md5-x86_64.S
@@ -698,4 +698,5 @@
 	.byte	0xf3,0xc3
 .cfi_endproc	
 .size	md5_block_asm_data_order,.-md5_block_asm_data_order
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S b/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S
index 067575e..b5218c5 100644
--- a/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S
+++ b/linux-x86_64/crypto/fipsmodule/p256-x86_64-asm.S
@@ -4539,4 +4539,5 @@
 	.byte	0xf3,0xc3
 .cfi_endproc	
 .size	ecp_nistz256_point_add_affinex,.-ecp_nistz256_point_add_affinex
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S b/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S
index 5dfecc8..7d8b307 100644
--- a/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S
+++ b/linux-x86_64/crypto/fipsmodule/p256_beeu-x86_64-asm.S
@@ -339,4 +339,5 @@
 .cfi_endproc	
 
 .size	beeu_mod_inverse_vartime, .-beeu_mod_inverse_vartime
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S b/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S
index fefccd6..3c6aeb8 100644
--- a/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/rdrand-x86_64.S
@@ -59,4 +59,5 @@
 	.byte	0xf3,0xc3
 .cfi_endproc	
 .size	CRYPTO_rdrand_multiple8_buf,.-CRYPTO_rdrand_multiple8_buf
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S b/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S
index 579c705..18e5eca 100644
--- a/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S
+++ b/linux-x86_64/crypto/fipsmodule/rsaz-avx2.S
@@ -1745,4 +1745,5 @@
 .long	2,2,2,2, 3,3,3,3
 .long	4,4,4,4, 4,4,4,4
 .align	64
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S b/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S
index 044f36f..c468196 100644
--- a/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/sha1-x86_64.S
@@ -3597,4 +3597,5 @@
 .byte	0xf,0xe,0xd,0xc,0xb,0xa,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
 .byte	83,72,65,49,32,98,108,111,99,107,32,116,114,97,110,115,102,111,114,109,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	64
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S b/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S
index 55b540f..f26b9b2 100644
--- a/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/sha256-x86_64.S
@@ -3969,4 +3969,5 @@
 	.byte	0xf3,0xc3
 .cfi_endproc	
 .size	sha256_block_data_order_avx,.-sha256_block_data_order_avx
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S b/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S
index 509e144..983f343 100644
--- a/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/sha512-x86_64.S
@@ -2988,4 +2988,5 @@
 	.byte	0xf3,0xc3
 .cfi_endproc	
 .size	sha512_block_data_order_avx,.-sha512_block_data_order_avx
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S b/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S
index 8546d0d..b87b947 100644
--- a/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S
+++ b/linux-x86_64/crypto/fipsmodule/vpaes-x86_64.S
@@ -1129,4 +1129,5 @@
 .byte	86,101,99,116,111,114,32,80,101,114,109,117,116,97,116,105,111,110,32,65,69,83,32,102,111,114,32,120,56,54,95,54,52,47,83,83,83,69,51,44,32,77,105,107,101,32,72,97,109,98,117,114,103,32,40,83,116,97,110,102,111,114,100,32,85,110,105,118,101,114,115,105,116,121,41,0
 .align	64
 .size	_vpaes_consts,.-_vpaes_consts
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/x86_64-mont.S b/linux-x86_64/crypto/fipsmodule/x86_64-mont.S
index f3637f0..40090d9 100644
--- a/linux-x86_64/crypto/fipsmodule/x86_64-mont.S
+++ b/linux-x86_64/crypto/fipsmodule/x86_64-mont.S
@@ -1256,4 +1256,5 @@
 .size	bn_mulx4x_mont,.-bn_mulx4x_mont
 .byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	16
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S b/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S
index b12393e..eec6992 100644
--- a/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S
+++ b/linux-x86_64/crypto/fipsmodule/x86_64-mont5.S
@@ -3786,4 +3786,5 @@
 .long	0,0, 1,1
 .long	2,2, 2,2
 .byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,119,105,116,104,32,115,99,97,116,116,101,114,47,103,97,116,104,101,114,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/test/trampoline-x86_64.S b/linux-x86_64/crypto/test/trampoline-x86_64.S
index 91a13f3..6424f73 100644
--- a/linux-x86_64/crypto/test/trampoline-x86_64.S
+++ b/linux-x86_64/crypto/test/trampoline-x86_64.S
@@ -514,4 +514,5 @@
 	std
 	.byte	0xf3,0xc3
 .size	abi_test_set_direction_flag,.-abi_test_set_direction_flag
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/linux-x86_64/crypto/third_party/sike/asm/fp-x86_64.S b/linux-x86_64/crypto/third_party/sike/asm/fp-x86_64.S
index 4b3c925..bb2f097 100644
--- a/linux-x86_64/crypto/third_party/sike/asm/fp-x86_64.S
+++ b/linux-x86_64/crypto/third_party/sike/asm/fp-x86_64.S
@@ -1867,4 +1867,5 @@
 .cfi_adjust_cfa_offset	-8
 	.byte	0xf3,0xc3
 .cfi_endproc	
+.section	.note.GNU-stack,"",@progbits
 #endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3fe86bf..66596af 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -117,7 +117,7 @@
 if(CMAKE_COMPILER_IS_GNUCXX OR CLANG)
   # Note clang-cl is odd and sets both CLANG and MSVC. We base our configuration
   # primarily on our normal Clang one.
-  set(C_CXX_FLAGS "-Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings")
+  set(C_CXX_FLAGS "-Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings -Wvla")
   if(MSVC)
     # clang-cl sets different default warnings than clang. It also treats -Wall
     # as -Weverything, to match MSVC. Instead -W3 is the alias for -Wall.
diff --git a/src/crypto/curve25519/asm/x25519-asm-arm.S b/src/crypto/curve25519/asm/x25519-asm-arm.S
index 905af07..9a26add 100644
--- a/src/crypto/curve25519/asm/x25519-asm-arm.S
+++ b/src/crypto/curve25519/asm/x25519-asm-arm.S
@@ -2129,4 +2129,8 @@
 vpop {q4,q5,q6,q7}
 bx lr
 
+#if defined(__ELF__)
+.section	.note.GNU-stack,"",%progbits
+#endif
+
 #endif  /* !OPENSSL_NO_ASM && __arm__ && !__APPLE__ */
diff --git a/src/crypto/fipsmodule/rand/internal.h b/src/crypto/fipsmodule/rand/internal.h
index c7ed74d..07563b7 100644
--- a/src/crypto/fipsmodule/rand/internal.h
+++ b/src/crypto/fipsmodule/rand/internal.h
@@ -41,6 +41,11 @@
 void CRYPTO_sysrand(uint8_t *buf, size_t len);
 
 #if defined(OPENSSL_URANDOM) && defined(BORINGSSL_FIPS)
+// CRYPTO_sysrand_for_seed fills |len| bytes at |buf| with entropy from the
+// operating system. It may draw from the |GRND_RANDOM| pool on Android,
+// depending on the vendor's configuration.
+void CRYPTO_sysrand_for_seed(uint8_t *buf, size_t len);
+
 // CRYPTO_sysrand_if_available fills |len| bytes at |buf| with entropy from the
 // operating system, if the entropy pool is initialized. If it is uninitialized,
 // it will not block and will instead fill |buf| with all zeros or early
diff --git a/src/crypto/fipsmodule/rand/rand.c b/src/crypto/fipsmodule/rand/rand.c
index 60e92c5..87d7b30 100644
--- a/src/crypto/fipsmodule/rand/rand.c
+++ b/src/crypto/fipsmodule/rand/rand.c
@@ -32,9 +32,9 @@
 
 
 // It's assumed that the operating system always has an unfailing source of
-// entropy which is accessed via |CRYPTO_sysrand|. (If the operating system
-// entropy source fails, it's up to |CRYPTO_sysrand| to abort the process—we
-// don't try to handle it.)
+// entropy which is accessed via |CRYPTO_sysrand[_for_seed]|. (If the operating
+// system entropy source fails, it's up to |CRYPTO_sysrand| to abort the
+// process—we don't try to handle it.)
 //
 // In addition, the hardware may provide a low-latency RNG. Intel's rdrand
 // instruction is the canonical example of this. When a hardware RNG is
@@ -61,11 +61,11 @@
   // (re)seeded. This is bound by |kReseedInterval|.
   unsigned calls;
   // last_block_valid is non-zero iff |last_block| contains data from
-  // |CRYPTO_sysrand|.
+  // |CRYPTO_sysrand_for_seed|.
   int last_block_valid;
 
 #if defined(BORINGSSL_FIPS)
-  // last_block contains the previous block from |CRYPTO_sysrand|.
+  // last_block contains the previous block from |CRYPTO_sysrand_for_seed|.
   uint8_t last_block[CRNGT_BLOCK_SIZE];
   // next and prev form a NULL-terminated, double-linked list of all states in
   // a process.
@@ -169,7 +169,7 @@
                           uint8_t seed[CTR_DRBG_ENTROPY_LEN]) {
   if (!state->last_block_valid) {
     if (!hwrand(state->last_block, sizeof(state->last_block))) {
-      CRYPTO_sysrand(state->last_block, sizeof(state->last_block));
+      CRYPTO_sysrand_for_seed(state->last_block, sizeof(state->last_block));
     }
     state->last_block_valid = 1;
   }
@@ -181,7 +181,7 @@
 
   int used_hwrand = hwrand(entropy, sizeof(entropy));
   if (!used_hwrand) {
-    CRYPTO_sysrand(entropy, sizeof(entropy));
+    CRYPTO_sysrand_for_seed(entropy, sizeof(entropy));
   }
 
   // See FIPS 140-2, section 4.9.2. This is the “continuous random number
diff --git a/src/crypto/fipsmodule/rand/urandom.c b/src/crypto/fipsmodule/rand/urandom.c
index 9fa0c97..33c0b03 100644
--- a/src/crypto/fipsmodule/rand/urandom.c
+++ b/src/crypto/fipsmodule/rand/urandom.c
@@ -36,6 +36,10 @@
 #endif
 #include <sys/syscall.h>
 
+#if defined(OPENSSL_ANDROID)
+#include <sys/system_properties.h>
+#endif
+
 #if !defined(OPENSSL_ANDROID)
 #define OPENSSL_HAS_GETAUXVAL
 #endif
@@ -120,6 +124,9 @@
 #if !defined(GRND_NONBLOCK)
 #define GRND_NONBLOCK 1
 #endif
+#if !defined(GRND_RANDOM)
+#define GRND_RANDOM 2
+#endif
 
 #endif  // OPENSSL_LINUX
 
@@ -138,10 +145,36 @@
 DEFINE_BSS_GET(int, urandom_fd)
 
 #if defined(USE_NR_getrandom)
+
 // getrandom_ready is one if |getrandom| had been initialized by the time
 // |init_once| was called and zero otherwise.
 DEFINE_BSS_GET(int, getrandom_ready)
+
+// extra_getrandom_flags_for_seed contains a value that is ORed into the flags
+// for getrandom() when reading entropy for a seed.
+DEFINE_BSS_GET(int, extra_getrandom_flags_for_seed)
+
+// On Android, check a system property to decide whether to set
+// |extra_getrandom_flags_for_seed| otherwise they will default to zero.  If
+// ro.oem_boringcrypto_hwrand is true then |extra_getrandom_flags_for_seed| will
+// be set to GRND_RANDOM, causing all random data to be drawn from the same
+// source as /dev/random.
+static void maybe_set_extra_getrandom_flags(void) {
+#if defined(BORINGSSL_FIPS) && defined(OPENSSL_ANDROID)
+  char value[PROP_VALUE_MAX + 1];
+  int length = __system_property_get("ro.boringcrypto.hwrand", value);
+  if (length < 0 || length > PROP_VALUE_MAX) {
+    return;
+  }
+
+  value[length] = 0;
+  if (strcasecmp(value, "true") == 0) {
+    *extra_getrandom_flags_for_seed_bss_get() = GRND_RANDOM;
+  }
 #endif
+}
+
+#endif  // USE_NR_getrandom
 
 DEFINE_STATIC_ONCE(rand_once)
 
@@ -176,6 +209,7 @@
 
   if (have_getrandom) {
     *urandom_fd_bss_get() = kHaveGetrandom;
+    maybe_set_extra_getrandom_flags();
     return;
   }
 #endif  // USE_NR_getrandom
@@ -346,11 +380,23 @@
 // on success and zero on error. If |block| is one, this function will block
 // until the entropy pool is initialized. Otherwise, this function may fail,
 // setting |errno| to |EAGAIN| if the entropy pool has not yet been initialized.
-static int fill_with_entropy(uint8_t *out, size_t len, int block) {
+// If |seed| is one, this function will OR in the value of
+// |*extra_getrandom_flags_for_seed()| when using |getrandom|.
+static int fill_with_entropy(uint8_t *out, size_t len, int block, int seed) {
   if (len == 0) {
     return 1;
   }
 
+#if defined(USE_NR_getrandom)
+  int getrandom_flags = 0;
+  if (block) {
+    getrandom_flags |= GRND_NONBLOCK;
+  }
+  if (seed) {
+    getrandom_flags |= *extra_getrandom_flags_for_seed_bss_get();
+  }
+#endif
+
   CRYPTO_once(rand_once_bss_get(), init_once);
   if (block) {
     CRYPTO_once(wait_for_entropy_once_bss_get(), wait_for_entropy);
@@ -364,7 +410,7 @@
 
     if (*urandom_fd_bss_get() == kHaveGetrandom) {
 #if defined(USE_NR_getrandom)
-      r = boringssl_getrandom(out, len, block ? 0 : GRND_NONBLOCK);
+      r = boringssl_getrandom(out, len, getrandom_flags);
 #elif defined(OPENSSL_MACOS)
       if (__builtin_available(macos 10.12, *)) {
         // |getentropy| can only request 256 bytes at a time.
@@ -400,7 +446,15 @@
 
 // CRYPTO_sysrand puts |requested| random bytes into |out|.
 void CRYPTO_sysrand(uint8_t *out, size_t requested) {
-  if (!fill_with_entropy(out, requested, /*block=*/1)) {
+  if (!fill_with_entropy(out, requested, /*block=*/1, /*seed=*/0)) {
+    perror("entropy fill failed");
+    abort();
+  }
+}
+
+#if defined(BORINGSSL_FIPS)
+void CRYPTO_sysrand_for_seed(uint8_t *out, size_t requested) {
+  if (!fill_with_entropy(out, requested, /*block=*/1, /*seed=*/1)) {
     perror("entropy fill failed");
     abort();
   }
@@ -412,12 +466,11 @@
 #endif
 }
 
-#if defined(BORINGSSL_FIPS)
 void CRYPTO_sysrand_if_available(uint8_t *out, size_t requested) {
   // Return all zeros if |fill_with_entropy| fails.
   OPENSSL_memset(out, 0, requested);
 
-  if (!fill_with_entropy(out, requested, /*block=*/0) &&
+  if (!fill_with_entropy(out, requested, /*block=*/0, /*seed=*/0) &&
       errno != EAGAIN) {
     perror("opportunistic entropy fill failed");
     abort();
diff --git a/src/crypto/hrss/asm/poly_rq_mul.S b/src/crypto/hrss/asm/poly_rq_mul.S
index ebaabd3..0b684c3 100644
--- a/src/crypto/hrss/asm/poly_rq_mul.S
+++ b/src/crypto/hrss/asm/poly_rq_mul.S
@@ -8460,4 +8460,8 @@
 .cfi_endproc
 .size poly_Rq_mul,.-poly_Rq_mul
 
+#if defined(__ELF__)
+.section	.note.GNU-stack,"",@progbits
+#endif
+
 #endif
diff --git a/src/crypto/perlasm/arm-xlate.pl b/src/crypto/perlasm/arm-xlate.pl
index 4dec276..adbd239 100755
--- a/src/crypto/perlasm/arm-xlate.pl
+++ b/src/crypto/perlasm/arm-xlate.pl
@@ -228,6 +228,9 @@
     print "\n";
 }
 
+# See https://www.airs.com/blog/archives/518.
+print ".section\t.note.GNU-stack,\"\",\%progbits\n" if ($flavour =~ /linux/);
+
 print "#endif\n" if ($flavour eq "linux32" || $flavour eq "linux64");
 print "#endif  // !OPENSSL_NO_ASM\n";
 
diff --git a/src/crypto/perlasm/ppc-xlate.pl b/src/crypto/perlasm/ppc-xlate.pl
index 0ce231f..f8e42a2 100644
--- a/src/crypto/perlasm/ppc-xlate.pl
+++ b/src/crypto/perlasm/ppc-xlate.pl
@@ -309,6 +309,9 @@
     print "\n";
 }
 
+# See https://www.airs.com/blog/archives/518.
+print ".section\t.note.GNU-stack,\"\",\@progbits\n" if ($flavour =~ /linux/);
+
 print "#endif  // !OPENSSL_NO_ASM && __powerpc64__\n";
 
 close STDOUT;
diff --git a/src/crypto/perlasm/x86_64-xlate.pl b/src/crypto/perlasm/x86_64-xlate.pl
index f928411..d2854cf 100755
--- a/src/crypto/perlasm/x86_64-xlate.pl
+++ b/src/crypto/perlasm/x86_64-xlate.pl
@@ -1260,6 +1260,8 @@
 
 print "\n$current_segment\tENDS\n"	if ($current_segment && $masm);
 print "END\n"				if ($masm);
+# See https://www.airs.com/blog/archives/518.
+print ".section\t.note.GNU-stack,\"\",\@progbits\n" if ($elf);
 print "#endif\n"			if ($gas);
 
 
diff --git a/src/crypto/perlasm/x86asm.pl b/src/crypto/perlasm/x86asm.pl
index 24f0fc1..b331cd4 100644
--- a/src/crypto/perlasm/x86asm.pl
+++ b/src/crypto/perlasm/x86asm.pl
@@ -297,6 +297,8 @@
 ___
     }
     print @out;
+    # See https://www.airs.com/blog/archives/518.
+    print ".section\t.note.GNU-stack,\"\",\@progbits\n" if ($elf);
     print "#endif\n" unless ($win32 || $netware);
 }
 
diff --git a/src/crypto/poly1305/poly1305_arm_asm.S b/src/crypto/poly1305/poly1305_arm_asm.S
index 04f7c4c..77b3c48 100644
--- a/src/crypto/poly1305/poly1305_arm_asm.S
+++ b/src/crypto/poly1305/poly1305_arm_asm.S
@@ -2022,4 +2022,8 @@
 add sp,sp,#0
 bx lr
 
+#if defined(__ELF__)
+.section	.note.GNU-stack,"",%progbits
+#endif
+
 #endif  /* __arm__ && !OPENSSL_NO_ASM && !__APPLE__ */
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 6810a64..8cd03be 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -560,6 +560,13 @@
 #define SSL_ERROR_HANDOFF 17
 #define SSL_ERROR_HANDBACK 18
 
+// SSL_ERROR_WANT_RENEGOTIATE indicates the operation is pending a response to
+// a renegotiation request from the server. The caller may call
+// |SSL_renegotiate| to schedule a renegotiation and retry the operation.
+//
+// See also |ssl_renegotiate_explicit|.
+#define SSL_ERROR_WANT_RENEGOTIATE 19
+
 // SSL_error_description returns a string representation of |err|, where |err|
 // is one of the |SSL_ERROR_*| constants returned by |SSL_get_error|, or NULL
 // if the value is unrecognized.
@@ -3605,6 +3612,7 @@
   ssl_renegotiate_once,
   ssl_renegotiate_freely,
   ssl_renegotiate_ignore,
+  ssl_renegotiate_explicit,
 };
 
 // SSL_set_renegotiate_mode configures how |ssl|, a client, reacts to
@@ -3618,6 +3626,13 @@
 // Note that ignoring HelloRequest messages may cause the connection to stall
 // if the server waits for the renegotiation to complete.
 //
+// If set to |ssl_renegotiate_explicit|, |SSL_read| and |SSL_peek| calls which
+// encounter a HelloRequest will pause with |SSL_ERROR_WANT_RENEGOTIATE|.
+// |SSL_write| will continue to work while paused. The caller may call
+// |SSL_renegotiate| to begin the renegotiation at a later point. This mode may
+// be used if callers wish to eagerly call |SSL_peek| without triggering a
+// renegotiation.
+//
 // If configuration shedding is enabled (see |SSL_set_shed_handshake_config|),
 // configuration is released if, at any point after the handshake, renegotiation
 // is disabled. It is not possible to switch from disabling renegotiation to
@@ -3630,6 +3645,16 @@
 OPENSSL_EXPORT void SSL_set_renegotiate_mode(SSL *ssl,
                                              enum ssl_renegotiate_mode_t mode);
 
+// SSL_renegotiate starts a deferred renegotiation on |ssl| if it was configured
+// with |ssl_renegotiate_explicit| and has a pending HelloRequest. It returns
+// one on success and zero on error.
+//
+// This function does not do perform any I/O. On success, a subsequent
+// |SSL_do_handshake| call will run the handshake. |SSL_write| and
+// |SSL_read| will also complete the handshake before sending or receiving
+// application data.
+OPENSSL_EXPORT int SSL_renegotiate(SSL *ssl);
+
 // SSL_renegotiate_pending returns one if |ssl| is in the middle of a
 // renegotiation.
 OPENSSL_EXPORT int SSL_renegotiate_pending(SSL *ssl);
@@ -4081,9 +4106,6 @@
 // SSL_set_read_ahead returns one.
 OPENSSL_EXPORT int SSL_set_read_ahead(SSL *ssl, int yes);
 
-// SSL_renegotiate put an error on the error queue and returns zero.
-OPENSSL_EXPORT int SSL_renegotiate(SSL *ssl);
-
 // SSL_set_state does nothing.
 OPENSSL_EXPORT void SSL_set_state(SSL *ssl, int state);
 
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index ec3594c..7f163a4 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -353,6 +353,97 @@
   size_t size_ = 0;
 };
 
+// GrowableArray<T> is an array that owns elements of |T|, backed by an
+// Array<T>. When necessary, pushing will automatically trigger a resize.
+//
+// Note, for simplicity, this class currently differs from |std::vector| in that
+// |T| must be efficiently default-constructible. Allocated elements beyond the
+// end of the array are constructed and destructed.
+template <typename T>
+class GrowableArray {
+ public:
+  GrowableArray() = default;
+  GrowableArray(const GrowableArray &) = delete;
+  GrowableArray(GrowableArray &&other) { *this = std::move(other); }
+  ~GrowableArray() {}
+
+  GrowableArray &operator=(const GrowableArray &) = delete;
+  GrowableArray &operator=(GrowableArray &&other) {
+    size_ = other.size_;
+    other.size_ = 0;
+    array_ = std::move(other.array_);
+    return *this;
+  }
+
+  size_t size() const { return size_; }
+  bool empty() const { return size_ == 0; }
+
+  const T &operator[](size_t i) const { return array_[i]; }
+  T &operator[](size_t i) { return array_[i]; }
+
+  T *begin() { return array_.data(); }
+  const T *cbegin() const { return array_.data(); }
+  T *end() { return array_.data() + size_; }
+  const T *cend() const { return array_.data() + size_; }
+
+  // Push adds |elem| at the end of the internal array, growing if necessary. It
+  // returns false when allocation fails.
+  bool Push(T elem) {
+    if (!MaybeGrow()) {
+      return false;
+    }
+    array_[size_] = std::move(elem);
+    size_++;
+    return true;
+  }
+
+  // CopyFrom replaces the contents of the array with a copy of |in|. It returns
+  // true on success and false on allocation error.
+  bool CopyFrom(Span<const T> in) {
+    if (!array_.CopyFrom(in)) {
+      return false;
+    }
+    size_ = in.size();
+    return true;
+  }
+
+ private:
+  // If there is no room for one more element, creates a new backing array with
+  // double the size of the old one and copies elements over.
+  bool MaybeGrow() {
+    if (array_.size() == 0) {
+      return array_.Init(kDefaultSize);
+    }
+    // No need to grow if we have room for one more T.
+    if (size_ < array_.size()) {
+      return true;
+    }
+    // Double the array's size if it's safe to do so.
+    if (array_.size() > std::numeric_limits<size_t>::max() / 2) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+      return false;
+    }
+    Array<T> new_array;
+    if (!new_array.Init(array_.size() * 2)) {
+      return false;
+    }
+    for (size_t i = 0; i < array_.size(); i++) {
+      new_array[i] = std::move(array_[i]);
+    }
+    array_ = std::move(new_array);
+
+    return true;
+  }
+
+  // |size_| is the number of elements stored in this GrowableArray.
+  size_t size_ = 0;
+  // |array_| is the backing array. Note that |array_.size()| is this
+  // GrowableArray's current capacity and that |size_ <= array_.size()|.
+  Array<T> array_;
+  // |kDefaultSize| is the default initial size of the backing array.
+  static constexpr size_t kDefaultSize = 16;
+};
+
 // CBBFinishArray behaves like |CBB_finish| but stores the result in an Array.
 OPENSSL_EXPORT bool CBBFinishArray(CBB *cbb, Array<uint8_t> *out);
 
@@ -2155,8 +2246,6 @@
 
 DEFINE_LHASH_OF(SSL_SESSION)
 
-DEFINE_NAMED_STACK_OF(CertCompressionAlg, bssl::CertCompressionAlg)
-
 BSSL_NAMESPACE_BEGIN
 
 // An ssl_shutdown_t describes the shutdown state of one end of the connection,
@@ -2294,6 +2383,10 @@
   // alert_dispatch is true there is an alert in |send_alert| to be sent.
   bool alert_dispatch : 1;
 
+  // renegotiate_pending is whether the read half of the channel is blocked on a
+  // HelloRequest.
+  bool renegotiate_pending : 1;
+
   // hs_buf is the buffer of handshake data to process.
   UniquePtr<BUF_MEM> hs_buf;
 
@@ -3137,7 +3230,7 @@
   bssl::UniquePtr<STACK_OF(SRTP_PROTECTION_PROFILE)> srtp_profiles;
 
   // Defined compression algorithms for certificates.
-  bssl::UniquePtr<STACK_OF(CertCompressionAlg)> cert_compression_algs;
+  bssl::GrowableArray<bssl::CertCompressionAlg> cert_compression_algs;
 
   // Supported group values inherited by SSL structure
   bssl::Array<uint16_t> supported_group_list;
diff --git a/src/ssl/s3_lib.cc b/src/ssl/s3_lib.cc
index 41dd588..d7f8a85 100644
--- a/src/ssl/s3_lib.cc
+++ b/src/ssl/s3_lib.cc
@@ -181,7 +181,8 @@
       tls13_downgrade(false),
       token_binding_negotiated(false),
       pq_experiment_signal_seen(false),
-      alert_dispatch(false) {}
+      alert_dispatch(false),
+      renegotiate_pending(false) {}
 
 SSL3_STATE::~SSL3_STATE() {}
 
diff --git a/src/ssl/ssl_lib.cc b/src/ssl/ssl_lib.cc
index 1186312..703c2bc 100644
--- a/src/ssl/ssl_lib.cc
+++ b/src/ssl/ssl_lib.cc
@@ -478,6 +478,7 @@
       return false;
 
     case ssl_renegotiate_freely:
+    case ssl_renegotiate_explicit:
       return true;
     case ssl_renegotiate_once:
       return ssl->s3->total_renegotiations == 0;
@@ -945,29 +946,16 @@
     return 1;  // Ignore the HelloRequest.
   }
 
-  if (!ssl_can_renegotiate(ssl) ||
-      // Renegotiation is only supported at quiescent points in the application
-      // protocol, namely in HTTPS, just before reading the HTTP response.
-      // Require the record-layer be idle and avoid complexities of sending a
-      // handshake record while an application_data record is being written.
-      !ssl->s3->write_buffer.empty() ||
-      ssl->s3->write_shutdown != ssl_shutdown_none) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
+  ssl->s3->renegotiate_pending = true;
+  if (ssl->renegotiate_mode == ssl_renegotiate_explicit) {
+    return 1;  // Handle it later.
+  }
+
+  if (!SSL_renegotiate(ssl)) {
     ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_NO_RENEGOTIATION);
     return 0;
   }
 
-  // Begin a new handshake.
-  if (ssl->s3->hs != nullptr) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return 0;
-  }
-  ssl->s3->hs = ssl_handshake_new(ssl);
-  if (ssl->s3->hs == nullptr) {
-    return 0;
-  }
-
-  ssl->s3->total_renegotiations++;
   return 1;
 }
 
@@ -1012,6 +1000,11 @@
   }
 
   while (ssl->s3->pending_app_data.empty()) {
+    if (ssl->s3->renegotiate_pending) {
+      ssl->s3->rwstate = SSL_ERROR_WANT_RENEGOTIATE;
+      return -1;
+    }
+
     // Complete the current handshake, if any. False Start will cause
     // |SSL_do_handshake| to return mid-handshake, so this may require multiple
     // iterations.
@@ -1353,6 +1346,7 @@
     case SSL_ERROR_PENDING_TICKET:
     case SSL_ERROR_EARLY_DATA_REJECTED:
     case SSL_ERROR_WANT_CERTIFICATE_VERIFY:
+    case SSL_ERROR_WANT_RENEGOTIATE:
       return ssl->s3->rwstate;
 
     case SSL_ERROR_WANT_READ: {
@@ -1743,8 +1737,39 @@
 
 int SSL_renegotiate(SSL *ssl) {
   // Caller-initiated renegotiation is not supported.
-  OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-  return 0;
+  if (!ssl->s3->renegotiate_pending) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+
+  if (!ssl_can_renegotiate(ssl)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
+    return 0;
+  }
+
+  // Renegotiation is only supported at quiescent points in the application
+  // protocol, namely in HTTPS, just before reading the HTTP response.
+  // Require the record-layer be idle and avoid complexities of sending a
+  // handshake record while an application_data record is being written.
+  if (!ssl->s3->write_buffer.empty() ||
+      ssl->s3->write_shutdown != ssl_shutdown_none) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
+    return 0;
+  }
+
+  // Begin a new handshake.
+  if (ssl->s3->hs != nullptr) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+  ssl->s3->hs = ssl_handshake_new(ssl);
+  if (ssl->s3->hs == nullptr) {
+    return 0;
+  }
+
+  ssl->s3->renegotiate_pending = false;
+  ssl->s3->total_renegotiations++;
+  return 1;
 }
 
 int SSL_renegotiate_pending(SSL *ssl) {
@@ -2226,36 +2251,17 @@
                                      ssl_cert_decompression_func_t decompress) {
   assert(compress != nullptr || decompress != nullptr);
 
-  for (const auto *alg : ctx->cert_compression_algs.get()) {
-    if (alg->alg_id == alg_id) {
+  for (const auto &alg : ctx->cert_compression_algs) {
+    if (alg.alg_id == alg_id) {
       return 0;
     }
   }
 
-  UniquePtr<CertCompressionAlg> alg = MakeUnique<CertCompressionAlg>();
-  if (alg == nullptr) {
-    return 0;
-  }
-
-  alg->alg_id = alg_id;
-  alg->compress = compress;
-  alg->decompress = decompress;
-
-  if (ctx->cert_compression_algs == nullptr) {
-    ctx->cert_compression_algs.reset(sk_CertCompressionAlg_new_null());
-    if (ctx->cert_compression_algs == nullptr) {
-      return 0;
-    }
-  }
-
-  if (!PushToStack(ctx->cert_compression_algs.get(), std::move(alg))) {
-    if (sk_CertCompressionAlg_num(ctx->cert_compression_algs.get()) == 0) {
-      ctx->cert_compression_algs.reset();
-    }
-    return 0;
-  }
-
-  return 1;
+  CertCompressionAlg alg;
+  alg.alg_id = alg_id;
+  alg.compress = compress;
+  alg.decompress = decompress;
+  return ctx->cert_compression_algs.Push(alg);
 }
 
 void SSL_CTX_set_tls_channel_id_enabled(SSL_CTX *ctx, int enabled) {
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 2df005a..c01443e 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -24,6 +24,7 @@
 
 #include <gtest/gtest.h>
 
+#include <openssl/aead.h>
 #include <openssl/base64.h>
 #include <openssl/bio.h>
 #include <openssl/cipher.h>
@@ -472,6 +473,74 @@
   return true;
 }
 
+TEST(GrowableArrayTest, Resize) {
+  GrowableArray<size_t> array;
+  ASSERT_TRUE(array.empty());
+  EXPECT_EQ(array.size(), 0u);
+
+  ASSERT_TRUE(array.Push(42));
+  ASSERT_TRUE(!array.empty());
+  EXPECT_EQ(array.size(), 1u);
+
+  // Force a resize operation to occur
+  for (size_t i = 0; i < 16; i++) {
+    ASSERT_TRUE(array.Push(i + 1));
+  }
+
+  EXPECT_EQ(array.size(), 17u);
+
+  // Verify that expected values are still contained in array
+  for (size_t i = 0; i < array.size(); i++) {
+    EXPECT_EQ(array[i], i == 0 ? 42 : i);
+  }
+}
+
+TEST(GrowableArrayTest, MoveConstructor) {
+  GrowableArray<size_t> array;
+  for (size_t i = 0; i < 100; i++) {
+    ASSERT_TRUE(array.Push(i));
+  }
+
+  GrowableArray<size_t> array_moved(std::move(array));
+  for (size_t i = 0; i < 100; i++) {
+    EXPECT_EQ(array_moved[i], i);
+  }
+}
+
+TEST(GrowableArrayTest, GrowableArrayContainingGrowableArrays) {
+  // Representative example of a struct that contains a GrowableArray.
+  struct TagAndArray {
+    size_t tag;
+    GrowableArray<size_t> array;
+  };
+
+  GrowableArray<TagAndArray> array;
+  for (size_t i = 0; i < 100; i++) {
+    TagAndArray elem;
+    elem.tag = i;
+    for (size_t j = 0; j < i; j++) {
+      ASSERT_TRUE(elem.array.Push(j));
+    }
+    ASSERT_TRUE(array.Push(std::move(elem)));
+  }
+  EXPECT_EQ(array.size(), static_cast<size_t>(100));
+
+  GrowableArray<TagAndArray> array_moved(std::move(array));
+  EXPECT_EQ(array_moved.size(), static_cast<size_t>(100));
+  size_t count = 0;
+  for (const TagAndArray &elem : array_moved) {
+    // Test the square bracket operator returns the same value as iteration.
+    EXPECT_EQ(&elem, &array_moved[count]);
+
+    EXPECT_EQ(elem.tag, count);
+    EXPECT_EQ(elem.array.size(), count);
+    for (size_t j = 0; j < count; j++) {
+      EXPECT_EQ(elem.array[j], j);
+    }
+    count++;
+  }
+}
+
 TEST(SSLTest, CipherRules) {
   for (const CipherTest &t : kCipherTests) {
     SCOPED_TRACE(t.rule);
@@ -5586,5 +5655,139 @@
   }
 }
 
+TEST(SSLTest, WriteWhileExplicitRenegotiate) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(ctx);
+
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> pkey = GetTestKey();
+  ASSERT_TRUE(cert);
+  ASSERT_TRUE(pkey);
+  ASSERT_TRUE(SSL_CTX_use_certificate(ctx.get(), cert.get()));
+  ASSERT_TRUE(SSL_CTX_use_PrivateKey(ctx.get(), pkey.get()));
+  ASSERT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), TLS1_2_VERSION));
+  ASSERT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_2_VERSION));
+  ASSERT_TRUE(SSL_CTX_set_strict_cipher_list(
+      ctx.get(), "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"));
+
+  bssl::UniquePtr<SSL> client, server;
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+                                     ClientConfig(), true /* do_handshake */,
+                                     false /* don't shed handshake config */));
+  SSL_set_renegotiate_mode(client.get(), ssl_renegotiate_explicit);
+
+  static const uint8_t kInput[] = {'h', 'e', 'l', 'l', 'o'};
+
+  // Write "hello" until the buffer is full, so |client| has a pending write.
+  size_t num_writes = 0;
+  for (;;) {
+    int ret = SSL_write(client.get(), kInput, sizeof(kInput));
+    if (ret != int(sizeof(kInput))) {
+      ASSERT_EQ(-1, ret);
+      ASSERT_EQ(SSL_ERROR_WANT_WRITE, SSL_get_error(client.get(), ret));
+      break;
+    }
+    num_writes++;
+  }
+
+  // Encrypt a HelloRequest.
+  uint8_t in[] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  // Fuzzer-mode records are unencrypted.
+  uint8_t record[5 + sizeof(in)];
+  record[0] = SSL3_RT_HANDSHAKE;
+  record[1] = 3;
+  record[2] = 3;  // TLS 1.2
+  record[3] = 0;
+  record[4] = sizeof(record) - 5;
+  memcpy(record + 5, in, sizeof(in));
+#else
+  // Extract key material from |server|.
+  static const size_t kKeyLen = 32;
+  static const size_t kNonceLen = 12;
+  ASSERT_EQ(2u * (kKeyLen + kNonceLen), SSL_get_key_block_len(server.get()));
+  uint8_t key_block[2u * (kKeyLen + kNonceLen)];
+  ASSERT_TRUE(
+      SSL_generate_key_block(server.get(), key_block, sizeof(key_block)));
+  Span<uint8_t> key = MakeSpan(key_block + kKeyLen, kKeyLen);
+  Span<uint8_t> nonce =
+      MakeSpan(key_block + kKeyLen + kKeyLen + kNonceLen, kNonceLen);
+
+  uint8_t ad[13];
+  uint64_t seq = SSL_get_write_sequence(server.get());
+  for (size_t i = 0; i < 8; i++) {
+    // The nonce is XORed with the sequence number.
+    nonce[11 - i] ^= uint8_t(seq);
+    ad[7 - i] = uint8_t(seq);
+    seq >>= 8;
+  }
+
+  ad[8] = SSL3_RT_HANDSHAKE;
+  ad[9] = 3;
+  ad[10] = 3;  // TLS 1.2
+  ad[11] = 0;
+  ad[12] = sizeof(in);
+
+  uint8_t record[5 + sizeof(in) + 16];
+  record[0] = SSL3_RT_HANDSHAKE;
+  record[1] = 3;
+  record[2] = 3;  // TLS 1.2
+  record[3] = 0;
+  record[4] = sizeof(record) - 5;
+
+  ScopedEVP_AEAD_CTX aead;
+  ASSERT_TRUE(EVP_AEAD_CTX_init(aead.get(), EVP_aead_chacha20_poly1305(),
+                                key.data(), key.size(),
+                                EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
+  size_t len;
+  ASSERT_TRUE(EVP_AEAD_CTX_seal(aead.get(), record + 5, &len,
+                                sizeof(record) - 5, nonce.data(), nonce.size(),
+                                in, sizeof(in), ad, sizeof(ad)));
+  ASSERT_EQ(sizeof(record) - 5, len);
+#endif  // BORINGSSL_UNSAFE_FUZZER_MODE
+
+  ASSERT_EQ(int(sizeof(record)),
+            BIO_write(SSL_get_wbio(server.get()), record, sizeof(record)));
+
+  // |SSL_read| should pick up the HelloRequest.
+  uint8_t byte;
+  ASSERT_EQ(-1, SSL_read(client.get(), &byte, 1));
+  ASSERT_EQ(SSL_ERROR_WANT_RENEGOTIATE, SSL_get_error(client.get(), -1));
+
+  // Drain the data from the |client|.
+  uint8_t buf[sizeof(kInput)];
+  for (size_t i = 0; i < num_writes; i++) {
+    ASSERT_EQ(int(sizeof(buf)), SSL_read(server.get(), buf, sizeof(buf)));
+    EXPECT_EQ(Bytes(buf), Bytes(kInput));
+  }
+
+  // |client| should be able to finish the pending write and continue to write,
+  // despite the paused HelloRequest.
+  ASSERT_EQ(int(sizeof(kInput)),
+            SSL_write(client.get(), kInput, sizeof(kInput)));
+  ASSERT_EQ(int(sizeof(buf)), SSL_read(server.get(), buf, sizeof(buf)));
+  EXPECT_EQ(Bytes(buf), Bytes(kInput));
+
+  ASSERT_EQ(int(sizeof(kInput)),
+            SSL_write(client.get(), kInput, sizeof(kInput)));
+  ASSERT_EQ(int(sizeof(buf)), SSL_read(server.get(), buf, sizeof(buf)));
+  EXPECT_EQ(Bytes(buf), Bytes(kInput));
+
+  // |SSL_read| is stuck until we acknowledge the HelloRequest.
+  ASSERT_EQ(-1, SSL_read(client.get(), &byte, 1));
+  ASSERT_EQ(SSL_ERROR_WANT_RENEGOTIATE, SSL_get_error(client.get(), -1));
+
+  ASSERT_TRUE(SSL_renegotiate(client.get()));
+  ASSERT_EQ(-1, SSL_read(client.get(), &byte, 1));
+  ASSERT_EQ(SSL_ERROR_WANT_READ, SSL_get_error(client.get(), -1));
+
+  // We never renegotiate as a server.
+  ASSERT_EQ(-1, SSL_read(server.get(), buf, sizeof(buf)));
+  ASSERT_EQ(SSL_ERROR_SSL, SSL_get_error(server.get(), -1));
+  uint32_t err = ERR_get_error();
+  EXPECT_EQ(ERR_LIB_SSL, ERR_GET_LIB(err));
+  EXPECT_EQ(SSL_R_NO_RENEGOTIATION, ERR_GET_REASON(err));
+}
+
 }  // namespace
 BSSL_NAMESPACE_END
diff --git a/src/ssl/t1_lib.cc b/src/ssl/t1_lib.cc
index 52cea6c..cc29a83 100644
--- a/src/ssl/t1_lib.cc
+++ b/src/ssl/t1_lib.cc
@@ -2756,8 +2756,8 @@
   bool first = true;
   CBB contents, algs;
 
-  for (const auto *alg : hs->ssl->ctx->cert_compression_algs.get()) {
-    if (alg->decompress == nullptr) {
+  for (const auto &alg : hs->ssl->ctx->cert_compression_algs) {
+    if (alg.decompress == nullptr) {
       continue;
     }
 
@@ -2767,7 +2767,7 @@
       return false;
     }
     first = false;
-    if (!CBB_add_u16(&algs, alg->alg_id)) {
+    if (!CBB_add_u16(&algs, alg.alg_id)) {
       return false;
     }
   }
@@ -2794,8 +2794,8 @@
     return true;
   }
 
-  const size_t num_algs =
-      sk_CertCompressionAlg_num(hs->ssl->ctx->cert_compression_algs.get());
+  const SSL_CTX *ctx = hs->ssl->ctx.get();
+  const size_t num_algs = ctx->cert_compression_algs.size();
 
   CBS alg_ids;
   if (!CBS_get_u8_length_prefixed(contents, &alg_ids) ||
@@ -2823,9 +2823,8 @@
     given_alg_ids[given_alg_idx++] = alg_id;
 
     for (size_t i = 0; i < num_algs; i++) {
-      const auto *alg = sk_CertCompressionAlg_value(
-          hs->ssl->ctx->cert_compression_algs.get(), i);
-      if (alg->alg_id == alg_id && alg->compress != nullptr) {
+      const auto &alg = ctx->cert_compression_algs[i];
+      if (alg.alg_id == alg_id && alg.compress != nullptr) {
         if (i < best_index) {
           best_index = i;
         }
@@ -2845,10 +2844,7 @@
   if (best_index < num_algs &&
       ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
     hs->cert_compression_negotiated = true;
-    hs->cert_compression_alg_id =
-        sk_CertCompressionAlg_value(hs->ssl->ctx->cert_compression_algs.get(),
-                                    best_index)
-            ->alg_id;
+    hs->cert_compression_alg_id = ctx->cert_compression_algs[best_index].alg_id;
   }
 
   return true;
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 261f6c6..9bd389b 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -1126,6 +1126,15 @@
     return false;
   }
 
+  if (config->renegotiate_explicit &&
+      SSL_total_renegotiations(ssl) !=
+          GetTestState(ssl)->explicit_renegotiates) {
+    fprintf(stderr, "Performed %d renegotiations, but triggered %d of them\n",
+            SSL_total_renegotiations(ssl),
+            GetTestState(ssl)->explicit_renegotiates);
+    return false;
+  }
+
   return true;
 }
 
diff --git a/src/ssl/test/handshake_util.cc b/src/ssl/test/handshake_util.cc
index 4b1dcc8..fe96751 100644
--- a/src/ssl/test/handshake_util.cc
+++ b/src/ssl/test/handshake_util.cc
@@ -40,8 +40,18 @@
 bool RetryAsync(SSL *ssl, int ret) {
   const TestConfig *config = GetTestConfig(ssl);
   TestState *test_state = GetTestState(ssl);
-  // No error or not async; don't retry.
-  if (ret >= 0 || !config->async) {
+  if (ret >= 0) {
+    return false;
+  }
+
+  int ssl_err = SSL_get_error(ssl, ret);
+  if (ssl_err == SSL_ERROR_WANT_RENEGOTIATE && config->renegotiate_explicit) {
+    test_state->explicit_renegotiates++;
+    return SSL_renegotiate(ssl);
+  }
+
+  if (!config->async) {
+    // Only asynchronous tests should trigger other retries.
     return false;
   }
 
@@ -62,7 +72,7 @@
 
   // See if we needed to read or write more. If so, allow one byte through on
   // the appropriate end to maximally stress the state machine.
-  switch (SSL_get_error(ssl, ret)) {
+  switch (ssl_err) {
     case SSL_ERROR_WANT_READ:
       AsyncBioAllowRead(test_state->async_bio, 1);
       return true;
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 5a4b0cc..758566a 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -5268,6 +5268,18 @@
 		})
 
 		tests = append(tests, testCase{
+			name: "Renegotiate-Client-Explicit",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			renegotiate: 1,
+			flags: []string{
+				"-renegotiate-explicit",
+				"-expect-total-renegotiations", "1",
+			},
+		})
+
+		tests = append(tests, testCase{
 			name: "SendHalfHelloRequest",
 			config: Config{
 				MaxVersion: VersionTLS12,
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index bd32ce9..8d8a068 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -102,6 +102,7 @@
     {"-renegotiate-once", &TestConfig::renegotiate_once},
     {"-renegotiate-freely", &TestConfig::renegotiate_freely},
     {"-renegotiate-ignore", &TestConfig::renegotiate_ignore},
+    {"-renegotiate-explicit", &TestConfig::renegotiate_explicit},
     {"-forbid-renegotiation-after-handshake",
      &TestConfig::forbid_renegotiation_after_handshake},
     {"-enable-all-curves", &TestConfig::enable_all_curves},
@@ -1577,6 +1578,9 @@
   if (renegotiate_ignore) {
     SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_ignore);
   }
+  if (renegotiate_explicit) {
+    SSL_set_renegotiate_mode(ssl.get(), ssl_renegotiate_explicit);
+  }
   if (!check_close_notify) {
     SSL_set_quiet_shutdown(ssl.get(), 1);
   }
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index ce4b416..8c25ed2 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -119,6 +119,7 @@
   bool renegotiate_once = false;
   bool renegotiate_freely = false;
   bool renegotiate_ignore = false;
+  bool renegotiate_explicit = false;
   bool forbid_renegotiation_after_handshake = false;
   int expect_peer_signature_algorithm = 0;
   bool enable_all_curves = false;
diff --git a/src/ssl/test/test_state.h b/src/ssl/test/test_state.h
index 2364286..2aa9e30 100644
--- a/src/ssl/test/test_state.h
+++ b/src/ssl/test/test_state.h
@@ -61,6 +61,7 @@
   // cert_verified is true if certificate verification has been driven to
   // completion. This tests that the callback is not called again after this.
   bool cert_verified = false;
+  int explicit_renegotiates = 0;
 };
 
 bool SetTestState(SSL *ssl, std::unique_ptr<TestState> state);
diff --git a/src/ssl/tls13_both.cc b/src/ssl/tls13_both.cc
index 7457155..18bdef2 100644
--- a/src/ssl/tls13_both.cc
+++ b/src/ssl/tls13_both.cc
@@ -133,9 +133,9 @@
     }
 
     ssl_cert_decompression_func_t decompress = nullptr;
-    for (const auto* alg : ssl->ctx->cert_compression_algs.get()) {
-      if (alg->alg_id == alg_id) {
-        decompress = alg->decompress;
+    for (const auto &alg : ssl->ctx->cert_compression_algs) {
+      if (alg.alg_id == alg_id) {
+        decompress = alg.decompress;
         break;
       }
     }
@@ -517,9 +517,9 @@
   }
 
   const CertCompressionAlg *alg = nullptr;
-  for (const auto *candidate : ssl->ctx->cert_compression_algs.get()) {
-    if (candidate->alg_id == hs->cert_compression_alg_id) {
-      alg = candidate;
+  for (const auto &candidate : ssl->ctx->cert_compression_algs) {
+    if (candidate.alg_id == hs->cert_compression_alg_id) {
+      alg = &candidate;
       break;
     }
   }
diff --git a/src/ssl/tls13_server.cc b/src/ssl/tls13_server.cc
index a52a49c..f6a81d4 100644
--- a/src/ssl/tls13_server.cc
+++ b/src/ssl/tls13_server.cc
@@ -976,7 +976,7 @@
   // the case of a small server write buffer. Consumers which don't write data
   // to the client will need to do a zero-byte write if they wish to flush the
   // tickets.
-  if (hs->ssl->ctx->quic_method != nullptr && sent_tickets) {
+  if (hs->ssl->quic_method != nullptr && sent_tickets) {
     return ssl_hs_flush;
   }
   return ssl_hs_ok;
diff --git a/src/tool/speed.cc b/src/tool/speed.cc
index 160d90f..68073a9 100644
--- a/src/tool/speed.cc
+++ b/src/tool/speed.cc
@@ -13,9 +13,9 @@
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
 #include <algorithm>
-#include <string>
 #include <functional>
 #include <memory>
+#include <string>
 #include <vector>
 
 #include <assert.h>
@@ -54,6 +54,8 @@
 
 #include "../third_party/sike/sike.h"
 
+// g_print_json is true if printed output is JSON formatted.
+static bool g_print_json = false;
 
 // TimeResults represents the results of benchmarking a function.
 struct TimeResults {
@@ -62,20 +64,54 @@
   // us is the number of microseconds that elapsed in the time period.
   unsigned us;
 
-  void Print(const std::string &description) {
-    printf("Did %u %s operations in %uus (%.1f ops/sec)\n", num_calls,
-           description.c_str(), us,
-           (static_cast<double>(num_calls) / us) * 1000000);
+  void Print(const std::string &description) const {
+    if (g_print_json) {
+      PrintJSON(description);
+    } else {
+      printf("Did %u %s operations in %uus (%.1f ops/sec)\n", num_calls,
+             description.c_str(), us,
+             (static_cast<double>(num_calls) / us) * 1000000);
+    }
   }
 
-  void PrintWithBytes(const std::string &description, size_t bytes_per_call) {
-    printf("Did %u %s operations in %uus (%.1f ops/sec): %.1f MB/s\n",
-           num_calls, description.c_str(), us,
-           (static_cast<double>(num_calls) / us) * 1000000,
-           static_cast<double>(bytes_per_call * num_calls) / us);
+  void PrintWithBytes(const std::string &description,
+                      size_t bytes_per_call) const {
+    if (g_print_json) {
+      PrintJSON(description, bytes_per_call);
+    } else {
+      printf("Did %u %s operations in %uus (%.1f ops/sec): %.1f MB/s\n",
+             num_calls, description.c_str(), us,
+             (static_cast<double>(num_calls) / us) * 1000000,
+             static_cast<double>(bytes_per_call * num_calls) / us);
+    }
   }
+
+ private:
+  void PrintJSON(const std::string &description,
+                 size_t bytes_per_call = 0) const {
+    if (first_json_printed) {
+      puts(",");
+    }
+
+    printf("{\"description\": \"%s\", \"numCalls\": %u, \"microseconds\": %u",
+           description.c_str(), num_calls, us);
+
+    if (bytes_per_call > 0) {
+      printf(", \"bytesPerCall\": %zu", bytes_per_call);
+    }
+
+    printf("}");
+    first_json_printed = true;
+  }
+
+  // first_json_printed is true if |g_print_json| is true and the first item in
+  // the JSON results has been printed already. This is used to handle the
+  // commas between each item in the result list.
+  static bool first_json_printed;
 };
 
+bool TimeResults::first_json_printed = false;
+
 #if defined(OPENSSL_WINDOWS)
 static uint64_t time_now() { return GetTickCount64() * 1000; }
 #elif defined(OPENSSL_APPLE)
@@ -274,24 +310,29 @@
     }
 
     std::sort(durations.begin(), durations.end());
-    printf("Did %u RSA %d key-gen operations in %uus (%.1f ops/sec)\n",
-           num_calls, size, us,
-           (static_cast<double>(num_calls) / us) * 1000000);
+    const std::string description =
+        std::string("RSA ") + std::to_string(size) + std::string(" key-gen");
+    const TimeResults results = {num_calls, us};
+    results.Print(description);
     const size_t n = durations.size();
     assert(n > 0);
 
-    // |min| and |max| must be stored in temporary variables to avoid an MSVC
-    // bug on x86. There, size_t is a typedef for unsigned, but MSVC's printf
-    // warning tries to retain the distinction and suggest %zu for size_t
-    // instead of %u. It gets confused if std::vector<unsigned> and
-    // std::vector<size_t> are both instantiated. Being typedefs, the two
-    // instantiations are identical, which somehow breaks the size_t vs unsigned
-    // metadata.
-    unsigned min = durations[0];
-    unsigned median = n & 1 ? durations[n / 2]
-                            : (durations[n / 2 - 1] + durations[n / 2]) / 2;
-    unsigned max = durations[n - 1];
-    printf("  min: %uus, median: %uus, max: %uus\n", min, median, max);
+    // Distribution information is useful, but doesn't fit into the standard
+    // format used by |g_print_json|.
+    if (!g_print_json) {
+      // |min| and |max| must be stored in temporary variables to avoid an MSVC
+      // bug on x86. There, size_t is a typedef for unsigned, but MSVC's printf
+      // warning tries to retain the distinction and suggest %zu for size_t
+      // instead of %u. It gets confused if std::vector<unsigned> and
+      // std::vector<size_t> are both instantiated. Being typedefs, the two
+      // instantiations are identical, which somehow breaks the size_t vs
+      // unsigned metadata.
+      unsigned min = durations[0];
+      unsigned median = n & 1 ? durations[n / 2]
+                              : (durations[n / 2 - 1] + durations[n / 2]) / 2;
+      unsigned max = durations[n - 1];
+      printf("  min: %uus, median: %uus, max: %uus\n", min, median, max);
+    }
   }
 
   return true;
@@ -979,6 +1020,16 @@
         "16,256,1350,8192,16384)",
     },
     {
+        "-json",
+        kBooleanArgument,
+        "If this flag is set, speed will print the output of each benchmark in "
+        "JSON format as follows: \"{\"description\": "
+        "\"descriptionOfOperation\", \"numCalls\": 1234, "
+        "\"timeInMicroseconds\": 1234567, \"bytesPerCall\": 1234}\". When "
+        "there is no information about the bytes per call for an  operation, "
+        "the JSON field for bytesPerCall will be omitted.",
+    },
+    {
         "",
         kOptionalArgument,
         "",
@@ -997,6 +1048,10 @@
     selected = args_map["-filter"];
   }
 
+  if (args_map.count("-json") != 0) {
+    g_print_json = true;
+  }
+
   if (args_map.count("-timeout") != 0) {
     g_timeout_seconds = atoi(args_map["-timeout"].c_str());
   }
@@ -1036,6 +1091,9 @@
   // knowledge in them and construct a couple of the AD bytes internally.
   static const size_t kLegacyADLen = kTLSADLen - 2;
 
+  if (g_print_json) {
+    puts("[");
+  }
   if (!SpeedRSA(selected) ||
       !SpeedAEAD(EVP_aead_aes_128_gcm(), "AES-128-GCM", kTLSADLen, selected) ||
       !SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM", kTLSADLen, selected) ||
@@ -1077,6 +1135,9 @@
       !SpeedHRSS(selected)) {
     return false;
   }
+  if (g_print_json) {
+    puts("\n]");
+  }
 
   return true;
 }