external/boringssl: Sync to 7c5728649affe20e2952b11a0aeaf0e7b114aad9.
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/68f37b7a3f451aa1ca8c93669c024d01f6270ae8..7c5728649affe20e2952b11a0aeaf0e7b114aad9
This also removes sha256-armv4.S from libcrypto_sources_no_clang; clang
can assemble it now. The other files still need to be there though.
Note this pulls in a fix to a wpa_supplicant regression introduced in
c895d6b1c580258e72e1ed3fcc86d38970ded9e1.
Test: make checkbuild
Test: cts-tradefed run cts -m CtsLibcoreTestCases -a arm64-v8a
Test: cts-tradefed run cts -m CtsLibcoreOkHttpTestCases -a arm64-v8a
Change-Id: Ife1d9ea1c87a0b7b1814b8e3590d6f1eaf721629
diff --git a/Android.bp b/Android.bp
index 8614e40..d120abf 100644
--- a/Android.bp
+++ b/Android.bp
@@ -44,7 +44,6 @@
libcrypto_sources_no_clang = [
"linux-arm/crypto/aes/aes-armv4.S",
"linux-arm/crypto/aes/bsaes-armv7.S",
- "linux-arm/crypto/sha/sha256-armv4.S",
]
cc_defaults {
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index aefa36f..bb85060 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-68f37b7a3f451aa1ca8c93669c024d01f6270ae8
+7c5728649affe20e2952b11a0aeaf0e7b114aad9
diff --git a/err_data.c b/err_data.c
index 90d1962..e75a0ca 100644
--- a/err_data.c
+++ b/err_data.c
@@ -178,42 +178,42 @@
0x28340c19,
0x283480ac,
0x283500ea,
- 0x2c32295b,
- 0x2c32a969,
- 0x2c33297b,
- 0x2c33a98d,
- 0x2c3429a1,
- 0x2c34a9b3,
- 0x2c3529ce,
- 0x2c35a9e0,
- 0x2c3629f3,
+ 0x2c32299a,
+ 0x2c32a9a8,
+ 0x2c3329ba,
+ 0x2c33a9cc,
+ 0x2c3429e0,
+ 0x2c34a9f2,
+ 0x2c352a0d,
+ 0x2c35aa1f,
+ 0x2c362a32,
0x2c36832d,
- 0x2c372a00,
- 0x2c37aa12,
- 0x2c382a25,
- 0x2c38aa3c,
- 0x2c392a4a,
- 0x2c39aa5a,
- 0x2c3a2a6c,
- 0x2c3aaa80,
- 0x2c3b2a91,
- 0x2c3baab0,
- 0x2c3c2ac4,
- 0x2c3caada,
- 0x2c3d2af3,
- 0x2c3dab10,
- 0x2c3e2b21,
- 0x2c3eab2f,
- 0x2c3f2b47,
- 0x2c3fab5f,
- 0x2c402b6c,
+ 0x2c372a3f,
+ 0x2c37aa51,
+ 0x2c382a64,
+ 0x2c38aa7b,
+ 0x2c392a89,
+ 0x2c39aa99,
+ 0x2c3a2aab,
+ 0x2c3aaabf,
+ 0x2c3b2ad0,
+ 0x2c3baaef,
+ 0x2c3c2b03,
+ 0x2c3cab19,
+ 0x2c3d2b32,
+ 0x2c3dab4f,
+ 0x2c3e2b60,
+ 0x2c3eab6e,
+ 0x2c3f2b86,
+ 0x2c3fab9e,
+ 0x2c402bab,
0x2c4090e7,
- 0x2c412b7d,
- 0x2c41ab90,
+ 0x2c412bbc,
+ 0x2c41abcf,
0x2c4210c0,
- 0x2c42aba1,
+ 0x2c42abe0,
0x2c430720,
- 0x2c43aaa2,
+ 0x2c43aae1,
0x30320000,
0x30328015,
0x3033001f,
@@ -439,64 +439,64 @@
0x40601f92,
0x40609fb4,
0x40611ff8,
- 0x4061a00d,
- 0x40622024,
- 0x4062a035,
- 0x40632046,
- 0x4063a05b,
- 0x40642072,
- 0x4064a09e,
- 0x406520b9,
- 0x4065a0d0,
- 0x406620e8,
- 0x4066a112,
- 0x4067213d,
- 0x4067a15e,
- 0x40682171,
- 0x4068a192,
- 0x406921c4,
- 0x4069a1f2,
- 0x406a2213,
- 0x406aa233,
- 0x406b23bb,
- 0x406ba3de,
- 0x406c23f4,
- 0x406ca656,
- 0x406d2685,
- 0x406da6ad,
- 0x406e26db,
- 0x406ea6f3,
- 0x406f2712,
- 0x406fa727,
- 0x4070273a,
- 0x4070a757,
+ 0x4061a030,
+ 0x40622047,
+ 0x4062a058,
+ 0x40632069,
+ 0x4063a07e,
+ 0x40642095,
+ 0x4064a0c1,
+ 0x406520dc,
+ 0x4065a0f3,
+ 0x4066210b,
+ 0x4066a135,
+ 0x40672160,
+ 0x4067a181,
+ 0x40682194,
+ 0x4068a1b5,
+ 0x406921e7,
+ 0x4069a215,
+ 0x406a2236,
+ 0x406aa256,
+ 0x406b23de,
+ 0x406ba401,
+ 0x406c2417,
+ 0x406ca679,
+ 0x406d26a8,
+ 0x406da6d0,
+ 0x406e26fe,
+ 0x406ea732,
+ 0x406f2751,
+ 0x406fa766,
+ 0x40702779,
+ 0x4070a796,
0x40710800,
- 0x4071a769,
- 0x4072277c,
- 0x4072a795,
- 0x407327ad,
+ 0x4071a7a8,
+ 0x407227bb,
+ 0x4072a7d4,
+ 0x407327ec,
0x4073936d,
- 0x407427c1,
- 0x4074a7db,
- 0x407527ec,
- 0x4075a800,
- 0x4076280e,
+ 0x40742800,
+ 0x4074a81a,
+ 0x4075282b,
+ 0x4075a83f,
+ 0x4076284d,
0x407691aa,
- 0x40772833,
- 0x4077a855,
- 0x40782870,
- 0x4078a8a9,
- 0x407928c0,
- 0x4079a8d6,
- 0x407a28e2,
- 0x407aa8f5,
- 0x407b290a,
- 0x407ba91c,
- 0x407c2931,
- 0x407ca93a,
- 0x407d21ad,
+ 0x40772872,
+ 0x4077a894,
+ 0x407828af,
+ 0x4078a8e8,
+ 0x407928ff,
+ 0x4079a915,
+ 0x407a2921,
+ 0x407aa934,
+ 0x407b2949,
+ 0x407ba95b,
+ 0x407c2970,
+ 0x407ca979,
+ 0x407d21d0,
0x407d9c57,
- 0x407e2885,
+ 0x407e28c4,
0x407e9e27,
0x407f1a67,
0x407f9887,
@@ -504,48 +504,50 @@
0x40809a8f,
0x40811cea,
0x40819c08,
- 0x408226c6,
+ 0x408226e9,
0x4082986d,
0x40831e02,
- 0x4083a083,
+ 0x4083a0a6,
0x40841aa3,
0x40849e5f,
0x40851ee4,
0x40859fdc,
0x40861f38,
0x40869c71,
- 0x41f422e6,
- 0x41f92378,
- 0x41fe226b,
- 0x41fea447,
- 0x41ff2538,
- 0x420322ff,
- 0x42082321,
- 0x4208a35d,
- 0x4209224f,
- 0x4209a397,
- 0x420a22a6,
- 0x420aa286,
- 0x420b22c6,
- 0x420ba33f,
- 0x420c2554,
- 0x420ca414,
- 0x420d242e,
- 0x420da465,
- 0x4212247f,
- 0x4217251b,
- 0x4217a4c1,
- 0x421c24e3,
- 0x421f249e,
- 0x4221256b,
- 0x422624fe,
- 0x422b263a,
- 0x422ba5e8,
- 0x422c2622,
- 0x422ca5a7,
- 0x422d2586,
- 0x422da607,
- 0x422e25cd,
+ 0x40872716,
+ 0x4087a00d,
+ 0x41f42309,
+ 0x41f9239b,
+ 0x41fe228e,
+ 0x41fea46a,
+ 0x41ff255b,
+ 0x42032322,
+ 0x42082344,
+ 0x4208a380,
+ 0x42092272,
+ 0x4209a3ba,
+ 0x420a22c9,
+ 0x420aa2a9,
+ 0x420b22e9,
+ 0x420ba362,
+ 0x420c2577,
+ 0x420ca437,
+ 0x420d2451,
+ 0x420da488,
+ 0x421224a2,
+ 0x4217253e,
+ 0x4217a4e4,
+ 0x421c2506,
+ 0x421f24c1,
+ 0x4221258e,
+ 0x42262521,
+ 0x422b265d,
+ 0x422ba60b,
+ 0x422c2645,
+ 0x422ca5ca,
+ 0x422d25a9,
+ 0x422da62a,
+ 0x422e25f0,
0x4432072b,
0x4432873a,
0x44330746,
@@ -588,69 +590,69 @@
0x4c3d136d,
0x4c3d937c,
0x4c3e1389,
- 0x50322bb3,
- 0x5032abc2,
- 0x50332bcd,
- 0x5033abdd,
- 0x50342bf6,
- 0x5034ac10,
- 0x50352c1e,
- 0x5035ac34,
- 0x50362c46,
- 0x5036ac5c,
- 0x50372c75,
- 0x5037ac88,
- 0x50382ca0,
- 0x5038acb1,
- 0x50392cc6,
- 0x5039acda,
- 0x503a2cfa,
- 0x503aad10,
- 0x503b2d28,
- 0x503bad3a,
- 0x503c2d56,
- 0x503cad6d,
- 0x503d2d86,
- 0x503dad9c,
- 0x503e2da9,
- 0x503eadbf,
- 0x503f2dd1,
+ 0x50322bf2,
+ 0x5032ac01,
+ 0x50332c0c,
+ 0x5033ac1c,
+ 0x50342c35,
+ 0x5034ac4f,
+ 0x50352c5d,
+ 0x5035ac73,
+ 0x50362c85,
+ 0x5036ac9b,
+ 0x50372cb4,
+ 0x5037acc7,
+ 0x50382cdf,
+ 0x5038acf0,
+ 0x50392d05,
+ 0x5039ad19,
+ 0x503a2d39,
+ 0x503aad4f,
+ 0x503b2d67,
+ 0x503bad79,
+ 0x503c2d95,
+ 0x503cadac,
+ 0x503d2dc5,
+ 0x503daddb,
+ 0x503e2de8,
+ 0x503eadfe,
+ 0x503f2e10,
0x503f8382,
- 0x50402de4,
- 0x5040adf4,
- 0x50412e0e,
- 0x5041ae1d,
- 0x50422e37,
- 0x5042ae54,
- 0x50432e64,
- 0x5043ae74,
- 0x50442e83,
+ 0x50402e23,
+ 0x5040ae33,
+ 0x50412e4d,
+ 0x5041ae5c,
+ 0x50422e76,
+ 0x5042ae93,
+ 0x50432ea3,
+ 0x5043aeb3,
+ 0x50442ec2,
0x5044843f,
- 0x50452e97,
- 0x5045aeb5,
- 0x50462ec8,
- 0x5046aede,
- 0x50472ef0,
- 0x5047af05,
- 0x50482f2b,
- 0x5048af39,
- 0x50492f4c,
- 0x5049af61,
- 0x504a2f77,
- 0x504aaf87,
- 0x504b2fa7,
- 0x504bafba,
- 0x504c2fdd,
- 0x504cb00b,
- 0x504d301d,
- 0x504db03a,
- 0x504e3055,
- 0x504eb071,
- 0x504f3083,
- 0x504fb09a,
- 0x505030a9,
+ 0x50452ed6,
+ 0x5045aef4,
+ 0x50462f07,
+ 0x5046af1d,
+ 0x50472f2f,
+ 0x5047af44,
+ 0x50482f6a,
+ 0x5048af78,
+ 0x50492f8b,
+ 0x5049afa0,
+ 0x504a2fb6,
+ 0x504aafc6,
+ 0x504b2fe6,
+ 0x504baff9,
+ 0x504c301c,
+ 0x504cb04a,
+ 0x504d305c,
+ 0x504db079,
+ 0x504e3094,
+ 0x504eb0b0,
+ 0x504f30c2,
+ 0x504fb0d9,
+ 0x505030e8,
0x505086ef,
- 0x505130bc,
+ 0x505130fb,
0x58320ec9,
0x68320e8b,
0x68328c25,
@@ -1098,6 +1100,7 @@
"PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\0"
"PRE_SHARED_KEY_MUST_BE_LAST\0"
"PROTOCOL_IS_SHUTDOWN\0"
+ "PSK_IDENTITY_BINDER_COUNT_MISMATCH\0"
"PSK_IDENTITY_NOT_FOUND\0"
"PSK_NO_CLIENT_CB\0"
"PSK_NO_SERVER_CB\0"
@@ -1159,6 +1162,7 @@
"TOO_MANY_EMPTY_FRAGMENTS\0"
"TOO_MANY_KEY_UPDATES\0"
"TOO_MANY_WARNING_ALERTS\0"
+ "TOO_MUCH_SKIPPED_EARLY_DATA\0"
"UNABLE_TO_FIND_ECDH_PARAMETERS\0"
"UNEXPECTED_EXTENSION\0"
"UNEXPECTED_MESSAGE\0"
diff --git a/linux-arm/crypto/sha/sha256-armv4.S b/linux-arm/crypto/sha/sha256-armv4.S
index 6040041..f37fd7c 100644
--- a/linux-arm/crypto/sha/sha256-armv4.S
+++ b/linux-arm/crypto/sha/sha256-armv4.S
@@ -1,4 +1,11 @@
#if defined(__arm__)
+@ Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+@
+@ Licensed under the OpenSSL license (the "License"). You may not use
+@ this file except in compliance with the License. You can obtain a copy
+@ in the file LICENSE in the source distribution or at
+@ https://www.openssl.org/source/license.html
+
@ ====================================================================
@ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -45,16 +52,11 @@
#endif
.text
-#if __ARM_ARCH__<7
-.code 32
-#else
+#if defined(__thumb2__)
.syntax unified
-# if defined(__thumb2__) && !defined(__APPLE__)
-# define adrl adr
.thumb
-# else
+#else
.code 32
-# endif
#endif
.type K256,%object
@@ -89,10 +91,10 @@
.type sha256_block_data_order,%function
sha256_block_data_order:
.Lsha256_block_data_order:
-#if __ARM_ARCH__<7
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
sub r3,pc,#8 @ sha256_block_data_order
#else
- adr r3,sha256_block_data_order
+ adr r3,.Lsha256_block_data_order
#endif
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap
@@ -1878,13 +1880,14 @@
.globl sha256_block_data_order_neon
.hidden sha256_block_data_order_neon
.type sha256_block_data_order_neon,%function
-.align 4
+.align 5
+.skip 16
sha256_block_data_order_neon:
.LNEON:
stmdb sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
sub r11,sp,#16*4+16
- adrl r14,K256
+ adr r14,K256
bic r11,r11,#15 @ align for 128-bit stores
mov r12,sp
mov sp,r11 @ alloca
@@ -2660,7 +2663,7 @@
#endif
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
-# if defined(__thumb2__) && !defined(__APPLE__)
+# if defined(__thumb2__)
# define INST(a,b,c,d) .byte c,d|0xc,a,b
# else
# define INST(a,b,c,d) .byte a,b,c,d
@@ -2671,16 +2674,11 @@
sha256_block_data_order_armv8:
.LARMv8:
vld1.32 {q0,q1},[r0]
-# ifdef __APPLE__
sub r3,r3,#256+32
-# elif defined(__thumb2__)
- adr r3,.LARMv8
- sub r3,r3,#.LARMv8-K256
-# else
- adrl r3,K256
-# endif
add r2,r1,r2,lsl#6 @ len to point at the end of inp
+ b .Loop_v8
+.align 4
.Loop_v8:
vld1.8 {q8,q9},[r1]!
vld1.8 {q10,q11},[r1]!
diff --git a/sources.bp b/sources.bp
index 8ae4dc9..537a22a 100644
--- a/sources.bp
+++ b/sources.bp
@@ -163,6 +163,7 @@
"src/crypto/modes/ctr.c",
"src/crypto/modes/gcm.c",
"src/crypto/modes/ofb.c",
+ "src/crypto/modes/polyval.c",
"src/crypto/newhope/error_correction.c",
"src/crypto/newhope/newhope.c",
"src/crypto/newhope/ntt.c",
diff --git a/sources.mk b/sources.mk
index deafdc9..b229e92 100644
--- a/sources.mk
+++ b/sources.mk
@@ -161,6 +161,7 @@
src/crypto/modes/ctr.c\
src/crypto/modes/gcm.c\
src/crypto/modes/ofb.c\
+ src/crypto/modes/polyval.c\
src/crypto/newhope/error_correction.c\
src/crypto/newhope/newhope.c\
src/crypto/newhope/ntt.c\
diff --git a/src/.gitignore b/src/.gitignore
index a2e3ed2..9f396f6 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -4,3 +4,18 @@
*.swo
doc/*.html
doc/doc.css
+
+util/bot/android_tools
+util/bot/cmake-linux64
+util/bot/cmake-linux64.tar.gz
+util/bot/cmake-mac
+util/bot/cmake-mac.tar.gz
+util/bot/cmake-win32
+util/bot/cmake-win32.zip
+util/bot/golang
+util/bot/gyp
+util/bot/llvm-build
+util/bot/perl-win32
+util/bot/perl-win32.zip
+util/bot/win_toolchain.json
+util/bot/yasm-win32.exe
diff --git a/src/FUZZING.md b/src/FUZZING.md
index f004c27..77c50c1 100644
--- a/src/FUZZING.md
+++ b/src/FUZZING.md
@@ -37,6 +37,7 @@
| `pkcs8` | 2048 |
| `privkey` | 2048 |
| `server` | 4096 |
+| `session` | 8192 |
| `spki` | 1024 |
| `read_pem` | 512 |
| `ssl_ctx_api` | 256 |
diff --git a/src/crypto/bio/bio_test.cc b/src/crypto/bio/bio_test.cc
index 01b93f6..4ae6c6e 100644
--- a/src/crypto/bio/bio_test.cc
+++ b/src/crypto/bio/bio_test.cc
@@ -135,152 +135,6 @@
return true;
}
-
-// BioReadZeroCopyWrapper is a wrapper around the zero-copy APIs to make
-// testing easier.
-static size_t BioReadZeroCopyWrapper(BIO *bio, uint8_t *data, size_t len) {
- uint8_t *read_buf;
- size_t read_buf_offset;
- size_t available_bytes;
- size_t len_read = 0;
-
- do {
- if (!BIO_zero_copy_get_read_buf(bio, &read_buf, &read_buf_offset,
- &available_bytes)) {
- return 0;
- }
-
- available_bytes = std::min(available_bytes, len - len_read);
- memmove(data + len_read, read_buf + read_buf_offset, available_bytes);
-
- BIO_zero_copy_get_read_buf_done(bio, available_bytes);
-
- len_read += available_bytes;
- } while (len - len_read > 0 && available_bytes > 0);
-
- return len_read;
-}
-
-// BioWriteZeroCopyWrapper is a wrapper around the zero-copy APIs to make
-// testing easier.
-static size_t BioWriteZeroCopyWrapper(BIO *bio, const uint8_t *data,
- size_t len) {
- uint8_t *write_buf;
- size_t write_buf_offset;
- size_t available_bytes;
- size_t len_written = 0;
-
- do {
- if (!BIO_zero_copy_get_write_buf(bio, &write_buf, &write_buf_offset,
- &available_bytes)) {
- return 0;
- }
-
- available_bytes = std::min(available_bytes, len - len_written);
- memmove(write_buf + write_buf_offset, data + len_written, available_bytes);
-
- BIO_zero_copy_get_write_buf_done(bio, available_bytes);
-
- len_written += available_bytes;
- } while (len - len_written > 0 && available_bytes > 0);
-
- return len_written;
-}
-
-static bool TestZeroCopyBioPairs() {
- // Test read and write, especially triggering the ring buffer wrap-around.
- uint8_t bio1_application_send_buffer[1024];
- uint8_t bio2_application_recv_buffer[1024];
-
- const size_t kLengths[] = {254, 255, 256, 257, 510, 511, 512, 513};
-
- // These trigger ring buffer wrap around.
- const size_t kPartialLengths[] = {0, 1, 2, 3, 128, 255, 256, 257, 511, 512};
-
- static const size_t kBufferSize = 512;
-
- srand(1);
- for (size_t i = 0; i < sizeof(bio1_application_send_buffer); i++) {
- bio1_application_send_buffer[i] = rand() & 255;
- }
-
- // Transfer bytes from bio1_application_send_buffer to
- // bio2_application_recv_buffer in various ways.
- for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kLengths); i++) {
- for (size_t j = 0; j < OPENSSL_ARRAY_SIZE(kPartialLengths); j++) {
- size_t total_write = 0;
- size_t total_read = 0;
-
- BIO *bio1, *bio2;
- if (!BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize)) {
- return false;
- }
- bssl::UniquePtr<BIO> bio1_scoper(bio1);
- bssl::UniquePtr<BIO> bio2_scoper(bio2);
-
- total_write += BioWriteZeroCopyWrapper(
- bio1, bio1_application_send_buffer, kLengths[i]);
-
- // This tests interleaved read/write calls. Do a read between zero copy
- // write calls.
- uint8_t *write_buf;
- size_t write_buf_offset;
- size_t available_bytes;
- if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset,
- &available_bytes)) {
- return false;
- }
-
- // Free kPartialLengths[j] bytes in the beginning of bio1 write buffer.
- // This enables ring buffer wrap around for the next write.
- total_read += BIO_read(bio2, bio2_application_recv_buffer + total_read,
- kPartialLengths[j]);
-
- size_t interleaved_write_len = std::min(kPartialLengths[j],
- available_bytes);
-
- // Write the data for the interleaved write call. If the buffer becomes
- // empty after a read, the write offset is normally set to 0. Check that
- // this does not happen for interleaved read/write and that
- // |write_buf_offset| is still valid.
- memcpy(write_buf + write_buf_offset,
- bio1_application_send_buffer + total_write, interleaved_write_len);
- if (BIO_zero_copy_get_write_buf_done(bio1, interleaved_write_len)) {
- total_write += interleaved_write_len;
- }
-
- // Do another write in case |write_buf_offset| was wrapped.
- total_write += BioWriteZeroCopyWrapper(
- bio1, bio1_application_send_buffer + total_write,
- kPartialLengths[j] - interleaved_write_len);
-
- // Drain the rest.
- size_t bytes_left = BIO_pending(bio2);
- total_read += BioReadZeroCopyWrapper(
- bio2, bio2_application_recv_buffer + total_read, bytes_left);
-
- if (total_read != total_write) {
- fprintf(stderr, "Lengths not equal in round (%u, %u)\n", (unsigned)i,
- (unsigned)j);
- return false;
- }
- if (total_read > kLengths[i] + kPartialLengths[j]) {
- fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i,
- (unsigned)j);
- return false;
- }
- if (memcmp(bio1_application_send_buffer, bio2_application_recv_buffer,
- total_read) != 0) {
- fprintf(stderr, "Buffers not equal in round (%u, %u)\n", (unsigned)i,
- (unsigned)j);
- return false;
- }
- }
- }
-
- return true;
-}
-
static bool TestPrintf() {
// Test a short output, a very long one, and various sizes around
// 256 (the size of the buffer) to ensure edge cases are correct.
@@ -409,7 +263,137 @@
return true;
}
-int main(void) {
+static bool TestPair() {
+ // Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
+ for (int i = 0; i < 2; i++) {
+ BIO *bio1, *bio2;
+ if (!BIO_new_bio_pair(&bio1, 10, &bio2, 10)) {
+ return false;
+ }
+ bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
+
+ if (i == 1) {
+ std::swap(bio1, bio2);
+ }
+
+ // Check initial states.
+ if (BIO_ctrl_get_write_guarantee(bio1) != 10 ||
+ BIO_ctrl_get_read_request(bio1) != 0) {
+ return false;
+ }
+
+ // Data written in one end may be read out the other.
+ char buf[20];
+ if (BIO_write(bio1, "12345", 5) != 5 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 5 ||
+ BIO_read(bio2, buf, sizeof(buf)) != 5 ||
+ memcmp(buf, "12345", 5) != 0 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 10) {
+ return false;
+ }
+
+ // Attempting to write more than 10 bytes will write partially.
+ if (BIO_write(bio1, "1234567890___", 13) != 10 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 0 ||
+ BIO_write(bio1, "z", 1) != -1 ||
+ !BIO_should_write(bio1) ||
+ BIO_read(bio2, buf, sizeof(buf)) != 10 ||
+ memcmp(buf, "1234567890", 10) != 0 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 10) {
+ return false;
+ }
+
+ // Unsuccessful reads update the read request.
+ if (BIO_read(bio2, buf, 5) != -1 ||
+ !BIO_should_read(bio2) ||
+ BIO_ctrl_get_read_request(bio1) != 5) {
+ return false;
+ }
+
+ // The read request is clamped to the size of the buffer.
+ if (BIO_read(bio2, buf, 20) != -1 ||
+ !BIO_should_read(bio2) ||
+ BIO_ctrl_get_read_request(bio1) != 10) {
+ return false;
+ }
+
+ // Data may be written and read in chunks.
+ if (BIO_write(bio1, "12345", 5) != 5 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 5 ||
+ BIO_write(bio1, "67890___", 8) != 5 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 0 ||
+ BIO_read(bio2, buf, 3) != 3 ||
+ memcmp(buf, "123", 3) != 0 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 3 ||
+ BIO_read(bio2, buf, sizeof(buf)) != 7 ||
+ memcmp(buf, "4567890", 7) != 0 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 10) {
+ return false;
+ }
+
+ // Successful reads reset the read request.
+ if (BIO_ctrl_get_read_request(bio1) != 0) {
+ return false;
+ }
+
+ // Test writes and reads starting in the middle of the ring buffer and
+ // wrapping to front.
+ if (BIO_write(bio1, "abcdefgh", 8) != 8 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 2 ||
+ BIO_read(bio2, buf, 3) != 3 ||
+ memcmp(buf, "abc", 3) != 0 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 5 ||
+ BIO_write(bio1, "ijklm___", 8) != 5 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 0 ||
+ BIO_read(bio2, buf, sizeof(buf)) != 10 ||
+ memcmp(buf, "defghijklm", 10) != 0 ||
+ BIO_ctrl_get_write_guarantee(bio1) != 10) {
+ return false;
+ }
+
+ // Data may flow from both ends in parallel.
+ if (BIO_write(bio1, "12345", 5) != 5 ||
+ BIO_write(bio2, "67890", 5) != 5 ||
+ BIO_read(bio2, buf, sizeof(buf)) != 5 ||
+ memcmp(buf, "12345", 5) != 0 ||
+ BIO_read(bio1, buf, sizeof(buf)) != 5 ||
+ memcmp(buf, "67890", 5) != 0) {
+ return false;
+ }
+
+ // Closing the write end causes an EOF on the read half, after draining.
+ if (BIO_write(bio1, "12345", 5) != 5 ||
+ !BIO_shutdown_wr(bio1) ||
+ BIO_read(bio2, buf, sizeof(buf)) != 5 ||
+ memcmp(buf, "12345", 5) != 0 ||
+ BIO_read(bio2, buf, sizeof(buf)) != 0) {
+ return false;
+ }
+
+ // A closed write end may not be written to.
+ if (BIO_ctrl_get_write_guarantee(bio1) != 0 ||
+ BIO_write(bio1, "_____", 5) != -1) {
+ return false;
+ }
+
+ uint32_t err = ERR_get_error();
+ if (ERR_GET_LIB(err) != ERR_LIB_BIO ||
+ ERR_GET_REASON(err) != BIO_R_BROKEN_PIPE) {
+ return false;
+ }
+
+ // The other end is still functional.
+ if (BIO_write(bio2, "12345", 5) != 5 ||
+ BIO_read(bio1, buf, sizeof(buf)) != 5 ||
+ memcmp(buf, "12345", 5) != 0) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int main() {
CRYPTO_library_init();
#if defined(OPENSSL_WINDOWS)
@@ -429,8 +413,8 @@
if (!TestSocketConnect() ||
!TestPrintf() ||
- !TestZeroCopyBioPairs() ||
- !TestASN1()) {
+ !TestASN1() ||
+ !TestPair()) {
return 1;
}
diff --git a/src/crypto/bio/pair.c b/src/crypto/bio/pair.c
index 2da2d20..df36343 100644
--- a/src/crypto/bio/pair.c
+++ b/src/crypto/bio/pair.c
@@ -72,12 +72,6 @@
size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
size_t size;
uint8_t *buf; /* "size" elements (if != NULL) */
- char buf_externally_allocated; /* true iff buf was externally allocated. */
-
- char zero_copy_read_lock; /* true iff a zero copy read operation
- * is in progress. */
- char zero_copy_write_lock; /* true iff a zero copy write operation
- * is in progress. */
size_t request; /* valid iff peer != NULL; 0 if len != 0,
* otherwise set by peer to number of bytes
@@ -145,263 +139,12 @@
bio_destroy_pair(bio);
}
- if (!b->buf_externally_allocated) {
- OPENSSL_free(b->buf);
- }
-
+ OPENSSL_free(b->buf);
OPENSSL_free(b);
return 1;
}
-static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b,
- uint8_t** out_read_buf,
- size_t* out_buf_offset) {
- size_t max_available;
- if (peer_b->len > peer_b->size - peer_b->offset) {
- /* Only the first half of the ring buffer can be read. */
- max_available = peer_b->size - peer_b->offset;
- } else {
- max_available = peer_b->len;
- }
-
- *out_read_buf = peer_b->buf;
- *out_buf_offset = peer_b->offset;
- return max_available;
-}
-
-int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf,
- size_t* out_buf_offset,
- size_t* out_available_bytes) {
- struct bio_bio_st* b;
- struct bio_bio_st* peer_b;
- size_t max_available;
- *out_available_bytes = 0;
-
- BIO_clear_retry_flags(bio);
-
- if (!bio->init) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
- return 0;
- }
-
- b = bio->ptr;
-
- if (!b || !b->peer) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
- return 0;
- }
-
- peer_b = b->peer->ptr;
- if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
- return 0;
- }
-
- if (peer_b->zero_copy_read_lock) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
- return 0;
- }
-
- peer_b->request = 0; /* Is not used by zero-copy API. */
-
- max_available =
- bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset);
-
- assert(peer_b->buf != NULL);
- if (max_available > 0) {
- peer_b->zero_copy_read_lock = 1;
- }
-
- *out_available_bytes = max_available;
- return 1;
-}
-
-int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
- struct bio_bio_st* b;
- struct bio_bio_st* peer_b;
- size_t max_available;
- size_t dummy_read_offset;
- uint8_t* dummy_read_buf;
-
- assert(BIO_get_retry_flags(bio) == 0);
-
- if (!bio->init) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
- return 0;
- }
-
- b = bio->ptr;
-
- if (!b || !b->peer) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
- return 0;
- }
-
- peer_b = b->peer->ptr;
- if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
- return 0;
- }
-
- if (!peer_b->zero_copy_read_lock) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
- return 0;
- }
-
- max_available =
- bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
- if (bytes_read > max_available) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
- return 0;
- }
-
- assert(peer_b->len >= bytes_read);
- peer_b->len -= bytes_read;
- assert(peer_b->offset + bytes_read <= peer_b->size);
-
- /* Move read offset. If zero_copy_write_lock == 1 we must advance the
- * offset even if buffer becomes empty, to make sure
- * write_offset = (offset + len) mod size does not change. */
- if (peer_b->offset + bytes_read == peer_b->size ||
- (!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
- peer_b->offset = 0;
- } else {
- peer_b->offset += bytes_read;
- }
-
- bio->num_read += bytes_read;
- peer_b->zero_copy_read_lock = 0;
- return 1;
-}
-
-static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b,
- uint8_t** out_write_buf,
- size_t* out_buf_offset) {
- size_t write_offset;
- size_t max_available;
-
- assert(b->len <= b->size);
-
- write_offset = b->offset + b->len;
-
- if (write_offset >= b->size) {
- /* Only the first half of the ring buffer can be written to. */
- write_offset -= b->size;
- /* write up to the start of the ring buffer. */
- max_available = b->offset - write_offset;
- } else {
- /* write up to the end the buffer. */
- max_available = b->size - write_offset;
- }
-
- *out_write_buf = b->buf;
- *out_buf_offset = write_offset;
- return max_available;
-}
-
-int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf,
- size_t* out_buf_offset,
- size_t* out_available_bytes) {
- struct bio_bio_st* b;
- struct bio_bio_st* peer_b;
- size_t max_available;
-
- *out_available_bytes = 0;
- BIO_clear_retry_flags(bio);
-
- if (!bio->init) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
- return 0;
- }
-
- b = bio->ptr;
-
- if (!b || !b->buf || !b->peer) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
- return 0;
- }
- peer_b = b->peer->ptr;
- if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
- return 0;
- }
-
- assert(b->buf != NULL);
-
- if (b->zero_copy_write_lock) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
- return 0;
- }
-
- b->request = 0;
- if (b->closed) {
- /* Bio is already closed. */
- OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
- return 0;
- }
-
- max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset);
-
- if (max_available > 0) {
- b->zero_copy_write_lock = 1;
- }
-
- *out_available_bytes = max_available;
- return 1;
-}
-
-int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) {
- struct bio_bio_st* b;
- struct bio_bio_st* peer_b;
-
- size_t rest;
- size_t dummy_write_offset;
- uint8_t* dummy_write_buf;
-
- if (!bio->init) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
- return 0;
- }
-
- b = bio->ptr;
-
- if (!b || !b->buf || !b->peer) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
- return 0;
- }
- peer_b = b->peer->ptr;
- if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
- return 0;
- }
-
- b->request = 0;
- if (b->closed) {
- /* BIO is already closed. */
- OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
- return 0;
- }
-
- if (!b->zero_copy_write_lock) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
- return 0;
- }
-
- rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset);
-
- if (bytes_written > rest) {
- OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
- return 0;
- }
-
- bio->num_write += bytes_written;
- /* Move write offset. */
- b->len += bytes_written;
- b->zero_copy_write_lock = 0;
- return 1;
-}
-
static int bio_read(BIO *bio, char *buf, int size_) {
size_t size = size_;
size_t rest;
@@ -422,7 +165,7 @@
peer_b->request = 0; /* will be set in "retry_read" situation */
- if (buf == NULL || size == 0 || peer_b->zero_copy_read_lock) {
+ if (buf == NULL || size == 0) {
return 0;
}
@@ -467,10 +210,7 @@
memcpy(buf, peer_b->buf + peer_b->offset, chunk);
peer_b->len -= chunk;
- /* If zero_copy_write_lock == 1 we must advance the offset even if buffer
- * becomes empty, to make sure write_offset = (offset + len) % size
- * does not change. */
- if (peer_b->len || peer_b->zero_copy_write_lock) {
+ if (peer_b->len) {
peer_b->offset += chunk;
assert(peer_b->offset <= peer_b->size);
if (peer_b->offset == peer_b->size) {
@@ -504,10 +244,6 @@
assert(b->peer != NULL);
assert(b->buf != NULL);
- if (b->zero_copy_write_lock) {
- return 0;
- }
-
b->request = 0;
if (b->closed) {
/* we already closed */
@@ -564,9 +300,8 @@
return num;
}
-static int bio_make_pair(BIO* bio1, BIO* bio2,
- size_t writebuf1_len, uint8_t* ext_writebuf1,
- size_t writebuf2_len, uint8_t* ext_writebuf2) {
+static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
+ size_t writebuf2_len) {
struct bio_bio_st *b1, *b2;
assert(bio1 != NULL);
@@ -580,23 +315,14 @@
return 0;
}
- assert(b1->buf_externally_allocated == 0);
- assert(b2->buf_externally_allocated == 0);
-
if (b1->buf == NULL) {
if (writebuf1_len) {
b1->size = writebuf1_len;
}
- if (!ext_writebuf1) {
- b1->buf_externally_allocated = 0;
- b1->buf = OPENSSL_malloc(b1->size);
- if (b1->buf == NULL) {
- OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- } else {
- b1->buf = ext_writebuf1;
- b1->buf_externally_allocated = 1;
+ b1->buf = OPENSSL_malloc(b1->size);
+ if (b1->buf == NULL) {
+ OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
+ return 0;
}
b1->len = 0;
b1->offset = 0;
@@ -606,16 +332,10 @@
if (writebuf2_len) {
b2->size = writebuf2_len;
}
- if (!ext_writebuf2) {
- b2->buf_externally_allocated = 0;
- b2->buf = OPENSSL_malloc(b2->size);
- if (b2->buf == NULL) {
- OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
- return 0;
- }
- } else {
- b2->buf = ext_writebuf2;
- b2->buf_externally_allocated = 1;
+ b2->buf = OPENSSL_malloc(b2->size);
+ if (b2->buf == NULL) {
+ OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
+ return 0;
}
b2->len = 0;
b2->offset = 0;
@@ -624,13 +344,9 @@
b1->peer = bio2;
b1->closed = 0;
b1->request = 0;
- b1->zero_copy_read_lock = 0;
- b1->zero_copy_write_lock = 0;
b2->peer = bio1;
b2->closed = 0;
b2->request = 0;
- b2->zero_copy_read_lock = 0;
- b2->zero_copy_write_lock = 0;
bio1->init = 1;
bio2->init = 1;
@@ -744,50 +460,22 @@
static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
-int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
- BIO** bio2_p, size_t writebuf2) {
- return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p,
- writebuf2, NULL);
-}
-
-int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len,
- uint8_t* ext_writebuf1,
- BIO** bio2_p, size_t writebuf2_len,
- uint8_t* ext_writebuf2) {
- BIO *bio1 = NULL, *bio2 = NULL;
- int ret = 0;
-
- /* External buffers must have sizes greater than 0. */
- if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) {
- goto err;
- }
-
- bio1 = BIO_new(bio_s_bio());
- if (bio1 == NULL) {
- goto err;
- }
- bio2 = BIO_new(bio_s_bio());
- if (bio2 == NULL) {
- goto err;
- }
-
- if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len,
- ext_writebuf2)) {
- goto err;
- }
- ret = 1;
-
-err:
- if (ret == 0) {
+int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1_len,
+ BIO** bio2_p, size_t writebuf2_len) {
+ BIO *bio1 = BIO_new(bio_s_bio());
+ BIO *bio2 = BIO_new(bio_s_bio());
+ if (bio1 == NULL || bio2 == NULL ||
+ !bio_make_pair(bio1, bio2, writebuf1_len, writebuf2_len)) {
BIO_free(bio1);
- bio1 = NULL;
BIO_free(bio2);
- bio2 = NULL;
+ *bio1_p = NULL;
+ *bio2_p = NULL;
+ return 0;
}
*bio1_p = bio1;
*bio2_p = bio2;
- return ret;
+ return 1;
}
size_t BIO_ctrl_get_read_request(BIO *bio) {
diff --git a/src/crypto/bn/bn_test.cc b/src/crypto/bn/bn_test.cc
index 672d83f..044af5f 100644
--- a/src/crypto/bn/bn_test.cc
+++ b/src/crypto/bn/bn_test.cc
@@ -568,21 +568,25 @@
bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
bssl::UniquePtr<BIGNUM> p = GetBIGNUM(t, "P");
bssl::UniquePtr<BIGNUM> mod_sqrt = GetBIGNUM(t, "ModSqrt");
- if (!a || !p || !mod_sqrt) {
+ bssl::UniquePtr<BIGNUM> mod_sqrt2(BN_new());
+ if (!a || !p || !mod_sqrt || !mod_sqrt2 ||
+ // There are two possible answers.
+ !BN_sub(mod_sqrt2.get(), p.get(), mod_sqrt.get())) {
return false;
}
+ // -0 is 0, not P.
+ if (BN_is_zero(mod_sqrt.get())) {
+ BN_zero(mod_sqrt2.get());
+ }
+
bssl::UniquePtr<BIGNUM> ret(BN_new());
- bssl::UniquePtr<BIGNUM> ret2(BN_new());
if (!ret ||
- !ret2 ||
- !BN_mod_sqrt(ret.get(), a.get(), p.get(), ctx) ||
- // There are two possible answers.
- !BN_sub(ret2.get(), p.get(), ret.get())) {
+ !BN_mod_sqrt(ret.get(), a.get(), p.get(), ctx)) {
return false;
}
- if (BN_cmp(ret2.get(), mod_sqrt.get()) != 0 &&
+ if (BN_cmp(ret.get(), mod_sqrt2.get()) != 0 &&
!ExpectBIGNUMsEqual(t, "sqrt(A) (mod P)", mod_sqrt.get(), ret.get())) {
return false;
}
@@ -590,6 +594,29 @@
return true;
}
+static bool TestNotModSquare(FileTest *t, BN_CTX *ctx) {
+ bssl::UniquePtr<BIGNUM> not_mod_square = GetBIGNUM(t, "NotModSquare");
+ bssl::UniquePtr<BIGNUM> p = GetBIGNUM(t, "P");
+ bssl::UniquePtr<BIGNUM> ret(BN_new());
+ if (!not_mod_square || !p || !ret) {
+ return false;
+ }
+
+ if (BN_mod_sqrt(ret.get(), not_mod_square.get(), p.get(), ctx)) {
+ t->PrintLine("BN_mod_sqrt unexpectedly succeeded.");
+ return false;
+ }
+
+ uint32_t err = ERR_peek_error();
+ if (ERR_GET_LIB(err) == ERR_LIB_BN &&
+ ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
+ ERR_clear_error();
+ return true;
+ }
+
+ return false;
+}
+
static bool TestModInv(FileTest *t, BN_CTX *ctx) {
bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
bssl::UniquePtr<BIGNUM> m = GetBIGNUM(t, "M");
@@ -634,6 +661,7 @@
{"ModExp", TestModExp},
{"Exp", TestExp},
{"ModSqrt", TestModSqrt},
+ {"NotModSquare", TestNotModSquare},
{"ModInv", TestModInv},
};
diff --git a/src/crypto/bn/bn_tests.txt b/src/crypto/bn/bn_tests.txt
index 692a642..ec89b8e 100644
--- a/src/crypto/bn/bn_tests.txt
+++ b/src/crypto/bn/bn_tests.txt
@@ -10737,6 +10737,28 @@
A = 2eee37cf06228a387788188e650bc6d8a2ff402931443f69156a29155eca07dcb45f3aac238d92943c0c25c896098716baa433f25bd696a142f5a69d5d937e81
P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
+
+# NotModSquare tests.
+#
+# These test vectors are such that NotModSquare is not a square modulo P.
+
+NotModSquare = 03
+P = 07
+
+NotModSquare = 05
+P = 07
+
+NotModSquare = 06
+P = 07
+
+NotModSquare = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951e
+P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
+
+
+# ModInv tests.
+#
+# These test vectors satisfy ModInv * A = 1 (mod M) and 0 <= ModInv < M.
+
ModInv = 00
A = 00
M = 01
diff --git a/src/crypto/bn/sqrt.c b/src/crypto/bn/sqrt.c
index e3a7b9a..fb962a9 100644
--- a/src/crypto/bn/sqrt.c
+++ b/src/crypto/bn/sqrt.c
@@ -456,7 +456,9 @@
}
/* We estimate that the square root of an n-bit number is 2^{n/2}. */
- BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2);
+ if (!BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2)) {
+ goto err;
+ }
/* This is Newton's method for finding a root of the equation |estimate|^2 -
* |in| = 0. */
diff --git a/src/crypto/bytestring/bytestring_test.cc b/src/crypto/bytestring/bytestring_test.cc
index 563c6b0..6ce071a 100644
--- a/src/crypto/bytestring/bytestring_test.cc
+++ b/src/crypto/bytestring/bytestring_test.cc
@@ -28,7 +28,6 @@
#include "internal.h"
#include "../internal.h"
-namespace bssl {
static bool TestSkip() {
static const uint8_t kData[] = {1, 2, 3};
@@ -317,7 +316,7 @@
}
static bool TestCBBFixed() {
- ScopedCBB cbb;
+ bssl::ScopedCBB cbb;
uint8_t buf[1];
uint8_t *out_buf;
size_t out_size;
@@ -401,7 +400,7 @@
}
static bool TestCBBDiscardChild() {
- ScopedCBB cbb;
+ bssl::ScopedCBB cbb;
CBB contents, inner_contents, inner_inner_contents;
if (!CBB_init(cbb.get(), 0) ||
@@ -804,7 +803,7 @@
uint8_t buf[10];
uint8_t *ptr;
size_t len;
- ScopedCBB cbb;
+ bssl::ScopedCBB cbb;
if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) ||
// Too large.
CBB_reserve(cbb.get(), &ptr, 11)) {
@@ -827,7 +826,7 @@
static bool TestStickyError() {
// Write an input that exceeds the limit for its length prefix.
- ScopedCBB cbb;
+ bssl::ScopedCBB cbb;
CBB child;
static const uint8_t kZeros[256] = {0};
if (!CBB_init(cbb.get(), 0) ||
@@ -890,7 +889,7 @@
return true;
}
-static int Main() {
+int main() {
CRYPTO_library_init();
if (!TestSkip() ||
@@ -918,9 +917,3 @@
printf("PASS\n");
return 0;
}
-
-} // namespace bssl
-
-int main() {
- return bssl::Main();
-}
diff --git a/src/crypto/cipher/aead_test.cc b/src/crypto/cipher/aead_test.cc
index b33a36d..313f041 100644
--- a/src/crypto/cipher/aead_test.cc
+++ b/src/crypto/cipher/aead_test.cc
@@ -23,7 +23,15 @@
#include "../test/file_test.h"
-namespace bssl {
+
+#if defined(OPENSSL_SMALL)
+const EVP_AEAD* EVP_aead_aes_128_gcm_siv(void) {
+ return nullptr;
+}
+const EVP_AEAD* EVP_aead_aes_256_gcm_siv(void) {
+ return nullptr;
+}
+#endif
// This program tests an AEAD against a series of test vectors from a file,
// using the FileTest format. As an example, here's a valid test case:
@@ -48,7 +56,7 @@
return false;
}
- ScopedEVP_AEAD_CTX ctx;
+ bssl::ScopedEVP_AEAD_CTX ctx;
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
tag.size(), evp_aead_seal)) {
t->PrintLine("Failed to init AEAD.");
@@ -198,7 +206,7 @@
const size_t max_overhead = EVP_AEAD_max_overhead(aead);
std::vector<uint8_t> key(key_len, 'a');
- ScopedEVP_AEAD_CTX ctx;
+ bssl::ScopedEVP_AEAD_CTX ctx;
if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len,
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
return false;
@@ -302,6 +310,8 @@
static const struct KnownAEAD kAEADs[] = {
{ "aes-128-gcm", EVP_aead_aes_128_gcm, false },
{ "aes-256-gcm", EVP_aead_aes_256_gcm, false },
+ { "aes-128-gcm-siv", EVP_aead_aes_128_gcm_siv, false },
+ { "aes-256-gcm-siv", EVP_aead_aes_256_gcm_siv, false },
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305, false },
{ "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old, false },
{ "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true },
@@ -321,7 +331,7 @@
{ "", NULL, false },
};
-static int Main(int argc, char **argv) {
+int main(int argc, char **argv) {
CRYPTO_library_init();
if (argc != 3) {
@@ -342,6 +352,11 @@
}
const EVP_AEAD *const aead = known_aead->func();
+ if (aead == NULL) {
+ // AEAD is not compiled in this configuration.
+ printf("PASS\n");
+ return 0;
+ }
if (!TestCleanupAfterInitFailure(aead)) {
return 1;
@@ -354,9 +369,3 @@
return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
}
-
-} // namespace bssl
-
-int main(int argc, char **argv) {
- return bssl::Main(argc, argv);
-}
diff --git a/src/crypto/cipher/cipher_test.cc b/src/crypto/cipher/cipher_test.cc
index cb42fc5..09802c2 100644
--- a/src/crypto/cipher/cipher_test.cc
+++ b/src/crypto/cipher/cipher_test.cc
@@ -63,7 +63,6 @@
#include "../test/file_test.h"
-namespace bssl {
static const EVP_CIPHER *GetCipher(const std::string &name) {
if (name == "DES-CBC") {
@@ -127,7 +126,7 @@
bool is_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE;
- ScopedEVP_CIPHER_CTX ctx;
+ bssl::ScopedEVP_CIPHER_CTX ctx;
if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr,
encrypt ? 1 : 0)) {
return false;
@@ -284,7 +283,7 @@
return true;
}
-static int Main(int argc, char **argv) {
+int main(int argc, char **argv) {
CRYPTO_library_init();
if (argc != 2) {
@@ -294,9 +293,3 @@
return FileTestMain(TestCipher, nullptr, argv[1]);
}
-
-} // namespace bssl
-
-int main(int argc, char **argv) {
- return bssl::Main(argc, argv);
-}
diff --git a/src/crypto/cipher/e_aes.c b/src/crypto/cipher/e_aes.c
index 9225d6a..f99022f 100644
--- a/src/crypto/cipher/e_aes.c
+++ b/src/crypto/cipher/e_aes.c
@@ -1446,6 +1446,305 @@
return &aead_aes_256_ctr_hmac_sha256;
}
+#if !defined(OPENSSL_SMALL)
+
+#define EVP_AEAD_AES_GCM_SIV_TAG_LEN 16
+
+struct aead_aes_gcm_siv_ctx {
+ union {
+ double align;
+ AES_KEY ks;
+ } ks;
+ block128_f kgk_block;
+ unsigned is_256:1;
+};
+
+static int aead_aes_gcm_siv_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+ size_t key_len, size_t tag_len) {
+ const size_t key_bits = key_len * 8;
+
+ if (key_bits != 128 && key_bits != 256) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
+ return 0; /* EVP_AEAD_CTX_init should catch this. */
+ }
+
+ if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
+ tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
+ }
+
+ if (tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
+ return 0;
+ }
+
+ struct aead_aes_gcm_siv_ctx *gcm_siv_ctx =
+ OPENSSL_malloc(sizeof(struct aead_aes_gcm_siv_ctx));
+ if (gcm_siv_ctx == NULL) {
+ return 0;
+ }
+ memset(gcm_siv_ctx, 0, sizeof(struct aead_aes_gcm_siv_ctx));
+
+ if (aesni_capable()) {
+ aesni_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+ gcm_siv_ctx->kgk_block = (block128_f)aesni_encrypt;
+ } else if (hwaes_capable()) {
+ aes_hw_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+ gcm_siv_ctx->kgk_block = (block128_f)aes_hw_encrypt;
+ } else if (vpaes_capable()) {
+ vpaes_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+ gcm_siv_ctx->kgk_block = (block128_f)vpaes_encrypt;
+ } else {
+ AES_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+ gcm_siv_ctx->kgk_block = (block128_f)AES_encrypt;
+ }
+
+ gcm_siv_ctx->is_256 = (key_len == 32);
+ ctx->aead_state = gcm_siv_ctx;
+
+ return 1;
+}
+
+static void aead_aes_gcm_siv_cleanup(EVP_AEAD_CTX *ctx) {
+ struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
+ OPENSSL_cleanse(gcm_siv_ctx, sizeof(struct aead_aes_gcm_siv_ctx));
+ OPENSSL_free(gcm_siv_ctx);
+}
+
+/* gcm_siv_crypt encrypts (or decrypts—it's the same thing) |in_len| bytes from
+ * |in| to |out|, using the block function |enc_block| with |key| in counter
+ * mode, starting at |initial_counter|. This differs from the traditional
+ * counter mode code in that the counter is handled little-endian, only the
+ * first four bytes are used and the GCM-SIV tweak to the final byte is
+ * applied. The |in| and |out| pointers may be equal but otherwise must not
+ * alias. */
+static void gcm_siv_crypt(uint8_t *out, const uint8_t *in, size_t in_len,
+ const uint8_t initial_counter[AES_BLOCK_SIZE],
+ block128_f enc_block, const AES_KEY *key) {
+ union {
+ uint32_t w[4];
+ uint8_t c[16];
+ } counter;
+
+ memcpy(counter.c, initial_counter, AES_BLOCK_SIZE);
+ counter.c[15] |= 0x80;
+
+ for (size_t done = 0; done < in_len;) {
+ uint8_t keystream[AES_BLOCK_SIZE];
+ enc_block(counter.c, keystream, key);
+ counter.w[0]++;
+
+ size_t todo = AES_BLOCK_SIZE;
+ if (in_len - done < todo) {
+ todo = in_len - done;
+ }
+
+ for (size_t i = 0; i < todo; i++) {
+ out[done + i] = keystream[i] ^ in[done + i];
+ }
+
+ done += todo;
+ }
+}
+
+/* gcm_siv_polyval evaluates POLYVAL at |auth_key| on the given plaintext and
+ * AD. The result is written to |out_tag|. */
+static void gcm_siv_polyval(uint8_t out_tag[16], const uint8_t *in,
+ size_t in_len, const uint8_t *ad, size_t ad_len,
+ const uint8_t auth_key[16]) {
+ struct polyval_ctx polyval_ctx;
+ CRYPTO_POLYVAL_init(&polyval_ctx, auth_key);
+
+ CRYPTO_POLYVAL_update_blocks(&polyval_ctx, ad, ad_len & ~15);
+
+ uint8_t scratch[16];
+ if (ad_len & 15) {
+ memset(scratch, 0, sizeof(scratch));
+ memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
+ CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
+ }
+
+ CRYPTO_POLYVAL_update_blocks(&polyval_ctx, in, in_len & ~15);
+ if (in_len & 15) {
+ memset(scratch, 0, sizeof(scratch));
+ memcpy(scratch, &in[in_len & ~15], in_len & 15);
+ CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
+ }
+
+ union {
+ uint8_t c[16];
+ struct {
+ uint64_t ad;
+ uint64_t in;
+ } bitlens;
+ } length_block;
+
+ length_block.bitlens.ad = ad_len * 8;
+ length_block.bitlens.in = in_len * 8;
+ CRYPTO_POLYVAL_update_blocks(&polyval_ctx, length_block.c,
+ sizeof(length_block));
+
+ CRYPTO_POLYVAL_finish(&polyval_ctx, out_tag);
+ out_tag[15] &= 0x7f;
+}
+
+/* gcm_siv_record_keys contains the keys used for a specific GCM-SIV record. */
+struct gcm_siv_record_keys {
+ uint8_t auth_key[16];
+ union {
+ double align;
+ AES_KEY ks;
+ } enc_key;
+ block128_f enc_block;
+};
+
+/* gcm_siv_keys calculates the keys for a specific GCM-SIV record with the
+ * given nonce and writes them to |*out_keys|. */
+static void gcm_siv_keys(
+ const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx,
+ struct gcm_siv_record_keys *out_keys,
+ const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_TAG_LEN]) {
+ const AES_KEY *const key = &gcm_siv_ctx->ks.ks;
+ gcm_siv_ctx->kgk_block(nonce, out_keys->auth_key, key);
+
+ if (gcm_siv_ctx->is_256) {
+ uint8_t record_enc_key[32];
+ gcm_siv_ctx->kgk_block(out_keys->auth_key, record_enc_key + 16, key);
+ gcm_siv_ctx->kgk_block(record_enc_key + 16, record_enc_key, key);
+ aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
+ record_enc_key, sizeof(record_enc_key));
+ } else {
+ uint8_t record_enc_key[16];
+ gcm_siv_ctx->kgk_block(out_keys->auth_key, record_enc_key, key);
+ aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
+ record_enc_key, sizeof(record_enc_key));
+ }
+}
+
+static int aead_aes_gcm_siv_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
+ const uint64_t in_len_64 = in_len;
+ const uint64_t ad_len_64 = ad_len;
+
+ if (in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN < in_len ||
+ in_len_64 > (UINT64_C(1) << 36) ||
+ ad_len_64 >= (UINT64_C(1) << 61)) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ if (max_out_len < in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ if (nonce_len != AES_BLOCK_SIZE) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+ return 0;
+ }
+
+ struct gcm_siv_record_keys keys;
+ gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
+
+ uint8_t tag[16];
+ gcm_siv_polyval(tag, in, in_len, ad, ad_len, keys.auth_key);
+ keys.enc_block(tag, tag, &keys.enc_key.ks);
+
+ gcm_siv_crypt(out, in, in_len, tag, keys.enc_block, &keys.enc_key.ks);
+
+ memcpy(&out[in_len], tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN);
+ *out_len = in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN;
+
+ return 1;
+}
+
+static int aead_aes_gcm_siv_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
+ size_t *out_len, size_t max_out_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *ad, size_t ad_len) {
+ const uint64_t ad_len_64 = ad_len;
+ if (ad_len_64 >= (UINT64_C(1) << 61)) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
+ return 0;
+ }
+
+ const uint64_t in_len_64 = in_len;
+ if (in_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN ||
+ in_len_64 > (UINT64_C(1) << 36) + AES_BLOCK_SIZE) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
+ const size_t plaintext_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
+
+ if (max_out_len < plaintext_len) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ struct gcm_siv_record_keys keys;
+ gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
+
+ gcm_siv_crypt(out, in, plaintext_len, &in[plaintext_len], keys.enc_block,
+ &keys.enc_key.ks);
+
+ uint8_t expected_tag[EVP_AEAD_AES_GCM_SIV_TAG_LEN];
+ gcm_siv_polyval(expected_tag, out, plaintext_len, ad, ad_len, keys.auth_key);
+ keys.enc_block(expected_tag, expected_tag, &keys.enc_key.ks);
+
+ if (CRYPTO_memcmp(expected_tag, &in[plaintext_len], sizeof(expected_tag)) !=
+ 0) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
+ return 0;
+ }
+
+ *out_len = plaintext_len;
+ return 1;
+}
+
+static const EVP_AEAD aead_aes_128_gcm_siv = {
+ 16, /* key length */
+ AES_BLOCK_SIZE, /* nonce length */
+ EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
+ EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
+
+ aead_aes_gcm_siv_init,
+ NULL /* init_with_direction */,
+ aead_aes_gcm_siv_cleanup,
+ aead_aes_gcm_siv_seal,
+ aead_aes_gcm_siv_open,
+ NULL /* get_iv */,
+};
+
+static const EVP_AEAD aead_aes_256_gcm_siv = {
+ 32, /* key length */
+ AES_BLOCK_SIZE, /* nonce length */
+ EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
+ EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
+
+ aead_aes_gcm_siv_init,
+ NULL /* init_with_direction */,
+ aead_aes_gcm_siv_cleanup,
+ aead_aes_gcm_siv_seal,
+ aead_aes_gcm_siv_open,
+ NULL /* get_iv */,
+};
+
+const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void) {
+ return &aead_aes_128_gcm_siv;
+}
+
+const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void) {
+ return &aead_aes_256_gcm_siv;
+}
+
+#endif /* !OPENSSL_SMALL */
+
int EVP_has_aes_hardware(void) {
#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
return aesni_capable() && crypto_gcm_clmul_enabled();
diff --git a/src/crypto/cipher/test/aes_128_gcm_siv_tests.txt b/src/crypto/cipher/test/aes_128_gcm_siv_tests.txt
new file mode 100644
index 0000000..a929b59
--- /dev/null
+++ b/src/crypto/cipher/test/aes_128_gcm_siv_tests.txt
@@ -0,0 +1,236 @@
+# This is the example from
+# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#section-8
+
+KEY: ee8e1ed9ff2540ae8f2ba9f50bc2f27c
+NONCE: 752abad3e0afb5f434dc4310f71f3d21
+IN: "Hello world"
+AD: "example"
+CT: 810649724764545b3625ff
+TAG: 010a10f4942710781d2948ac0192572f
+
+# Test vectors from
+# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#appendix-B
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN:
+AD:
+CT:
+TAG: cb52de357fad226ae428d0ed5a575496
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000
+AD:
+CT: 7e139f58002d68ee
+TAG: 715835541f2136f03b6dc80ae0a8ac46
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000
+AD:
+CT: 4a87f0cd26e5d5086e90da02
+TAG: 4dff905e48d512e9c34ae8f3be66ec43
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000
+AD:
+CT: 048ca58c46d2368ce00132389f40b511
+TAG: 971da9aa385283522c4f67a9aedb37e5
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000000000000000000002000000000000000000000000000000
+AD:
+CT: e1cf1cf545d2743ec005b26bd2c836ac1a4233d646c195ffa401f28063127baa
+TAG: 1071338b8c2930d3ec4c17cecbefa4b4
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+AD:
+CT: 2e7e6881a02d57b877794b2fbfbfef5484f1cf74f4ad53a751b2582c0e698466bd9a49dcab53806d8e31d864c4632d00
+TAG: 04b1b8a9c1630ff028b14d2e57bca429
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD:
+CT: 0ac5be860726209d9218de3e9d533743e1efe1595bc58f93f00e9bb9a7558dc1e1b14a9c0d49eb5064c7efa79842f9c7cfdd77614709f0b545d3227498e774d5
+TAG: 860b73a1ed8a5b9acd925c3f3f49c5c5
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000
+AD: 01
+CT: 4919e29e9890e452
+TAG: 1433a5c0284c911163888dbd128e6874
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000
+AD: 01
+CT: db55d6da719fe0473538294e
+TAG: 5a8ab948ccd205a70c78e8fdf954693b
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000
+AD: 01
+CT: aea3c54272abc1b58ed34a536743f4da
+TAG: da10d98bfe23784cfdfd0af97b6d5b78
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000000000000000000003000000000000000000000000000000
+AD: 01
+CT: aa694c0cfe148100cb5c6e27a77a7ff7b4233d6af251d9faa3d84f7c0d1113f1
+TAG: 778c5b68356a1a6a6f3c14a8f96c35ca
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 01
+CT: 9ac909928bcde79c2afa885df9c035c85a9eab136f6f6ea11034456bd306ea3c5dd542f706fffe538b5f139fa9dc622e
+TAG: 26c0c0d146d38787ca0fcbc3f911577a
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+AD: 01
+CT: c56be9d61ecf6a31a6289cddc9b91aaf84cdb53a3913b825d6eb5e157906dfb0a308c6b0b095d6fd1a5b761ca7fa0e39ca92f38ae206eec844c0c4ab0c1c165e
+TAG: a60986309b99431a35dd8c5ebeef8375
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000
+AD: 010000000000000000000000
+CT: 47995b96
+TAG: 16b668094202cadde992e0c16205793c
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0300000000000000000000000000000004000000
+AD: 010000000000000000000000000000000200
+CT: 8fe25de75089e9f849150e57ab7f7810981cd319
+TAG: 89ca91ebc560709432fe9496746404cc
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 030000000000000000000000000000000400
+AD: 0100000000000000000000000000000002000000
+CT: b26d43ae158316ac37f41579ccf1d461274e
+TAG: 13b7c01d08dd6969d51d1bf0fbbdc4d2
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN:
+AD:
+CT:
+TAG: cb52de357fad226ae428d0ed5a575496
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000
+AD:
+CT: 7e139f58002d68ee
+TAG: 715835541f2136f03b6dc80ae0a8ac46
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000
+AD:
+CT: 4a87f0cd26e5d5086e90da02
+TAG: 4dff905e48d512e9c34ae8f3be66ec43
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000
+AD:
+CT: 048ca58c46d2368ce00132389f40b511
+TAG: 971da9aa385283522c4f67a9aedb37e5
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000000000000000000002000000000000000000000000000000
+AD:
+CT: e1cf1cf545d2743ec005b26bd2c836ac1a4233d646c195ffa401f28063127baa
+TAG: 1071338b8c2930d3ec4c17cecbefa4b4
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+AD:
+CT: 2e7e6881a02d57b877794b2fbfbfef5484f1cf74f4ad53a751b2582c0e698466bd9a49dcab53806d8e31d864c4632d00
+TAG: 04b1b8a9c1630ff028b14d2e57bca429
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD:
+CT: 0ac5be860726209d9218de3e9d533743e1efe1595bc58f93f00e9bb9a7558dc1e1b14a9c0d49eb5064c7efa79842f9c7cfdd77614709f0b545d3227498e774d5
+TAG: 860b73a1ed8a5b9acd925c3f3f49c5c5
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000
+AD: 01
+CT: 4919e29e9890e452
+TAG: 1433a5c0284c911163888dbd128e6874
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000
+AD: 01
+CT: db55d6da719fe0473538294e
+TAG: 5a8ab948ccd205a70c78e8fdf954693b
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000
+AD: 01
+CT: aea3c54272abc1b58ed34a536743f4da
+TAG: da10d98bfe23784cfdfd0af97b6d5b78
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000000000000000000003000000000000000000000000000000
+AD: 01
+CT: aa694c0cfe148100cb5c6e27a77a7ff7b4233d6af251d9faa3d84f7c0d1113f1
+TAG: 778c5b68356a1a6a6f3c14a8f96c35ca
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 01
+CT: 9ac909928bcde79c2afa885df9c035c85a9eab136f6f6ea11034456bd306ea3c5dd542f706fffe538b5f139fa9dc622e
+TAG: 26c0c0d146d38787ca0fcbc3f911577a
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+AD: 01
+CT: c56be9d61ecf6a31a6289cddc9b91aaf84cdb53a3913b825d6eb5e157906dfb0a308c6b0b095d6fd1a5b761ca7fa0e39ca92f38ae206eec844c0c4ab0c1c165e
+TAG: a60986309b99431a35dd8c5ebeef8375
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000
+AD: 010000000000000000000000
+CT: 47995b96
+TAG: 16b668094202cadde992e0c16205793c
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0300000000000000000000000000000004000000
+AD: 010000000000000000000000000000000200
+CT: 8fe25de75089e9f849150e57ab7f7810981cd319
+TAG: 89ca91ebc560709432fe9496746404cc
+
+KEY: 01000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 030000000000000000000000000000000400
+AD: 0100000000000000000000000000000002000000
+CT: b26d43ae158316ac37f41579ccf1d461274e
+TAG: 13b7c01d08dd6969d51d1bf0fbbdc4d2
diff --git a/src/crypto/cipher/test/aes_256_gcm_siv_tests.txt b/src/crypto/cipher/test/aes_256_gcm_siv_tests.txt
new file mode 100644
index 0000000..cd38e23
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_gcm_siv_tests.txt
@@ -0,0 +1,226 @@
+# Test vectors from
+# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#appendix-B
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN:
+AD:
+CT:
+TAG: eb7ccf36eeff369241379c87cc08e4f0
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000
+AD:
+CT: ab3f382a6f0fb4c3
+TAG: a0a69e07b73281f5cdfd034f646cfa08
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000
+AD:
+CT: be8d81f033ca23b953da2197
+TAG: cdf3ba70da9c7cbd45f5140ba0cca9f1
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000
+AD:
+CT: 46e05b7116dbe27aaeffe99892194072
+TAG: be19d78991c62130cf97f628c37c3eaa
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000000000000000000002000000000000000000000000000000
+AD:
+CT: 23ddbe9ef342b03003f56d6b4a2e8aff035c7d7cfd705e1ab4502904254bb67a
+TAG: 16c5944034050657af7c0fec7efbc40f
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+AD:
+CT: b104c8945f280e75b52c05c45a63d1872c7f0552b1501968d9913d71207d0433f978f1a3eecdf782016b77e8c9d3ff53
+TAG: abedb4841c20f3b05e61e0fd1fcaf3d0
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD:
+CT: e3f2bd14f4c80c9cea4c90c81f0e4d7eedb87eb19a7c0cf5a5a95cd3e441a71083b1191d115e9a9ff008b93feeb5a86d012a3e0adb89de2d1e3225479022292f
+TAG: 3ced67f5e03bb476a738c1343926dc19
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000
+AD: 01
+CT: 4dca2c16c3b0413c
+TAG: ac9b952c76a6f8b5df315f88126daa1c
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000
+AD: 01
+CT: ee0ca9068b5b85dfe115a660
+TAG: 756d6155927271077d790a05390ecb71
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000
+AD: 01
+CT: 590edb785c0cb89d19f031fa7e7d4f91
+TAG: ac2c8f711c86dbecc8c7b663c5fbc1ea
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000000000000000000003000000000000000000000000000000
+AD: 01
+CT: dcf2024f5f98d463b82a8673c47dd82159748cac8bcc7c76b8cfa26029cb333c
+TAG: a9b406643e190e602fb104fbb842a1ac
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 01
+CT: 79216506b1ddadfe16366e4ec886d10dc9400b995259f74c0091f9b5a6add5680a612130f6c31ab833aa76d9b2be86de
+TAG: 3ddfe9ad2c350980942638d3f954ac6d
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+AD: 01
+CT: 9535eb67240c49f30a0de5a90670813fa615e71fcb4c522ca79d9a33459a22f8c6a56d650bf0b15eecdd706e7689cf6510a281724613fea76b5366b40574b1b9
+TAG: abcb59ee31d25ee8889b70d7c36f9a41
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000
+AD: 010000000000000000000000
+CT: 9611baa0
+TAG: 53daf2bc5916f7a6750f2432068dabee
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0300000000000000000000000000000004000000
+AD: 010000000000000000000000000000000200
+CT: 78e3a1b54daa6547f775f30c38a45e887aea5c87
+TAG: f65187d8c28adba364d659b627b16431
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 030000000000000000000000000000000400
+AD: 0100000000000000000000000000000002000000
+CT: c6d3d28704bf20067d62e1a3872d40dda44b
+TAG: 6ac0135a4379dbc67967ff55fd4d1f2f
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN:
+AD:
+CT:
+TAG: eb7ccf36eeff369241379c87cc08e4f0
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000
+AD:
+CT: ab3f382a6f0fb4c3
+TAG: a0a69e07b73281f5cdfd034f646cfa08
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000
+AD:
+CT: be8d81f033ca23b953da2197
+TAG: cdf3ba70da9c7cbd45f5140ba0cca9f1
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000
+AD:
+CT: 46e05b7116dbe27aaeffe99892194072
+TAG: be19d78991c62130cf97f628c37c3eaa
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0100000000000000000000000000000002000000000000000000000000000000
+AD:
+CT: 23ddbe9ef342b03003f56d6b4a2e8aff035c7d7cfd705e1ab4502904254bb67a
+TAG: 16c5944034050657af7c0fec7efbc40f
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+AD:
+CT: b104c8945f280e75b52c05c45a63d1872c7f0552b1501968d9913d71207d0433f978f1a3eecdf782016b77e8c9d3ff53
+TAG: abedb4841c20f3b05e61e0fd1fcaf3d0
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD:
+CT: e3f2bd14f4c80c9cea4c90c81f0e4d7eedb87eb19a7c0cf5a5a95cd3e441a71083b1191d115e9a9ff008b93feeb5a86d012a3e0adb89de2d1e3225479022292f
+TAG: 3ced67f5e03bb476a738c1343926dc19
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000
+AD: 01
+CT: 4dca2c16c3b0413c
+TAG: ac9b952c76a6f8b5df315f88126daa1c
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000
+AD: 01
+CT: ee0ca9068b5b85dfe115a660
+TAG: 756d6155927271077d790a05390ecb71
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000
+AD: 01
+CT: 590edb785c0cb89d19f031fa7e7d4f91
+TAG: ac2c8f711c86dbecc8c7b663c5fbc1ea
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0200000000000000000000000000000003000000000000000000000000000000
+AD: 01
+CT: dcf2024f5f98d463b82a8673c47dd82159748cac8bcc7c76b8cfa26029cb333c
+TAG: a9b406643e190e602fb104fbb842a1ac
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 01
+CT: 79216506b1ddadfe16366e4ec886d10dc9400b995259f74c0091f9b5a6add5680a612130f6c31ab833aa76d9b2be86de
+TAG: 3ddfe9ad2c350980942638d3f954ac6d
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+AD: 01
+CT: 9535eb67240c49f30a0de5a90670813fa615e71fcb4c522ca79d9a33459a22f8c6a56d650bf0b15eecdd706e7689cf6510a281724613fea76b5366b40574b1b9
+TAG: abcb59ee31d25ee8889b70d7c36f9a41
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 02000000
+AD: 010000000000000000000000
+CT: 9611baa0
+TAG: 53daf2bc5916f7a6750f2432068dabee
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 0300000000000000000000000000000004000000
+AD: 010000000000000000000000000000000200
+CT: 78e3a1b54daa6547f775f30c38a45e887aea5c87
+TAG: f65187d8c28adba364d659b627b16431
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 03000000000000000000000000000000
+IN: 030000000000000000000000000000000400
+AD: 0100000000000000000000000000000002000000
+CT: c6d3d28704bf20067d62e1a3872d40dda44b
+TAG: 6ac0135a4379dbc67967ff55fd4d1f2f
diff --git a/src/crypto/cipher/tls_cbc.c b/src/crypto/cipher/tls_cbc.c
index dd6ab8c..eb56604 100644
--- a/src/crypto/cipher/tls_cbc.c
+++ b/src/crypto/cipher/tls_cbc.c
@@ -133,107 +133,32 @@
/* mac_end is the index of |in| just after the end of the MAC. */
unsigned mac_end = in_len;
unsigned mac_start = mac_end - md_size;
- /* scan_start contains the number of bytes that we can ignore because
- * the MAC's position can only vary by 255 bytes. */
- unsigned scan_start = 0;
- unsigned i, j;
- unsigned rotate_offset;
assert(orig_len >= in_len);
assert(in_len >= md_size);
assert(md_size <= EVP_MAX_MD_SIZE);
+ /* scan_start contains the number of bytes that we can ignore because
+ * the MAC's position can only vary by 255 bytes. */
+ unsigned scan_start = 0;
/* This information is public so it's safe to branch based on it. */
if (orig_len > md_size + 255 + 1) {
scan_start = orig_len - (md_size + 255 + 1);
}
- /* Ideally the next statement would be:
- *
- * rotate_offset = (mac_start - scan_start) % md_size;
- *
- * However, division is not a constant-time operation (at least on Intel
- * chips). Thus we enumerate the possible values of md_size and handle each
- * separately. The value of |md_size| is public information (it's determined
- * by the cipher suite in the ServerHello) so our timing can vary based on
- * its value. */
-
- rotate_offset = mac_start - scan_start;
- /* rotate_offset can be, at most, 255 (bytes of padding) + 1 (padding length)
- * + md_size = 256 + 48 (since SHA-384 is the largest hash) = 304. */
- assert(rotate_offset <= 304);
-
- /* Below is an SMT-LIB2 verification that the Barrett reductions below are
- * correct within this range:
- *
- * (define-fun barrett (
- * (x (_ BitVec 32))
- * (mul (_ BitVec 32))
- * (shift (_ BitVec 32))
- * (divisor (_ BitVec 32)) ) (_ BitVec 32)
- * (let ((q (bvsub x (bvmul divisor (bvlshr (bvmul x mul) shift))) ))
- * (ite (bvuge q divisor)
- * (bvsub q divisor)
- * q)))
- *
- * (declare-fun x () (_ BitVec 32))
- *
- * (assert (or
- * (let (
- * (divisor (_ bv20 32))
- * (mul (_ bv25 32))
- * (shift (_ bv9 32))
- * (limit (_ bv853 32)))
- *
- * (and (bvule x limit) (not (= (bvurem x divisor)
- * (barrett x mul shift divisor)))))
- *
- * (let (
- * (divisor (_ bv48 32))
- * (mul (_ bv10 32))
- * (shift (_ bv9 32))
- * (limit (_ bv768 32)))
- *
- * (and (bvule x limit) (not (= (bvurem x divisor)
- * (barrett x mul shift divisor)))))
- * ))
- *
- * (check-sat)
- * (get-model)
- */
-
- if (md_size == 16) {
- rotate_offset &= 15;
- } else if (md_size == 20) {
- /* 1/20 is approximated as 25/512 and then Barrett reduction is used.
- * Analytically, this is correct for 0 <= rotate_offset <= 853. */
- unsigned q = (rotate_offset * 25) >> 9;
- rotate_offset -= q * 20;
- rotate_offset -=
- constant_time_select(constant_time_ge(rotate_offset, 20), 20, 0);
- } else if (md_size == 32) {
- rotate_offset &= 31;
- } else if (md_size == 48) {
- /* 1/48 is approximated as 10/512 and then Barrett reduction is used.
- * Analytically, this is correct for 0 <= rotate_offset <= 768. */
- unsigned q = (rotate_offset * 10) >> 9;
- rotate_offset -= q * 48;
- rotate_offset -=
- constant_time_select(constant_time_ge(rotate_offset, 48), 48, 0);
- } else {
- /* This should be impossible therefore this path doesn't run in constant
- * time. */
- assert(0);
- rotate_offset = rotate_offset % md_size;
- }
-
+ unsigned rotate_offset = 0;
+ uint8_t mac_started = 0;
memset(rotated_mac, 0, md_size);
- for (i = scan_start, j = 0; i < orig_len; i++) {
- uint8_t mac_started = constant_time_ge_8(i, mac_start);
+ for (unsigned i = scan_start, j = 0; i < orig_len; i++, j++) {
+ if (j >= md_size) {
+ j -= md_size;
+ }
+ unsigned is_mac_start = constant_time_eq(i, mac_start);
+ mac_started |= is_mac_start;
uint8_t mac_ended = constant_time_ge_8(i, mac_end);
- uint8_t b = in[i];
- rotated_mac[j++] |= b & mac_started & ~mac_ended;
- j &= constant_time_lt(j, md_size);
+ rotated_mac[j] |= in[i] & mac_started & ~mac_ended;
+ /* Save the offset that |mac_start| is mapped to. */
+ rotate_offset |= j & is_mac_start;
}
/* Now rotate the MAC. We rotate in log(md_size) steps, one for each bit
@@ -243,7 +168,7 @@
/* Rotate by |offset| iff the corresponding bit is set in
* |rotate_offset|, placing the result in |rotated_mac_tmp|. */
const uint8_t skip_rotate = (rotate_offset & 1) - 1;
- for (i = 0, j = offset; i < md_size; i++, j++) {
+ for (unsigned i = 0, j = offset; i < md_size; i++, j++) {
if (j >= md_size) {
j -= md_size;
}
diff --git a/src/crypto/dh/dh_test.cc b/src/crypto/dh/dh_test.cc
index 9a3d780..99bb945 100644
--- a/src/crypto/dh/dh_test.cc
+++ b/src/crypto/dh/dh_test.cc
@@ -68,7 +68,6 @@
#include <openssl/err.h>
#include <openssl/mem.h>
-namespace bssl {
static bool RunBasicTests();
static bool RunRFC5114Tests();
@@ -76,7 +75,7 @@
static bool TestASN1();
static bool TestRFC3526();
-static int Main() {
+int main() {
CRYPTO_library_init();
if (!RunBasicTests() ||
@@ -568,7 +567,7 @@
return false;
}
- ScopedCBB cbb;
+ bssl::ScopedCBB cbb;
uint8_t *der;
size_t der_len;
if (!CBB_init(cbb.get(), 0) ||
@@ -661,9 +660,3 @@
return true;
}
-
-} // namespace bssl
-
-int main() {
- return bssl::Main();
-}
diff --git a/src/crypto/digest/digest_test.cc b/src/crypto/digest/digest_test.cc
index ecf0308..0d3f16e 100644
--- a/src/crypto/digest/digest_test.cc
+++ b/src/crypto/digest/digest_test.cc
@@ -28,8 +28,6 @@
#include "../internal.h"
-namespace bssl {
-
struct MD {
// name is the name of the digest.
const char* name;
@@ -161,7 +159,7 @@
}
static int TestDigest(const TestVector *test) {
- ScopedEVP_MD_CTX ctx;
+ bssl::ScopedEVP_MD_CTX ctx;
// Test the input provided.
if (!EVP_DigestInit_ex(ctx.get(), test->md.func(), NULL)) {
@@ -246,7 +244,7 @@
return true;
}
-static int Main() {
+int main() {
CRYPTO_library_init();
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTestVectors); i++) {
@@ -263,9 +261,3 @@
printf("PASS\n");
return 0;
}
-
-} // namespace bssl
-
-int main() {
- return bssl::Main();
-}
diff --git a/src/crypto/ec/oct.c b/src/crypto/ec/oct.c
index bf1957c..4e8272d 100644
--- a/src/crypto/ec/oct.c
+++ b/src/crypto/ec/oct.c
@@ -284,7 +284,7 @@
EC_POINT *point, const BIGNUM *x,
int y_bit, BN_CTX *ctx) {
if (BN_is_negative(x) || BN_cmp(x, &group->field) >= 0) {
- OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT);
+ OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT);
return 0;
}
@@ -381,19 +381,7 @@
if (y_bit != BN_is_odd(y)) {
if (BN_is_zero(y)) {
- int kron;
-
- kron = BN_kronecker(x, &group->field, ctx);
- if (kron == -2) {
- goto err;
- }
-
- if (kron == 1) {
- OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT);
- } else {
- /* BN_mod_sqrt() should have cought this error (not a square) */
- OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT);
- }
+ OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT);
goto err;
}
if (!BN_usub(y, &group->field, y)) {
diff --git a/src/crypto/ec/wnaf.c b/src/crypto/ec/wnaf.c
index ba2257c..1594354 100644
--- a/src/crypto/ec/wnaf.c
+++ b/src/crypto/ec/wnaf.c
@@ -90,10 +90,10 @@
* with the exception that the most significant digit may be only
* w-1 zeros away from that next non-zero digit.
*/
-static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) {
+static int8_t *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) {
int window_val;
int ok = 0;
- signed char *r = NULL;
+ int8_t *r = NULL;
int sign = 1;
int bit, next_bit, mask;
size_t len = 0, j;
@@ -109,9 +109,8 @@
return r;
}
- if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute
- values less than 2^7 */
- {
+ /* 'int8_t' can represent integers with absolute values less than 2^7. */
+ if (w <= 0 || w > 7) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -129,20 +128,18 @@
}
len = BN_num_bits(scalar);
- r = OPENSSL_malloc(
- len +
- 1); /* modified wNAF may be one digit longer than binary representation
- * (*ret_len will be set to the actual length, i.e. at most
- * BN_num_bits(scalar) + 1) */
+ /* The modified wNAF may be one digit longer than binary representation
+ * (*ret_len will be set to the actual length, i.e. at most
+ * BN_num_bits(scalar) + 1). */
+ r = OPENSSL_malloc(len + 1);
if (r == NULL) {
OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
goto err;
}
window_val = scalar->d[0] & mask;
j = 0;
- while ((window_val != 0) ||
- (j + w + 1 < len)) /* if j+w+1 >= len, window_val will not increase */
- {
+ /* If j+w+1 >= len, window_val will not increase. */
+ while (window_val != 0 || j + w + 1 < len) {
int digit = 0;
/* 0 <= window_val <= 2^(w+1) */
@@ -174,9 +171,8 @@
window_val -= digit;
- /* now window_val is 0 or 2^(w+1) in standard wNAF generation;
- * for modified window NAFs, it may also be 2^w
- */
+ /* Now window_val is 0 or 2^(w+1) in standard wNAF generation;
+ * for modified window NAFs, it may also be 2^w. */
if (window_val != 0 && window_val != next_bit && window_val != bit) {
OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
goto err;
@@ -217,12 +213,29 @@
* sometimes smaller windows will give better performance
* (thus the boundaries should be increased)
*/
-#define EC_window_bits_for_scalar_size(b) \
- ((size_t)((b) >= 2000 ? 6 : (b) >= 800 ? 5 : (b) >= 300 \
- ? 4 \
- : (b) >= 70 ? 3 : (b) >= 20 \
- ? 2 \
- : 1))
+static size_t window_bits_for_scalar_size(size_t b) {
+ if (b >= 2000) {
+ return 6;
+ }
+
+ if (b >= 800) {
+ return 5;
+ }
+
+ if (b >= 300) {
+ return 4;
+ }
+
+ if (b >= 70) {
+ return 3;
+ }
+
+ if (b >= 20) {
+ return 2;
+ }
+
+ return 1;
+}
int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) {
@@ -235,7 +248,7 @@
int r_is_inverted = 0;
int r_is_at_infinity = 1;
size_t *wsize = NULL; /* individual window sizes */
- signed char **wNAF = NULL; /* individual wNAFs */
+ int8_t **wNAF = NULL; /* individual wNAFs */
size_t *wNAF_len = NULL;
size_t max_len = 0;
size_t num_val;
@@ -294,7 +307,7 @@
size_t bits;
bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(g_scalar);
- wsize[i] = EC_window_bits_for_scalar_size(bits);
+ wsize[i] = window_bits_for_scalar_size(bits);
num_val += (size_t)1 << (wsize[i] - 1);
wNAF[i + 1] = NULL; /* make sure we always have a pivot */
wNAF[i] =
@@ -364,7 +377,7 @@
}
}
-#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */
+#if 1 /* optional; window_bits_for_scalar_size assumes we do this step */
if (!EC_POINTs_make_affine(group, num_val, val, ctx)) {
goto err;
}
@@ -429,7 +442,7 @@
OPENSSL_free(wsize);
OPENSSL_free(wNAF_len);
if (wNAF != NULL) {
- signed char **w;
+ int8_t **w;
for (w = wNAF; *w != NULL; w++) {
OPENSSL_free(*w);
diff --git a/src/crypto/err/ssl.errordata b/src/crypto/err/ssl.errordata
index b50f9ab..e9b2066 100644
--- a/src/crypto/err/ssl.errordata
+++ b/src/crypto/err/ssl.errordata
@@ -109,6 +109,7 @@
SSL,193,PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE
SSL,267,PRE_SHARED_KEY_MUST_BE_LAST
SSL,194,PROTOCOL_IS_SHUTDOWN
+SSL,271,PSK_IDENTITY_BINDER_COUNT_MISMATCH
SSL,195,PSK_IDENTITY_NOT_FOUND
SSL,196,PSK_NO_CLIENT_CB
SSL,197,PSK_NO_SERVER_CB
@@ -170,6 +171,7 @@
SSL,219,TOO_MANY_EMPTY_FRAGMENTS
SSL,260,TOO_MANY_KEY_UPDATES
SSL,220,TOO_MANY_WARNING_ALERTS
+SSL,270,TOO_MUCH_SKIPPED_EARLY_DATA
SSL,221,UNABLE_TO_FIND_ECDH_PARAMETERS
SSL,222,UNEXPECTED_EXTENSION
SSL,223,UNEXPECTED_MESSAGE
diff --git a/src/crypto/evp/evp_extra_test.cc b/src/crypto/evp/evp_extra_test.cc
index 755fa83..4d41760 100644
--- a/src/crypto/evp/evp_extra_test.cc
+++ b/src/crypto/evp/evp_extra_test.cc
@@ -27,7 +27,6 @@
#include <openssl/pkcs8.h>
#include <openssl/rsa.h>
-namespace bssl {
// kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
// should never use this key anywhere but in an example.
@@ -371,7 +370,7 @@
static bool TestEVP_DigestSignInit(void) {
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
- ScopedEVP_MD_CTX md_ctx;
+ bssl::ScopedEVP_MD_CTX md_ctx;
if (!pkey ||
!EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
!EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg))) {
@@ -409,7 +408,7 @@
static bool TestEVP_DigestVerifyInit(void) {
bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
- ScopedEVP_MD_CTX md_ctx;
+ bssl::ScopedEVP_MD_CTX md_ctx;
if (!pkey ||
!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL,
pkey.get()) ||
@@ -591,7 +590,7 @@
if (!empty) {
return false;
}
- ScopedCBB cbb;
+ bssl::ScopedCBB cbb;
if (EVP_marshal_public_key(cbb.get(), empty.get())) {
fprintf(stderr, "Marshalled empty public key.\n");
return false;
@@ -670,7 +669,7 @@
return true;
}
-static int Main(void) {
+int main() {
CRYPTO_library_init();
if (!TestEVP_DigestSignInit()) {
@@ -718,9 +717,3 @@
printf("PASS\n");
return 0;
}
-
-} // namespace bssl
-
-int main() {
- return bssl::Main();
-}
diff --git a/src/crypto/evp/evp_test.cc b/src/crypto/evp/evp_test.cc
index 68b869a..bfaa38a 100644
--- a/src/crypto/evp/evp_test.cc
+++ b/src/crypto/evp/evp_test.cc
@@ -75,7 +75,6 @@
#include "../test/file_test.h"
-namespace bssl {
// evp_test dispatches between multiple test types. PrivateKey tests take a key
// name parameter and single block, decode it as a PEM private key, and save it
@@ -141,7 +140,7 @@
}
// The key must re-encode correctly.
- ScopedCBB cbb;
+ bssl::ScopedCBB cbb;
uint8_t *der;
size_t der_len;
if (!CBB_init(cbb.get(), 0) ||
@@ -253,7 +252,7 @@
return true;
}
-static int Main(int argc, char *argv[]) {
+int main(int argc, char *argv[]) {
CRYPTO_library_init();
if (argc != 2) {
fprintf(stderr, "%s <test file.txt>\n", argv[0]);
@@ -263,9 +262,3 @@
KeyMap map;
return FileTestMain(TestEVP, &map, argv[1]);
}
-
-} // namespace bssl
-
-int main(int argc, char *argv[]) {
- return bssl::Main(argc, argv);
-}
diff --git a/src/crypto/hmac/hmac_test.cc b/src/crypto/hmac/hmac_test.cc
index 60a9581..7b216e2 100644
--- a/src/crypto/hmac/hmac_test.cc
+++ b/src/crypto/hmac/hmac_test.cc
@@ -67,7 +67,6 @@
#include "../test/file_test.h"
-namespace bssl {
static const EVP_MD *GetDigest(const std::string &name) {
if (name == "MD5") {
@@ -117,7 +116,7 @@
}
// Test using HMAC_CTX.
- ScopedHMAC_CTX ctx;
+ bssl::ScopedHMAC_CTX ctx;
if (!HMAC_Init_ex(ctx.get(), key.data(), key.size(), digest, nullptr) ||
!HMAC_Update(ctx.get(), input.data(), input.size()) ||
!HMAC_Final(ctx.get(), mac.get(), &mac_len) ||
@@ -158,7 +157,7 @@
return true;
}
-static int Main(int argc, char *argv[]) {
+int main(int argc, char *argv[]) {
CRYPTO_library_init();
if (argc != 2) {
@@ -168,9 +167,3 @@
return FileTestMain(TestHMAC, nullptr, argv[1]);
}
-
-} // namespace bssl
-
-int main(int argc, char **argv) {
- return bssl::Main(argc, argv);
-}
diff --git a/src/crypto/modes/CMakeLists.txt b/src/crypto/modes/CMakeLists.txt
index 17faa15..dc9e504 100644
--- a/src/crypto/modes/CMakeLists.txt
+++ b/src/crypto/modes/CMakeLists.txt
@@ -48,10 +48,11 @@
OBJECT
cbc.c
- ctr.c
- ofb.c
cfb.c
+ ctr.c
gcm.c
+ ofb.c
+ polyval.c
${MODES_ARCH_SOURCES}
)
diff --git a/src/crypto/modes/cbc.c b/src/crypto/modes/cbc.c
index e41f2b4..6e9fe24 100644
--- a/src/crypto/modes/cbc.c
+++ b/src/crypto/modes/cbc.c
@@ -52,10 +52,6 @@
#include "internal.h"
-#ifndef STRICT_ALIGNMENT
-# define STRICT_ALIGNMENT 0
-#endif
-
void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const void *key, uint8_t ivec[16],
block128_f block) {
diff --git a/src/crypto/modes/gcm.c b/src/crypto/modes/gcm.c
index eb63aa0..3b793e8 100644
--- a/src/crypto/modes/gcm.c
+++ b/src/crypto/modes/gcm.c
@@ -65,14 +65,6 @@
#define GHASH_ASM
#endif
-#if defined(BSWAP4) && STRICT_ALIGNMENT == 1
-/* redefine, because alignment is ensured */
-#undef GETU32
-#define GETU32(p) BSWAP4(*(const uint32_t *)(p))
-#undef PUTU32
-#define PUTU32(p, v) *(uint32_t *)(p) = BSWAP4(v)
-#endif
-
#define PACK(s) ((size_t)(s) << (sizeof(size_t) * 8 - 16))
#define REDUCE1BIT(V) \
do { \
@@ -121,27 +113,10 @@
Htable[15].hi = V.hi ^ Htable[7].hi, Htable[15].lo = V.lo ^ Htable[7].lo;
#if defined(GHASH_ASM) && defined(OPENSSL_ARM)
- /* ARM assembler expects specific dword order in Htable. */
- {
- int j;
- const union {
- long one;
- char little;
- } is_endian = {1};
-
- if (is_endian.little) {
- for (j = 0; j < 16; ++j) {
- V = Htable[j];
- Htable[j].hi = V.lo;
- Htable[j].lo = V.hi;
- }
- } else {
- for (j = 0; j < 16; ++j) {
- V = Htable[j];
- Htable[j].hi = V.lo << 32 | V.lo >> 32;
- Htable[j].lo = V.hi << 32 | V.hi >> 32;
- }
- }
+ for (int j = 0; j < 16; ++j) {
+ V = Htable[j];
+ Htable[j].hi = V.lo;
+ Htable[j].lo = V.hi;
}
#endif
}
@@ -157,10 +132,6 @@
u128 Z;
int cnt = 15;
size_t rem, nlo, nhi;
- const union {
- long one;
- char little;
- } is_endian = {1};
nlo = ((const uint8_t *)Xi)[15];
nhi = nlo >> 4;
@@ -203,26 +174,8 @@
Z.lo ^= Htable[nlo].lo;
}
- if (is_endian.little) {
-#ifdef BSWAP8
- Xi[0] = BSWAP8(Z.hi);
- Xi[1] = BSWAP8(Z.lo);
-#else
- uint8_t *p = (uint8_t *)Xi;
- uint32_t v;
- v = (uint32_t)(Z.hi >> 32);
- PUTU32(p, v);
- v = (uint32_t)(Z.hi);
- PUTU32(p + 4, v);
- v = (uint32_t)(Z.lo >> 32);
- PUTU32(p + 8, v);
- v = (uint32_t)(Z.lo);
- PUTU32(p + 12, v);
-#endif
- } else {
- Xi[0] = Z.hi;
- Xi[1] = Z.lo;
- }
+ Xi[0] = CRYPTO_bswap8(Z.hi);
+ Xi[1] = CRYPTO_bswap8(Z.lo);
}
/* Streamed gcm_mult_4bit, see CRYPTO_gcm128_[en|de]crypt for
@@ -230,15 +183,11 @@
* performance improvement, at least not on x86[_64]. It's here
* mostly as reference and a placeholder for possible future
* non-trivial optimization[s]... */
-static void gcm_ghash_4bit(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
- size_t len) {
+static void gcm_ghash_4bit(uint64_t Xi[2], const u128 Htable[16],
+ const uint8_t *inp, size_t len) {
u128 Z;
int cnt;
size_t rem, nlo, nhi;
- const union {
- long one;
- char little;
- } is_endian = {1};
do {
cnt = 15;
@@ -285,26 +234,8 @@
Z.lo ^= Htable[nlo].lo;
}
- if (is_endian.little) {
-#ifdef BSWAP8
- Xi[0] = BSWAP8(Z.hi);
- Xi[1] = BSWAP8(Z.lo);
-#else
- uint8_t *p = (uint8_t *)Xi;
- uint32_t v;
- v = (uint32_t)(Z.hi >> 32);
- PUTU32(p, v);
- v = (uint32_t)(Z.hi);
- PUTU32(p + 4, v);
- v = (uint32_t)(Z.lo >> 32);
- PUTU32(p + 8, v);
- v = (uint32_t)(Z.lo);
- PUTU32(p + 12, v);
-#endif
- } else {
- Xi[0] = Z.hi;
- Xi[1] = Z.lo;
- }
+ Xi[0] = CRYPTO_bswap8(Z.hi);
+ Xi[1] = CRYPTO_bswap8(Z.lo);
} while (inp += 16, len -= 16);
}
#else /* GHASH_ASM */
@@ -425,96 +356,88 @@
#endif
#endif
-void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key,
- block128_f block) {
- const union {
- long one;
- char little;
- } is_endian = {1};
+void CRYPTO_ghash_init(gmult_func *out_mult, ghash_func *out_hash,
+ u128 out_table[16], const uint8_t *gcm_key) {
+ union {
+ uint64_t u[2];
+ uint8_t c[16];
+ } H;
- memset(ctx, 0, sizeof(*ctx));
- ctx->block = block;
+ memcpy(H.c, gcm_key, 16);
- (*block)(ctx->H.c, ctx->H.c, key);
-
- if (is_endian.little) {
-/* H is stored in host byte order */
-#ifdef BSWAP8
- ctx->H.u[0] = BSWAP8(ctx->H.u[0]);
- ctx->H.u[1] = BSWAP8(ctx->H.u[1]);
-#else
- uint8_t *p = ctx->H.c;
- uint64_t hi, lo;
- hi = (uint64_t)GETU32(p) << 32 | GETU32(p + 4);
- lo = (uint64_t)GETU32(p + 8) << 32 | GETU32(p + 12);
- ctx->H.u[0] = hi;
- ctx->H.u[1] = lo;
-#endif
- }
+ /* H is stored in host byte order */
+ H.u[0] = CRYPTO_bswap8(H.u[0]);
+ H.u[1] = CRYPTO_bswap8(H.u[1]);
#if defined(GHASH_ASM_X86_OR_64)
if (crypto_gcm_clmul_enabled()) {
if (((OPENSSL_ia32cap_P[1] >> 22) & 0x41) == 0x41) { /* AVX+MOVBE */
- gcm_init_avx(ctx->Htable, ctx->H.u);
- ctx->gmult = gcm_gmult_avx;
- ctx->ghash = gcm_ghash_avx;
- } else {
- gcm_init_clmul(ctx->Htable, ctx->H.u);
- ctx->gmult = gcm_gmult_clmul;
- ctx->ghash = gcm_ghash_clmul;
+ gcm_init_avx(out_table, H.u);
+ *out_mult = gcm_gmult_avx;
+ *out_hash = gcm_ghash_avx;
+ return;
}
+
+ gcm_init_clmul(out_table, H.u);
+ *out_mult = gcm_gmult_clmul;
+ *out_hash = gcm_ghash_clmul;
return;
}
- gcm_init_4bit(ctx->Htable, ctx->H.u);
#if defined(GHASH_ASM_X86) /* x86 only */
if (OPENSSL_ia32cap_P[0] & (1 << 25)) { /* check SSE bit */
- ctx->gmult = gcm_gmult_4bit_mmx;
- ctx->ghash = gcm_ghash_4bit_mmx;
- } else {
- ctx->gmult = gcm_gmult_4bit_x86;
- ctx->ghash = gcm_ghash_4bit_x86;
+ gcm_init_4bit(out_table, H.u);
+ *out_mult = gcm_gmult_4bit_mmx;
+ *out_hash = gcm_ghash_4bit_mmx;
+ return;
}
-#else
- ctx->gmult = gcm_gmult_4bit;
- ctx->ghash = gcm_ghash_4bit;
#endif
#elif defined(GHASH_ASM_ARM)
if (pmull_capable()) {
- gcm_init_v8(ctx->Htable, ctx->H.u);
- ctx->gmult = gcm_gmult_v8;
- ctx->ghash = gcm_ghash_v8;
- } else if (neon_capable()) {
- gcm_init_neon(ctx->Htable,ctx->H.u);
- ctx->gmult = gcm_gmult_neon;
- ctx->ghash = gcm_ghash_neon;
- } else {
- gcm_init_4bit(ctx->Htable, ctx->H.u);
- ctx->gmult = gcm_gmult_4bit;
- ctx->ghash = gcm_ghash_4bit;
+ gcm_init_v8(out_table, H.u);
+ *out_mult = gcm_gmult_v8;
+ *out_hash = gcm_ghash_v8;
+ return;
+ }
+
+ if (neon_capable()) {
+ gcm_init_neon(out_table, H.u);
+ *out_mult = gcm_gmult_neon;
+ *out_hash = gcm_ghash_neon;
+ return;
}
#elif defined(GHASH_ASM_PPC64LE)
if (CRYPTO_is_PPC64LE_vcrypto_capable()) {
- gcm_init_p8(ctx->Htable, ctx->H.u);
- ctx->gmult = gcm_gmult_p8;
- ctx->ghash = gcm_ghash_p8;
- } else {
- gcm_init_4bit(ctx->Htable, ctx->H.u);
- ctx->gmult = gcm_gmult_4bit;
- ctx->ghash = gcm_ghash_4bit;
+ gcm_init_p8(out_table, H.u);
+ *out_mult = gcm_gmult_p8;
+ *out_hash = gcm_ghash_p8;
+ return;
}
-#else
- gcm_init_4bit(ctx->Htable, ctx->H.u);
- ctx->gmult = gcm_gmult_4bit;
- ctx->ghash = gcm_ghash_4bit;
#endif
+
+ gcm_init_4bit(out_table, H.u);
+#if defined(GHASH_ASM_X86)
+ *out_mult = gcm_gmult_4bit_x86;
+ *out_hash = gcm_ghash_4bit_x86;
+#else
+ *out_mult = gcm_gmult_4bit;
+ *out_hash = gcm_ghash_4bit;
+#endif
+}
+
+void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *aes_key,
+ block128_f block) {
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->block = block;
+
+ uint8_t gcm_key[16];
+ memset(gcm_key, 0, sizeof(gcm_key));
+ (*block)(gcm_key, gcm_key, aes_key);
+
+ CRYPTO_ghash_init(&ctx->gmult, &ctx->ghash, ctx->Htable, gcm_key);
}
void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key,
const uint8_t *iv, size_t len) {
- const union {
- long one;
- char little;
- } is_endian = {1};
unsigned int ctr;
#ifdef GCM_FUNCREF_4BIT
void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult;
@@ -551,39 +474,15 @@
GCM_MUL(ctx, Yi);
}
len0 <<= 3;
- if (is_endian.little) {
-#ifdef BSWAP8
- ctx->Yi.u[1] ^= BSWAP8(len0);
-#else
- ctx->Yi.c[8] ^= (uint8_t)(len0 >> 56);
- ctx->Yi.c[9] ^= (uint8_t)(len0 >> 48);
- ctx->Yi.c[10] ^= (uint8_t)(len0 >> 40);
- ctx->Yi.c[11] ^= (uint8_t)(len0 >> 32);
- ctx->Yi.c[12] ^= (uint8_t)(len0 >> 24);
- ctx->Yi.c[13] ^= (uint8_t)(len0 >> 16);
- ctx->Yi.c[14] ^= (uint8_t)(len0 >> 8);
- ctx->Yi.c[15] ^= (uint8_t)(len0);
-#endif
- } else {
- ctx->Yi.u[1] ^= len0;
- }
+ ctx->Yi.u[1] ^= CRYPTO_bswap8(len0);
GCM_MUL(ctx, Yi);
-
- if (is_endian.little) {
- ctr = GETU32(ctx->Yi.c + 12);
- } else {
- ctr = ctx->Yi.d[3];
- }
+ ctr = GETU32_aligned(ctx->Yi.c + 12);
}
(*ctx->block)(ctx->Yi.c, ctx->EK0.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
}
int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len) {
@@ -656,10 +555,6 @@
int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const void *key,
const unsigned char *in, unsigned char *out,
size_t len) {
- const union {
- long one;
- char little;
- } is_endian = {1};
unsigned int n, ctr;
uint64_t mlen = ctx->len.u[1];
block128_f block = ctx->block;
@@ -684,11 +579,7 @@
ctx->ares = 0;
}
- if (is_endian.little) {
- ctr = GETU32(ctx->Yi.c + 12);
- } else {
- ctr = ctx->Yi.d[3];
- }
+ ctr = GETU32_aligned(ctx->Yi.c + 12);
n = ctx->mres;
if (n) {
@@ -709,11 +600,7 @@
if (n == 0) {
(*block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
}
ctx->Xi.c[n] ^= out[i] = in[i] ^ ctx->EKi.c[n];
n = (n + 1) % 16;
@@ -735,11 +622,7 @@
(*block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
out_t[i] = in_t[i] ^ ctx->EKi.t[i];
}
@@ -758,11 +641,7 @@
(*block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
out_t[i] = in_t[i] ^ ctx->EKi.t[i];
}
@@ -779,11 +658,7 @@
(*block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
ctx->Xi.t[i] ^= out_t[i] = in_t[i] ^ ctx->EKi.t[i];
}
@@ -796,11 +671,7 @@
if (len) {
(*block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
while (len--) {
ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n];
++n;
@@ -814,10 +685,6 @@
int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key,
const unsigned char *in, unsigned char *out,
size_t len) {
- const union {
- long one;
- char little;
- } is_endian = {1};
unsigned int n, ctr;
uint64_t mlen = ctx->len.u[1];
block128_f block = ctx->block;
@@ -842,11 +709,7 @@
ctx->ares = 0;
}
- if (is_endian.little) {
- ctr = GETU32(ctx->Yi.c + 12);
- } else {
- ctr = ctx->Yi.d[3];
- }
+ ctr = GETU32_aligned(ctx->Yi.c + 12);
n = ctx->mres;
if (n) {
@@ -870,11 +733,7 @@
if (n == 0) {
(*block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
}
c = in[i];
out[i] = c ^ ctx->EKi.c[n];
@@ -899,11 +758,7 @@
(*block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
out_t[i] = in_t[i] ^ ctx->EKi.t[i];
}
@@ -922,11 +777,7 @@
(*block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
out_t[i] = in_t[i] ^ ctx->EKi.t[i];
}
@@ -942,11 +793,7 @@
(*block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
size_t c = in_t[i];
out_t[i] = c ^ ctx->EKi.t[i];
@@ -961,11 +808,7 @@
if (len) {
(*block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
while (len--) {
uint8_t c = in[n];
ctx->Xi.c[n] ^= c;
@@ -981,10 +824,6 @@
int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
const uint8_t *in, uint8_t *out, size_t len,
ctr128_f stream) {
- const union {
- long one;
- char little;
- } is_endian = {1};
unsigned int n, ctr;
uint64_t mlen = ctx->len.u[1];
#ifdef GCM_FUNCREF_4BIT
@@ -1034,21 +873,13 @@
}
#endif
- if (is_endian.little) {
- ctr = GETU32(ctx->Yi.c + 12);
- } else {
- ctr = ctx->Yi.d[3];
- }
+ ctr = GETU32_aligned(ctx->Yi.c + 12);
#if defined(GHASH)
while (len >= GHASH_CHUNK) {
(*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
ctr += GHASH_CHUNK / 16;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
GHASH(ctx, out, GHASH_CHUNK);
out += GHASH_CHUNK;
in += GHASH_CHUNK;
@@ -1061,11 +892,7 @@
(*stream)(in, out, j, key, ctx->Yi.c);
ctr += (unsigned int)j;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
in += i;
len -= i;
#if defined(GHASH)
@@ -1084,11 +911,7 @@
if (len) {
(*ctx->block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
while (len--) {
ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n];
++n;
@@ -1102,10 +925,6 @@
int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
const uint8_t *in, uint8_t *out, size_t len,
ctr128_f stream) {
- const union {
- long one;
- char little;
- } is_endian = {1};
unsigned int n, ctr;
uint64_t mlen = ctx->len.u[1];
#ifdef GCM_FUNCREF_4BIT
@@ -1157,22 +976,14 @@
}
#endif
- if (is_endian.little) {
- ctr = GETU32(ctx->Yi.c + 12);
- } else {
- ctr = ctx->Yi.d[3];
- }
+ ctr = GETU32_aligned(ctx->Yi.c + 12);
#if defined(GHASH)
while (len >= GHASH_CHUNK) {
GHASH(ctx, in, GHASH_CHUNK);
(*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
ctr += GHASH_CHUNK / 16;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
out += GHASH_CHUNK;
in += GHASH_CHUNK;
len -= GHASH_CHUNK;
@@ -1198,11 +1009,7 @@
#endif
(*stream)(in, out, j, key, ctx->Yi.c);
ctr += (unsigned int)j;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
out += i;
in += i;
len -= i;
@@ -1210,11 +1017,7 @@
if (len) {
(*ctx->block)(ctx->Yi.c, ctx->EKi.c, key);
++ctr;
- if (is_endian.little) {
- PUTU32(ctx->Yi.c + 12, ctr);
- } else {
- ctx->Yi.d[3] = ctr;
- }
+ PUTU32_aligned(ctx->Yi.c + 12, ctr);
while (len--) {
uint8_t c = in[n];
ctx->Xi.c[n] ^= c;
@@ -1228,10 +1031,6 @@
}
int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, size_t len) {
- const union {
- long one;
- char little;
- } is_endian = {1};
uint64_t alen = ctx->len.u[0] << 3;
uint64_t clen = ctx->len.u[1] << 3;
#ifdef GCM_FUNCREF_4BIT
@@ -1242,20 +1041,8 @@
GCM_MUL(ctx, Xi);
}
- if (is_endian.little) {
-#ifdef BSWAP8
- alen = BSWAP8(alen);
- clen = BSWAP8(clen);
-#else
- uint8_t *p = ctx->len.c;
-
- ctx->len.u[0] = alen;
- ctx->len.u[1] = clen;
-
- alen = (uint64_t)GETU32(p) << 32 | GETU32(p + 4);
- clen = (uint64_t)GETU32(p + 8) << 32 | GETU32(p + 12);
-#endif
- }
+ alen = CRYPTO_bswap8(alen);
+ clen = CRYPTO_bswap8(clen);
ctx->Xi.u[0] ^= alen;
ctx->Xi.u[1] ^= clen;
diff --git a/src/crypto/modes/gcm_test.cc b/src/crypto/modes/gcm_test.cc
index 51d966e..8baf20e 100644
--- a/src/crypto/modes/gcm_test.cc
+++ b/src/crypto/modes/gcm_test.cc
@@ -46,6 +46,13 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ==================================================================== */
+/* Per C99, various stdint.h and inttypes.h macros (the latter used by
+ * internal.h) are unavailable in C++ unless some macros are defined. C++11
+ * overruled this decision, but older Android NDKs still require it. */
+#if !defined(__STDC_CONSTANT_MACROS)
+#define __STDC_CONSTANT_MACROS
+#endif
+
#include <stdio.h>
#include <string.h>
@@ -388,12 +395,22 @@
return ret;
}
+static bool TestByteSwap() {
+ return CRYPTO_bswap4(0x01020304) == 0x04030201 &&
+ CRYPTO_bswap8(UINT64_C(0x0102030405060708)) ==
+ UINT64_C(0x0807060504030201);
+}
+
int main(void) {
int ret = 0;
unsigned i;
CRYPTO_library_init();
+ if (!TestByteSwap()) {
+ ret = 1;
+ }
+
for (i = 0; i < sizeof(test_cases) / sizeof(struct test_case); i++) {
if (!run_test_case(i, &test_cases[i])) {
ret = 1;
diff --git a/src/crypto/modes/internal.h b/src/crypto/modes/internal.h
index 430d040..a53da04 100644
--- a/src/crypto/modes/internal.h
+++ b/src/crypto/modes/internal.h
@@ -51,6 +51,8 @@
#include <openssl/base.h>
+#include <string.h>
+
#if defined(__cplusplus)
extern "C" {
#endif
@@ -64,90 +66,58 @@
#define STRICT_ALIGNMENT 0
#endif
-#if !defined(PEDANTIC) && !defined(OPENSSL_NO_ASM)
#if defined(__GNUC__) && __GNUC__ >= 2
-#if defined(OPENSSL_X86_64)
-#define BSWAP8(x) \
- ({ \
- uint64_t ret = (x); \
- asm("bswapq %0" : "+r"(ret)); \
- ret; \
- })
-#define BSWAP4(x) \
- ({ \
- uint32_t ret = (x); \
- asm("bswapl %0" : "+r"(ret)); \
- ret; \
- })
-#elif defined(OPENSSL_X86)
-#define BSWAP8(x) \
- ({ \
- uint32_t lo = (uint64_t)(x) >> 32, hi = (x); \
- asm("bswapl %0; bswapl %1" : "+r"(hi), "+r"(lo)); \
- (uint64_t) hi << 32 | lo; \
- })
-#define BSWAP4(x) \
- ({ \
- uint32_t ret = (x); \
- asm("bswapl %0" : "+r"(ret)); \
- ret; \
- })
-#elif defined(OPENSSL_AARCH64)
-#define BSWAP8(x) \
- ({ \
- uint64_t ret; \
- asm("rev %0,%1" : "=r"(ret) : "r"(x)); \
- ret; \
- })
-#define BSWAP4(x) \
- ({ \
- uint32_t ret; \
- asm("rev %w0,%w1" : "=r"(ret) : "r"(x)); \
- ret; \
- })
-#elif defined(OPENSSL_ARM) && !defined(STRICT_ALIGNMENT)
-#define BSWAP8(x) \
- ({ \
- uint32_t lo = (uint64_t)(x) >> 32, hi = (x); \
- asm("rev %0,%0; rev %1,%1" : "+r"(hi), "+r"(lo)); \
- (uint64_t) hi << 32 | lo; \
- })
-#define BSWAP4(x) \
- ({ \
- uint32_t ret; \
- asm("rev %0,%1" : "=r"(ret) : "r"((uint32_t)(x))); \
- ret; \
- })
-#endif
+static inline uint32_t CRYPTO_bswap4(uint32_t x) {
+ return __builtin_bswap32(x);
+}
+
+static inline uint64_t CRYPTO_bswap8(uint64_t x) {
+ return __builtin_bswap64(x);
+}
#elif defined(_MSC_VER)
-#if _MSC_VER >= 1300
OPENSSL_MSVC_PRAGMA(warning(push, 3))
#include <intrin.h>
OPENSSL_MSVC_PRAGMA(warning(pop))
#pragma intrinsic(_byteswap_uint64, _byteswap_ulong)
-#define BSWAP8(x) _byteswap_uint64((uint64_t)(x))
-#define BSWAP4(x) _byteswap_ulong((uint32_t)(x))
-#elif defined(OPENSSL_X86)
-__inline uint32_t _bswap4(uint32_t val) {
- _asm mov eax, val
- _asm bswap eax
+static inline uint32_t CRYPTO_bswap4(uint32_t x) {
+ return _byteswap_ulong(x);
}
-#define BSWAP4(x) _bswap4(x)
-#endif
-#endif
-#endif
-#if defined(BSWAP4) && !defined(STRICT_ALIGNMENT)
-#define GETU32(p) BSWAP4(*(const uint32_t *)(p))
-#define PUTU32(p, v) *(uint32_t *)(p) = BSWAP4(v)
+static inline uint64_t CRYPTO_bswap8(uint64_t x) {
+ return _byteswap_uint64(x);
+}
#else
-#define GETU32(p) \
- ((uint32_t)(p)[0] << 24 | (uint32_t)(p)[1] << 16 | (uint32_t)(p)[2] << 8 | (uint32_t)(p)[3])
-#define PUTU32(p, v) \
- ((p)[0] = (uint8_t)((v) >> 24), (p)[1] = (uint8_t)((v) >> 16), \
- (p)[2] = (uint8_t)((v) >> 8), (p)[3] = (uint8_t)(v))
+static inline uint32_t CRYPTO_bswap4(uint32_t x) {
+ x = (x >> 16) | (x << 16);
+ x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8);
+ return x;
+}
+
+static inline uint64_t CRYPTO_bswap8(uint64_t x) {
+ return CRYPTO_bswap4(x >> 32) | (((uint64_t)CRYPTO_bswap4(x)) << 32);
+}
#endif
+static inline uint32_t GETU32(const void *in) {
+ uint32_t v;
+ memcpy(&v, in, sizeof(v));
+ return CRYPTO_bswap4(v);
+}
+
+static inline void PUTU32(void *out, uint32_t v) {
+ v = CRYPTO_bswap4(v);
+ memcpy(out, &v, sizeof(v));
+}
+
+static inline uint32_t GETU32_aligned(const void *in) {
+ const char *alias = (const char *) in;
+ return CRYPTO_bswap4(*((const uint32_t *) alias));
+}
+
+static inline void PUTU32_aligned(void *in, uint32_t v) {
+ char *alias = (char *) in;
+ *((uint32_t *) alias) = CRYPTO_bswap4(v);
+}
/* block128_f is the type of a 128-bit, block cipher. */
typedef void (*block128_f)(const uint8_t in[16], uint8_t out[16],
@@ -156,6 +126,16 @@
/* GCM definitions */
typedef struct { uint64_t hi,lo; } u128;
+/* gmult_func multiplies |Xi| by the GCM key and writes the result back to
+ * |Xi|. */
+typedef void (*gmult_func)(uint64_t Xi[2], const u128 Htable[16]);
+
+/* ghash_func repeatedly multiplies |Xi| by the GCM key and adds in blocks from
+ * |inp|. The result is written back to |Xi| and the |len| argument must be a
+ * multiple of 16. */
+typedef void (*ghash_func)(uint64_t Xi[2], const u128 Htable[16],
+ const uint8_t *inp, size_t len);
+
/* This differs from upstream's |gcm128_context| in that it does not have the
* |key| pointer, in order to make it |memcpy|-friendly. Rather the key is
* passed into each call that needs it. */
@@ -166,14 +146,11 @@
uint32_t d[4];
uint8_t c[16];
size_t t[16 / sizeof(size_t)];
- } Yi, EKi, EK0, len, Xi, H;
+ } Yi, EKi, EK0, len, Xi;
- /* Relative position of Xi, H and pre-computed Htable is used in some
- * assembler modules, i.e. don't change the order! */
u128 Htable[16];
- void (*gmult)(uint64_t Xi[2], const u128 Htable[16]);
- void (*ghash)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
- size_t len);
+ gmult_func gmult;
+ ghash_func ghash;
unsigned int mres, ares;
block128_f block;
@@ -212,6 +189,12 @@
uint8_t ecount_buf[16], unsigned *num,
ctr128_f ctr);
+#if !defined(OPENSSL_NO_ASM) && \
+ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
+void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
+ const void *key, const uint8_t *ivec);
+#endif
+
/* GCM.
*
@@ -222,6 +205,12 @@
typedef struct gcm128_context GCM128_CONTEXT;
+/* CRYPTO_ghash_init writes a precomputed table of powers of |gcm_key| to
+ * |out_table| and sets |*out_mult| and |*out_hash| to (potentially hardware
+ * accelerated) functions for performing operations in the GHASH field. */
+void CRYPTO_ghash_init(gmult_func *out_mult, ghash_func *out_hash,
+ u128 out_table[16], const uint8_t *gcm_key);
+
/* CRYPTO_gcm128_init initialises |ctx| to use |block| (typically AES) with
* the given key. */
OPENSSL_EXPORT void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key,
@@ -345,11 +334,36 @@
block128_f block);
-#if !defined(OPENSSL_NO_ASM) && \
- (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
-void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
- const void *key, const uint8_t *ivec);
-#endif
+/* POLYVAL.
+ *
+ * POLYVAL is a polynomial authenticator that operates over a field very
+ * similar to the one that GHASH uses. See
+ * https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#section-3. */
+
+typedef union {
+ uint64_t u[2];
+ uint8_t c[16];
+} polyval_block;
+
+struct polyval_ctx {
+ polyval_block S;
+ u128 Htable[16];
+ gmult_func gmult;
+ ghash_func ghash;
+};
+
+/* CRYPTO_POLYVAL_init initialises |ctx| using |key|. */
+void CRYPTO_POLYVAL_init(struct polyval_ctx *ctx, const uint8_t key[16]);
+
+/* CRYPTO_POLYVAL_update_blocks updates the accumulator in |ctx| given the
+ * blocks from |in|. Only a whole number of blocks can be processed so |in_len|
+ * must be a multiple of 16. */
+void CRYPTO_POLYVAL_update_blocks(struct polyval_ctx *ctx, const uint8_t *in,
+ size_t in_len);
+
+/* CRYPTO_POLYVAL_finish writes the accumulator from |ctx| to |out|. */
+void CRYPTO_POLYVAL_finish(const struct polyval_ctx *ctx, uint8_t out[16]);
+
#if defined(__cplusplus)
} /* extern C */
diff --git a/src/crypto/modes/polyval.c b/src/crypto/modes/polyval.c
new file mode 100644
index 0000000..c5121a1
--- /dev/null
+++ b/src/crypto/modes/polyval.c
@@ -0,0 +1,93 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/base.h>
+
+#if !defined(OPENSSL_SMALL)
+
+#include <assert.h>
+#include <string.h>
+
+#include "internal.h"
+#include "../internal.h"
+
+
+/* byte_reverse reverses the order of the bytes in |b->c|. */
+static void byte_reverse(polyval_block *b) {
+ const uint64_t t = CRYPTO_bswap8(b->u[0]);
+ b->u[0] = CRYPTO_bswap8(b->u[1]);
+ b->u[1] = t;
+}
+
+/* reverse_and_mulX_ghash interprets the bytes |b->c| as a reversed element of
+ * the GHASH field, multiplies that by 'x' and serialises the result back into
+ * |b|, but with GHASH's backwards bit ordering. */
+static void reverse_and_mulX_ghash(polyval_block *b) {
+ uint64_t hi = b->u[0];
+ uint64_t lo = b->u[1];
+ const unsigned carry = constant_time_eq(hi & 1, 1);
+ hi >>= 1;
+ hi |= lo << 63;
+ lo >>= 1;
+ lo ^= ((uint64_t) constant_time_select(carry, 0xe1, 0)) << 56;
+
+ b->u[0] = CRYPTO_bswap8(lo);
+ b->u[1] = CRYPTO_bswap8(hi);
+}
+
+/* POLYVAL(H, X_1, ..., X_n) =
+ * ByteReverse(GHASH(mulX_GHASH(ByteReverse(H)), ByteReverse(X_1), ...,
+ * ByteReverse(X_n))).
+ *
+ * See https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#appendix-A. */
+
+void CRYPTO_POLYVAL_init(struct polyval_ctx *ctx, const uint8_t key[16]) {
+ polyval_block H;
+ memcpy(H.c, key, 16);
+ reverse_and_mulX_ghash(&H);
+
+ CRYPTO_ghash_init(&ctx->gmult, &ctx->ghash, ctx->Htable, H.c);
+ memset(&ctx->S, 0, sizeof(ctx->S));
+}
+
+void CRYPTO_POLYVAL_update_blocks(struct polyval_ctx *ctx, const uint8_t *in,
+ size_t in_len) {
+ assert((in_len & 15) == 0);
+ polyval_block reversed[32];
+
+ while (in_len > 0) {
+ size_t todo = in_len;
+ if (todo > sizeof(reversed)) {
+ todo = sizeof(reversed);
+ }
+ memcpy(reversed, in, todo);
+ in_len -= todo;
+
+ size_t blocks = todo / sizeof(polyval_block);
+ for (size_t i = 0; i < blocks; i++) {
+ byte_reverse(&reversed[i]);
+ }
+
+ ctx->ghash(ctx->S.u, ctx->Htable, (const uint8_t *) reversed, todo);
+ }
+}
+
+void CRYPTO_POLYVAL_finish(const struct polyval_ctx *ctx, uint8_t out[16]) {
+ polyval_block S = ctx->S;
+ byte_reverse(&S);
+ memcpy(out, &S.c, sizeof(polyval_block));
+}
+
+
+#endif /* !OPENSSL_SMALL */
diff --git a/src/crypto/rand/urandom.c b/src/crypto/rand/urandom.c
index 2572625..17d194c 100644
--- a/src/crypto/rand/urandom.c
+++ b/src/crypto/rand/urandom.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+#include <stdio.h>
#include <string.h>
#include <unistd.h>
@@ -87,12 +88,16 @@
/* requested_lock is used to protect the |*_requested| variables. */
static struct CRYPTO_STATIC_MUTEX requested_lock = CRYPTO_STATIC_MUTEX_INIT;
-/* urandom_fd_requested is set by |RAND_set_urandom_fd|. It's protected by
+/* The following constants are magic values of |urandom_fd|. */
+static const int kUnset = -2;
+static const int kHaveGetrandom = -3;
+
+/* urandom_fd_requested is set by |RAND_set_urandom_fd|. It's protected by
* |requested_lock|. */
-static int urandom_fd_requested = -2;
+static int urandom_fd_requested = -2 /* kUnset */;
/* urandom_fd is a file descriptor to /dev/urandom. It's protected by |once|. */
-static int urandom_fd = -2;
+static int urandom_fd = -2 /* kUnset */;
/* urandom_buffering_requested is set by |RAND_enable_fork_unsafe_buffering|.
* It's protected by |requested_lock|. */
@@ -115,12 +120,31 @@
CRYPTO_STATIC_MUTEX_unlock_read(&requested_lock);
#if defined(USE_SYS_getrandom)
- /* Initial test of getrandom to find any unexpected behavior. */
uint8_t dummy;
- syscall(SYS_getrandom, &dummy, sizeof(dummy), GRND_NONBLOCK);
-#endif
+ long getrandom_ret =
+ syscall(SYS_getrandom, &dummy, sizeof(dummy), GRND_NONBLOCK);
- if (fd == -2) {
+ if (getrandom_ret == 1) {
+ urandom_fd = kHaveGetrandom;
+ return;
+ } else if (getrandom_ret == -1 && errno == EAGAIN) {
+ fprintf(stderr,
+ "getrandom indicates that the entropy pool has not been "
+ "initialized. Rather than continue with poor entropy, this process "
+ "will block until entropy is available.\n");
+ do {
+ getrandom_ret =
+ syscall(SYS_getrandom, &dummy, sizeof(dummy), 0 /* no flags */);
+ } while (getrandom_ret == -1 && errno == EINTR);
+
+ if (getrandom_ret == 1) {
+ urandom_fd = kHaveGetrandom;
+ return;
+ }
+ }
+#endif /* USE_SYS_getrandom */
+
+ if (fd == kUnset) {
do {
fd = open("/dev/urandom", O_RDONLY);
} while (fd == -1 && errno == EINTR);
@@ -156,7 +180,9 @@
CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock);
CRYPTO_once(&once, init_once);
- if (urandom_fd != fd) {
+ if (urandom_fd == kHaveGetrandom) {
+ close(fd);
+ } else if (urandom_fd != fd) {
abort(); // Already initialized.
}
}
@@ -168,7 +194,7 @@
abort();
}
} else {
- fd = -2;
+ fd = kUnset;
}
CRYPTO_STATIC_MUTEX_lock_write(&requested_lock);
@@ -177,7 +203,15 @@
CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock);
CRYPTO_once(&once, init_once);
- if (urandom_buffering != 1 || (fd >= 0 && urandom_fd != fd)) {
+ if (urandom_buffering != 1) {
+ abort(); // Already initialized
+ }
+
+ if (urandom_fd == kHaveGetrandom) {
+ if (fd >= 0) {
+ close(fd);
+ }
+ } else if (urandom_fd != fd) {
abort(); // Already initialized.
}
}
@@ -209,9 +243,19 @@
ssize_t r;
while (len > 0) {
- do {
- r = read(urandom_fd, out, len);
- } while (r == -1 && errno == EINTR);
+ if (urandom_fd == kHaveGetrandom) {
+#if defined(USE_SYS_getrandom)
+ do {
+ r = syscall(SYS_getrandom, out, len, 0 /* no flags */);
+ } while (r == -1 && errno == EINTR);
+#else
+ abort();
+#endif
+ } else {
+ do {
+ r = read(urandom_fd, out, len);
+ } while (r == -1 && errno == EINTR);
+ }
if (r <= 0) {
return 0;
diff --git a/src/crypto/sha/asm/sha256-armv4.pl b/src/crypto/sha/asm/sha256-armv4.pl
index e1be226..bac7ce8 100644
--- a/src/crypto/sha/asm/sha256-armv4.pl
+++ b/src/crypto/sha/asm/sha256-armv4.pl
@@ -1,4 +1,11 @@
-#!/usr/bin/env perl
+#! /usr/bin/env perl
+# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License"). You may not use
+# this file except in compliance with the License. You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -175,16 +182,11 @@
#endif
.text
-#if __ARM_ARCH__<7
-.code 32
-#else
+#if defined(__thumb2__)
.syntax unified
-# if defined(__thumb2__) && !defined(__APPLE__)
-# define adrl adr
.thumb
-# else
+#else
.code 32
-# endif
#endif
.type K256,%object
@@ -218,10 +220,10 @@
.type sha256_block_data_order,%function
sha256_block_data_order:
.Lsha256_block_data_order:
-#if __ARM_ARCH__<7
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
sub r3,pc,#8 @ sha256_block_data_order
#else
- adr r3,sha256_block_data_order
+ adr r3,.Lsha256_block_data_order
#endif
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
ldr r12,.LOPENSSL_armcap
@@ -473,13 +475,14 @@
.global sha256_block_data_order_neon
.type sha256_block_data_order_neon,%function
-.align 4
+.align 5
+.skip 16
sha256_block_data_order_neon:
.LNEON:
stmdb sp!,{r4-r12,lr}
sub $H,sp,#16*4+16
- adrl $Ktbl,K256
+ adr $Ktbl,K256
bic $H,$H,#15 @ align for 128-bit stores
mov $t2,sp
mov sp,$H @ alloca
@@ -599,7 +602,7 @@
$code.=<<___;
#if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
-# if defined(__thumb2__) && !defined(__APPLE__)
+# if defined(__thumb2__)
# define INST(a,b,c,d) .byte c,d|0xc,a,b
# else
# define INST(a,b,c,d) .byte a,b,c,d
@@ -610,16 +613,11 @@
sha256_block_data_order_armv8:
.LARMv8:
vld1.32 {$ABCD,$EFGH},[$ctx]
-# ifdef __APPLE__
sub $Ktbl,$Ktbl,#256+32
-# elif defined(__thumb2__)
- adr $Ktbl,.LARMv8
- sub $Ktbl,$Ktbl,#.LARMv8-K256
-# else
- adrl $Ktbl,K256
-# endif
add $len,$inp,$len,lsl#6 @ len to point at the end of inp
+ b .Loop_v8
+.align 4
.Loop_v8:
vld1.8 {@MSG[0]-@MSG[1]},[$inp]!
vld1.8 {@MSG[2]-@MSG[3]},[$inp]!
diff --git a/src/crypto/x509/x509_test.cc b/src/crypto/x509/x509_test.cc
index c39d98d..0c25754 100644
--- a/src/crypto/x509/x509_test.cc
+++ b/src/crypto/x509/x509_test.cc
@@ -25,7 +25,6 @@
#include <openssl/pool.h>
#include <openssl/x509.h>
-namespace bssl {
static const char kCrossSigningRootPEM[] =
"-----BEGIN CERTIFICATE-----\n"
@@ -724,7 +723,7 @@
}
// Test PKCS#1 v1.5.
- ScopedEVP_MD_CTX md_ctx;
+ bssl::ScopedEVP_MD_CTX md_ctx;
if (!EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
!SignatureRoundTrips(md_ctx.get(), pkey.get())) {
fprintf(stderr, "RSA PKCS#1 with SHA-256 failed\n");
@@ -941,7 +940,51 @@
return true;
}
-static int Main() {
+static bool TestFailedParseFromBuffer() {
+ static const uint8_t kNonsense[] = {1, 2, 3, 4, 5};
+
+ bssl::UniquePtr<CRYPTO_BUFFER> buf(
+ CRYPTO_BUFFER_new(kNonsense, sizeof(kNonsense), nullptr));
+ if (!buf) {
+ return false;
+ }
+
+ bssl::UniquePtr<X509> cert(X509_parse_from_buffer(buf.get()));
+ if (cert) {
+ fprintf(stderr, "Nonsense somehow parsed.\n");
+ return false;
+ }
+ ERR_clear_error();
+
+ // Test a buffer with trailing data.
+ size_t data_len;
+ bssl::UniquePtr<uint8_t> data;
+ if (!PEMToDER(&data, &data_len, kRootCAPEM)) {
+ return false;
+ }
+
+ std::unique_ptr<uint8_t[]> data_with_trailing_byte(new uint8_t[data_len + 1]);
+ memcpy(data_with_trailing_byte.get(), data.get(), data_len);
+ data_with_trailing_byte[data_len] = 0;
+
+ bssl::UniquePtr<CRYPTO_BUFFER> buf_with_trailing_byte(
+ CRYPTO_BUFFER_new(data_with_trailing_byte.get(), data_len + 1, nullptr));
+ if (!buf_with_trailing_byte) {
+ return false;
+ }
+
+ bssl::UniquePtr<X509> root(
+ X509_parse_from_buffer(buf_with_trailing_byte.get()));
+ if (root) {
+ fprintf(stderr, "Parsed buffer with trailing byte.\n");
+ return false;
+ }
+ ERR_clear_error();
+
+ return true;
+}
+
+int main() {
CRYPTO_library_init();
if (!TestVerify() ||
@@ -952,16 +995,11 @@
!TestFromBuffer() ||
!TestFromBufferTrailingData() ||
!TestFromBufferModified() ||
- !TestFromBufferReused()) {
+ !TestFromBufferReused() ||
+ !TestFailedParseFromBuffer()) {
return 1;
}
printf("PASS\n");
return 0;
}
-
-} // namespace bssl
-
-int main() {
- return bssl::Main();
-}
diff --git a/src/crypto/x509/x_x509.c b/src/crypto/x509/x_x509.c
index 845d4b2..d3cd5b0 100644
--- a/src/crypto/x509/x_x509.c
+++ b/src/crypto/x509/x_x509.c
@@ -106,6 +106,7 @@
ret->crldp = NULL;
ret->buf = NULL;
CRYPTO_new_ex_data(&ret->ex_data);
+ CRYPTO_MUTEX_init(&ret->lock);
break;
case ASN1_OP_D2I_PRE:
@@ -120,6 +121,7 @@
break;
case ASN1_OP_FREE_POST:
+ CRYPTO_MUTEX_cleanup(&ret->lock);
CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data);
X509_CERT_AUX_free(ret->aux);
ASN1_OCTET_STRING_free(ret->skid);
@@ -129,9 +131,7 @@
GENERAL_NAMES_free(ret->altname);
NAME_CONSTRAINTS_free(ret->nc);
CRYPTO_BUFFER_free(ret->buf);
-
- if (ret->name != NULL)
- OPENSSL_free(ret->name);
+ OPENSSL_free(ret->name);
break;
}
@@ -162,8 +162,8 @@
X509 *x509p = x509;
X509 *ret = d2i_X509(&x509p, &inp, CRYPTO_BUFFER_len(buf));
if (ret == NULL ||
- (inp - CRYPTO_BUFFER_data(buf)) != (ptrdiff_t) CRYPTO_BUFFER_len(buf)) {
- X509_free(x509);
+ inp - CRYPTO_BUFFER_data(buf) != (ptrdiff_t)CRYPTO_BUFFER_len(buf)) {
+ X509_free(x509p);
return NULL;
}
assert(x509p == x509);
diff --git a/src/crypto/x509v3/v3_purp.c b/src/crypto/x509v3/v3_purp.c
index 9152444..324de85 100644
--- a/src/crypto/x509v3/v3_purp.c
+++ b/src/crypto/x509v3/v3_purp.c
@@ -146,9 +146,7 @@
{
int idx;
const X509_PURPOSE *pt;
- if (!(x->ex_flags & EXFLAG_SET)) {
- x509v3_cache_extensions(x);
- }
+ x509v3_cache_extensions(x);
if (id == -1)
return 1;
idx = X509_PURPOSE_get_by_id(id);
@@ -407,16 +405,6 @@
setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
}
-/*
- * g_x509_cache_extensions_lock is used to protect against concurrent calls
- * to |x509v3_cache_extensions|. Ideally this would be done with a
- * |CRYPTO_once_t| in the |X509| structure, but |CRYPTO_once_t| isn't public.
- * Note: it's not entirely clear whether this lock is needed. Not all paths to
- * this function took a lock in OpenSSL.
- */
-static struct CRYPTO_STATIC_MUTEX g_x509_cache_extensions_lock =
- CRYPTO_STATIC_MUTEX_INIT;
-
static void x509v3_cache_extensions(X509 *x)
{
BASIC_CONSTRAINTS *bs;
@@ -428,10 +416,17 @@
size_t i;
int j;
- CRYPTO_STATIC_MUTEX_lock_write(&g_x509_cache_extensions_lock);
+ CRYPTO_MUTEX_lock_read(&x->lock);
+ const int is_set = x->ex_flags & EXFLAG_SET;
+ CRYPTO_MUTEX_unlock_read(&x->lock);
+ if (is_set) {
+ return;
+ }
+
+ CRYPTO_MUTEX_lock_write(&x->lock);
if (x->ex_flags & EXFLAG_SET) {
- CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_cache_extensions_lock);
+ CRYPTO_MUTEX_unlock_write(&x->lock);
return;
}
@@ -564,7 +559,7 @@
}
x->ex_flags |= EXFLAG_SET;
- CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_cache_extensions_lock);
+ CRYPTO_MUTEX_unlock_write(&x->lock);
}
/*
@@ -604,10 +599,7 @@
int X509_check_ca(X509 *x)
{
- if (!(x->ex_flags & EXFLAG_SET)) {
- x509v3_cache_extensions(x);
- }
-
+ x509v3_cache_extensions(x);
return check_ca(x);
}
diff --git a/src/include/openssl/aead.h b/src/include/openssl/aead.h
index fff0e49..eaa2b8f 100644
--- a/src/include/openssl/aead.h
+++ b/src/include/openssl/aead.h
@@ -114,6 +114,14 @@
* authentication. See |EVP_aead_aes_128_ctr_hmac_sha256| for details. */
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void);
+/* EVP_aead_aes_128_gcm_siv is AES-128 in GCM-SIV mode. See
+ * https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02 */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void);
+
+/* EVP_aead_aes_256_gcm_siv is AES-256 in GCM-SIV mode. See
+ * https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02 */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void);
+
/* EVP_has_aes_hardware returns one if we enable hardware support for fast and
* constant-time AES-GCM. */
OPENSSL_EXPORT int EVP_has_aes_hardware(void);
diff --git a/src/include/openssl/bio.h b/src/include/openssl/bio.h
index 3c8b97d..58a4747 100644
--- a/src/include/openssl/bio.h
+++ b/src/include/openssl/bio.h
@@ -616,18 +616,6 @@
OPENSSL_EXPORT int BIO_new_bio_pair(BIO **out1, size_t writebuf1, BIO **out2,
size_t writebuf2);
-/* BIO_new_bio_pair_external_buf is the same as |BIO_new_bio_pair| with the
- * difference that the caller keeps ownership of the write buffers
- * |ext_writebuf1_len| and |ext_writebuf2_len|. This is useful when using zero
- * copy API for read and write operations, in cases where the buffers need to
- * outlive the BIO pairs. It returns one on success and zero on error. */
-OPENSSL_EXPORT int BIO_new_bio_pair_external_buf(BIO** bio1_p,
- size_t writebuf1_len,
- uint8_t* ext_writebuf1,
- BIO** bio2_p,
- size_t writebuf2_len,
- uint8_t* ext_writebuf2);
-
/* BIO_ctrl_get_read_request returns the number of bytes that the other side of
* |bio| tried (unsuccessfully) to read. */
OPENSSL_EXPORT size_t BIO_ctrl_get_read_request(BIO *bio);
@@ -643,63 +631,6 @@
OPENSSL_EXPORT int BIO_shutdown_wr(BIO *bio);
-/* Zero copy versions of BIO_read and BIO_write for BIO pairs. */
-
-/* BIO_zero_copy_get_read_buf initiates a zero copy read operation.
- * |out_read_buf| is set to the internal read buffer, and |out_buf_offset| is
- * set to the current read position of |out_read_buf|. The number of bytes
- * available for read from |out_read_buf| + |out_buf_offset| is returned in
- * |out_available_bytes|. Note that this function might report fewer bytes
- * available than |BIO_pending|, if the internal ring buffer is wrapped. It
- * returns one on success. In case of error it returns zero and pushes to the
- * error stack.
- *
- * The zero copy read operation is completed by calling
- * |BIO_zero_copy_get_read_buf_done|. Neither |BIO_zero_copy_get_read_buf| nor
- * any other I/O read operation may be called while a zero copy read operation
- * is active. */
-OPENSSL_EXPORT int BIO_zero_copy_get_read_buf(BIO* bio,
- uint8_t** out_read_buf,
- size_t* out_buf_offset,
- size_t* out_available_bytes);
-
-/* BIO_zero_copy_get_read_buf_done must be called after reading from a BIO using
- * |BIO_zero_copy_get_read_buf| to finish the read operation. The |bytes_read|
- * argument is the number of bytes read.
- *
- * It returns one on success. In case of error it returns zero and pushes to the
- * error stack. */
-OPENSSL_EXPORT int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read);
-
-/* BIO_zero_copy_get_write_buf initiates a zero copy write operation.
- * |out_write_buf| is set to to the internal write buffer, and |out_buf_offset|
- * is set to the current write position of |out_write_buf|.
- * The number of bytes available for write from |out_write_buf| +
- * |out_buf_offset| is returned in |out_available_bytes|. Note that this
- * function might report fewer bytes available than
- * |BIO_ctrl_get_write_guarantee|, if the internal buffer is wrapped. It returns
- * one on success. In case of error it returns zero and pushes to the error
- * stack.
- *
- * The zero copy write operation is completed by calling
- * |BIO_zero_copy_get_write_buf_done|. Neither |BIO_zero_copy_get_write_buf|
- * nor any other I/O write operation may be called while a zero copy write
- * operation is active. */
-OPENSSL_EXPORT int BIO_zero_copy_get_write_buf(BIO* bio,
- uint8_t** out_write_buf,
- size_t* out_buf_offset,
- size_t* out_available_bytes);
-
-/* BIO_zero_copy_get_write_buf_done must be called after writing to a BIO using
- * |BIO_zero_copy_get_write_buf| to finish the write operation. The
- * |bytes_written| argument gives the number of bytes written.
- *
- * It returns one on success. In case of error it returns zero and pushes to the
- * error stack. */
-OPENSSL_EXPORT int BIO_zero_copy_get_write_buf_done(BIO* bio,
- size_t bytes_written);
-
-
/* BIO_NOCLOSE and |BIO_CLOSE| can be used as symbolic arguments when a "close
* flag" is passed to a BIO function. */
#define BIO_NOCLOSE 0
diff --git a/src/include/openssl/bn.h b/src/include/openssl/bn.h
index 764d8c5..8deb278 100644
--- a/src/include/openssl/bn.h
+++ b/src/include/openssl/bn.h
@@ -575,8 +575,10 @@
OPENSSL_EXPORT int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a,
const BIGNUM *m);
-/* BN_mod_sqrt returns a |BIGNUM|, r, such that r^2 == a (mod p). |p| must be a
- * prime. */
+/* BN_mod_sqrt returns a newly-allocated |BIGNUM|, r, such that
+ * r^2 == a (mod p). |p| must be a prime. It returns NULL on error or if |a| is
+ * not a square mod |p|. In the latter case, it will add |BN_R_NOT_A_SQUARE| to
+ * the error queue. */
OPENSSL_EXPORT BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p,
BN_CTX *ctx);
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index f5b9f9d..c29040a 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -608,11 +608,6 @@
* client's. */
#define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
-/* SSL_OP_DISABLE_NPN configures an individual |SSL| to not advertise NPN,
- * despite |SSL_CTX_set_next_proto_select_cb| being configured on the
- * |SSL_CTX|. */
-#define SSL_OP_DISABLE_NPN 0x00800000L
-
/* The following flags toggle individual protocol versions. This is deprecated.
* Use |SSL_CTX_set_min_proto_version| and |SSL_CTX_set_max_proto_version|
* instead. */
@@ -1620,7 +1615,7 @@
* should not be used. */
OPENSSL_EXPORT int SSL_SESSION_set1_id_context(SSL_SESSION *session,
const uint8_t *sid_ctx,
- unsigned sid_ctx_len);
+ size_t sid_ctx_len);
/* Session caching.
@@ -1721,6 +1716,15 @@
* |ctx|. */
OPENSSL_EXPORT long SSL_CTX_get_timeout(const SSL_CTX *ctx);
+/* SSL_set_session_timeout sets the default lifetime, in seconds, of the
+ * session created in |ssl| to |timeout|, and returns the old value.
+ *
+ * By default the value |SSL_DEFAULT_SESSION_TIMEOUT| is used, which can be
+ * overridden at the context level by calling |SSL_CTX_set_timeout|.
+ *
+ * If |timeout| is zero the newly created session will not be resumable. */
+OPENSSL_EXPORT long SSL_set_session_timeout(SSL *ssl, long timeout);
+
/* SSL_CTX_set_session_id_context sets |ctx|'s session ID context to |sid_ctx|.
* It returns one on success and zero on error. The session ID context is an
* application-defined opaque byte string. A session will not be used in a
@@ -1734,13 +1738,13 @@
* relevant if a server requires client auth. */
OPENSSL_EXPORT int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
const uint8_t *sid_ctx,
- unsigned sid_ctx_len);
+ size_t sid_ctx_len);
/* SSL_set_session_id_context sets |ssl|'s session ID context to |sid_ctx|. It
* returns one on success and zero on error. See also
* |SSL_CTX_set_session_id_context|. */
OPENSSL_EXPORT int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
- unsigned sid_ctx_len);
+ size_t sid_ctx_len);
/* SSL_SESSION_CACHE_MAX_SIZE_DEFAULT is the default maximum size of a session
* cache. */
@@ -2502,15 +2506,14 @@
*
* See draft-balfanz-tls-channelid-01. */
-/* SSL_CTX_enable_tls_channel_id either configures a TLS server to accept TLS
- * Channel IDs from clients, or configures a client to send TLS Channel IDs to
- * a server. It returns one. */
-OPENSSL_EXPORT int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx);
+/* SSL_CTX_set_tls_channel_id_enabled configures whether connections associated
+ * with |ctx| should enable Channel ID. */
+OPENSSL_EXPORT void SSL_CTX_set_tls_channel_id_enabled(SSL_CTX *ctx,
+ int enabled);
-/* SSL_enable_tls_channel_id either configures a TLS server to accept TLS
- * Channel IDs from clients, or configures a client to send TLS Channel IDs to
- * server. It returns one. */
-OPENSSL_EXPORT int SSL_enable_tls_channel_id(SSL *ssl);
+/* SSL_set_tls_channel_id_enabled configures whether |ssl| should enable Channel
+ * ID. */
+OPENSSL_EXPORT void SSL_set_tls_channel_id_enabled(SSL *ssl, int enabled);
/* SSL_CTX_set1_tls_channel_id configures a TLS client to send a TLS Channel ID
* to compatible servers. |private_key| must be a P-256 EC key. It returns one
@@ -2942,10 +2945,11 @@
OPENSSL_EXPORT int SSL_set_max_send_fragment(SSL *ssl,
size_t max_send_fragment);
-/* ssl_early_callback_ctx is passed to certain callbacks that are called very
- * early on during the server handshake. At this point, much of the SSL* hasn't
- * been filled out and only the ClientHello can be depended on. */
-struct ssl_early_callback_ctx {
+/* ssl_early_callback_ctx (aka |SSL_CLIENT_HELLO|) is passed to certain
+ * callbacks that are called very early on during the server handshake. At this
+ * point, much of the SSL* hasn't been filled out and only the ClientHello can
+ * be depended on. */
+typedef struct ssl_early_callback_ctx {
SSL *ssl;
const uint8_t *client_hello;
size_t client_hello_len;
@@ -2960,15 +2964,15 @@
size_t compression_methods_len;
const uint8_t *extensions;
size_t extensions_len;
-};
+} SSL_CLIENT_HELLO;
-/* SSL_early_callback_ctx_extension_get searches the extensions in |ctx| for an
- * extension of the given type. If not found, it returns zero. Otherwise it
- * sets |out_data| to point to the extension contents (not including the type
- * and length bytes), sets |out_len| to the length of the extension contents
- * and returns one. */
+/* SSL_early_callback_ctx_extension_get searches the extensions in
+ * |client_hello| for an extension of the given type. If not found, it returns
+ * zero. Otherwise it sets |out_data| to point to the extension contents (not
+ * including the type and length bytes), sets |out_len| to the length of the
+ * extension contents and returns one. */
OPENSSL_EXPORT int SSL_early_callback_ctx_extension_get(
- const struct ssl_early_callback_ctx *ctx, uint16_t extension_type,
+ const SSL_CLIENT_HELLO *client_hello, uint16_t extension_type,
const uint8_t **out_data, size_t *out_len);
/* SSL_CTX_set_select_certificate_cb sets a callback that is called before most
@@ -2978,19 +2982,19 @@
* pause the handshake to perform an asynchronous operation. If paused,
* |SSL_get_error| will return |SSL_ERROR_PENDING_CERTIFICATE|.
*
- * Note: The |ssl_early_callback_ctx| is only valid for the duration of the
- * callback and is not valid while the handshake is paused. Further, unlike with
- * most callbacks, when the handshake loop is resumed, it will not call the
- * callback a second time. The caller must finish reconfiguring the connection
- * before resuming the handshake. */
+ * Note: The |SSL_CLIENT_HELLO| is only valid for the duration of the callback
+ * and is not valid while the handshake is paused. Further, unlike with most
+ * callbacks, when the handshake loop is resumed, it will not call the callback
+ * a second time. The caller must finish reconfiguring the connection before
+ * resuming the handshake. */
OPENSSL_EXPORT void SSL_CTX_set_select_certificate_cb(
- SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *));
+ SSL_CTX *ctx, int (*cb)(const SSL_CLIENT_HELLO *));
/* SSL_CTX_set_dos_protection_cb sets a callback that is called once the
* resumption decision for a ClientHello has been made. It can return one to
* allow the handshake to continue or zero to cause the handshake to abort. */
OPENSSL_EXPORT void SSL_CTX_set_dos_protection_cb(
- SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *));
+ SSL_CTX *ctx, int (*cb)(const SSL_CLIENT_HELLO *));
/* SSL_ST_* are possible values for |SSL_state| and the bitmasks that make them
* up. */
@@ -3146,11 +3150,6 @@
/* SSL_library_init calls |CRYPTO_library_init| and returns one. */
OPENSSL_EXPORT int SSL_library_init(void);
-/* SSL_set_reject_peer_renegotiations calls |SSL_set_renegotiate_mode| with
- * |ssl_never_renegotiate| if |reject| is one and |ssl_renegotiate_freely| if
- * zero. */
-OPENSSL_EXPORT void SSL_set_reject_peer_renegotiations(SSL *ssl, int reject);
-
/* SSL_CIPHER_description writes a description of |cipher| into |buf| and
* returns |buf|. If |buf| is NULL, it returns a newly allocated string, to be
* freed with |OPENSSL_free|, or NULL on error.
@@ -3627,6 +3626,12 @@
/* SSL_set_max_version calls |SSL_set_max_proto_version|. */
OPENSSL_EXPORT int SSL_set_max_version(SSL *ssl, uint16_t version);
+/* SSL_CTX_enable_tls_channel_id calls |SSL_CTX_set_tls_channel_id_enabled|. */
+OPENSSL_EXPORT int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx);
+
+/* SSL_enable_tls_channel_id calls |SSL_set_tls_channel_id_enabled|. */
+OPENSSL_EXPORT int SSL_enable_tls_channel_id(SSL *ssl);
+
/* Private structures.
*
@@ -3679,7 +3684,7 @@
/* this is used to determine whether the session is being reused in
* the appropriate context. It is up to the application to set this,
* via SSL_new */
- unsigned int sid_ctx_length;
+ uint8_t sid_ctx_length;
uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
char *psk_identity;
@@ -3730,7 +3735,7 @@
* SHA-2, depending on TLS version) for the original, full handshake that
* created a session. This is used by Channel IDs during resumption. */
uint8_t original_handshake_hash[EVP_MAX_MD_SIZE];
- unsigned original_handshake_hash_len;
+ uint8_t original_handshake_hash_len;
uint32_t tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */
@@ -3903,7 +3908,7 @@
void *msg_callback_arg;
int verify_mode;
- unsigned int sid_ctx_length;
+ uint8_t sid_ctx_length;
uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
int (*default_verify_callback)(
int ok, X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */
@@ -3916,12 +3921,12 @@
* with an error and cause SSL_get_error to return
* SSL_ERROR_PENDING_CERTIFICATE. Note: when the handshake loop is resumed, it
* will not call the callback a second time. */
- int (*select_certificate_cb)(const struct ssl_early_callback_ctx *);
+ int (*select_certificate_cb)(const SSL_CLIENT_HELLO *);
/* dos_protection_cb is called once the resumption decision for a ClientHello
* has been made. It returns one to continue the handshake or zero to
* abort. */
- int (*dos_protection_cb) (const struct ssl_early_callback_ctx *);
+ int (*dos_protection_cb) (const SSL_CLIENT_HELLO *);
/* Maximum amount of data to send in one fragment. actual record size can be
* more than this due to padding and MAC overheads. */
@@ -4042,6 +4047,8 @@
int freelist_max_len;
};
+typedef struct ssl_handshake_st SSL_HANDSHAKE;
+
struct ssl_st {
/* method is the method table corresponding to the current protocol (DTLS or
* TLS). */
@@ -4080,7 +4087,7 @@
* with a better mechanism. */
BIO *bbio;
- int (*handshake_func)(SSL *);
+ int (*handshake_func)(SSL_HANDSHAKE *hs);
BUF_MEM *init_buf; /* buffer used during init */
@@ -4123,7 +4130,7 @@
/* the session_id_context is used to ensure sessions are only reused
* in the appropriate context */
- unsigned int sid_ctx_length;
+ uint8_t sid_ctx_length;
uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
/* session is the configured session to be offered by the client. This session
@@ -4157,8 +4164,6 @@
uint32_t options; /* protocol behaviour */
uint32_t mode; /* API behaviour */
uint32_t max_cert_list;
- int client_version; /* what was passed, used for
- * SSLv3/TLS rollback check */
char *tlsext_hostname;
size_t supported_group_list_len;
uint16_t *supported_group_list; /* our list */
@@ -4215,6 +4220,10 @@
/* TODO(agl): remove once node.js not longer references this. */
int tlsext_status_type;
+
+ /* session_timeout is the default lifetime in seconds of the session
+ * created in this connection. */
+ long session_timeout;
};
@@ -4267,7 +4276,6 @@
#define SSL_CTRL_NEED_TMP_RSA doesnt_exist
#define SSL_CTRL_OPTIONS doesnt_exist
#define SSL_CTRL_SESS_NUMBER doesnt_exist
-#define SSL_CTRL_SET_CHANNEL_ID doesnt_exist
#define SSL_CTRL_SET_CURVES doesnt_exist
#define SSL_CTRL_SET_CURVES_LIST doesnt_exist
#define SSL_CTRL_SET_MAX_CERT_LIST doesnt_exist
@@ -4299,7 +4307,6 @@
#define SSL_CTX_clear_chain_certs SSL_CTX_clear_chain_certs
#define SSL_CTX_clear_mode SSL_CTX_clear_mode
#define SSL_CTX_clear_options SSL_CTX_clear_options
-#define SSL_CTX_enable_tls_channel_id SSL_CTX_enable_tls_channel_id
#define SSL_CTX_get0_chain_certs SSL_CTX_get0_chain_certs
#define SSL_CTX_get_extra_chain_certs SSL_CTX_get_extra_chain_certs
#define SSL_CTX_get_max_cert_list SSL_CTX_get_max_cert_list
@@ -4315,7 +4322,6 @@
#define SSL_CTX_set0_chain SSL_CTX_set0_chain
#define SSL_CTX_set1_chain SSL_CTX_set1_chain
#define SSL_CTX_set1_curves SSL_CTX_set1_curves
-#define SSL_CTX_set1_tls_channel_id SSL_CTX_set1_tls_channel_id
#define SSL_CTX_set_max_cert_list SSL_CTX_set_max_cert_list
#define SSL_CTX_set_max_send_fragment SSL_CTX_set_max_send_fragment
#define SSL_CTX_set_mode SSL_CTX_set_mode
@@ -4336,7 +4342,6 @@
#define SSL_clear_chain_certs SSL_clear_chain_certs
#define SSL_clear_mode SSL_clear_mode
#define SSL_clear_options SSL_clear_options
-#define SSL_enable_tls_channel_id SSL_enable_tls_channel_id
#define SSL_get0_certificate_types SSL_get0_certificate_types
#define SSL_get0_chain_certs SSL_get0_chain_certs
#define SSL_get_max_cert_list SSL_get_max_cert_list
@@ -4344,14 +4349,12 @@
#define SSL_get_options SSL_get_options
#define SSL_get_secure_renegotiation_support \
SSL_get_secure_renegotiation_support
-#define SSL_get_tls_channel_id SSL_get_tls_channel_id
#define SSL_need_tmp_RSA SSL_need_tmp_RSA
#define SSL_num_renegotiations SSL_num_renegotiations
#define SSL_session_reused SSL_session_reused
#define SSL_set0_chain SSL_set0_chain
#define SSL_set1_chain SSL_set1_chain
#define SSL_set1_curves SSL_set1_curves
-#define SSL_set1_tls_channel_id SSL_set1_tls_channel_id
#define SSL_set_max_cert_list SSL_set_max_cert_list
#define SSL_set_max_send_fragment SSL_set_max_send_fragment
#define SSL_set_mode SSL_set_mode
@@ -4552,6 +4555,8 @@
#define SSL_R_PRE_SHARED_KEY_MUST_BE_LAST 267
#define SSL_R_OLD_SESSION_PRF_HASH_MISMATCH 268
#define SSL_R_INVALID_SCT_LIST 269
+#define SSL_R_TOO_MUCH_SKIPPED_EARLY_DATA 270
+#define SSL_R_PSK_IDENTITY_BINDER_COUNT_MISMATCH 271
#define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
#define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
#define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
diff --git a/src/include/openssl/x509.h b/src/include/openssl/x509.h
index 8f2e1c3..ffd0fbc 100644
--- a/src/include/openssl/x509.h
+++ b/src/include/openssl/x509.h
@@ -263,6 +263,7 @@
unsigned char sha1_hash[SHA_DIGEST_LENGTH];
X509_CERT_AUX *aux;
CRYPTO_BUFFER *buf;
+ CRYPTO_MUTEX lock;
} /* X509 */;
DECLARE_STACK_OF(X509)
diff --git a/src/ssl/custom_extensions.c b/src/ssl/custom_extensions.c
index 46b5efb..10fbfc8 100644
--- a/src/ssl/custom_extensions.c
+++ b/src/ssl/custom_extensions.c
@@ -58,7 +58,8 @@
return 1;
}
-static int custom_ext_add_hello(SSL *ssl, CBB *extensions) {
+static int custom_ext_add_hello(SSL_HANDSHAKE *hs, CBB *extensions) {
+ SSL *const ssl = hs->ssl;
STACK_OF(SSL_CUSTOM_EXTENSION) *stack = ssl->ctx->client_custom_extensions;
if (ssl->server) {
stack = ssl->ctx->server_custom_extensions;
@@ -72,7 +73,7 @@
const SSL_CUSTOM_EXTENSION *ext = sk_SSL_CUSTOM_EXTENSION_value(stack, i);
if (ssl->server &&
- !(ssl->s3->hs->custom_extensions.received & (1u << i))) {
+ !(hs->custom_extensions.received & (1u << i))) {
/* Servers cannot echo extensions that the client didn't send. */
continue;
}
@@ -102,8 +103,8 @@
}
if (!ssl->server) {
- assert((ssl->s3->hs->custom_extensions.sent & (1u << i)) == 0);
- ssl->s3->hs->custom_extensions.sent |= (1u << i);
+ assert((hs->custom_extensions.sent & (1u << i)) == 0);
+ hs->custom_extensions.sent |= (1u << i);
}
break;
@@ -121,12 +122,13 @@
return 1;
}
-int custom_ext_add_clienthello(SSL *ssl, CBB *extensions) {
- return custom_ext_add_hello(ssl, extensions);
+int custom_ext_add_clienthello(SSL_HANDSHAKE *hs, CBB *extensions) {
+ return custom_ext_add_hello(hs, extensions);
}
-int custom_ext_parse_serverhello(SSL *ssl, int *out_alert, uint16_t value,
- const CBS *extension) {
+int custom_ext_parse_serverhello(SSL_HANDSHAKE *hs, int *out_alert,
+ uint16_t value, const CBS *extension) {
+ SSL *const ssl = hs->ssl;
unsigned index;
const SSL_CUSTOM_EXTENSION *ext =
custom_ext_find(ssl->ctx->client_custom_extensions, &index, value);
@@ -134,7 +136,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->hs->custom_extensions.sent & (1u << index))) {
+ !(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;
@@ -152,8 +154,9 @@
return 1;
}
-int custom_ext_parse_clienthello(SSL *ssl, int *out_alert, uint16_t value,
- const CBS *extension) {
+int custom_ext_parse_clienthello(SSL_HANDSHAKE *hs, int *out_alert,
+ uint16_t value, const CBS *extension) {
+ SSL *const ssl = hs->ssl;
unsigned index;
const SSL_CUSTOM_EXTENSION *ext =
custom_ext_find(ssl->ctx->server_custom_extensions, &index, value);
@@ -162,8 +165,8 @@
return 1;
}
- assert((ssl->s3->hs->custom_extensions.received & (1u << index)) == 0);
- ssl->s3->hs->custom_extensions.received |= (1u << index);
+ assert((hs->custom_extensions.received & (1u << index)) == 0);
+ hs->custom_extensions.received |= (1u << index);
if (ext->parse_callback &&
!ext->parse_callback(ssl, value, CBS_data(extension), CBS_len(extension),
@@ -176,8 +179,8 @@
return 1;
}
-int custom_ext_add_serverhello(SSL *ssl, CBB *extensions) {
- return custom_ext_add_hello(ssl, extensions);
+int custom_ext_add_serverhello(SSL_HANDSHAKE *hs, CBB *extensions) {
+ return custom_ext_add_hello(hs, extensions);
}
/* MAX_NUM_CUSTOM_EXTENSIONS is the maximum number of custom extensions that
diff --git a/src/ssl/d1_lib.c b/src/ssl/d1_lib.c
index a63b8c9..cafb4c2 100644
--- a/src/ssl/d1_lib.c
+++ b/src/ssl/d1_lib.c
@@ -113,10 +113,6 @@
ssl->d1 = NULL;
}
-int dtls1_supports_cipher(const SSL_CIPHER *cipher) {
- return cipher->algorithm_enc != SSL_eNULL;
-}
-
void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
ssl->initial_timeout_duration_ms = duration_ms;
}
@@ -260,11 +256,3 @@
dtls1_start_timer(ssl);
return dtls1_retransmit_outgoing_messages(ssl);
}
-
-void dtls1_expect_flight(SSL *ssl) {
- dtls1_start_timer(ssl);
-}
-
-void dtls1_received_flight(SSL *ssl) {
- dtls1_stop_timer(ssl);
-}
diff --git a/src/ssl/dtls_method.c b/src/ssl/dtls_method.c
index 8e92cc9..89b5491 100644
--- a/src/ssl/dtls_method.c
+++ b/src/ssl/dtls_method.c
@@ -94,6 +94,14 @@
return 0;
}
+static int dtls1_supports_cipher(const SSL_CIPHER *cipher) {
+ return cipher->algorithm_enc != SSL_eNULL;
+}
+
+static void dtls1_expect_flight(SSL *ssl) { dtls1_start_timer(ssl); }
+
+static void dtls1_received_flight(SSL *ssl) { dtls1_stop_timer(ssl); }
+
static int dtls1_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
/* Cipher changes are illegal when there are buffered incoming messages. */
if (dtls_has_incoming_messages(ssl)) {
diff --git a/src/ssl/handshake_client.c b/src/ssl/handshake_client.c
index 70d8d96..4a58af9 100644
--- a/src/ssl/handshake_client.c
+++ b/src/ssl/handshake_client.c
@@ -170,23 +170,24 @@
#include "internal.h"
-static int ssl3_send_client_hello(SSL *ssl);
-static int dtls1_get_hello_verify(SSL *ssl);
-static int ssl3_get_server_hello(SSL *ssl);
-static int ssl3_get_server_certificate(SSL *ssl);
-static int ssl3_get_cert_status(SSL *ssl);
-static int ssl3_verify_server_cert(SSL *ssl);
-static int ssl3_get_server_key_exchange(SSL *ssl);
-static int ssl3_get_certificate_request(SSL *ssl);
-static int ssl3_get_server_hello_done(SSL *ssl);
-static int ssl3_send_client_certificate(SSL *ssl);
-static int ssl3_send_client_key_exchange(SSL *ssl);
-static int ssl3_send_cert_verify(SSL *ssl);
-static int ssl3_send_next_proto(SSL *ssl);
-static int ssl3_send_channel_id(SSL *ssl);
-static int ssl3_get_new_session_ticket(SSL *ssl);
+static int ssl3_send_client_hello(SSL_HANDSHAKE *hs);
+static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_hello(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_get_cert_status(SSL_HANDSHAKE *hs);
+static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_hello_done(SSL_HANDSHAKE *hs);
+static int ssl3_send_client_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs);
+static int ssl3_send_next_proto(SSL_HANDSHAKE *hs);
+static int ssl3_send_channel_id(SSL_HANDSHAKE *hs);
+static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs);
-int ssl3_connect(SSL *ssl) {
+int ssl3_connect(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int ret = -1;
int state, skip = 0;
@@ -205,12 +206,6 @@
case SSL_ST_CONNECT:
ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
- ssl->s3->hs = ssl_handshake_new(tls13_client_handshake);
- if (ssl->s3->hs == NULL) {
- ret = -1;
- goto end;
- }
-
if (!ssl_init_wbio_buffer(ssl)) {
ret = -1;
goto end;
@@ -221,7 +216,7 @@
case SSL3_ST_CW_CLNT_HELLO_A:
case SSL3_ST_CW_CLNT_HELLO_B:
- ret = ssl3_send_client_hello(ssl);
+ ret = ssl3_send_client_hello(hs);
if (ret <= 0) {
goto end;
}
@@ -236,7 +231,7 @@
case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
assert(SSL_is_dtls(ssl));
- ret = dtls1_get_hello_verify(ssl);
+ ret = dtls1_get_hello_verify(hs);
if (ret <= 0) {
goto end;
}
@@ -249,7 +244,7 @@
break;
case SSL3_ST_CR_SRVR_HELLO_A:
- ret = ssl3_get_server_hello(ssl);
+ ret = ssl3_get_server_hello(hs);
if (ssl->state == SSL_ST_TLS13) {
break;
}
@@ -266,7 +261,7 @@
case SSL3_ST_CR_CERT_A:
if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
- ret = ssl3_get_server_certificate(ssl);
+ ret = ssl3_get_server_certificate(hs);
if (ret <= 0) {
goto end;
}
@@ -277,8 +272,8 @@
break;
case SSL3_ST_CR_CERT_STATUS_A:
- if (ssl->s3->hs->certificate_status_expected) {
- ret = ssl3_get_cert_status(ssl);
+ if (hs->certificate_status_expected) {
+ ret = ssl3_get_cert_status(hs);
if (ret <= 0) {
goto end;
}
@@ -290,7 +285,7 @@
case SSL3_ST_VERIFY_SERVER_CERT:
if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
- ret = ssl3_verify_server_cert(ssl);
+ ret = ssl3_verify_server_cert(hs);
if (ret <= 0) {
goto end;
}
@@ -301,7 +296,7 @@
break;
case SSL3_ST_CR_KEY_EXCH_A:
- ret = ssl3_get_server_key_exchange(ssl);
+ ret = ssl3_get_server_key_exchange(hs);
if (ret <= 0) {
goto end;
}
@@ -310,7 +305,7 @@
case SSL3_ST_CR_CERT_REQ_A:
if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
- ret = ssl3_get_certificate_request(ssl);
+ ret = ssl3_get_certificate_request(hs);
if (ret <= 0) {
goto end;
}
@@ -321,7 +316,7 @@
break;
case SSL3_ST_CR_SRVR_DONE_A:
- ret = ssl3_get_server_hello_done(ssl);
+ ret = ssl3_get_server_hello_done(hs);
if (ret <= 0) {
goto end;
}
@@ -332,8 +327,8 @@
case SSL3_ST_CW_CERT_A:
case SSL3_ST_CW_CERT_B:
case SSL3_ST_CW_CERT_C:
- if (ssl->s3->hs->cert_request) {
- ret = ssl3_send_client_certificate(ssl);
+ if (hs->cert_request) {
+ ret = ssl3_send_client_certificate(hs);
if (ret <= 0) {
goto end;
}
@@ -345,7 +340,7 @@
case SSL3_ST_CW_KEY_EXCH_A:
case SSL3_ST_CW_KEY_EXCH_B:
- ret = ssl3_send_client_key_exchange(ssl);
+ ret = ssl3_send_client_key_exchange(hs);
if (ret <= 0) {
goto end;
}
@@ -355,8 +350,8 @@
case SSL3_ST_CW_CERT_VRFY_A:
case SSL3_ST_CW_CERT_VRFY_B:
case SSL3_ST_CW_CERT_VRFY_C:
- if (ssl->s3->hs->cert_request) {
- ret = ssl3_send_cert_verify(ssl);
+ if (hs->cert_request) {
+ ret = ssl3_send_cert_verify(hs);
if (ret <= 0) {
goto end;
}
@@ -374,7 +369,7 @@
ssl->state = SSL3_ST_CW_NEXT_PROTO_A;
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+ if (!tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
ret = -1;
goto end;
}
@@ -383,8 +378,8 @@
case SSL3_ST_CW_NEXT_PROTO_A:
case SSL3_ST_CW_NEXT_PROTO_B:
- if (ssl->s3->hs->next_proto_neg_seen) {
- ret = ssl3_send_next_proto(ssl);
+ if (hs->next_proto_neg_seen) {
+ ret = ssl3_send_next_proto(hs);
if (ret <= 0) {
goto end;
}
@@ -397,7 +392,7 @@
case SSL3_ST_CW_CHANNEL_ID_A:
case SSL3_ST_CW_CHANNEL_ID_B:
if (ssl->s3->tlsext_channel_id_valid) {
- ret = ssl3_send_channel_id(ssl);
+ ret = ssl3_send_channel_id(hs);
if (ret <= 0) {
goto end;
}
@@ -409,7 +404,7 @@
case SSL3_ST_CW_FINISHED_A:
case SSL3_ST_CW_FINISHED_B:
- ret = ssl3_send_finished(ssl, SSL3_ST_CW_FINISHED_A,
+ ret = ssl3_send_finished(hs, SSL3_ST_CW_FINISHED_A,
SSL3_ST_CW_FINISHED_B);
if (ret <= 0) {
goto end;
@@ -441,15 +436,15 @@
case SSL3_ST_FALSE_START:
ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
- ssl->s3->hs->in_false_start = 1;
+ hs->in_false_start = 1;
ssl_free_wbio_buffer(ssl);
ret = 1;
goto end;
case SSL3_ST_CR_SESSION_TICKET_A:
- if (ssl->s3->hs->ticket_expected) {
- ret = ssl3_get_new_session_ticket(ssl);
+ if (hs->ticket_expected) {
+ ret = ssl3_get_new_session_ticket(hs);
if (ret <= 0) {
goto end;
}
@@ -465,7 +460,7 @@
goto end;
}
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_CLIENT_READ)) {
+ if (!tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_CLIENT_READ)) {
ret = -1;
goto end;
}
@@ -473,7 +468,7 @@
break;
case SSL3_ST_CR_FINISHED_A:
- ret = ssl3_get_finished(ssl);
+ ret = ssl3_get_finished(hs);
if (ret <= 0) {
goto end;
}
@@ -499,7 +494,7 @@
break;
case SSL_ST_TLS13:
- ret = tls13_handshake(ssl);
+ ret = tls13_handshake(hs);
if (ret <= 0) {
goto end;
}
@@ -540,12 +535,9 @@
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);
+ ssl_update_cache(hs, SSL_SESS_CACHE_CLIENT);
}
- ssl_handshake_free(ssl->s3->hs);
- ssl->s3->hs = NULL;
-
ret = 1;
ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1);
goto end;
@@ -650,7 +642,7 @@
/* For SSLv3, the SCSV is added. Otherwise the renegotiation extension is
* added. */
- if (ssl->client_version == SSL3_VERSION &&
+ if (max_version == SSL3_VERSION &&
!ssl->s3->initial_handshake_complete) {
if (!CBB_add_u16(&child, SSL3_CK_SCSV & 0xffff)) {
return 0;
@@ -666,7 +658,8 @@
return CBB_flush(out);
}
-int ssl_write_client_hello(SSL *ssl) {
+int ssl_write_client_hello(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
@@ -682,7 +675,7 @@
!ssl->s3->initial_handshake_complete;
CBB child;
- if (!CBB_add_u16(&body, ssl->client_version) ||
+ if (!CBB_add_u16(&body, hs->client_version) ||
!CBB_add_bytes(&body, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
!CBB_add_u8_length_prefixed(&body, &child) ||
(has_session &&
@@ -703,7 +696,7 @@
if (!ssl_write_client_cipher_list(ssl, &body, min_version, max_version) ||
!CBB_add_u8(&body, 1 /* one compression method */) ||
!CBB_add_u8(&body, 0 /* null compression */) ||
- !ssl_add_clienthello_tlsext(ssl, &body, header_len + CBB_len(&body))) {
+ !ssl_add_clienthello_tlsext(hs, &body, header_len + CBB_len(&body))) {
goto err;
}
@@ -715,7 +708,7 @@
/* Now that the length prefixes have been computed, fill in the placeholder
* PSK binder. */
- if (ssl->s3->hs->needs_psk_binder &&
+ if (hs->needs_psk_binder &&
!tls13_write_psk_binder(ssl, msg, len)) {
OPENSSL_free(msg);
goto err;
@@ -728,7 +721,8 @@
return 0;
}
-static int ssl3_send_client_hello(SSL *ssl) {
+static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_CW_CLNT_HELLO_B) {
return ssl->method->write_message(ssl);
}
@@ -745,18 +739,18 @@
return -1;
}
+ uint16_t max_wire_version = ssl->method->version_to_wire(max_version);
assert(ssl->state == SSL3_ST_CW_CLNT_HELLO_A);
if (!ssl->s3->have_version) {
- ssl->version = ssl->method->version_to_wire(max_version);
- /* Only set |ssl->client_version| on the initial handshake. Renegotiations,
- * although locked to a version, reuse the value. When using the plain RSA
- * key exchange, the ClientHello version is checked in the premaster secret.
- * Some servers fail when this value changes. */
- ssl->client_version = ssl->version;
+ ssl->version = max_wire_version;
+ }
- if (max_version >= TLS1_3_VERSION) {
- ssl->client_version = ssl->method->version_to_wire(TLS1_2_VERSION);
- }
+ /* Always advertise the ClientHello version from the original maximum version,
+ * even on renegotiation. The static RSA key exchange uses this field, and
+ * some servers fail when it changes across handshakes. */
+ hs->client_version = max_wire_version;
+ if (max_version >= TLS1_3_VERSION) {
+ hs->client_version = ssl->method->version_to_wire(TLS1_2_VERSION);
}
/* If the configured session has expired or was created at a disabled
@@ -781,7 +775,7 @@
return -1;
}
- if (!ssl_write_client_hello(ssl)) {
+ if (!ssl_write_client_hello(hs)) {
return -1;
}
@@ -789,7 +783,8 @@
return ssl->method->write_message(ssl);
}
-static int dtls1_get_hello_verify(SSL *ssl) {
+static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int al;
CBS hello_verify_request, cookie;
uint16_t server_version;
@@ -831,7 +826,8 @@
return -1;
}
-static int ssl3_get_server_hello(SSL *ssl) {
+static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
CERT *ct = ssl->cert;
int al = SSL_AD_INTERNAL_ERROR;
CBS server_hello, server_random, session_id;
@@ -894,10 +890,11 @@
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
ssl->state = SSL_ST_TLS13;
+ hs->do_tls13_handshake = tls13_client_handshake;
return 1;
}
- ssl_clear_tls13_state(ssl);
+ ssl_clear_tls13_state(hs);
if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_HELLO) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
@@ -930,7 +927,7 @@
/* The session wasn't resumed. Create a fresh SSL_SESSION to
* fill out. */
ssl_set_session(ssl, NULL);
- if (!ssl_get_new_session(ssl, 0 /* client */)) {
+ if (!ssl_get_new_session(hs, 0 /* client */)) {
goto f_err;
}
/* Note: session_id could be empty. */
@@ -1001,7 +998,7 @@
}
/* TLS extensions */
- if (!ssl_parse_serverhello_tlsext(ssl, &server_hello)) {
+ if (!ssl_parse_serverhello_tlsext(hs, &server_hello)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
goto err;
}
@@ -1034,7 +1031,8 @@
return -1;
}
-static int ssl3_get_server_certificate(SSL *ssl) {
+static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int ret =
ssl->method->ssl_get_message(ssl, SSL3_MT_CERTIFICATE, ssl_hash_message);
if (ret <= 0) {
@@ -1078,7 +1076,8 @@
return -1;
}
-static int ssl3_get_cert_status(SSL *ssl) {
+static int ssl3_get_cert_status(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int al;
CBS certificate_status, ocsp_response;
uint8_t status_type;
@@ -1119,7 +1118,8 @@
return -1;
}
-static int ssl3_verify_server_cert(SSL *ssl) {
+static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!ssl_verify_cert_chain(ssl, &ssl->s3->new_session->verify_result,
ssl->s3->new_session->x509_chain)) {
return -1;
@@ -1128,7 +1128,8 @@
return 1;
}
-static int ssl3_get_server_key_exchange(SSL *ssl) {
+static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int al;
EVP_PKEY *pkey = NULL;
DH *dh = NULL;
@@ -1191,7 +1192,7 @@
* empty hint. Having different capabilities is odd, so we interpret empty
* and missing as identical. */
if (CBS_len(&psk_identity_hint) != 0 &&
- !CBS_strdup(&psk_identity_hint, &ssl->s3->hs->peer_psk_identity_hint)) {
+ !CBS_strdup(&psk_identity_hint, &hs->peer_psk_identity_hint)) {
al = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
goto f_err;
@@ -1234,11 +1235,11 @@
goto err;
}
- SSL_ECDH_CTX_init_for_dhe(&ssl->s3->hs->ecdh_ctx, dh);
+ SSL_ECDH_CTX_init_for_dhe(&hs->ecdh_ctx, dh);
dh = NULL;
/* Save the peer public key for later. */
- if (!CBS_stow(&dh_Ys, &ssl->s3->hs->peer_key, &ssl->s3->hs->peer_key_len)) {
+ if (!CBS_stow(&dh_Ys, &hs->peer_key, &hs->peer_key_len)) {
goto err;
}
} else if (alg_k & SSL_kECDHE) {
@@ -1264,12 +1265,12 @@
}
/* Initialize ECDH and save the peer public key for later. */
- 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)) {
+ if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
+ !CBS_stow(&point, &hs->peer_key, &hs->peer_key_len)) {
goto err;
}
} else if (alg_k & SSL_kCECPQ1) {
- SSL_ECDH_CTX_init_for_cecpq1(&ssl->s3->hs->ecdh_ctx);
+ SSL_ECDH_CTX_init_for_cecpq1(&hs->ecdh_ctx);
CBS key;
if (!CBS_get_u16_length_prefixed(&server_key_exchange, &key)) {
al = SSL_AD_DECODE_ERROR;
@@ -1277,7 +1278,7 @@
goto f_err;
}
- if (!CBS_stow(&key, &ssl->s3->hs->peer_key, &ssl->s3->hs->peer_key_len)) {
+ if (!CBS_stow(&key, &hs->peer_key, &hs->peer_key_len)) {
goto err;
}
} else if (!(alg_k & SSL_kPSK)) {
@@ -1382,7 +1383,8 @@
return -1;
}
-static int ssl3_get_certificate_request(SSL *ssl) {
+static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int msg_ret = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message);
if (msg_ret <= 0) {
return msg_ret;
@@ -1413,8 +1415,8 @@
return -1;
}
- if (!CBS_stow(&certificate_types, &ssl->s3->hs->certificate_types,
- &ssl->s3->hs->num_certificate_types)) {
+ if (!CBS_stow(&certificate_types, &hs->certificate_types,
+ &hs->num_certificate_types)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return -1;
}
@@ -1422,7 +1424,7 @@
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
CBS supported_signature_algorithms;
if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) ||
- !tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) {
+ !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return -1;
@@ -1443,13 +1445,14 @@
return -1;
}
- 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;
+ hs->cert_request = 1;
+ sk_X509_NAME_pop_free(hs->ca_names, X509_NAME_free);
+ hs->ca_names = ca_sk;
return 1;
}
-static int ssl3_get_server_hello_done(SSL *ssl) {
+static int ssl3_get_server_hello_done(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int ret = ssl->method->ssl_get_message(ssl, SSL3_MT_SERVER_HELLO_DONE,
ssl_hash_message);
if (ret <= 0) {
@@ -1466,7 +1469,8 @@
return 1;
}
-static int ssl3_send_client_certificate(SSL *ssl) {
+static int ssl3_send_client_certificate(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_CW_CERT_A) {
/* Call cert_cb to update the certificate. */
if (ssl->cert->cert_cb) {
@@ -1496,7 +1500,7 @@
}
if (!ssl_has_certificate(ssl)) {
- ssl->s3->hs->cert_request = 0;
+ hs->cert_request = 0;
/* Without a client certificate, the handshake buffer may be released. */
ssl3_free_handshake_buffer(ssl);
@@ -1520,7 +1524,8 @@
OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned),
SIZE_T_IS_SMALLER_THAN_UNSIGNED);
-static int ssl3_send_client_key_exchange(SSL *ssl) {
+static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_CW_KEY_EXCH_B) {
return ssl->method->write_message(ssl);
}
@@ -1548,9 +1553,9 @@
char identity[PSK_MAX_IDENTITY_LEN + 1];
memset(identity, 0, sizeof(identity));
- psk_len = ssl->psk_client_callback(
- ssl, ssl->s3->hs->peer_psk_identity_hint, identity, sizeof(identity),
- psk, sizeof(psk));
+ psk_len =
+ ssl->psk_client_callback(ssl, hs->peer_psk_identity_hint, identity,
+ sizeof(identity), psk, sizeof(psk));
if (psk_len == 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
@@ -1598,8 +1603,8 @@
EVP_PKEY_free(pkey);
- pms[0] = ssl->client_version >> 8;
- pms[1] = ssl->client_version & 0xff;
+ pms[0] = hs->client_version >> 8;
+ pms[1] = hs->client_version & 0xff;
if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
goto err;
}
@@ -1627,15 +1632,14 @@
} 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->hs->ecdh_ctx, &body, &child)) {
+ if (!SSL_ECDH_CTX_add_key(&hs->ecdh_ctx, &body, &child)) {
goto err;
}
/* Compute the premaster. */
uint8_t alert;
- 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)) {
+ if (!SSL_ECDH_CTX_accept(&hs->ecdh_ctx, &child, &pms, &pms_len, &alert,
+ hs->peer_key, hs->peer_key_len)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
goto err;
}
@@ -1644,10 +1648,10 @@
}
/* The key exchange state may now be discarded. */
- 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;
+ SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+ OPENSSL_free(hs->peer_key);
+ hs->peer_key = NULL;
+ 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. */
@@ -1717,7 +1721,8 @@
return -1;
}
-static int ssl3_send_cert_verify(SSL *ssl) {
+static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_CW_CERT_VRFY_C) {
return ssl->method->write_message(ssl);
}
@@ -1731,7 +1736,7 @@
}
uint16_t signature_algorithm;
- if (!tls1_choose_signature_algorithm(ssl, &signature_algorithm)) {
+ if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) {
goto err;
}
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
@@ -1819,7 +1824,8 @@
return -1;
}
-static int ssl3_send_next_proto(SSL *ssl) {
+static int ssl3_send_next_proto(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_CW_NEXT_PROTO_B) {
return ssl->method->write_message(ssl);
}
@@ -1846,7 +1852,8 @@
return ssl->method->write_message(ssl);
}
-static int ssl3_send_channel_id(SSL *ssl) {
+static int ssl3_send_channel_id(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_CW_CHANNEL_ID_B) {
return ssl->method->write_message(ssl);
}
@@ -1875,7 +1882,8 @@
return ssl->method->write_message(ssl);
}
-static int ssl3_get_new_session_ticket(SSL *ssl) {
+static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int ret = ssl->method->ssl_get_message(ssl, SSL3_MT_NEW_SESSION_TICKET,
ssl_hash_message);
if (ret <= 0) {
@@ -1897,7 +1905,7 @@
/* RFC 5077 allows a server to change its mind and send no ticket after
* negotiating the extension. The value of |ticket_expected| is checked in
* |ssl_update_cache| so is cleared here to avoid an unnecessary update. */
- ssl->s3->hs->ticket_expected = 0;
+ hs->ticket_expected = 0;
return 1;
}
diff --git a/src/ssl/handshake_server.c b/src/ssl/handshake_server.c
index 3b66ab7..c114074 100644
--- a/src/ssl/handshake_server.c
+++ b/src/ssl/handshake_server.c
@@ -171,21 +171,22 @@
#include "../crypto/internal.h"
-static int ssl3_get_client_hello(SSL *ssl);
-static int ssl3_send_server_hello(SSL *ssl);
-static int ssl3_send_server_certificate(SSL *ssl);
-static int ssl3_send_certificate_status(SSL *ssl);
-static int ssl3_send_server_key_exchange(SSL *ssl);
-static int ssl3_send_certificate_request(SSL *ssl);
-static int ssl3_send_server_hello_done(SSL *ssl);
-static int ssl3_get_client_certificate(SSL *ssl);
-static int ssl3_get_client_key_exchange(SSL *ssl);
-static int ssl3_get_cert_verify(SSL *ssl);
-static int ssl3_get_next_proto(SSL *ssl);
-static int ssl3_get_channel_id(SSL *ssl);
-static int ssl3_send_new_session_ticket(SSL *ssl);
+static int ssl3_get_client_hello(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_hello(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_send_certificate_status(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_send_certificate_request(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs);
+static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs);
+static int ssl3_get_next_proto(SSL_HANDSHAKE *hs);
+static int ssl3_get_channel_id(SSL_HANDSHAKE *hs);
+static int ssl3_send_new_session_ticket(SSL_HANDSHAKE *hs);
-int ssl3_accept(SSL *ssl) {
+int ssl3_accept(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
uint32_t alg_a;
int ret = -1;
int state, skip = 0;
@@ -205,12 +206,6 @@
case SSL_ST_ACCEPT:
ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
- ssl->s3->hs = ssl_handshake_new(tls13_server_handshake);
- if (ssl->s3->hs == NULL) {
- ret = -1;
- goto end;
- }
-
/* Enable a write buffer. This groups handshake messages within a flight
* into a single write. */
if (!ssl_init_wbio_buffer(ssl)) {
@@ -232,7 +227,7 @@
case SSL3_ST_SR_CLNT_HELLO_C:
case SSL3_ST_SR_CLNT_HELLO_D:
case SSL3_ST_SR_CLNT_HELLO_E:
- ret = ssl3_get_client_hello(ssl);
+ ret = ssl3_get_client_hello(hs);
if (ssl->state == SSL_ST_TLS13) {
break;
}
@@ -245,7 +240,7 @@
case SSL3_ST_SW_SRVR_HELLO_A:
case SSL3_ST_SW_SRVR_HELLO_B:
- ret = ssl3_send_server_hello(ssl);
+ ret = ssl3_send_server_hello(hs);
if (ret <= 0) {
goto end;
}
@@ -259,7 +254,7 @@
case SSL3_ST_SW_CERT_A:
case SSL3_ST_SW_CERT_B:
if (ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
- ret = ssl3_send_server_certificate(ssl);
+ ret = ssl3_send_server_certificate(hs);
if (ret <= 0) {
goto end;
}
@@ -271,8 +266,8 @@
case SSL3_ST_SW_CERT_STATUS_A:
case SSL3_ST_SW_CERT_STATUS_B:
- if (ssl->s3->hs->certificate_status_expected) {
- ret = ssl3_send_certificate_status(ssl);
+ if (hs->certificate_status_expected) {
+ ret = ssl3_send_certificate_status(hs);
if (ret <= 0) {
goto end;
}
@@ -290,7 +285,7 @@
/* PSK ciphers send ServerKeyExchange if there is an identity hint. */
if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher) ||
((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
- ret = ssl3_send_server_key_exchange(ssl);
+ ret = ssl3_send_server_key_exchange(hs);
if (ret <= 0) {
goto end;
}
@@ -303,8 +298,8 @@
case SSL3_ST_SW_CERT_REQ_A:
case SSL3_ST_SW_CERT_REQ_B:
- if (ssl->s3->hs->cert_request) {
- ret = ssl3_send_certificate_request(ssl);
+ if (hs->cert_request) {
+ ret = ssl3_send_certificate_request(hs);
if (ret <= 0) {
goto end;
}
@@ -316,7 +311,7 @@
case SSL3_ST_SW_SRVR_DONE_A:
case SSL3_ST_SW_SRVR_DONE_B:
- ret = ssl3_send_server_hello_done(ssl);
+ ret = ssl3_send_server_hello_done(hs);
if (ret <= 0) {
goto end;
}
@@ -325,8 +320,8 @@
break;
case SSL3_ST_SR_CERT_A:
- if (ssl->s3->hs->cert_request) {
- ret = ssl3_get_client_certificate(ssl);
+ if (hs->cert_request) {
+ ret = ssl3_get_client_certificate(hs);
if (ret <= 0) {
goto end;
}
@@ -336,7 +331,7 @@
case SSL3_ST_SR_KEY_EXCH_A:
case SSL3_ST_SR_KEY_EXCH_B:
- ret = ssl3_get_client_key_exchange(ssl);
+ ret = ssl3_get_client_key_exchange(hs);
if (ret <= 0) {
goto end;
}
@@ -344,7 +339,7 @@
break;
case SSL3_ST_SR_CERT_VRFY_A:
- ret = ssl3_get_cert_verify(ssl);
+ ret = ssl3_get_cert_verify(hs);
if (ret <= 0) {
goto end;
}
@@ -358,7 +353,7 @@
goto end;
}
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ if (!tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_SERVER_READ)) {
ret = -1;
goto end;
}
@@ -367,8 +362,8 @@
break;
case SSL3_ST_SR_NEXT_PROTO_A:
- if (ssl->s3->hs->next_proto_neg_seen) {
- ret = ssl3_get_next_proto(ssl);
+ if (hs->next_proto_neg_seen) {
+ ret = ssl3_get_next_proto(hs);
if (ret <= 0) {
goto end;
}
@@ -380,7 +375,7 @@
case SSL3_ST_SR_CHANNEL_ID_A:
if (ssl->s3->tlsext_channel_id_valid) {
- ret = ssl3_get_channel_id(ssl);
+ ret = ssl3_get_channel_id(hs);
if (ret <= 0) {
goto end;
}
@@ -391,7 +386,7 @@
break;
case SSL3_ST_SR_FINISHED_A:
- ret = ssl3_get_finished(ssl);
+ ret = ssl3_get_finished(hs);
if (ret <= 0) {
goto end;
}
@@ -416,8 +411,8 @@
case SSL3_ST_SW_SESSION_TICKET_A:
case SSL3_ST_SW_SESSION_TICKET_B:
- if (ssl->s3->hs->ticket_expected) {
- ret = ssl3_send_new_session_ticket(ssl);
+ if (hs->ticket_expected) {
+ ret = ssl3_send_new_session_ticket(hs);
if (ret <= 0) {
goto end;
}
@@ -434,7 +429,7 @@
}
ssl->state = SSL3_ST_SW_FINISHED_A;
- if (!tls1_change_cipher_state(ssl, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
+ if (!tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
ret = -1;
goto end;
}
@@ -442,7 +437,7 @@
case SSL3_ST_SW_FINISHED_A:
case SSL3_ST_SW_FINISHED_B:
- ret = ssl3_send_finished(ssl, SSL3_ST_SW_FINISHED_A,
+ ret = ssl3_send_finished(hs, SSL3_ST_SW_FINISHED_A,
SSL3_ST_SW_FINISHED_B);
if (ret <= 0) {
goto end;
@@ -469,7 +464,7 @@
break;
case SSL_ST_TLS13:
- ret = tls13_handshake(ssl);
+ ret = tls13_handshake(hs);
if (ret <= 0) {
goto end;
}
@@ -503,10 +498,7 @@
ssl_free_wbio_buffer(ssl);
ssl->s3->initial_handshake_complete = 1;
- ssl_update_cache(ssl, SSL_SESS_CACHE_SERVER);
-
- ssl_handshake_free(ssl->s3->hs);
- ssl->s3->hs = NULL;
+ ssl_update_cache(hs, SSL_SESS_CACHE_SERVER);
ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1);
ret = 1;
@@ -532,8 +524,8 @@
return ret;
}
-int ssl_client_cipher_list_contains_cipher(
- const struct ssl_early_callback_ctx *client_hello, uint16_t id) {
+int ssl_client_cipher_list_contains_cipher(const SSL_CLIENT_HELLO *client_hello,
+ uint16_t id) {
CBS cipher_suites;
CBS_init(&cipher_suites, client_hello->cipher_suites,
client_hello->cipher_suites_len);
@@ -552,9 +544,9 @@
return 0;
}
-static int negotiate_version(
- SSL *ssl, uint8_t *out_alert,
- const struct ssl_early_callback_ctx *client_hello) {
+static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+ const SSL_CLIENT_HELLO *client_hello) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
*out_alert = SSL_AD_PROTOCOL_VERSION;
@@ -564,8 +556,8 @@
uint16_t version = 0;
/* Check supported_versions extension if it is present. */
CBS supported_versions;
- if (ssl_early_callback_get_extension(client_hello, &supported_versions,
- TLSEXT_TYPE_supported_versions)) {
+ if (ssl_client_hello_get_extension(client_hello, &supported_versions,
+ TLSEXT_TYPE_supported_versions)) {
CBS versions;
if (!CBS_get_u8_length_prefixed(&supported_versions, &versions) ||
CBS_len(&supported_versions) != 0 ||
@@ -644,7 +636,7 @@
return 0;
}
- ssl->client_version = client_hello->version;
+ hs->client_version = client_hello->version;
ssl->version = ssl->method->version_to_wire(version);
ssl->s3->enc_method = ssl3_get_enc_method(version);
assert(ssl->s3->enc_method != NULL);
@@ -661,7 +653,171 @@
return 0;
}
-static int ssl3_get_client_hello(SSL *ssl) {
+static STACK_OF(SSL_CIPHER) *
+ ssl_parse_client_cipher_list(const SSL_CLIENT_HELLO *client_hello) {
+ CBS cipher_suites;
+ CBS_init(&cipher_suites, client_hello->cipher_suites,
+ client_hello->cipher_suites_len);
+
+ STACK_OF(SSL_CIPHER) *sk = sk_SSL_CIPHER_new_null();
+ if (sk == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ while (CBS_len(&cipher_suites) > 0) {
+ uint16_t cipher_suite;
+
+ if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+ goto err;
+ }
+
+ const SSL_CIPHER *c = SSL_get_cipher_by_value(cipher_suite);
+ if (c != NULL && !sk_SSL_CIPHER_push(sk, c)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+
+ return sk;
+
+err:
+ sk_SSL_CIPHER_free(sk);
+ return NULL;
+}
+
+/* ssl_get_compatible_server_ciphers determines the key exchange and
+ * authentication cipher suite masks compatible with the server configuration
+ * and current ClientHello parameters of |hs|. It sets |*out_mask_k| to the key
+ * exchange mask and |*out_mask_a| to the authentication mask. */
+static void ssl_get_compatible_server_ciphers(SSL_HANDSHAKE *hs,
+ uint32_t *out_mask_k,
+ uint32_t *out_mask_a) {
+ SSL *const ssl = hs->ssl;
+ if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+ *out_mask_k = SSL_kGENERIC;
+ *out_mask_a = SSL_aGENERIC;
+ return;
+ }
+
+ uint32_t mask_k = 0;
+ uint32_t mask_a = 0;
+
+ if (ssl->cert->x509_leaf != NULL && ssl_has_private_key(ssl)) {
+ int type = ssl_private_key_type(ssl);
+ if (type == NID_rsaEncryption) {
+ mask_k |= SSL_kRSA;
+ mask_a |= SSL_aRSA;
+ } else if (ssl_is_ecdsa_key_type(type)) {
+ mask_a |= SSL_aECDSA;
+ }
+ }
+
+ if (ssl->cert->dh_tmp != NULL || ssl->cert->dh_tmp_cb != NULL) {
+ mask_k |= SSL_kDHE;
+ }
+
+ /* Check for a shared group to consider ECDHE ciphers. */
+ uint16_t unused;
+ if (tls1_get_shared_group(hs, &unused)) {
+ mask_k |= SSL_kECDHE;
+ }
+
+ /* CECPQ1 ciphers are always acceptable if supported by both sides. */
+ mask_k |= SSL_kCECPQ1;
+
+ /* PSK requires a server callback. */
+ if (ssl->psk_server_callback != NULL) {
+ mask_k |= SSL_kPSK;
+ mask_a |= SSL_aPSK;
+ }
+
+ *out_mask_k = mask_k;
+ *out_mask_a = mask_a;
+}
+
+static const SSL_CIPHER *ssl3_choose_cipher(
+ SSL_HANDSHAKE *hs, const SSL_CLIENT_HELLO *client_hello,
+ const struct ssl_cipher_preference_list_st *server_pref) {
+ SSL *const ssl = hs->ssl;
+ const SSL_CIPHER *c, *ret = NULL;
+ STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
+ int ok;
+ size_t cipher_index;
+ uint32_t alg_k, alg_a, mask_k, mask_a;
+ /* in_group_flags will either be NULL, or will point to an array of bytes
+ * which indicate equal-preference groups in the |prio| stack. See the
+ * comment about |in_group_flags| in the |ssl_cipher_preference_list_st|
+ * struct. */
+ const uint8_t *in_group_flags;
+ /* group_min contains the minimal index so far found in a group, or -1 if no
+ * such value exists yet. */
+ int group_min = -1;
+
+ STACK_OF(SSL_CIPHER) *clnt = ssl_parse_client_cipher_list(client_hello);
+ if (clnt == NULL) {
+ return NULL;
+ }
+
+ if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
+ prio = srvr;
+ in_group_flags = server_pref->in_group_flags;
+ allow = clnt;
+ } else {
+ prio = clnt;
+ in_group_flags = NULL;
+ allow = srvr;
+ }
+
+ ssl_get_compatible_server_ciphers(hs, &mask_k, &mask_a);
+
+ for (size_t i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
+ c = sk_SSL_CIPHER_value(prio, i);
+
+ ok = 1;
+
+ /* Check the TLS version. */
+ if (SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) ||
+ SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl)) {
+ ok = 0;
+ }
+
+ alg_k = c->algorithm_mkey;
+ alg_a = c->algorithm_auth;
+
+ ok = ok && (alg_k & mask_k) && (alg_a & mask_a);
+
+ if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c)) {
+ if (in_group_flags != NULL && in_group_flags[i] == 1) {
+ /* This element of |prio| is in a group. Update the minimum index found
+ * so far and continue looking. */
+ if (group_min == -1 || (size_t)group_min > cipher_index) {
+ group_min = cipher_index;
+ }
+ } else {
+ if (group_min != -1 && (size_t)group_min < cipher_index) {
+ cipher_index = group_min;
+ }
+ ret = sk_SSL_CIPHER_value(allow, cipher_index);
+ break;
+ }
+ }
+
+ if (in_group_flags != NULL && in_group_flags[i] == 0 && group_min != -1) {
+ /* We are about to leave a group, but we found a match in it, so that's
+ * our answer. */
+ ret = sk_SSL_CIPHER_value(allow, group_min);
+ break;
+ }
+ }
+
+ sk_SSL_CIPHER_free(clnt);
+ return ret;
+}
+
+static int ssl3_get_client_hello(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
uint8_t al = SSL_AD_INTERNAL_ERROR;
int ret = -1;
SSL_SESSION *session = NULL;
@@ -677,9 +833,9 @@
ssl->state = SSL3_ST_SR_CLNT_HELLO_B;
}
- struct ssl_early_callback_ctx client_hello;
- if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
- ssl->init_num)) {
+ SSL_CLIENT_HELLO client_hello;
+ if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+ ssl->init_num)) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
goto f_err;
@@ -711,12 +867,13 @@
/* Negotiate the protocol version if we have not done so yet. */
if (!ssl->s3->have_version) {
- if (!negotiate_version(ssl, &al, &client_hello)) {
+ if (!negotiate_version(hs, &al, &client_hello)) {
goto f_err;
}
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
ssl->state = SSL_ST_TLS13;
+ hs->do_tls13_handshake = tls13_server_handshake;
return 1;
}
}
@@ -739,7 +896,7 @@
}
/* TLS extensions. */
- if (!ssl_parse_clienthello_tlsext(ssl, &client_hello)) {
+ if (!ssl_parse_clienthello_tlsext(hs, &client_hello)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
goto err;
}
@@ -765,7 +922,7 @@
/* Negotiate the cipher suite. This must be done after |cert_cb| so the
* certificate is finalized. */
ssl->s3->tmp.new_cipher =
- ssl3_choose_cipher(ssl, &client_hello, ssl_get_cipher_preferences(ssl));
+ ssl3_choose_cipher(hs, &client_hello, ssl_get_cipher_preferences(ssl));
if (ssl->s3->tmp.new_cipher == NULL) {
al = SSL_AD_HANDSHAKE_FAILURE;
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
@@ -812,14 +969,14 @@
if (session != NULL) {
/* Use the old session. */
- ssl->s3->hs->ticket_expected = renew_ticket;
+ hs->ticket_expected = renew_ticket;
ssl->session = session;
session = NULL;
ssl->s3->session_reused = 1;
} else {
- ssl->s3->hs->ticket_expected = tickets_supported;
+ hs->ticket_expected = tickets_supported;
ssl_set_session(ssl, NULL);
- if (!ssl_get_new_session(ssl, 1 /* server */)) {
+ if (!ssl_get_new_session(hs, 1 /* server */)) {
goto err;
}
@@ -841,8 +998,8 @@
ssl->s3->new_session->cipher = ssl->s3->tmp.new_cipher;
/* On new sessions, stash the SNI value in the session. */
- if (ssl->s3->hs->hostname != NULL) {
- ssl->s3->new_session->tlsext_hostname = BUF_strdup(ssl->s3->hs->hostname);
+ if (hs->hostname != NULL) {
+ ssl->s3->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
if (ssl->s3->new_session->tlsext_hostname == NULL) {
al = SSL_AD_INTERNAL_ERROR;
goto f_err;
@@ -850,18 +1007,18 @@
}
/* Determine whether to request a client certificate. */
- ssl->s3->hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+ 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->hs->cert_request = 0;
+ 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->hs->cert_request = 0;
+ hs->cert_request = 0;
}
- if (!ssl->s3->hs->cert_request) {
+ if (!hs->cert_request) {
/* OpenSSL returns X509_V_OK when no certificates are requested. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
ssl->s3->new_session->verify_result = X509_V_OK;
@@ -870,7 +1027,7 @@
/* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was
* deferred. Complete it now. */
- if (!ssl_negotiate_alpn(ssl, &al, &client_hello)) {
+ if (!ssl_negotiate_alpn(hs, &al, &client_hello)) {
goto f_err;
}
@@ -880,7 +1037,7 @@
}
/* Release the handshake buffer if client authentication isn't required. */
- if (!ssl->s3->hs->cert_request) {
+ if (!hs->cert_request) {
ssl3_free_handshake_buffer(ssl);
}
@@ -896,7 +1053,8 @@
return ret;
}
-static int ssl3_send_server_hello(SSL *ssl) {
+static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_SW_SRVR_HELLO_B) {
return ssl->method->write_message(ssl);
}
@@ -945,7 +1103,7 @@
session->session_id_length) ||
!CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
!CBB_add_u8(&body, 0 /* no compression */) ||
- !ssl_add_serverhello_tlsext(ssl, &body) ||
+ !ssl_add_serverhello_tlsext(hs, &body) ||
!ssl_complete_message(ssl, &cbb)) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
CBB_cleanup(&cbb);
@@ -956,7 +1114,8 @@
return ssl->method->write_message(ssl);
}
-static int ssl3_send_server_certificate(SSL *ssl) {
+static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_SW_CERT_B) {
return ssl->method->write_message(ssl);
}
@@ -973,7 +1132,8 @@
return ssl->method->write_message(ssl);
}
-static int ssl3_send_certificate_status(SSL *ssl) {
+static int ssl3_send_certificate_status(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_SW_CERT_STATUS_B) {
return ssl->method->write_message(ssl);
}
@@ -995,7 +1155,8 @@
return ssl->method->write_message(ssl);
}
-static int ssl3_send_server_key_exchange(SSL *ssl) {
+static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_SW_KEY_EXCH_C) {
return ssl->method->write_message(ssl);
}
@@ -1043,19 +1204,19 @@
goto err;
}
- SSL_ECDH_CTX_init_for_dhe(&ssl->s3->hs->ecdh_ctx, dh);
+ SSL_ECDH_CTX_init_for_dhe(&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->hs->ecdh_ctx, &child)) {
+ !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) {
goto err;
}
} else if (alg_k & SSL_kECDHE) {
/* Determine the group to use. */
uint16_t group_id;
- if (!tls1_get_shared_group(ssl, &group_id)) {
+ if (!tls1_get_shared_group(hs, &group_id)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_ECDH_KEY);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
goto err;
@@ -1063,25 +1224,24 @@
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->hs->ecdh_ctx, group_id) ||
+ if (!SSL_ECDH_CTX_init(&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->hs->ecdh_ctx, &child)) {
+ !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) {
goto err;
}
} else if (alg_k & SSL_kCECPQ1) {
- SSL_ECDH_CTX_init_for_cecpq1(&ssl->s3->hs->ecdh_ctx);
+ SSL_ECDH_CTX_init_for_cecpq1(&hs->ecdh_ctx);
if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
- !SSL_ECDH_CTX_offer(&ssl->s3->hs->ecdh_ctx, &child)) {
+ !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) {
goto err;
}
} else {
assert(alg_k & SSL_kPSK);
}
- if (!CBB_finish(&cbb, &ssl->s3->hs->server_params,
- &ssl->s3->hs->server_params_len)) {
+ if (!CBB_finish(&cbb, &hs->server_params, &hs->server_params_len)) {
goto err;
}
}
@@ -1090,8 +1250,7 @@
CBB body;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_SERVER_KEY_EXCHANGE) ||
- !CBB_add_bytes(&body, ssl->s3->hs->server_params,
- ssl->s3->hs->server_params_len)) {
+ !CBB_add_bytes(&body, hs->server_params, hs->server_params_len)) {
goto err;
}
@@ -1104,7 +1263,7 @@
/* Determine the signature algorithm. */
uint16_t signature_algorithm;
- if (!tls1_choose_signature_algorithm(ssl, &signature_algorithm)) {
+ if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) {
goto err;
}
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
@@ -1130,11 +1289,13 @@
uint8_t *transcript_data;
size_t transcript_len;
if (!CBB_init(&transcript,
- 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->hs->server_params,
- ssl->s3->hs->server_params_len) ||
+ 2 * SSL3_RANDOM_SIZE + 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, hs->server_params,
+ hs->server_params_len) ||
!CBB_finish(&transcript, &transcript_data, &transcript_len)) {
CBB_cleanup(&transcript);
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
@@ -1170,9 +1331,9 @@
goto err;
}
- OPENSSL_free(ssl->s3->hs->server_params);
- ssl->s3->hs->server_params = NULL;
- ssl->s3->hs->server_params_len = 0;
+ OPENSSL_free(hs->server_params);
+ hs->server_params = NULL;
+ hs->server_params_len = 0;
ssl->state = SSL3_ST_SW_KEY_EXCH_C;
return ssl->method->write_message(ssl);
@@ -1220,7 +1381,8 @@
return 1;
}
-static int ssl3_send_certificate_request(SSL *ssl) {
+static int ssl3_send_certificate_request(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_SW_CERT_REQ_B) {
return ssl->method->write_message(ssl);
}
@@ -1261,7 +1423,8 @@
return -1;
}
-static int ssl3_send_server_hello_done(SSL *ssl) {
+static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_SW_SRVR_DONE_B) {
return ssl->method->write_message(ssl);
}
@@ -1278,8 +1441,9 @@
return ssl->method->write_message(ssl);
}
-static int ssl3_get_client_certificate(SSL *ssl) {
- assert(ssl->s3->hs->cert_request);
+static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ assert(hs->cert_request);
int msg_ret = ssl->method->ssl_get_message(ssl, -1, ssl_hash_message);
if (msg_ret <= 0) {
@@ -1377,7 +1541,8 @@
return -1;
}
-static int ssl3_get_client_key_exchange(SSL *ssl) {
+static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int al;
CBS client_key_exchange;
uint32_t alg_k;
@@ -1544,9 +1709,9 @@
/* The premaster secret must begin with |client_version|. This too must be
* checked in constant time (http://eprint.iacr.org/2003/052/). */
good &= constant_time_eq_8(decrypt_buf[padding_len],
- (unsigned)(ssl->client_version >> 8));
+ (unsigned)(hs->client_version >> 8));
good &= constant_time_eq_8(decrypt_buf[padding_len + 1],
- (unsigned)(ssl->client_version & 0xff));
+ (unsigned)(hs->client_version & 0xff));
/* Select, in constant time, either the decrypted premaster or the random
* premaster based on |good|. */
@@ -1560,8 +1725,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->hs->ecdh_ctx, &client_key_exchange,
- &peer_key) ||
+ if (!SSL_ECDH_CTX_get_key(&hs->ecdh_ctx, &client_key_exchange, &peer_key) ||
CBS_len(&client_key_exchange) != 0) {
al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
@@ -1570,7 +1734,7 @@
/* Compute the premaster. */
uint8_t alert;
- if (!SSL_ECDH_CTX_finish(&ssl->s3->hs->ecdh_ctx, &premaster_secret,
+ if (!SSL_ECDH_CTX_finish(&hs->ecdh_ctx, &premaster_secret,
&premaster_secret_len, &alert, CBS_data(&peer_key),
CBS_len(&peer_key))) {
al = alert;
@@ -1578,7 +1742,7 @@
}
/* The key exchange state may now be discarded. */
- SSL_ECDH_CTX_cleanup(&ssl->s3->hs->ecdh_ctx);
+ SSL_ECDH_CTX_cleanup(&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. */
@@ -1646,7 +1810,8 @@
return -1;
}
-static int ssl3_get_cert_verify(SSL *ssl) {
+static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int al, ret = 0;
CBS certificate_verify, signature;
X509 *peer = ssl->s3->new_session->x509_peer;
@@ -1762,7 +1927,8 @@
/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
* sets the next_proto member in s if found */
-static int ssl3_get_next_proto(SSL *ssl) {
+static int ssl3_get_next_proto(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int ret =
ssl->method->ssl_get_message(ssl, SSL3_MT_NEXT_PROTO, ssl_hash_message);
if (ret <= 0) {
@@ -1788,7 +1954,8 @@
}
/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
-static int ssl3_get_channel_id(SSL *ssl) {
+static int ssl3_get_channel_id(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int msg_ret = ssl->method->ssl_get_message(ssl, SSL3_MT_CHANNEL_ID,
ssl_dont_hash_message);
if (msg_ret <= 0) {
@@ -1802,7 +1969,8 @@
return 1;
}
-static int ssl3_send_new_session_ticket(SSL *ssl) {
+static int ssl3_send_new_session_ticket(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == SSL3_ST_SW_SESSION_TICKET_B) {
return ssl->method->write_message(ssl);
}
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 1d78ec1..995adcf 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -509,12 +509,12 @@
void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension);
-int custom_ext_add_clienthello(SSL *ssl, CBB *extensions);
-int custom_ext_parse_serverhello(SSL *ssl, int *out_alert, uint16_t value,
- const CBS *extension);
-int custom_ext_parse_clienthello(SSL *ssl, int *out_alert, uint16_t value,
- const CBS *extension);
-int custom_ext_add_serverhello(SSL *ssl, CBB *extensions);
+int custom_ext_add_clienthello(SSL_HANDSHAKE *hs, CBB *extensions);
+int custom_ext_parse_serverhello(SSL_HANDSHAKE *hs, int *out_alert,
+ uint16_t value, const CBS *extension);
+int custom_ext_parse_clienthello(SSL_HANDSHAKE *hs, int *out_alert,
+ uint16_t value, const CBS *extension);
+int custom_ext_add_serverhello(SSL_HANDSHAKE *hs, CBB *extensions);
/* Handshake hash.
@@ -798,11 +798,12 @@
/* tls13_init_key_schedule initializes the handshake hash and key derivation
* state. The cipher suite and PRF hash must have been selected at this point.
* It returns one on success and zero on error. */
-int tls13_init_key_schedule(SSL *ssl);
+int tls13_init_key_schedule(SSL_HANDSHAKE *hs);
/* tls13_advance_key_schedule incorporates |in| into the key schedule with
* HKDF-Extract. It returns one on success and zero on error. */
-int tls13_advance_key_schedule(SSL *ssl, const uint8_t *in, size_t len);
+int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
+ size_t len);
/* tls13_get_context_hash writes Hash(Handshake Context) to |out| which must
* have room for at least |EVP_MAX_MD_SIZE| bytes. On success, it returns one
@@ -810,13 +811,6 @@
* zero. */
int tls13_get_context_hash(SSL *ssl, uint8_t *out, size_t *out_len);
-enum tls_record_type_t {
- type_early_handshake,
- type_early_data,
- type_handshake,
- type_data,
-};
-
/* tls13_set_traffic_key sets the read or write traffic keys to
* |traffic_secret|. It returns one on success and zero on error. */
int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
@@ -826,7 +820,7 @@
/* tls13_set_handshake_traffic derives the handshake traffic secret and
* switches both read and write traffic to it. It returns one on success and
* zero on error. */
-int tls13_set_handshake_traffic(SSL *ssl);
+int tls13_set_handshake_traffic(SSL_HANDSHAKE *hs);
/* tls13_rotate_traffic_key derives the next read or write traffic secret. It
* returns one on success and zero on error. */
@@ -835,10 +829,10 @@
/* tls13_derive_application_secrets derives the initial application data traffic
* and exporter secrets based on the handshake transcripts and |master_secret|.
* It returns one on success and zero on error. */
-int tls13_derive_application_secrets(SSL *ssl);
+int tls13_derive_application_secrets(SSL_HANDSHAKE *hs);
/* tls13_derive_resumption_secret derives the |resumption_secret|. */
-int tls13_derive_resumption_secret(SSL *ssl);
+int tls13_derive_resumption_secret(SSL_HANDSHAKE *hs);
/* tls13_export_keying_material provides an exporter interface to use the
* |exporter_secret|. */
@@ -851,7 +845,8 @@
* the integrity of the Finished message, and stores the result in |out| and
* length in |out_len|. |is_server| is 1 if this is for the Server Finished and
* 0 for the Client Finished. */
-int tls13_finished_mac(SSL *ssl, uint8_t *out, size_t *out_len, int is_server);
+int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out,
+ size_t *out_len, int is_server);
/* tls13_write_psk_binder calculates the PSK binder value and replaces the last
* bytes of |msg| with the resulting value. It returns 1 on success, and 0 on
@@ -878,15 +873,18 @@
ssl_hs_private_key_operation,
};
-typedef struct ssl_handshake_st {
- /* wait contains the operation |do_handshake| is currently blocking on or
- * |ssl_hs_ok| if none. */
- enum ssl_hs_wait_t wait;
+struct ssl_handshake_st {
+ /* ssl is a non-owning pointer to the parent |SSL| object. */
+ SSL *ssl;
- /* do_handshake runs the handshake. On completion, it returns |ssl_hs_ok|.
- * Otherwise, it returns a value corresponding to what operation is needed to
- * progress. */
- enum ssl_hs_wait_t (*do_handshake)(SSL *ssl);
+ /* do_tls13_handshake runs the TLS 1.3 handshake. On completion, it returns
+ * |ssl_hs_ok|. Otherwise, it returns a value corresponding to what operation
+ * is needed to progress. */
+ enum ssl_hs_wait_t (*do_tls13_handshake)(SSL_HANDSHAKE *hs);
+
+ /* wait contains the operation |do_tls13_handshake| is currently blocking on
+ * or |ssl_hs_ok| if none. */
+ enum ssl_hs_wait_t wait;
int state;
@@ -916,26 +914,13 @@
uint16_t received;
} custom_extensions;
- /* ecdh_ctx is the current ECDH instance. */
- SSL_ECDH_CTX ecdh_ctx;
-
- /* scts_requested is one if the SCT extension is in the ClientHello. */
- unsigned scts_requested:1;
-
- /* needs_psk_binder if the ClientHello has a placeholder PSK binder to be
- * filled in. */
- unsigned needs_psk_binder:1;
-
- unsigned received_hello_retry_request:1;
-
- /* accept_psk_mode stores whether the client's PSK mode is compatible with our
- * preferences. */
- unsigned accept_psk_mode:1;
-
/* retry_group is the group ID selected by the server in HelloRetryRequest in
* TLS 1.3. */
uint16_t retry_group;
+ /* ecdh_ctx is the current ECDH instance. */
+ SSL_ECDH_CTX ecdh_ctx;
+
/* cookie is the value of the cookie received from the server, if any. */
uint8_t *cookie;
size_t cookie_len;
@@ -972,10 +957,43 @@
uint8_t *server_params;
size_t server_params_len;
+ /* 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;
+
+ /* hostname, on the server, is the value of the SNI extension. */
+ char *hostname;
+
+ /* key_block is the record-layer key block for TLS 1.2 and earlier. */
+ uint8_t *key_block;
+ uint8_t key_block_len;
+
/* session_tickets_sent, in TLS 1.3, is the number of tickets the server has
* sent. */
uint8_t session_tickets_sent;
+ /* scts_requested is one if the SCT extension is in the ClientHello. */
+ unsigned scts_requested:1;
+
+ /* needs_psk_binder if the ClientHello has a placeholder PSK binder to be
+ * filled in. */
+ unsigned needs_psk_binder:1;
+
+ unsigned received_hello_retry_request:1;
+
+ /* accept_psk_mode stores whether the client's PSK mode is compatible with our
+ * preferences. */
+ unsigned accept_psk_mode:1;
+
/* cert_request is one if a client certificate was requested and zero
* otherwise. */
unsigned cert_request:1;
@@ -1003,40 +1021,23 @@
* or received. */
unsigned ticket_expected: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;
+ /* client_version is the value sent or received in the ClientHello version. */
+ uint16_t client_version;
+} /* SSL_HANDSHAKE */;
- /* 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;
-
- /* key_block is the record-layer key block for TLS 1.2 and earlier. */
- uint8_t *key_block;
- uint8_t key_block_len;
-
- /* hostname, on the server, is the value of the SNI extension. */
- char *hostname;
-} SSL_HANDSHAKE;
-
-SSL_HANDSHAKE *ssl_handshake_new(enum ssl_hs_wait_t (*do_handshake)(SSL *ssl));
+SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl);
/* ssl_handshake_free releases all memory associated with |hs|. */
void ssl_handshake_free(SSL_HANDSHAKE *hs);
/* tls13_handshake runs the TLS 1.3 handshake. It returns one on success and <=
* 0 on error. */
-int tls13_handshake(SSL *ssl);
+int tls13_handshake(SSL_HANDSHAKE *hs);
-/* The following are implementations of |do_handshake| for the client and
+/* The following are implementations of |do_tls13_handshake| for the client and
* server. */
-enum ssl_hs_wait_t tls13_client_handshake(SSL *ssl);
-enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl);
+enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs);
+enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs);
/* tls13_post_handshake processes a post-handshake message. It returns one on
* success and zero on failure. */
@@ -1048,40 +1049,40 @@
int tls13_process_certificate(SSL *ssl, int allow_anonymous);
int tls13_process_certificate_verify(SSL *ssl);
-int tls13_process_finished(SSL *ssl);
+int tls13_process_finished(SSL_HANDSHAKE *hs);
-int tls13_prepare_certificate(SSL *ssl);
+int tls13_prepare_certificate(SSL_HANDSHAKE *hs);
enum ssl_private_key_result_t tls13_prepare_certificate_verify(
- SSL *ssl, int is_first_run);
-int tls13_prepare_finished(SSL *ssl);
+ SSL_HANDSHAKE *hs, int is_first_run);
+int tls13_prepare_finished(SSL_HANDSHAKE *hs);
int tls13_process_new_session_ticket(SSL *ssl);
-int ssl_ext_key_share_parse_serverhello(SSL *ssl, uint8_t **out_secret,
+int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t **out_secret,
size_t *out_secret_len,
uint8_t *out_alert, CBS *contents);
-int ssl_ext_key_share_parse_clienthello(SSL *ssl, int *out_found,
+int ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, int *out_found,
uint8_t **out_secret,
size_t *out_secret_len,
uint8_t *out_alert, CBS *contents);
-int ssl_ext_key_share_add_serverhello(SSL *ssl, CBB *out);
+int ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out);
-int ssl_ext_pre_shared_key_parse_serverhello(SSL *ssl, uint8_t *out_alert,
- CBS *contents);
-int ssl_ext_pre_shared_key_parse_clienthello(SSL *ssl,
+int ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert, CBS *contents);
+int ssl_ext_pre_shared_key_parse_clienthello(SSL_HANDSHAKE *hs,
SSL_SESSION **out_session,
CBS *out_binders,
uint8_t *out_alert, CBS *contents);
-int ssl_ext_pre_shared_key_add_serverhello(SSL *ssl, CBB *out);
+int ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE *hs, CBB *out);
/* ssl_is_sct_list_valid does a shallow parse of the SCT list in |contents| and
* returns one iff it's valid. */
int ssl_is_sct_list_valid(const CBS *contents);
-int ssl_write_client_hello(SSL *ssl);
+int ssl_write_client_hello(SSL_HANDSHAKE *hs);
/* ssl_clear_tls13_state releases client state only needed for TLS 1.3. It
* should be called once the version is known to be TLS 1.2 or earlier. */
-void ssl_clear_tls13_state(SSL *ssl);
+void ssl_clear_tls13_state(SSL_HANDSHAKE *hs);
enum ssl_cert_verify_context_t {
ssl_cert_verify_server,
@@ -1101,8 +1102,8 @@
/* ssl_negotiate_alpn negotiates the ALPN extension, if applicable. It returns
* one on successful negotiation or if nothing was negotiated. It returns zero
* and sets |*out_alert| to an alert on error. */
-int ssl_negotiate_alpn(SSL *ssl, uint8_t *out_alert,
- const struct ssl_early_callback_ctx *client_hello);
+int ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+ const SSL_CLIENT_HELLO *client_hello);
typedef struct {
uint16_t type;
@@ -1139,17 +1140,14 @@
/* ClientHello functions. */
-int ssl_early_callback_init(SSL *ssl, struct ssl_early_callback_ctx *ctx,
- const uint8_t *in, size_t in_len);
+int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out, const uint8_t *in,
+ size_t in_len);
-int ssl_early_callback_get_extension(const struct ssl_early_callback_ctx *ctx,
- CBS *out, uint16_t extension_type);
+int ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
+ CBS *out, uint16_t extension_type);
-STACK_OF(SSL_CIPHER) *
- ssl_parse_client_cipher_list(const struct ssl_early_callback_ctx *ctx);
-
-int ssl_client_cipher_list_contains_cipher(
- const struct ssl_early_callback_ctx *client_hello, uint16_t id);
+int ssl_client_cipher_list_contains_cipher(const SSL_CLIENT_HELLO *client_hello,
+ uint16_t id);
/* GREASE. */
@@ -1173,13 +1171,14 @@
/* 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);
+ * algorithms and saves them on |hs|. It returns one on success and zero on
+ * error. */
+int tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, 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
+ * with |hs|'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);
+int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, 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. */
@@ -1381,18 +1380,6 @@
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. */
@@ -1424,10 +1411,13 @@
enum ssl_shutdown_t send_shutdown;
int alert_dispatch;
- uint8_t send_alert[2];
int total_renegotiations;
+ /* early_data_skipped is the amount of early data that has been skipped by the
+ * record layer. */
+ uint16_t early_data_skipped;
+
/* empty_record_count is the number of consecutive empty records received. */
uint8_t empty_record_count;
@@ -1438,6 +1428,39 @@
/* key_update_count is the number of consecutive KeyUpdates received. */
uint8_t key_update_count;
+ /* skip_early_data instructs the record layer to skip unexpected early data
+ * messages when 0RTT is rejected. */
+ unsigned skip_early_data:1;
+
+ /* 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;
+
+ /* session_reused indicates whether a session was resumed. */
+ unsigned session_reused:1;
+
+ unsigned send_connection_binding:1;
+
+ /* 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. */
+ unsigned tlsext_channel_id_valid:1;
+
+ uint8_t send_alert[2];
+
+ /* pending_message is the current outgoing handshake message. */
+ uint8_t *pending_message;
+ uint32_t pending_message_len;
+
/* aead_read_ctx is the current read cipher state. */
SSL_AEAD_CTX *aead_read_ctx;
@@ -1448,31 +1471,33 @@
* 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 write_traffic_secret_len;
+ uint8_t read_traffic_secret_len;
uint8_t exporter_secret_len;
+ /* Connection binding to prevent renegotiation attacks */
+ uint8_t previous_client_finished[12];
+ uint8_t previous_client_finished_len;
+ uint8_t previous_server_finished_len;
+ uint8_t previous_server_finished[12];
+
/* 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;
+ int message_type;
+
/* used when SSL_ST_FLUSH_DATA is entered */
int next_state;
@@ -1504,16 +1529,6 @@
* 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.
*
@@ -1532,11 +1547,6 @@
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
@@ -1642,7 +1652,7 @@
CERT *ssl_cert_dup(CERT *cert);
void ssl_cert_clear_certs(CERT *c);
void ssl_cert_free(CERT *c);
-int ssl_get_new_session(SSL *ssl, int is_server);
+int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server);
int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session);
/* ssl_session_is_context_valid returns one if |session|'s session ID context
@@ -1665,14 +1675,14 @@
ssl_session_retry,
};
-/* ssl_get_prev_session looks up the previous session based on |ctx|. On
- * success, it sets |*out_session| to the session or NULL if none was found. If
- * the session could not be looked up synchronously, it returns
+/* ssl_get_prev_session looks up the previous session based on |client_hello|.
+ * On success, it sets |*out_session| to the session or NULL if none was found.
+ * If the session could not be looked up synchronously, it returns
* |ssl_session_retry| and should be called again. Otherwise, it returns
* |ssl_session_error|. */
enum ssl_session_result_t ssl_get_prev_session(
SSL *ssl, SSL_SESSION **out_session, int *out_tickets_supported,
- int *out_renew_ticket, const struct ssl_early_callback_ctx *ctx);
+ int *out_renew_ticket, const SSL_CLIENT_HELLO *client_hello);
/* The following flags determine which parts of the session are duplicated. */
#define SSL_SESSION_DUP_AUTH_ONLY 0x0
@@ -1699,27 +1709,13 @@
const struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(
const SSL *ssl);
-int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain);
-int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain);
-int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509);
-int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509);
-void ssl_cert_set_cert_cb(CERT *cert,
- int (*cb)(SSL *ssl, void *arg), void *arg);
-
int ssl_verify_cert_chain(SSL *ssl, long *out_verify_result,
STACK_OF(X509) * cert_chain);
-void ssl_update_cache(SSL *ssl, int mode);
-
-/* ssl_get_compatible_server_ciphers determines the key exchange and
- * authentication cipher suite masks compatible with the server configuration
- * and current ClientHello parameters of |ssl|. It sets |*out_mask_k| to the key
- * exchange mask and |*out_mask_a| to the authentication mask. */
-void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k,
- uint32_t *out_mask_a);
+void ssl_update_cache(SSL_HANDSHAKE *hs, int mode);
int ssl_verify_alarm_type(long type);
-int ssl3_get_finished(SSL *ssl);
+int ssl3_get_finished(SSL_HANDSHAKE *hs);
int ssl3_send_change_cipher_spec(SSL *ssl);
int ssl3_send_alert(SSL *ssl, int level, int desc);
int ssl3_get_message(SSL *ssl, int msg_type,
@@ -1734,8 +1730,7 @@
int ssl3_cert_verify_hash(SSL *ssl, const EVP_MD **out_md, uint8_t *out,
size_t *out_len, uint16_t signature_algorithm);
-int ssl3_send_finished(SSL *ssl, int a, int b);
-int ssl3_supports_cipher(const SSL_CIPHER *cipher);
+int ssl3_send_finished(SSL_HANDSHAKE *hs, int a, int b);
int ssl3_dispatch_alert(SSL *ssl);
int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
int peek);
@@ -1746,23 +1741,16 @@
int ssl3_write_bytes(SSL *ssl, int type, const void *buf, int len);
int ssl3_output_cert_chain(SSL *ssl);
-const SSL_CIPHER *ssl3_choose_cipher(
- SSL *ssl, const struct ssl_early_callback_ctx *client_hello,
- const struct ssl_cipher_preference_list_st *srvr);
-
int ssl3_new(SSL *ssl);
void ssl3_free(SSL *ssl);
-int ssl3_accept(SSL *ssl);
-int ssl3_connect(SSL *ssl);
+int ssl3_accept(SSL_HANDSHAKE *hs);
+int ssl3_connect(SSL_HANDSHAKE *hs);
int ssl3_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
int ssl3_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
int ssl3_queue_message(SSL *ssl, uint8_t *msg, size_t len);
int ssl3_write_message(SSL *ssl);
-void ssl3_expect_flight(SSL *ssl);
-void ssl3_received_flight(SSL *ssl);
-
int dtls1_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
int dtls1_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
size_t *out_len);
@@ -1802,10 +1790,7 @@
CBS *out_body);
int dtls1_check_timeout_num(SSL *ssl);
int dtls1_handshake_write(SSL *ssl);
-void dtls1_expect_flight(SSL *ssl);
-void dtls1_received_flight(SSL *ssl);
-int dtls1_supports_cipher(const SSL_CIPHER *cipher);
void dtls1_start_timer(SSL *ssl);
void dtls1_stop_timer(SSL *ssl);
int dtls1_is_timer_expired(SSL *ssl);
@@ -1829,7 +1814,7 @@
int ssl_init_wbio_buffer(SSL *ssl);
void ssl_free_wbio_buffer(SSL *ssl);
-int tls1_change_cipher_state(SSL *ssl, int which);
+int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which);
int tls1_handshake_digest(SSL *ssl, uint8_t *out, size_t out_len);
int tls1_generate_master_secret(SSL *ssl, uint8_t *out, const uint8_t *premaster,
size_t premaster_len);
@@ -1846,7 +1831,7 @@
/* tls1_get_shared_group sets |*out_group_id| to the first preferred shared
* group between client and server preferences and returns one. If none may be
* found, it returns zero. */
-int tls1_get_shared_group(SSL *ssl, uint16_t *out_group_id);
+int tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id);
/* tls1_set_curves converts the array of |ncurves| NIDs pointed to by |curves|
* into a newly allocated array of TLS group IDs. On success, the function
@@ -1866,12 +1851,12 @@
* 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
* length. (It does not include the record header.) */
-int ssl_add_clienthello_tlsext(SSL *ssl, CBB *out, size_t header_len);
+int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len);
-int ssl_add_serverhello_tlsext(SSL *ssl, CBB *out);
-int ssl_parse_clienthello_tlsext(
- SSL *ssl, const struct ssl_early_callback_ctx *client_hello);
-int ssl_parse_serverhello_tlsext(SSL *ssl, CBS *cbs);
+int ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out);
+int ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs,
+ const SSL_CLIENT_HELLO *client_hello);
+int ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs);
#define tlsext_tick_md EVP_sha256
diff --git a/src/ssl/s3_both.c b/src/ssl/s3_both.c
index d872020..d775cca 100644
--- a/src/ssl/s3_both.c
+++ b/src/ssl/s3_both.c
@@ -130,14 +130,14 @@
#include "internal.h"
-SSL_HANDSHAKE *ssl_handshake_new(enum ssl_hs_wait_t (*do_handshake)(SSL *ssl)) {
+SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) {
SSL_HANDSHAKE *hs = OPENSSL_malloc(sizeof(SSL_HANDSHAKE));
if (hs == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return NULL;
}
memset(hs, 0, sizeof(SSL_HANDSHAKE));
- hs->do_handshake = do_handshake;
+ hs->ssl = ssl;
hs->wait = ssl_hs_ok;
return hs;
}
@@ -260,7 +260,8 @@
return 1;
}
-int ssl3_send_finished(SSL *ssl, int a, int b) {
+int ssl3_send_finished(SSL_HANDSHAKE *hs, int a, int b) {
+ SSL *const ssl = hs->ssl;
if (ssl->state == b) {
return ssl->method->write_message(ssl);
}
@@ -309,7 +310,8 @@
return ssl->method->write_message(ssl);
}
-int ssl3_get_finished(SSL *ssl) {
+int ssl3_get_finished(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int ret = ssl->method->ssl_get_message(ssl, SSL3_MT_FINISHED,
ssl_dont_hash_message);
if (ret <= 0) {
diff --git a/src/ssl/s3_lib.c b/src/ssl/s3_lib.c
index 901b8af..1aad8e6 100644
--- a/src/ssl/s3_lib.c
+++ b/src/ssl/s3_lib.c
@@ -162,14 +162,6 @@
#include "internal.h"
-int ssl3_supports_cipher(const SSL_CIPHER *cipher) {
- return 1;
-}
-
-void ssl3_expect_flight(SSL *ssl) {}
-
-void ssl3_received_flight(SSL *ssl) {}
-
int ssl3_new(SSL *ssl) {
SSL3_STATE *s3;
@@ -240,84 +232,6 @@
return NULL;
}
-const SSL_CIPHER *ssl3_choose_cipher(
- SSL *ssl, const struct ssl_early_callback_ctx *client_hello,
- const struct ssl_cipher_preference_list_st *server_pref) {
- const SSL_CIPHER *c, *ret = NULL;
- STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
- int ok;
- size_t cipher_index;
- uint32_t alg_k, alg_a, mask_k, mask_a;
- /* in_group_flags will either be NULL, or will point to an array of bytes
- * which indicate equal-preference groups in the |prio| stack. See the
- * comment about |in_group_flags| in the |ssl_cipher_preference_list_st|
- * struct. */
- const uint8_t *in_group_flags;
- /* group_min contains the minimal index so far found in a group, or -1 if no
- * such value exists yet. */
- int group_min = -1;
-
- STACK_OF(SSL_CIPHER) *clnt = ssl_parse_client_cipher_list(client_hello);
- if (clnt == NULL) {
- return NULL;
- }
-
- if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
- prio = srvr;
- in_group_flags = server_pref->in_group_flags;
- allow = clnt;
- } else {
- prio = clnt;
- in_group_flags = NULL;
- allow = srvr;
- }
-
- ssl_get_compatible_server_ciphers(ssl, &mask_k, &mask_a);
-
- for (size_t i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
- c = sk_SSL_CIPHER_value(prio, i);
-
- ok = 1;
-
- /* Check the TLS version. */
- if (SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) ||
- SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl)) {
- ok = 0;
- }
-
- alg_k = c->algorithm_mkey;
- alg_a = c->algorithm_auth;
-
- ok = ok && (alg_k & mask_k) && (alg_a & mask_a);
-
- if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c)) {
- if (in_group_flags != NULL && in_group_flags[i] == 1) {
- /* This element of |prio| is in a group. Update the minimum index found
- * so far and continue looking. */
- if (group_min == -1 || (size_t)group_min > cipher_index) {
- group_min = cipher_index;
- }
- } else {
- if (group_min != -1 && (size_t)group_min < cipher_index) {
- cipher_index = group_min;
- }
- ret = sk_SSL_CIPHER_value(allow, cipher_index);
- break;
- }
- }
-
- if (in_group_flags != NULL && in_group_flags[i] == 0 && group_min != -1) {
- /* We are about to leave a group, but we found a match in it, so that's
- * our answer. */
- ret = sk_SSL_CIPHER_value(allow, group_min);
- break;
- }
- }
-
- sk_SSL_CIPHER_free(clnt);
- return ret;
-}
-
/* If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and
* handshake macs if required. */
uint32_t ssl_get_algorithm_prf(const SSL *ssl) {
diff --git a/src/ssl/ssl_asn1.c b/src/ssl/ssl_asn1.c
index 2a7b7d4..aab6052 100644
--- a/src/ssl/ssl_asn1.c
+++ b/src/ssl/ssl_asn1.c
@@ -473,7 +473,7 @@
/* SSL_SESSION_parse_bounded_octet_string parses an optional ASN.1 OCTET STRING
* explicitly tagged with |tag| of size at most |max_out|. */
static int SSL_SESSION_parse_bounded_octet_string(
- CBS *cbs, uint8_t *out, unsigned *out_len, unsigned max_out, unsigned tag) {
+ CBS *cbs, uint8_t *out, uint8_t *out_len, uint8_t max_out, unsigned tag) {
CBS value;
if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag) ||
CBS_len(&value) > max_out) {
@@ -481,7 +481,7 @@
return 0;
}
memcpy(out, CBS_data(&value), CBS_len(&value));
- *out_len = (unsigned)CBS_len(&value);
+ *out_len = (uint8_t)CBS_len(&value);
return 1;
}
diff --git a/src/ssl/ssl_cert.c b/src/ssl/ssl_cert.c
index 7f6cf63..c0bdb5c 100644
--- a/src/ssl/ssl_cert.c
+++ b/src/ssl/ssl_cert.c
@@ -244,13 +244,13 @@
OPENSSL_free(c);
}
-int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
+static int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
sk_X509_pop_free(cert->x509_chain, X509_free);
cert->x509_chain = chain;
return 1;
}
-int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain) {
+static int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain) {
STACK_OF(X509) *dchain;
if (chain == NULL) {
return ssl_cert_set0_chain(cert, NULL);
@@ -269,7 +269,7 @@
return 1;
}
-int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509) {
+static int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509) {
if (cert->x509_chain == NULL) {
cert->x509_chain = sk_X509_new_null();
}
@@ -280,7 +280,7 @@
return 1;
}
-int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509) {
+static int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509) {
if (!ssl_cert_add0_chain_cert(cert, x509)) {
return 0;
}
@@ -289,7 +289,8 @@
return 1;
}
-void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) {
+static void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg),
+ void *arg) {
c->cert_cb = cb;
c->cert_cb_arg = arg;
}
@@ -775,6 +776,15 @@
return SSL_set0_chain(ssl, NULL);
}
+void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
+ void *arg) {
+ ssl_cert_set_cert_cb(ctx->cert, cb, arg);
+}
+
+void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
+ ssl_cert_set_cert_cb(ssl->cert, cb, arg);
+}
+
int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) {
*out_chain = ctx->cert->x509_chain;
return 1;
diff --git a/src/ssl/ssl_lib.c b/src/ssl/ssl_lib.c
index 70a39ea..b0c0906 100644
--- a/src/ssl/ssl_lib.c
+++ b/src/ssl/ssl_lib.c
@@ -477,6 +477,13 @@
ssl->ctx->signed_cert_timestamps_enabled;
ssl->ocsp_stapling_enabled = ssl->ctx->ocsp_stapling_enabled;
+ ssl->session_timeout = SSL_DEFAULT_SESSION_TIMEOUT;
+
+ /* If the context has a default timeout, use it over the default. */
+ if (ctx->session_timeout != 0) {
+ ssl->session_timeout = ctx->session_timeout;
+ }
+
return ssl;
err:
@@ -617,7 +624,28 @@
return 1;
}
- return ssl->handshake_func(ssl);
+ /* Set up a new handshake if necessary. */
+ if (ssl->state == SSL_ST_INIT && ssl->s3->hs == NULL) {
+ ssl->s3->hs = ssl_handshake_new(ssl);
+ if (ssl->s3->hs == NULL) {
+ return -1;
+ }
+ }
+
+ /* Run the handshake. */
+ assert(ssl->s3->hs != NULL);
+ int ret = ssl->handshake_func(ssl->s3->hs);
+ if (ret <= 0) {
+ return ret;
+ }
+
+ /* Destroy the handshake object if the handshake has completely finished. */
+ if (!SSL_in_init(ssl)) {
+ ssl_handshake_free(ssl->s3->hs);
+ ssl->s3->hs = NULL;
+ }
+
+ return 1;
}
int SSL_connect(SSL *ssl) {
@@ -1106,24 +1134,28 @@
}
int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const uint8_t *sid_ctx,
- unsigned sid_ctx_len) {
+ size_t sid_ctx_len) {
if (sid_ctx_len > sizeof(ctx->sid_ctx)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
}
- ctx->sid_ctx_length = sid_ctx_len;
+
+ assert(sizeof(ctx->sid_ctx) < 256);
+ ctx->sid_ctx_length = (uint8_t)sid_ctx_len;
memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len);
return 1;
}
int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
- unsigned sid_ctx_len) {
- if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
+ size_t sid_ctx_len) {
+ if (sid_ctx_len > sizeof(ssl->sid_ctx)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
}
- ssl->sid_ctx_length = sid_ctx_len;
+
+ assert(sizeof(ssl->sid_ctx) < 256);
+ ssl->sid_ctx_length = (uint8_t)sid_ctx_len;
memcpy(ssl->sid_ctx, sid_ctx, sid_ctx_len);
return 1;
@@ -1664,39 +1696,6 @@
return 1;
}
-STACK_OF(SSL_CIPHER) *
- ssl_parse_client_cipher_list(const struct ssl_early_callback_ctx *ctx) {
- CBS cipher_suites;
- CBS_init(&cipher_suites, ctx->cipher_suites, ctx->cipher_suites_len);
-
- STACK_OF(SSL_CIPHER) *sk = sk_SSL_CIPHER_new_null();
- if (sk == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
-
- while (CBS_len(&cipher_suites) > 0) {
- uint16_t cipher_suite;
-
- if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
- goto err;
- }
-
- const SSL_CIPHER *c = SSL_get_cipher_by_value(cipher_suite);
- if (c != NULL && !sk_SSL_CIPHER_push(sk, c)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- }
-
- return sk;
-
-err:
- sk_SSL_CIPHER_free(sk);
- return NULL;
-}
-
const char *SSL_get_servername(const SSL *ssl, const int type) {
if (type != TLSEXT_NAMETYPE_host_name) {
return NULL;
@@ -1942,13 +1941,21 @@
}
+void SSL_CTX_set_tls_channel_id_enabled(SSL_CTX *ctx, int enabled) {
+ ctx->tlsext_channel_id_enabled = !!enabled;
+}
+
int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx) {
- ctx->tlsext_channel_id_enabled = 1;
+ SSL_CTX_set_tls_channel_id_enabled(ctx, 1);
return 1;
}
+void SSL_set_tls_channel_id_enabled(SSL *ssl, int enabled) {
+ ssl->tlsext_channel_id_enabled = !!enabled;
+}
+
int SSL_enable_tls_channel_id(SSL *ssl) {
- ssl->tlsext_channel_id_enabled = 1;
+ SSL_set_tls_channel_id_enabled(ssl, 1);
return 1;
}
@@ -2013,15 +2020,6 @@
X509_VERIFY_PARAM_set_depth(ctx->param, depth);
}
-void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
- void *arg) {
- ssl_cert_set_cert_cb(ctx->cert, cb, arg);
-}
-
-void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
- ssl_cert_set_cert_cb(ssl->cert, cb, arg);
-}
-
size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) {
if (ssl->server || ssl->s3->hs == NULL) {
*out_types = NULL;
@@ -2031,51 +2029,8 @@
return ssl->s3->hs->num_certificate_types;
}
-void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k,
- uint32_t *out_mask_a) {
- if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
- *out_mask_k = SSL_kGENERIC;
- *out_mask_a = SSL_aGENERIC;
- return;
- }
-
- uint32_t mask_k = 0;
- uint32_t mask_a = 0;
-
- if (ssl->cert->x509_leaf != NULL && ssl_has_private_key(ssl)) {
- int type = ssl_private_key_type(ssl);
- if (type == NID_rsaEncryption) {
- mask_k |= SSL_kRSA;
- mask_a |= SSL_aRSA;
- } else if (ssl_is_ecdsa_key_type(type)) {
- mask_a |= SSL_aECDSA;
- }
- }
-
- if (ssl->cert->dh_tmp != NULL || ssl->cert->dh_tmp_cb != NULL) {
- mask_k |= SSL_kDHE;
- }
-
- /* Check for a shared group to consider ECDHE ciphers. */
- uint16_t unused;
- if (tls1_get_shared_group(ssl, &unused)) {
- mask_k |= SSL_kECDHE;
- }
-
- /* CECPQ1 ciphers are always acceptable if supported by both sides. */
- mask_k |= SSL_kCECPQ1;
-
- /* PSK requires a server callback. */
- if (ssl->psk_server_callback != NULL) {
- mask_k |= SSL_kPSK;
- mask_a |= SSL_aPSK;
- }
-
- *out_mask_k = mask_k;
- *out_mask_a = mask_a;
-}
-
-void ssl_update_cache(SSL *ssl, int mode) {
+void ssl_update_cache(SSL_HANDSHAKE *hs, int mode) {
+ SSL *const ssl = hs->ssl;
SSL_CTX *ctx = ssl->initial_ctx;
/* Never cache sessions with empty session IDs. */
if (ssl->s3->established_session->session_id_length == 0 ||
@@ -2091,7 +2046,7 @@
* decides to renew the ticket. Once the handshake is completed, it should be
* inserted into the cache. */
if (ssl->s3->established_session != ssl->session ||
- (!ssl->server && ssl->s3->hs->ticket_expected)) {
+ (!ssl->server && hs->ticket_expected)) {
if (use_internal_cache) {
SSL_CTX_add_session(ctx, ssl->s3->established_session);
}
@@ -2813,13 +2768,13 @@
int SSL_is_dtls(const SSL *ssl) { return ssl->method->is_dtls; }
-void SSL_CTX_set_select_certificate_cb(
- SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *)) {
+void SSL_CTX_set_select_certificate_cb(SSL_CTX *ctx,
+ int (*cb)(const SSL_CLIENT_HELLO *)) {
ctx->select_certificate_cb = cb;
}
-void SSL_CTX_set_dos_protection_cb(
- SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *)) {
+void SSL_CTX_set_dos_protection_cb(SSL_CTX *ctx,
+ int (*cb)(const SSL_CLIENT_HELLO *)) {
ctx->dos_protection_cb = cb;
}
@@ -2827,11 +2782,6 @@
ssl->renegotiate_mode = mode;
}
-void SSL_set_reject_peer_renegotiations(SSL *ssl, int reject) {
- SSL_set_renegotiate_mode(
- ssl, reject ? ssl_renegotiate_never : ssl_renegotiate_freely);
-}
-
int SSL_get_ivs(const SSL *ssl, const uint8_t **out_read_iv,
const uint8_t **out_write_iv, size_t *out_iv_len) {
if (ssl->s3->aead_read_ctx == NULL || ssl->s3->aead_write_ctx == NULL) {
@@ -2922,9 +2872,13 @@
}
int SSL_clear(SSL *ssl) {
- if (ssl->method == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_METHOD_SPECIFIED);
- return 0;
+ /* In OpenSSL, reusing a client |SSL| with |SSL_clear| causes the previously
+ * established session to be offered the next time around. wpa_supplicant
+ * depends on this behavior, so emulate it. */
+ SSL_SESSION *session = NULL;
+ if (!ssl->server && ssl->s3->established_session != NULL) {
+ session = ssl->s3->established_session;
+ SSL_SESSION_up_ref(session);
}
/* TODO(davidben): Some state on |ssl| is reset both in |SSL_new| and
@@ -2952,6 +2906,7 @@
ssl->method->ssl_free(ssl);
if (!ssl->method->ssl_new(ssl)) {
+ SSL_SESSION_free(session);
return 0;
}
@@ -2959,7 +2914,10 @@
ssl->d1->mtu = mtu;
}
- ssl->client_version = ssl->version;
+ if (session != NULL) {
+ SSL_set_session(ssl, session);
+ SSL_SESSION_free(session);
+ }
return 1;
}
diff --git a/src/ssl/ssl_session.c b/src/ssl/ssl_session.c
index a6b669d..67e809d 100644
--- a/src/ssl/ssl_session.c
+++ b/src/ssl/ssl_session.c
@@ -392,13 +392,14 @@
}
int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx,
- unsigned sid_ctx_len) {
- if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
+ size_t sid_ctx_len) {
+ if (sid_ctx_len > sizeof(session->sid_ctx)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
}
- session->sid_ctx_length = sid_ctx_len;
+ assert(sizeof(session->sid_ctx) < 256);
+ session->sid_ctx_length = (uint8_t)sid_ctx_len;
memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
return 1;
@@ -449,7 +450,8 @@
return CRYPTO_get_ex_data(&session->ex_data, idx);
}
-int ssl_get_new_session(SSL *ssl, int is_server) {
+int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
+ SSL *const ssl = hs->ssl;
if (ssl->mode & SSL_MODE_NO_SESSION_CREATION) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_MAY_NOT_BE_CREATED);
return 0;
@@ -465,15 +467,12 @@
ssl_get_current_time(ssl, &now);
session->time = now.tv_sec;
- /* If the context has a default timeout, use it over the default. */
- if (ssl->initial_ctx->session_timeout != 0) {
- session->timeout = ssl->initial_ctx->session_timeout;
- }
+ session->timeout = ssl->session_timeout;
session->ssl_version = ssl->version;
if (is_server) {
- if (ssl->s3->hs->ticket_expected) {
+ if (hs->ticket_expected) {
/* Don't set session IDs for sessions resumed with tickets. This will keep
* them out of the session cache. */
session->session_id_length = 0;
@@ -724,7 +723,7 @@
enum ssl_session_result_t ssl_get_prev_session(
SSL *ssl, SSL_SESSION **out_session, int *out_tickets_supported,
- int *out_renew_ticket, const struct ssl_early_callback_ctx *ctx) {
+ int *out_renew_ticket, const SSL_CLIENT_HELLO *client_hello) {
/* This is used only by servers. */
assert(ssl->server);
SSL_SESSION *session = NULL;
@@ -736,17 +735,18 @@
const int tickets_supported =
!(SSL_get_options(ssl) & SSL_OP_NO_TICKET) &&
ssl->version > SSL3_VERSION &&
- SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_session_ticket,
- &ticket, &ticket_len);
+ SSL_early_callback_ctx_extension_get(
+ client_hello, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len);
if (tickets_supported && ticket_len > 0) {
if (!tls_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len,
- ctx->session_id, ctx->session_id_len)) {
+ client_hello->session_id,
+ client_hello->session_id_len)) {
return ssl_session_error;
}
} else {
/* The client didn't send a ticket, so the session ID is a real ID. */
enum ssl_session_result_t lookup_ret = ssl_lookup_session(
- ssl, &session, ctx->session_id, ctx->session_id_len);
+ ssl, &session, client_hello->session_id, client_hello->session_id_len);
if (lookup_ret != ssl_session_success) {
return lookup_ret;
}
@@ -875,6 +875,12 @@
return ctx->session_timeout;
}
+long SSL_set_session_timeout(SSL *ssl, long timeout) {
+ long old_timeout = ssl->session_timeout;
+ ssl->session_timeout = timeout;
+ return old_timeout;
+}
+
typedef struct timeout_param_st {
SSL_CTX *ctx;
long time;
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index ae9d5ca..9bdaad2 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -1246,7 +1246,37 @@
PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
}
-static bool ConnectClientAndServer(bssl::UniquePtr<SSL> *out_client, bssl::UniquePtr<SSL> *out_server,
+static bool CompleteHandshakes(SSL *client, SSL *server) {
+ // Drive both their handshakes to completion.
+ for (;;) {
+ int client_ret = SSL_do_handshake(client);
+ int client_err = SSL_get_error(client, client_ret);
+ if (client_err != SSL_ERROR_NONE &&
+ client_err != SSL_ERROR_WANT_READ &&
+ client_err != SSL_ERROR_WANT_WRITE) {
+ fprintf(stderr, "Client error: %d\n", client_err);
+ return false;
+ }
+
+ int server_ret = SSL_do_handshake(server);
+ int server_err = SSL_get_error(server, server_ret);
+ if (server_err != SSL_ERROR_NONE &&
+ server_err != SSL_ERROR_WANT_READ &&
+ server_err != SSL_ERROR_WANT_WRITE) {
+ fprintf(stderr, "Server error: %d\n", server_err);
+ return false;
+ }
+
+ if (client_ret == 1 && server_ret == 1) {
+ break;
+ }
+ }
+
+ return true;
+}
+
+static bool ConnectClientAndServer(bssl::UniquePtr<SSL> *out_client,
+ bssl::UniquePtr<SSL> *out_server,
SSL_CTX *client_ctx, SSL_CTX *server_ctx,
SSL_SESSION *session) {
bssl::UniquePtr<SSL> client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
@@ -1266,29 +1296,8 @@
SSL_set_bio(client.get(), bio1, bio1);
SSL_set_bio(server.get(), bio2, bio2);
- // Drive both their handshakes to completion.
- for (;;) {
- int client_ret = SSL_do_handshake(client.get());
- int client_err = SSL_get_error(client.get(), client_ret);
- if (client_err != SSL_ERROR_NONE &&
- client_err != SSL_ERROR_WANT_READ &&
- client_err != SSL_ERROR_WANT_WRITE) {
- fprintf(stderr, "Client error: %d\n", client_err);
- return false;
- }
-
- int server_ret = SSL_do_handshake(server.get());
- int server_err = SSL_get_error(server.get(), server_ret);
- if (server_err != SSL_ERROR_NONE &&
- server_err != SSL_ERROR_WANT_READ &&
- server_err != SSL_ERROR_WANT_WRITE) {
- fprintf(stderr, "Server error: %d\n", server_err);
- return false;
- }
-
- if (client_ret == 1 && server_ret == 1) {
- break;
- }
+ if (!CompleteHandshakes(client.get(), server.get())) {
+ return false;
}
*out_client = std::move(client);
@@ -2030,11 +2039,11 @@
return SSL_TLSEXT_ERR_OK;
}
-static int SwitchSessionIDContextEarly(
- const struct ssl_early_callback_ctx *ctx) {
+static int SwitchSessionIDContextEarly(const SSL_CLIENT_HELLO *client_hello) {
static const uint8_t kContext[] = {3};
- if (!SSL_set_session_id_context(ctx->ssl, kContext, sizeof(kContext))) {
+ if (!SSL_set_session_id_context(client_hello->ssl, kContext,
+ sizeof(kContext))) {
return -1;
}
@@ -2319,6 +2328,131 @@
return true;
}
+static int SetSessionTimeoutCallback(SSL *ssl, void *arg) {
+ long timeout = *(long *) arg;
+ SSL_set_session_timeout(ssl, timeout);
+ return 1;
+}
+
+static bool TestSessionTimeoutCertCallback(bool is_dtls,
+ const SSL_METHOD *method,
+ uint16_t version) {
+ static const int kStartTime = 1000;
+ g_current_time.tv_sec = kStartTime;
+
+ bssl::UniquePtr<X509> cert = GetTestCertificate();
+ bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+ if (!cert || !key) {
+ return false;
+ }
+
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
+ if (!server_ctx || !client_ctx ||
+ !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+ !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()) ||
+ !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;
+ }
+
+ SSL_CTX_set_session_cache_mode(client_ctx.get(), SSL_SESS_CACHE_BOTH);
+ SSL_CTX_set_session_cache_mode(server_ctx.get(), SSL_SESS_CACHE_BOTH);
+
+ SSL_CTX_set_current_time_cb(server_ctx.get(), CurrentTimeCallback);
+
+ long timeout = 25;
+ SSL_CTX_set_cert_cb(server_ctx.get(), SetSessionTimeoutCallback, &timeout);
+
+ bssl::UniquePtr<SSL_SESSION> session =
+ CreateClientSession(client_ctx.get(), server_ctx.get());
+ if (!session) {
+ fprintf(stderr, "Error getting session.\n");
+ return false;
+ }
+
+ // Advance the clock just behind the timeout.
+ g_current_time.tv_sec += timeout - 1;
+
+ if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
+ true /* expect session reused */)) {
+ fprintf(stderr, "Error resuming session.\n");
+ return false;
+ }
+
+ // Advance the clock one more second.
+ g_current_time.tv_sec++;
+
+ if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
+ false /* expect session not reused */)) {
+ fprintf(stderr, "Error resuming session.\n");
+ return false;
+ }
+
+ // Set session timeout to 0 to disable resumption.
+ timeout = 0;
+ g_current_time.tv_sec = kStartTime;
+
+ bssl::UniquePtr<SSL_SESSION> not_resumable_session =
+ CreateClientSession(client_ctx.get(), server_ctx.get());
+ if (!not_resumable_session) {
+ fprintf(stderr, "Error getting session.\n");
+ return false;
+ }
+
+ if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
+ not_resumable_session.get(),
+ false /* expect session not reused */)) {
+ fprintf(stderr, "Error resuming session with timeout of 0.\n");
+ return false;
+ }
+
+ // Set both context and connection (via callback) default session timeout.
+ // The connection one is the one that ends up being used.
+ timeout = 25;
+ g_current_time.tv_sec = kStartTime;
+
+ SSL_CTX_set_timeout(server_ctx.get(), timeout - 10);
+
+ bssl::UniquePtr<SSL_SESSION> ctx_and_cb_session =
+ CreateClientSession(client_ctx.get(), server_ctx.get());
+ if (!ctx_and_cb_session) {
+ fprintf(stderr, "Error getting session.\n");
+ return false;
+ }
+
+ if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
+ ctx_and_cb_session.get(),
+ true /* expect session reused */)) {
+ fprintf(stderr, "Error resuming session with timeout of 0.\n");
+ return false;
+ }
+
+ // Advance the clock just behind the timeout.
+ g_current_time.tv_sec += timeout - 1;
+
+ if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
+ ctx_and_cb_session.get(),
+ true /* expect session reused */)) {
+ fprintf(stderr, "Error resuming session.\n");
+ return false;
+ }
+
+ // Advance the clock one more second.
+ g_current_time.tv_sec++;
+
+ if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
+ ctx_and_cb_session.get(),
+ false /* expect session not reused */)) {
+ fprintf(stderr, "Error resuming session.\n");
+ return false;
+ }
+
+ return true;
+}
+
static int SwitchContext(SSL *ssl, int *out_alert, void *arg) {
SSL_CTX *ctx = reinterpret_cast<SSL_CTX*>(arg);
SSL_set_SSL_CTX(ssl, ctx);
@@ -2386,8 +2520,8 @@
return true;
}
-static int SetMaxVersion(const struct ssl_early_callback_ctx *ctx) {
- if (!SSL_set_max_proto_version(ctx->ssl, TLS1_2_VERSION)) {
+static int SetMaxVersion(const SSL_CLIENT_HELLO *client_hello) {
+ if (!SSL_set_max_proto_version(client_hello->ssl, TLS1_2_VERSION)) {
return -1;
}
@@ -2594,6 +2728,65 @@
return true;
}
+static bool TestSSLClearSessionResumption(bool is_dtls,
+ const SSL_METHOD *method,
+ uint16_t version) {
+ // Skip this for TLS 1.3. TLS 1.3's ticket mechanism is incompatible with this
+ // API pattern.
+ if (version == TLS1_3_VERSION) {
+ return true;
+ }
+
+ bssl::UniquePtr<X509> cert = GetTestCertificate();
+ bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+ bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
+ bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
+ if (!cert || !key || !server_ctx || !client_ctx ||
+ !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+ !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()) ||
+ !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;
+ }
+
+ // Connect a client and a server.
+ bssl::UniquePtr<SSL> client, server;
+ if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
+ server_ctx.get(), nullptr /* no session */)) {
+ return false;
+ }
+
+ if (SSL_session_reused(client.get()) ||
+ SSL_session_reused(server.get())) {
+ fprintf(stderr, "Session unexpectedly reused.\n");
+ return false;
+ }
+
+ // Reset everything.
+ if (!SSL_clear(client.get()) ||
+ !SSL_clear(server.get())) {
+ fprintf(stderr, "SSL_clear failed.\n");
+ return false;
+ }
+
+ // Attempt to connect a second time.
+ if (!CompleteHandshakes(client.get(), server.get())) {
+ fprintf(stderr, "Could not reuse SSL objects.\n");
+ return false;
+ }
+
+ // |SSL_clear| should implicitly offer the previous session to the server.
+ if (!SSL_session_reused(client.get()) ||
+ !SSL_session_reused(server.get())) {
+ fprintf(stderr, "Session was not reused in second try.\n");
+ return false;
+ }
+
+ return true;
+}
+
static bool ForEachVersion(bool (*test_func)(bool is_dtls,
const SSL_METHOD *method,
uint16_t version)) {
@@ -2664,11 +2857,13 @@
!TestClientHello() ||
!ForEachVersion(TestSessionIDContext) ||
!ForEachVersion(TestSessionTimeout) ||
+ !ForEachVersion(TestSessionTimeoutCertCallback) ||
!ForEachVersion(TestSNICallback) ||
!TestEarlyCallbackVersionSwitch() ||
!TestSetVersion() ||
!ForEachVersion(TestVersion) ||
- !ForEachVersion(TestALPNCipherAvailable)) {
+ !ForEachVersion(TestALPNCipherAvailable) ||
+ !ForEachVersion(TestSSLClearSessionResumption)) {
ERR_print_errors_fp(stderr);
return 1;
}
diff --git a/src/ssl/t1_enc.c b/src/ssl/t1_enc.c
index 4c7d3ee..70907e1 100644
--- a/src/ssl/t1_enc.c
+++ b/src/ssl/t1_enc.c
@@ -258,8 +258,9 @@
return 1;
}
-static int tls1_setup_key_block(SSL *ssl) {
- if (ssl->s3->hs->key_block_len != 0) {
+static int tls1_setup_key_block(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ if (hs->key_block_len != 0) {
return 1;
}
@@ -310,14 +311,15 @@
}
assert(key_block_len < 256);
- ssl->s3->hs->key_block_len = (uint8_t)key_block_len;
- ssl->s3->hs->key_block = keyblock;
+ hs->key_block_len = (uint8_t)key_block_len;
+ hs->key_block = keyblock;
return 1;
}
-int tls1_change_cipher_state(SSL *ssl, int which) {
+int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which) {
+ SSL *const ssl = hs->ssl;
/* Ensure the key block is set up. */
- if (!tls1_setup_key_block(ssl)) {
+ if (!tls1_setup_key_block(hs)) {
return 0;
}
@@ -333,9 +335,9 @@
size_t mac_secret_len = ssl->s3->tmp.new_mac_secret_len;
size_t key_len = ssl->s3->tmp.new_key_len;
size_t iv_len = ssl->s3->tmp.new_fixed_iv_len;
- assert((mac_secret_len + key_len + iv_len) * 2 == ssl->s3->hs->key_block_len);
+ assert((mac_secret_len + key_len + iv_len) * 2 == hs->key_block_len);
- const uint8_t *key_data = ssl->s3->hs->key_block;
+ const uint8_t *key_data = hs->key_block;
const uint8_t *client_write_mac_secret = key_data;
key_data += mac_secret_len;
const uint8_t *server_write_mac_secret = key_data;
diff --git a/src/ssl/t1_lib.c b/src/ssl/t1_lib.c
index 421232f..3530ff5 100644
--- a/src/ssl/t1_lib.c
+++ b/src/ssl/t1_lib.c
@@ -127,8 +127,8 @@
#include "../crypto/internal.h"
-static int ssl_check_clienthello_tlsext(SSL *ssl);
-static int ssl_check_serverhello_tlsext(SSL *ssl);
+static int ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs);
+static int ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs);
static int compare_uint16_t(const void *p1, const void *p2) {
uint16_t u1 = *((const uint16_t *)p1);
@@ -203,29 +203,29 @@
return ret;
}
-int ssl_early_callback_init(SSL *ssl, struct ssl_early_callback_ctx *ctx,
- const uint8_t *in, size_t in_len) {
- memset(ctx, 0, sizeof(*ctx));
- ctx->ssl = ssl;
- ctx->client_hello = in;
- ctx->client_hello_len = in_len;
+int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out, const uint8_t *in,
+ size_t in_len) {
+ memset(out, 0, sizeof(*out));
+ out->ssl = ssl;
+ out->client_hello = in;
+ out->client_hello_len = in_len;
CBS client_hello, random, session_id;
- CBS_init(&client_hello, ctx->client_hello, ctx->client_hello_len);
- if (!CBS_get_u16(&client_hello, &ctx->version) ||
+ CBS_init(&client_hello, out->client_hello, out->client_hello_len);
+ if (!CBS_get_u16(&client_hello, &out->version) ||
!CBS_get_bytes(&client_hello, &random, SSL3_RANDOM_SIZE) ||
!CBS_get_u8_length_prefixed(&client_hello, &session_id) ||
CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
return 0;
}
- ctx->random = CBS_data(&random);
- ctx->random_len = CBS_len(&random);
- ctx->session_id = CBS_data(&session_id);
- ctx->session_id_len = CBS_len(&session_id);
+ out->random = CBS_data(&random);
+ out->random_len = CBS_len(&random);
+ out->session_id = CBS_data(&session_id);
+ out->session_id_len = CBS_len(&session_id);
/* Skip past DTLS cookie */
- if (SSL_is_dtls(ctx->ssl)) {
+ if (SSL_is_dtls(out->ssl)) {
CBS cookie;
if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) ||
CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) {
@@ -241,16 +241,16 @@
return 0;
}
- ctx->cipher_suites = CBS_data(&cipher_suites);
- ctx->cipher_suites_len = CBS_len(&cipher_suites);
- ctx->compression_methods = CBS_data(&compression_methods);
- ctx->compression_methods_len = CBS_len(&compression_methods);
+ out->cipher_suites = CBS_data(&cipher_suites);
+ out->cipher_suites_len = CBS_len(&cipher_suites);
+ out->compression_methods = CBS_data(&compression_methods);
+ out->compression_methods_len = CBS_len(&compression_methods);
/* If the ClientHello ends here then it's valid, but doesn't have any
* extensions. (E.g. SSLv3.) */
if (CBS_len(&client_hello) == 0) {
- ctx->extensions = NULL;
- ctx->extensions_len = 0;
+ out->extensions = NULL;
+ out->extensions_len = 0;
return 1;
}
@@ -262,16 +262,16 @@
return 0;
}
- ctx->extensions = CBS_data(&extensions);
- ctx->extensions_len = CBS_len(&extensions);
+ out->extensions = CBS_data(&extensions);
+ out->extensions_len = CBS_len(&extensions);
return 1;
}
-int ssl_early_callback_get_extension(const struct ssl_early_callback_ctx *ctx,
- CBS *out, uint16_t extension_type) {
+int ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
+ CBS *out, uint16_t extension_type) {
CBS extensions;
- CBS_init(&extensions, ctx->extensions, ctx->extensions_len);
+ CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
while (CBS_len(&extensions) != 0) {
/* Decode the next extension. */
uint16_t type;
@@ -290,11 +290,12 @@
return 0;
}
-int SSL_early_callback_ctx_extension_get(
- const struct ssl_early_callback_ctx *ctx, uint16_t extension_type,
- const uint8_t **out_data, size_t *out_len) {
+int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello,
+ uint16_t extension_type,
+ const uint8_t **out_data,
+ size_t *out_len) {
CBS cbs;
- if (!ssl_early_callback_get_extension(ctx, &cbs, extension_type)) {
+ if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) {
return 0;
}
@@ -322,7 +323,8 @@
}
}
-int tls1_get_shared_group(SSL *ssl, uint16_t *out_group_id) {
+int tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) {
+ SSL *const ssl = hs->ssl;
assert(ssl->server);
const uint16_t *groups, *pref, *supp;
@@ -341,11 +343,11 @@
if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
pref = groups;
pref_len = groups_len;
- supp = ssl->s3->hs->peer_supported_group_list;
- supp_len = ssl->s3->hs->peer_supported_group_list_len;
+ supp = hs->peer_supported_group_list;
+ supp_len = hs->peer_supported_group_list_len;
} else {
- pref = ssl->s3->hs->peer_supported_group_list;
- pref_len = ssl->s3->hs->peer_supported_group_list_len;
+ pref = hs->peer_supported_group_list;
+ pref_len = hs->peer_supported_group_list_len;
supp = groups;
supp_len = groups_len;
}
@@ -597,16 +599,19 @@
* |*out_alert| isn't set, then a |decode_error| alert will be sent. */
struct tls_extension {
uint16_t value;
- void (*init)(SSL *ssl);
+ void (*init)(SSL_HANDSHAKE *hs);
- int (*add_clienthello)(SSL *ssl, CBB *out);
- int (*parse_serverhello)(SSL *ssl, uint8_t *out_alert, CBS *contents);
+ int (*add_clienthello)(SSL_HANDSHAKE *hs, CBB *out);
+ int (*parse_serverhello)(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+ CBS *contents);
- int (*parse_clienthello)(SSL *ssl, uint8_t *out_alert, CBS *contents);
- int (*add_serverhello)(SSL *ssl, CBB *out);
+ int (*parse_clienthello)(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+ CBS *contents);
+ int (*add_serverhello)(SSL_HANDSHAKE *hs, CBB *out);
};
-static int forbid_parse_serverhello(SSL *ssl, uint8_t *out_alert, CBS *contents) {
+static int forbid_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+ CBS *contents) {
if (contents != NULL) {
/* Servers MUST NOT send this extension. */
*out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
@@ -617,12 +622,13 @@
return 1;
}
-static int ignore_parse_clienthello(SSL *ssl, uint8_t *out_alert, CBS *contents) {
+static int ignore_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+ CBS *contents) {
/* This extension from the client is handled elsewhere. */
return 1;
}
-static int dont_add_serverhello(SSL *ssl, CBB *out) {
+static int dont_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
return 1;
}
@@ -630,7 +636,8 @@
*
* https://tools.ietf.org/html/rfc6066#section-3. */
-static int ext_sni_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_sni_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (ssl->tlsext_hostname == NULL) {
return 1;
}
@@ -650,8 +657,9 @@
return 1;
}
-static int ext_sni_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_sni_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL) {
return 1;
}
@@ -674,7 +682,7 @@
return 1;
}
-static int ext_sni_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
if (contents == NULL) {
return 1;
@@ -706,18 +714,18 @@
}
/* Copy the hostname as a string. */
- if (!CBS_strdup(&host_name, &ssl->s3->hs->hostname)) {
+ if (!CBS_strdup(&host_name, &hs->hostname)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
- ssl->s3->hs->should_ack_sni = 1;
+ hs->should_ack_sni = 1;
return 1;
}
-static int ext_sni_add_serverhello(SSL *ssl, CBB *out) {
- if (ssl->s3->session_reused ||
- !ssl->s3->hs->should_ack_sni) {
+static int ext_sni_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ if (hs->ssl->s3->session_reused ||
+ !hs->should_ack_sni) {
return 1;
}
@@ -734,7 +742,8 @@
*
* https://tools.ietf.org/html/rfc5746 */
-static int ext_ri_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_ri_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
@@ -761,8 +770,9 @@
return 1;
}
-static int ext_ri_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_ri_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents != NULL && ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 0;
}
@@ -834,8 +844,9 @@
return 1;
}
-static int ext_ri_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_ri_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
/* Renegotiation isn't supported as a server so this function should never be
* called after the initial handshake. */
assert(!ssl->s3->initial_handshake_complete);
@@ -868,7 +879,8 @@
return 1;
}
-static int ext_ri_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_ri_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
/* Renegotiation isn't supported as a server so this function should never be
* called after the initial handshake. */
assert(!ssl->s3->initial_handshake_complete);
@@ -891,9 +903,9 @@
*
* https://tools.ietf.org/html/rfc7627 */
-static int ext_ems_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_ems_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
uint16_t min_version, max_version;
- if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+ if (!ssl_get_version_range(hs->ssl, &min_version, &max_version)) {
return 0;
}
@@ -910,8 +922,9 @@
return 1;
}
-static int ext_ems_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_ems_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
/* Whether EMS is negotiated may not change on renegotation. */
if (ssl->s3->initial_handshake_complete) {
if ((contents != NULL) != ssl->s3->tmp.extended_master_secret) {
@@ -940,10 +953,12 @@
return 1;
}
-static int ext_ems_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_ems_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
- if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
- ssl->version == SSL3_VERSION) {
+ SSL *const ssl = hs->ssl;
+ uint16_t version = ssl3_protocol_version(ssl);
+ if (version >= TLS1_3_VERSION ||
+ version == SSL3_VERSION) {
return 1;
}
@@ -959,8 +974,8 @@
return 1;
}
-static int ext_ems_add_serverhello(SSL *ssl, CBB *out) {
- if (!ssl->s3->tmp.extended_master_secret) {
+static int ext_ems_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ if (!hs->ssl->s3->tmp.extended_master_secret) {
return 1;
}
@@ -977,7 +992,8 @@
*
* https://tools.ietf.org/html/rfc5077 */
-static int ext_ticket_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_ticket_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
@@ -1019,8 +1035,9 @@
return 1;
}
-static int ext_ticket_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_ticket_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL) {
return 1;
}
@@ -1038,17 +1055,17 @@
return 0;
}
- ssl->s3->hs->ticket_expected = 1;
+ hs->ticket_expected = 1;
return 1;
}
-static int ext_ticket_add_serverhello(SSL *ssl, CBB *out) {
- if (!ssl->s3->hs->ticket_expected) {
+static int ext_ticket_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ if (!hs->ticket_expected) {
return 1;
}
/* If |SSL_OP_NO_TICKET| is set, |ticket_expected| should never be true. */
- assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0);
+ assert((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) == 0);
if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
!CBB_add_u16(out, 0 /* length */)) {
@@ -1063,7 +1080,8 @@
*
* https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
-static int ext_sigalgs_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_sigalgs_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
@@ -1096,11 +1114,11 @@
return 1;
}
-static int ext_sigalgs_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_sigalgs_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
- OPENSSL_free(ssl->s3->hs->peer_sigalgs);
- ssl->s3->hs->peer_sigalgs = NULL;
- ssl->s3->hs->num_peer_sigalgs = 0;
+ OPENSSL_free(hs->peer_sigalgs);
+ hs->peer_sigalgs = NULL;
+ hs->num_peer_sigalgs = 0;
if (contents == NULL) {
return 1;
@@ -1110,7 +1128,7 @@
if (!CBS_get_u16_length_prefixed(contents, &supported_signature_algorithms) ||
CBS_len(contents) != 0 ||
CBS_len(&supported_signature_algorithms) == 0 ||
- !tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) {
+ !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
return 0;
}
@@ -1122,11 +1140,12 @@
*
* https://tools.ietf.org/html/rfc6066#section-8 */
-static void ext_ocsp_init(SSL *ssl) {
- ssl->tlsext_status_type = -1;
+static void ext_ocsp_init(SSL_HANDSHAKE *hs) {
+ hs->ssl->tlsext_status_type = -1;
}
-static int ext_ocsp_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_ocsp_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (!ssl->ocsp_stapling_enabled) {
return 1;
}
@@ -1145,8 +1164,9 @@
return 1;
}
-static int ext_ocsp_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_ocsp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL) {
return 1;
}
@@ -1166,11 +1186,11 @@
* 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->hs->certificate_status_expected = 1;
+ hs->certificate_status_expected = 1;
return 1;
}
-static int ext_ocsp_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_ocsp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
if (contents == NULL) {
return 1;
@@ -1183,21 +1203,22 @@
/* We cannot decide whether OCSP stapling will occur yet because the correct
* SSL_CTX might not have been selected. */
- ssl->s3->hs->ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp;
+ hs->ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp;
return 1;
}
-static int ext_ocsp_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_ocsp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
- !ssl->s3->hs->ocsp_stapling_requested ||
+ !hs->ocsp_stapling_requested ||
ssl->ctx->ocsp_response_length == 0 ||
ssl->s3->session_reused ||
!ssl_cipher_uses_certificate_auth(ssl->s3->tmp.new_cipher)) {
return 1;
}
- ssl->s3->hs->certificate_status_expected = 1;
+ hs->certificate_status_expected = 1;
return CBB_add_u16(out, TLSEXT_TYPE_status_request) &&
CBB_add_u16(out, 0 /* length */);
@@ -1208,10 +1229,10 @@
*
* https://htmlpreview.github.io/?https://github.com/agl/technotes/blob/master/nextprotoneg.html */
-static int ext_npn_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_npn_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (ssl->s3->initial_handshake_complete ||
ssl->ctx->next_proto_select_cb == NULL ||
- (ssl->options & SSL_OP_DISABLE_NPN) ||
SSL_is_dtls(ssl)) {
return 1;
}
@@ -1224,8 +1245,9 @@
return 1;
}
-static int ext_npn_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_npn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL) {
return 1;
}
@@ -1240,7 +1262,6 @@
assert(!ssl->s3->initial_handshake_complete);
assert(!SSL_is_dtls(ssl));
assert(ssl->ctx->next_proto_select_cb != NULL);
- assert(!(ssl->options & SSL_OP_DISABLE_NPN));
if (ssl->s3->alpn_selected != NULL) {
/* NPN and ALPN may not be negotiated in the same connection. */
@@ -1277,13 +1298,14 @@
}
ssl->s3->next_proto_negotiated_len = selected_len;
- ssl->s3->hs->next_proto_neg_seen = 1;
+ hs->next_proto_neg_seen = 1;
return 1;
}
-static int ext_npn_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_npn_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 1;
}
@@ -1299,14 +1321,15 @@
return 1;
}
- ssl->s3->hs->next_proto_neg_seen = 1;
+ hs->next_proto_neg_seen = 1;
return 1;
}
-static int ext_npn_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_npn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
/* |next_proto_neg_seen| might have been cleared when an ALPN extension was
* parsed. */
- if (!ssl->s3->hs->next_proto_neg_seen) {
+ if (!hs->next_proto_neg_seen) {
return 1;
}
@@ -1316,7 +1339,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->hs->next_proto_neg_seen = 0;
+ hs->next_proto_neg_seen = 0;
return 1;
}
@@ -1336,7 +1359,8 @@
*
* https://tools.ietf.org/html/rfc6962#section-3.3.1 */
-static int ext_sct_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_sct_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (!ssl->signed_cert_timestamps_enabled) {
return 1;
}
@@ -1349,8 +1373,9 @@
return 1;
}
-static int ext_sct_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_sct_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL) {
return 1;
}
@@ -1387,7 +1412,7 @@
return 1;
}
-static int ext_sct_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_sct_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
if (contents == NULL) {
return 1;
@@ -1397,11 +1422,12 @@
return 0;
}
- ssl->s3->hs->scts_requested = 1;
+ hs->scts_requested = 1;
return 1;
}
-static int ext_sct_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_sct_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
/* The extension shouldn't be sent when resuming sessions. */
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
ssl->s3->session_reused ||
@@ -1422,7 +1448,8 @@
*
* https://tools.ietf.org/html/rfc7301 */
-static int ext_alpn_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_alpn_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (ssl->alpn_client_proto_list == NULL ||
ssl->s3->initial_handshake_complete) {
return 1;
@@ -1441,8 +1468,9 @@
return 1;
}
-static int ext_alpn_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_alpn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL) {
return 1;
}
@@ -1450,7 +1478,7 @@
assert(!ssl->s3->initial_handshake_complete);
assert(ssl->alpn_client_proto_list != NULL);
- if (ssl->s3->hs->next_proto_neg_seen) {
+ if (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);
@@ -1504,11 +1532,12 @@
return 1;
}
-int ssl_negotiate_alpn(SSL *ssl, uint8_t *out_alert,
- const struct ssl_early_callback_ctx *client_hello) {
+int ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+ const SSL_CLIENT_HELLO *client_hello) {
+ SSL *const ssl = hs->ssl;
CBS contents;
if (ssl->ctx->alpn_select_cb == NULL ||
- !ssl_early_callback_get_extension(
+ !ssl_client_hello_get_extension(
client_hello, &contents,
TLSEXT_TYPE_application_layer_protocol_negotiation)) {
/* Ignore ALPN if not configured or no extension was supplied. */
@@ -1516,7 +1545,7 @@
}
/* ALPN takes precedence over NPN. */
- ssl->s3->hs->next_proto_neg_seen = 0;
+ hs->next_proto_neg_seen = 0;
CBS protocol_name_list;
if (!CBS_get_u16_length_prefixed(&contents, &protocol_name_list) ||
@@ -1559,7 +1588,8 @@
return 1;
}
-static int ext_alpn_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_alpn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (ssl->s3->alpn_selected == NULL) {
return 1;
}
@@ -1583,11 +1613,12 @@
*
* https://tools.ietf.org/html/draft-balfanz-tls-channelid-01 */
-static void ext_channel_id_init(SSL *ssl) {
- ssl->s3->tlsext_channel_id_valid = 0;
+static void ext_channel_id_init(SSL_HANDSHAKE *hs) {
+ hs->ssl->s3->tlsext_channel_id_valid = 0;
}
-static int ext_channel_id_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_channel_id_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (!ssl->tlsext_channel_id_enabled ||
SSL_is_dtls(ssl)) {
return 1;
@@ -1601,8 +1632,9 @@
return 1;
}
-static int ext_channel_id_parse_serverhello(SSL *ssl, uint8_t *out_alert,
- CBS *contents) {
+static int ext_channel_id_parse_serverhello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert, CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL) {
return 1;
}
@@ -1618,8 +1650,9 @@
return 1;
}
-static int ext_channel_id_parse_clienthello(SSL *ssl, uint8_t *out_alert,
- CBS *contents) {
+static int ext_channel_id_parse_clienthello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert, CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL ||
!ssl->tlsext_channel_id_enabled ||
SSL_is_dtls(ssl)) {
@@ -1634,7 +1667,8 @@
return 1;
}
-static int ext_channel_id_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_channel_id_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (!ssl->s3->tlsext_channel_id_valid) {
return 1;
}
@@ -1653,11 +1687,12 @@
* https://tools.ietf.org/html/rfc5764 */
-static void ext_srtp_init(SSL *ssl) {
- ssl->srtp_profile = NULL;
+static void ext_srtp_init(SSL_HANDSHAKE *hs) {
+ hs->ssl->srtp_profile = NULL;
}
-static int ext_srtp_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_srtp_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
STACK_OF(SRTP_PROTECTION_PROFILE) *profiles = SSL_get_srtp_profiles(ssl);
if (profiles == NULL) {
return 1;
@@ -1689,8 +1724,9 @@
return 1;
}
-static int ext_srtp_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_srtp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL) {
return 1;
}
@@ -1736,8 +1772,9 @@
return 0;
}
-static int ext_srtp_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_srtp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
if (contents == NULL) {
return 1;
}
@@ -1779,7 +1816,8 @@
return 1;
}
-static int ext_srtp_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_srtp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (ssl->srtp_profile == NULL) {
return 1;
}
@@ -1802,7 +1840,7 @@
*
* https://tools.ietf.org/html/rfc4492#section-5.1.2 */
-static int ext_ec_point_add_extension(SSL *ssl, CBB *out) {
+static int ext_ec_point_add_extension(SSL_HANDSHAKE *hs, CBB *out) {
CBB contents, formats;
if (!CBB_add_u16(out, TLSEXT_TYPE_ec_point_formats) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
@@ -1815,9 +1853,9 @@
return 1;
}
-static int ext_ec_point_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_ec_point_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
uint16_t min_version, max_version;
- if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+ if (!ssl_get_version_range(hs->ssl, &min_version, &max_version)) {
return 0;
}
@@ -1826,16 +1864,16 @@
return 1;
}
- return ext_ec_point_add_extension(ssl, out);
+ return ext_ec_point_add_extension(hs, out);
}
-static int ext_ec_point_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_ec_point_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
if (contents == NULL) {
return 1;
}
- if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+ if (ssl3_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
return 0;
}
@@ -1856,16 +1894,17 @@
return 1;
}
-static int ext_ec_point_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_ec_point_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
CBS *contents) {
- if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+ if (ssl3_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
return 1;
}
- return ext_ec_point_parse_serverhello(ssl, out_alert, contents);
+ return ext_ec_point_parse_serverhello(hs, out_alert, contents);
}
-static int ext_ec_point_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_ec_point_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
return 1;
}
@@ -1878,7 +1917,7 @@
return 1;
}
- return ext_ec_point_add_extension(ssl, out);
+ return ext_ec_point_add_extension(hs, out);
}
@@ -1886,7 +1925,8 @@
*
* https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.6 */
-static size_t ext_pre_shared_key_clienthello_length(SSL *ssl) {
+static size_t ext_pre_shared_key_clienthello_length(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
@@ -1906,7 +1946,8 @@
return 15 + ssl->session->tlsext_ticklen + binder_len;
}
-static int ext_pre_shared_key_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_pre_shared_key_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
@@ -1946,11 +1987,12 @@
return 0;
}
- ssl->s3->hs->needs_psk_binder = 1;
+ hs->needs_psk_binder = 1;
return CBB_flush(out);
}
-int ssl_ext_pre_shared_key_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+int ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert,
CBS *contents) {
uint16_t psk_id;
if (!CBS_get_u16(contents, &psk_id) ||
@@ -1970,18 +2012,20 @@
return 1;
}
-int ssl_ext_pre_shared_key_parse_clienthello(SSL *ssl,
+int ssl_ext_pre_shared_key_parse_clienthello(SSL_HANDSHAKE *hs,
SSL_SESSION **out_session,
CBS *out_binders,
uint8_t *out_alert,
CBS *contents) {
+ SSL *const ssl = hs->ssl;
/* We only process the first PSK identity since we don't support pure PSK. */
uint32_t obfuscated_ticket_age;
- CBS identity, ticket, binders;
- if (!CBS_get_u16_length_prefixed(contents, &identity) ||
- !CBS_get_u16_length_prefixed(&identity, &ticket) ||
- !CBS_get_u32(&identity, &obfuscated_ticket_age) ||
+ CBS identities, ticket, binders;
+ if (!CBS_get_u16_length_prefixed(contents, &identities) ||
+ !CBS_get_u16_length_prefixed(&identities, &ticket) ||
+ !CBS_get_u32(&identities, &obfuscated_ticket_age) ||
!CBS_get_u16_length_prefixed(contents, &binders) ||
+ CBS_len(&binders) == 0 ||
CBS_len(contents) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
*out_alert = SSL_AD_DECODE_ERROR;
@@ -1990,11 +2034,38 @@
*out_binders = binders;
- /* The PSK identity must have a corresponding binder. */
- CBS binder;
- if (!CBS_get_u8_length_prefixed(&binders, &binder)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- *out_alert = SSL_AD_DECODE_ERROR;
+ /* Check the syntax of the remaining identities, but do not process them. */
+ size_t num_identities = 1;
+ while (CBS_len(&identities) != 0) {
+ CBS unused_ticket;
+ uint32_t unused_obfuscated_ticket_age;
+ if (!CBS_get_u16_length_prefixed(&identities, &unused_ticket) ||
+ !CBS_get_u32(&identities, &unused_obfuscated_ticket_age)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ num_identities++;
+ }
+
+ /* Check the syntax of the binders. The value will be checked later if
+ * resuming. */
+ size_t num_binders = 0;
+ while (CBS_len(&binders) != 0) {
+ CBS binder;
+ if (!CBS_get_u8_length_prefixed(&binders, &binder)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ num_binders++;
+ }
+
+ if (num_identities != num_binders) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_BINDER_COUNT_MISMATCH);
+ *out_alert = SSL_AD_ILLEGAL_PARAMETER;
return 0;
}
@@ -2013,8 +2084,8 @@
return 1;
}
-int ssl_ext_pre_shared_key_add_serverhello(SSL *ssl, CBB *out) {
- if (!ssl->s3->session_reused) {
+int ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ if (!hs->ssl->s3->session_reused) {
return 1;
}
@@ -2034,7 +2105,10 @@
/* Pre-Shared Key Exchange Modes
*
* https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.7 */
-static int ext_psk_key_exchange_modes_add_clienthello(SSL *ssl, CBB *out) {
+
+static int ext_psk_key_exchange_modes_add_clienthello(SSL_HANDSHAKE *hs,
+ CBB *out) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
@@ -2055,7 +2129,7 @@
return CBB_flush(out);
}
-static int ext_psk_key_exchange_modes_parse_clienthello(SSL *ssl,
+static int ext_psk_key_exchange_modes_parse_clienthello(SSL_HANDSHAKE *hs,
uint8_t *out_alert,
CBS *contents) {
if (contents == NULL) {
@@ -2071,18 +2145,49 @@
}
/* We only support tickets with PSK_DHE_KE. */
- ssl->s3->hs->accept_psk_mode =
+ hs->accept_psk_mode =
memchr(CBS_data(&ke_modes), SSL_PSK_DHE_KE, CBS_len(&ke_modes)) != NULL;
return 1;
}
+/* Early Data Indication
+ *
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.8 */
+
+static int ext_early_data_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ /* TODO(svaldez): Support 0RTT. */
+ return 1;
+}
+
+static int ext_early_data_parse_clienthello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert, CBS *contents) {
+ SSL *const ssl = hs->ssl;
+ if (contents == NULL) {
+ return 1;
+ }
+
+ if (CBS_len(contents) != 0) {
+ *out_alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* Since we don't currently accept 0-RTT, we have to skip past any early data
+ * the client might have sent. */
+ if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+ ssl->s3->skip_early_data = 1;
+ }
+ return 1;
+}
+
+
/* Key Share
*
* 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) {
+static int ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
@@ -2099,18 +2204,18 @@
return 0;
}
- uint16_t group_id = ssl->s3->hs->retry_group;
- if (ssl->s3->hs->received_hello_retry_request) {
+ uint16_t group_id = hs->retry_group;
+ if (hs->received_hello_retry_request) {
/* 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 &&
- !CBB_add_bytes(&kse_bytes, ssl->s3->hs->key_share_bytes,
- ssl->s3->hs->key_share_bytes_len)) {
+ !CBB_add_bytes(&kse_bytes, hs->key_share_bytes,
+ hs->key_share_bytes_len)) {
return 0;
}
- OPENSSL_free(ssl->s3->hs->key_share_bytes);
- ssl->s3->hs->key_share_bytes = NULL;
- ssl->s3->hs->key_share_bytes_len = 0;
+ OPENSSL_free(hs->key_share_bytes);
+ hs->key_share_bytes = NULL;
+ hs->key_share_bytes_len = 0;
if (group_id == 0) {
return CBB_flush(out);
}
@@ -2139,19 +2244,18 @@
CBB key_exchange;
if (!CBB_add_u16(&kse_bytes, group_id) ||
!CBB_add_u16_length_prefixed(&kse_bytes, &key_exchange) ||
- !SSL_ECDH_CTX_init(&ssl->s3->hs->ecdh_ctx, group_id) ||
- !SSL_ECDH_CTX_offer(&ssl->s3->hs->ecdh_ctx, &key_exchange) ||
+ !SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
+ !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &key_exchange) ||
!CBB_flush(&kse_bytes)) {
return 0;
}
- if (!ssl->s3->hs->received_hello_retry_request) {
+ if (!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);
- ssl->s3->hs->key_share_bytes = BUF_memdup(CBB_data(&kse_bytes),
- CBB_len(&kse_bytes));
- if (ssl->s3->hs->key_share_bytes == NULL) {
+ hs->key_share_bytes_len = CBB_len(&kse_bytes);
+ hs->key_share_bytes = BUF_memdup(CBB_data(&kse_bytes), CBB_len(&kse_bytes));
+ if (hs->key_share_bytes == NULL) {
return 0;
}
}
@@ -2159,9 +2263,10 @@
return CBB_flush(out);
}
-int ssl_ext_key_share_parse_serverhello(SSL *ssl, uint8_t **out_secret,
+int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t **out_secret,
size_t *out_secret_len,
uint8_t *out_alert, CBS *contents) {
+ SSL *const ssl = hs->ssl;
CBS peer_key;
uint16_t group_id;
if (!CBS_get_u16(contents, &group_id) ||
@@ -2171,31 +2276,30 @@
return 0;
}
- if (SSL_ECDH_CTX_get_id(&ssl->s3->hs->ecdh_ctx) != group_id) {
+ if (SSL_ECDH_CTX_get_id(&hs->ecdh_ctx) != group_id) {
*out_alert = SSL_AD_ILLEGAL_PARAMETER;
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
return 0;
}
- if (!SSL_ECDH_CTX_finish(&ssl->s3->hs->ecdh_ctx, out_secret, out_secret_len,
- out_alert, CBS_data(&peer_key),
- CBS_len(&peer_key))) {
+ if (!SSL_ECDH_CTX_finish(&hs->ecdh_ctx, out_secret, out_secret_len, out_alert,
+ CBS_data(&peer_key), CBS_len(&peer_key))) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
ssl->s3->new_session->key_exchange_info = group_id;
- SSL_ECDH_CTX_cleanup(&ssl->s3->hs->ecdh_ctx);
+ SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
return 1;
}
-int ssl_ext_key_share_parse_clienthello(SSL *ssl, int *out_found,
+int ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, int *out_found,
uint8_t **out_secret,
size_t *out_secret_len,
uint8_t *out_alert, CBS *contents) {
uint16_t group_id;
CBS key_shares;
- if (!tls1_get_shared_group(ssl, &group_id)) {
+ if (!tls1_get_shared_group(hs, &group_id)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_GROUP);
*out_alert = SSL_AD_HANDSHAKE_FAILURE;
return 0;
@@ -2247,11 +2351,9 @@
CBB public_key;
if (!CBB_init(&public_key, 32) ||
!SSL_ECDH_CTX_init(&group, group_id) ||
- !SSL_ECDH_CTX_accept(&group, &public_key, &secret, &secret_len,
- out_alert, CBS_data(&peer_key),
- CBS_len(&peer_key)) ||
- !CBB_finish(&public_key, &ssl->s3->hs->public_key,
- &ssl->s3->hs->public_key_len)) {
+ !SSL_ECDH_CTX_accept(&group, &public_key, &secret, &secret_len, out_alert,
+ CBS_data(&peer_key), CBS_len(&peer_key)) ||
+ !CBB_finish(&public_key, &hs->public_key, &hs->public_key_len)) {
OPENSSL_free(secret);
SSL_ECDH_CTX_cleanup(&group);
CBB_cleanup(&public_key);
@@ -2267,23 +2369,23 @@
return 1;
}
-int ssl_ext_key_share_add_serverhello(SSL *ssl, CBB *out) {
+int ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
uint16_t group_id;
CBB kse_bytes, public_key;
- if (!tls1_get_shared_group(ssl, &group_id) ||
+ if (!tls1_get_shared_group(hs, &group_id) ||
!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
!CBB_add_u16_length_prefixed(out, &kse_bytes) ||
!CBB_add_u16(&kse_bytes, group_id) ||
!CBB_add_u16_length_prefixed(&kse_bytes, &public_key) ||
- !CBB_add_bytes(&public_key, ssl->s3->hs->public_key,
- ssl->s3->hs->public_key_len) ||
+ !CBB_add_bytes(&public_key, hs->public_key, hs->public_key_len) ||
!CBB_flush(out)) {
return 0;
}
- OPENSSL_free(ssl->s3->hs->public_key);
- ssl->s3->hs->public_key = NULL;
- ssl->s3->hs->public_key_len = 0;
+ OPENSSL_free(hs->public_key);
+ hs->public_key = NULL;
+ hs->public_key_len = 0;
ssl->s3->new_session->key_exchange_info = group_id;
return 1;
@@ -2294,7 +2396,8 @@
*
* https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.1 */
-static int ext_supported_versions_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_supported_versions_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
uint16_t min_version, max_version;
if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
return 0;
@@ -2335,8 +2438,8 @@
*
* 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) {
+static int ext_cookie_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ if (hs->cookie == NULL) {
return 1;
}
@@ -2344,15 +2447,15 @@
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_add_bytes(&cookie, hs->cookie, 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;
+ OPENSSL_free(hs->cookie);
+ hs->cookie = NULL;
+ hs->cookie_len = 0;
return 1;
}
@@ -2362,7 +2465,8 @@
* https://tools.ietf.org/html/rfc4492#section-5.1.2
* 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) {
+static int ext_supported_groups_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
CBB contents, groups_bytes;
if (!CBB_add_u16(out, TLSEXT_TYPE_supported_groups) ||
!CBB_add_u16_length_prefixed(out, &contents) ||
@@ -2390,14 +2494,16 @@
return CBB_flush(out);
}
-static int ext_supported_groups_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_supported_groups_parse_serverhello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert,
CBS *contents) {
/* This extension is not expected to be echoed by servers in TLS 1.2, but some
* BigIP servers send it nonetheless, so do not enforce this. */
return 1;
}
-static int ext_supported_groups_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs,
+ uint8_t *out_alert,
CBS *contents) {
if (contents == NULL) {
return 1;
@@ -2411,9 +2517,9 @@
return 0;
}
- ssl->s3->hs->peer_supported_group_list = OPENSSL_malloc(
- CBS_len(&supported_group_list));
- if (ssl->s3->hs->peer_supported_group_list == NULL) {
+ hs->peer_supported_group_list =
+ OPENSSL_malloc(CBS_len(&supported_group_list));
+ if (hs->peer_supported_group_list == NULL) {
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
@@ -2421,24 +2527,24 @@
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->hs->peer_supported_group_list[i])) {
+ &hs->peer_supported_group_list[i])) {
goto err;
}
}
assert(CBS_len(&supported_group_list) == 0);
- ssl->s3->hs->peer_supported_group_list_len = num_groups;
+ hs->peer_supported_group_list_len = num_groups;
return 1;
err:
- OPENSSL_free(ssl->s3->hs->peer_supported_group_list);
- ssl->s3->hs->peer_supported_group_list = NULL;
+ OPENSSL_free(hs->peer_supported_group_list);
+ hs->peer_supported_group_list = NULL;
*out_alert = SSL_AD_INTERNAL_ERROR;
return 0;
}
-static int ext_supported_groups_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_supported_groups_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
/* Servers don't echo this extension. */
return 1;
}
@@ -2561,6 +2667,14 @@
dont_add_serverhello,
},
{
+ TLSEXT_TYPE_early_data,
+ NULL,
+ ext_early_data_add_clienthello,
+ forbid_parse_serverhello,
+ ext_early_data_parse_clienthello,
+ dont_add_serverhello,
+ },
+ {
TLSEXT_TYPE_supported_versions,
NULL,
ext_supported_versions_add_clienthello,
@@ -2617,9 +2731,10 @@
tls_extension_find(&index, extension_value) != NULL;
}
-int ssl_add_clienthello_tlsext(SSL *ssl, CBB *out, size_t header_len) {
- /* don't add extensions for SSLv3 unless doing secure renegotiation */
- if (ssl->client_version == SSL3_VERSION &&
+int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) {
+ SSL *const ssl = hs->ssl;
+ /* Don't add extensions for SSLv3 unless doing secure renegotiation. */
+ if (hs->client_version == SSL3_VERSION &&
!ssl->s3->send_connection_binding) {
return 1;
}
@@ -2629,12 +2744,12 @@
goto err;
}
- ssl->s3->hs->extensions.sent = 0;
- ssl->s3->hs->custom_extensions.sent = 0;
+ hs->extensions.sent = 0;
+ hs->custom_extensions.sent = 0;
for (size_t i = 0; i < kNumExtensions; i++) {
if (kExtensions[i].init != NULL) {
- kExtensions[i].init(ssl);
+ kExtensions[i].init(hs);
}
}
@@ -2650,18 +2765,18 @@
for (size_t i = 0; i < kNumExtensions; i++) {
const size_t len_before = CBB_len(&extensions);
- if (!kExtensions[i].add_clienthello(ssl, &extensions)) {
+ if (!kExtensions[i].add_clienthello(hs, &extensions)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
goto err;
}
if (CBB_len(&extensions) != len_before) {
- ssl->s3->hs->extensions.sent |= (1u << i);
+ hs->extensions.sent |= (1u << i);
}
}
- if (!custom_ext_add_clienthello(ssl, &extensions)) {
+ if (!custom_ext_add_clienthello(hs, &extensions)) {
goto err;
}
@@ -2684,7 +2799,7 @@
}
if (!SSL_is_dtls(ssl)) {
- size_t psk_extension_len = ext_pre_shared_key_clienthello_length(ssl);
+ size_t psk_extension_len = ext_pre_shared_key_clienthello_length(hs);
header_len += 2 + CBB_len(&extensions) + psk_extension_len;
if (header_len > 0xff && header_len < 0x200) {
/* Add padding to workaround bugs in F5 terminators. See RFC 7685.
@@ -2714,7 +2829,7 @@
}
/* The PSK extension must be last, including after the padding. */
- if (!ext_pre_shared_key_add_clienthello(ssl, &extensions)) {
+ if (!ext_pre_shared_key_add_clienthello(hs, &extensions)) {
goto err;
}
@@ -2730,27 +2845,27 @@
return 0;
}
-int ssl_add_serverhello_tlsext(SSL *ssl, CBB *out) {
+int ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
CBB extensions;
if (!CBB_add_u16_length_prefixed(out, &extensions)) {
goto err;
}
- unsigned i;
- for (i = 0; i < kNumExtensions; i++) {
- if (!(ssl->s3->hs->extensions.received & (1u << i))) {
+ for (unsigned i = 0; i < kNumExtensions; i++) {
+ if (!(hs->extensions.received & (1u << i))) {
/* Don't send extensions that were not received. */
continue;
}
- if (!kExtensions[i].add_serverhello(ssl, &extensions)) {
+ if (!kExtensions[i].add_serverhello(hs, &extensions)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
goto err;
}
}
- if (!custom_ext_add_serverhello(ssl, &extensions)) {
+ if (!custom_ext_add_serverhello(hs, &extensions)) {
goto err;
}
@@ -2767,17 +2882,18 @@
return 0;
}
-static int ssl_scan_clienthello_tlsext(
- SSL *ssl, const struct ssl_early_callback_ctx *client_hello,
- int *out_alert) {
+static int ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs,
+ const SSL_CLIENT_HELLO *client_hello,
+ int *out_alert) {
+ SSL *const ssl = hs->ssl;
for (size_t i = 0; i < kNumExtensions; i++) {
if (kExtensions[i].init != NULL) {
- kExtensions[i].init(ssl);
+ kExtensions[i].init(hs);
}
}
- ssl->s3->hs->extensions.received = 0;
- ssl->s3->hs->custom_extensions.received = 0;
+ hs->extensions.received = 0;
+ hs->custom_extensions.received = 0;
CBS extensions;
CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
@@ -2803,16 +2919,16 @@
tls_extension_find(&ext_index, type);
if (ext == NULL) {
- if (!custom_ext_parse_clienthello(ssl, out_alert, type, &extension)) {
+ if (!custom_ext_parse_clienthello(hs, out_alert, type, &extension)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
return 0;
}
continue;
}
- ssl->s3->hs->extensions.received |= (1u << ext_index);
+ hs->extensions.received |= (1u << ext_index);
uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!ext->parse_clienthello(ssl, &alert, &extension)) {
+ if (!ext->parse_clienthello(hs, &alert, &extension)) {
*out_alert = alert;
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
ERR_add_error_dataf("extension %u", (unsigned)type);
@@ -2821,7 +2937,7 @@
}
for (size_t i = 0; i < kNumExtensions; i++) {
- if (ssl->s3->hs->extensions.received & (1u << i)) {
+ if (hs->extensions.received & (1u << i)) {
continue;
}
@@ -2835,13 +2951,13 @@
CBS_init(&fake_contents, kFakeRenegotiateExtension,
sizeof(kFakeRenegotiateExtension));
contents = &fake_contents;
- ssl->s3->hs->extensions.received |= (1u << i);
+ hs->extensions.received |= (1u << i);
}
/* Extension wasn't observed so call the callback with a NULL
* parameter. */
uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!kExtensions[i].parse_clienthello(ssl, &alert, contents)) {
+ if (!kExtensions[i].parse_clienthello(hs, &alert, contents)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
*out_alert = alert;
@@ -2852,15 +2968,16 @@
return 1;
}
-int ssl_parse_clienthello_tlsext(
- SSL *ssl, const struct ssl_early_callback_ctx *client_hello) {
+int ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs,
+ const SSL_CLIENT_HELLO *client_hello) {
+ SSL *const ssl = hs->ssl;
int alert = -1;
- if (ssl_scan_clienthello_tlsext(ssl, client_hello, &alert) <= 0) {
+ if (ssl_scan_clienthello_tlsext(hs, client_hello, &alert) <= 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return 0;
}
- if (ssl_check_clienthello_tlsext(ssl) <= 0) {
+ if (ssl_check_clienthello_tlsext(hs) <= 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_TLSEXT);
return 0;
}
@@ -2870,7 +2987,9 @@
OPENSSL_COMPILE_ASSERT(kNumExtensions <= sizeof(uint32_t) * 8, too_many_bits);
-static int ssl_scan_serverhello_tlsext(SSL *ssl, CBS *cbs, int *out_alert) {
+static int ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs,
+ int *out_alert) {
+ SSL *const ssl = hs->ssl;
/* Before TLS 1.3, ServerHello extensions blocks may be omitted if empty. */
if (CBS_len(cbs) == 0 && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
return 1;
@@ -2901,13 +3020,13 @@
tls_extension_find(&ext_index, type);
if (ext == NULL) {
- if (!custom_ext_parse_serverhello(ssl, out_alert, type, &extension)) {
+ if (!custom_ext_parse_serverhello(hs, out_alert, type, &extension)) {
return 0;
}
continue;
}
- if (!(ssl->s3->hs->extensions.sent & (1u << ext_index)) &&
+ if (!(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. */
@@ -2920,7 +3039,7 @@
received |= (1u << ext_index);
uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!ext->parse_serverhello(ssl, &alert, &extension)) {
+ if (!ext->parse_serverhello(hs, &alert, &extension)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
ERR_add_error_dataf("extension %u", (unsigned)type);
*out_alert = alert;
@@ -2933,7 +3052,7 @@
/* Extension wasn't observed so call the callback with a NULL
* parameter. */
uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!kExtensions[i].parse_serverhello(ssl, &alert, NULL)) {
+ if (!kExtensions[i].parse_serverhello(hs, &alert, NULL)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
*out_alert = alert;
@@ -2945,7 +3064,8 @@
return 1;
}
-static int ssl_check_clienthello_tlsext(SSL *ssl) {
+static int ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int ret = SSL_TLSEXT_ERR_NOACK;
int al = SSL_AD_UNRECOGNIZED_NAME;
@@ -2967,7 +3087,7 @@
return 1;
case SSL_TLSEXT_ERR_NOACK:
- ssl->s3->hs->should_ack_sni = 0;
+ hs->should_ack_sni = 0;
return 1;
default:
@@ -2975,7 +3095,8 @@
}
}
-static int ssl_check_serverhello_tlsext(SSL *ssl) {
+static int ssl_check_serverhello_tlsext(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
int ret = SSL_TLSEXT_ERR_OK;
int al = SSL_AD_UNRECOGNIZED_NAME;
@@ -3001,14 +3122,15 @@
}
}
-int ssl_parse_serverhello_tlsext(SSL *ssl, CBS *cbs) {
+int ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs) {
+ SSL *const ssl = hs->ssl;
int alert = -1;
- if (ssl_scan_serverhello_tlsext(ssl, cbs, &alert) <= 0) {
+ if (ssl_scan_serverhello_tlsext(hs, cbs, &alert) <= 0) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return 0;
}
- if (ssl_check_serverhello_tlsext(ssl) <= 0) {
+ if (ssl_check_serverhello_tlsext(hs) <= 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_SERVERHELLO_TLSEXT);
return 0;
}
@@ -3146,13 +3268,12 @@
return ret;
}
-int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *in_sigalgs) {
+int tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) {
/* Extension ignored for inappropriate versions */
- if (ssl3_protocol_version(ssl) < TLS1_2_VERSION) {
+ if (ssl3_protocol_version(hs->ssl) < TLS1_2_VERSION) {
return 1;
}
- SSL_HANDSHAKE *hs = ssl->s3->hs;
OPENSSL_free(hs->peer_sigalgs);
hs->peer_sigalgs = NULL;
hs->num_peer_sigalgs = 0;
@@ -3188,9 +3309,9 @@
return 1;
}
-int tls1_choose_signature_algorithm(SSL *ssl, uint16_t *out) {
+int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) {
+ SSL *const ssl = hs->ssl;
CERT *cert = ssl->cert;
- SSL_HANDSHAKE *hs = ssl->s3->hs;
/* Before TLS 1.2, the signature algorithm isn't negotiated as part of the
* handshake. It is fixed at MD5-SHA1 for RSA and SHA1 for ECDSA. */
@@ -3448,7 +3569,8 @@
return -1;
}
- ssl->s3->new_session->original_handshake_hash_len = digest_len;
+ assert(sizeof(ssl->s3->new_session->original_handshake_hash) < 256);
+ ssl->s3->new_session->original_handshake_hash_len = (uint8_t)digest_len;
return 1;
}
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 97860c4..b7f9c9d 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -65,7 +65,6 @@
#include "packeted_bio.h"
#include "test_config.h"
-namespace bssl {
#if !defined(OPENSSL_WINDOWS)
static int closesocket(int sock) {
@@ -246,7 +245,7 @@
return ssl_private_key_failure;
}
- ScopedEVP_MD_CTX ctx;
+ bssl::ScopedEVP_MD_CTX ctx;
EVP_PKEY_CTX *pctx;
if (!EVP_DigestSignInit(ctx.get(), &pctx, md, nullptr,
test_state->private_key.get())) {
@@ -438,9 +437,9 @@
return true;
}
-static int SelectCertificateCallback(const struct ssl_early_callback_ctx *ctx) {
- const TestConfig *config = GetTestConfig(ctx->ssl);
- GetTestState(ctx->ssl)->early_callback_called = true;
+static int SelectCertificateCallback(const SSL_CLIENT_HELLO *client_hello) {
+ const TestConfig *config = GetTestConfig(client_hello->ssl);
+ GetTestState(client_hello->ssl)->early_callback_called = true;
if (!config->expected_server_name.empty()) {
const uint8_t *extension_data;
@@ -448,9 +447,9 @@
CBS extension, server_name_list, host_name;
uint8_t name_type;
- if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
- &extension_data,
- &extension_len)) {
+ if (!SSL_early_callback_ctx_extension_get(
+ client_hello, TLSEXT_TYPE_server_name, &extension_data,
+ &extension_len)) {
fprintf(stderr, "Could not find server_name extension.\n");
return -1;
}
@@ -483,7 +482,7 @@
// Install the certificate asynchronously.
return 0;
}
- if (!InstallCertificate(ctx->ssl)) {
+ if (!InstallCertificate(client_hello->ssl)) {
return -1;
}
}
@@ -697,8 +696,8 @@
}
}
-static int DDoSCallback(const struct ssl_early_callback_ctx *early_context) {
- const TestConfig *config = GetTestConfig(early_context->ssl);
+static int DDoSCallback(const SSL_CLIENT_HELLO *client_hello) {
+ const TestConfig *config = GetTestConfig(client_hello->ssl);
static int callback_num = 0;
callback_num++;
@@ -981,7 +980,7 @@
SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), AlpnSelectCallback, NULL);
}
- SSL_CTX_enable_tls_channel_id(ssl_ctx.get());
+ SSL_CTX_set_tls_channel_id_enabled(ssl_ctx.get(), 1);
SSL_CTX_set_channel_id_cb(ssl_ctx.get(), ChannelIdCallback);
SSL_CTX_set_current_time_cb(ssl_ctx.get(), CurrentTimeCallback);
@@ -1520,10 +1519,10 @@
}
if (!config->expected_channel_id.empty() ||
config->enable_channel_id) {
- SSL_enable_tls_channel_id(ssl.get());
+ SSL_set_tls_channel_id_enabled(ssl.get(), 1);
}
if (!config->send_channel_id.empty()) {
- SSL_enable_tls_channel_id(ssl.get());
+ SSL_set_tls_channel_id_enabled(ssl.get(), 1);
if (!config->async) {
// The async case will be supplied by |ChannelIdCallback|.
bssl::UniquePtr<EVP_PKEY> pkey = LoadPrivateKey(config->send_channel_id);
@@ -1589,9 +1588,6 @@
if (!config->check_close_notify) {
SSL_set_quiet_shutdown(ssl.get(), 1);
}
- if (config->disable_npn) {
- SSL_set_options(ssl.get(), SSL_OP_DISABLE_NPN);
- }
if (config->p384_only) {
int nid = NID_secp384r1;
if (!SSL_set1_curves(ssl.get(), &nid, 1)) {
@@ -1873,7 +1869,7 @@
~StderrDelimiter() { fprintf(stderr, "--- DONE ---\n"); }
};
-static int Main(int argc, char **argv) {
+int main(int argc, char **argv) {
// To distinguish ASan's output from ours, add a trailing message to stderr.
// Anything following this line will be considered an error.
StderrDelimiter delimiter;
@@ -1941,9 +1937,3 @@
return 0;
}
-
-} // namespace bssl
-
-int main(int argc, char **argv) {
- return bssl::Main(argc, argv);
-}
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index a6496fd..9fbf5dc 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -1109,6 +1109,25 @@
// copies of each KeyShareEntry.
DuplicateKeyShares bool
+ // SendEarlyAlert, if true, sends a fatal alert after the ClientHello.
+ SendEarlyAlert bool
+
+ // SendEarlyDataLength, if non-zero, is the amount of early data to send after
+ // the ClientHello.
+ SendEarlyDataLength int
+
+ // OmitEarlyDataExtension, if true, causes the early data extension to
+ // be omitted in the ClientHello.
+ OmitEarlyDataExtension bool
+
+ // SendEarlyDataOnSecondClientHello, if true, causes the TLS 1.3 client to
+ // send early data after the second ClientHello.
+ SendEarlyDataOnSecondClientHello bool
+
+ // InterleaveEarlyData, if true, causes the TLS 1.3 client to send early
+ // data interleaved with the second ClientHello and the client Finished.
+ InterleaveEarlyData bool
+
// EmptyEncryptedExtensions, if true, causes the TLS 1.3 server to
// emit an empty EncryptedExtensions block.
EmptyEncryptedExtensions bool
@@ -1198,6 +1217,10 @@
// SendNoPSKBinder, if true, causes the client to send no PSK binders.
SendNoPSKBinder bool
+ // SendExtraPSKBinder, if true, causes the client to send an extra PSK
+ // binder.
+ SendExtraPSKBinder bool
+
// PSKBinderFirst, if true, causes the client to send the PSK Binder
// extension as the first extension instead of the last extension.
PSKBinderFirst bool
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index 39c2785..80a5b06 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -1768,3 +1768,16 @@
c.out.doKeyUpdate(c, true)
return nil
}
+
+func (c *Conn) sendFakeEarlyData(len int) error {
+ // Assemble a fake early data record. This does not use writeRecord
+ // because the record layer may be using different keys at this point.
+ payload := make([]byte, 5+len)
+ payload[0] = byte(recordTypeApplicationData)
+ payload[1] = 3
+ payload[2] = 1
+ payload[3] = byte(len >> 8)
+ payload[4] = byte(len)
+ _, err := c.conn.Write(payload)
+ return err
+}
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index d074778..7fa7ea2 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -319,6 +319,10 @@
hello.cipherSuites = c.config.Bugs.SendCipherSuites
}
+ if c.config.Bugs.SendEarlyDataLength > 0 && !c.config.Bugs.OmitEarlyDataExtension {
+ hello.hasEarlyData = true
+ }
+
var helloBytes []byte
if c.config.Bugs.SendV2ClientHello {
// Test that the peer left-pads random.
@@ -356,6 +360,12 @@
if err := c.simulatePacketLoss(nil); err != nil {
return err
}
+ if c.config.Bugs.SendEarlyAlert {
+ c.sendAlert(alertHandshakeFailure)
+ }
+ if c.config.Bugs.SendEarlyDataLength > 0 {
+ c.sendFakeEarlyData(c.config.Bugs.SendEarlyDataLength)
+ }
msg, err := c.readHandshake()
if err != nil {
return err
@@ -452,16 +462,28 @@
hello.hasKeyShares = false
}
- hello.hasEarlyData = false
+ hello.hasEarlyData = c.config.Bugs.SendEarlyDataOnSecondClientHello
hello.raw = nil
if len(hello.pskIdentities) > 0 {
generatePSKBinders(hello, pskCipherSuite, session.masterSecret, append(helloBytes, helloRetryRequest.marshal()...), c.config)
}
secondHelloBytes = hello.marshal()
- c.writeRecord(recordTypeHandshake, secondHelloBytes)
+
+ if c.config.Bugs.InterleaveEarlyData {
+ c.sendFakeEarlyData(4)
+ c.writeRecord(recordTypeHandshake, secondHelloBytes[:16])
+ c.sendFakeEarlyData(4)
+ c.writeRecord(recordTypeHandshake, secondHelloBytes[16:])
+ } else {
+ c.writeRecord(recordTypeHandshake, secondHelloBytes)
+ }
c.flushHandshake()
+ if c.config.Bugs.SendEarlyDataOnSecondClientHello {
+ c.sendFakeEarlyData(4)
+ }
+
msg, err = c.readHandshake()
if err != nil {
return err
@@ -622,7 +644,6 @@
//
// TODO(davidben): This will need to be handled slightly earlier once
// 0-RTT is implemented.
- var psk []byte
if hs.serverHello.hasPSKIdentity {
// We send at most one PSK identity.
if hs.session == nil || hs.serverHello.pskIdentity != 0 {
@@ -634,21 +655,18 @@
c.sendAlert(alertHandshakeFailure)
return errors.New("tls: server resumed an invalid session for the cipher suite")
}
- psk = hs.session.masterSecret
+ hs.finishedHash.addEntropy(hs.session.masterSecret)
c.didResume = true
} else {
- psk = zeroSecret
+ hs.finishedHash.addEntropy(zeroSecret)
}
- earlySecret := hs.finishedHash.extractKey(zeroSecret, psk)
-
if !hs.serverHello.hasKeyShare {
c.sendAlert(alertUnsupportedExtension)
return errors.New("tls: server omitted KeyShare on resumption.")
}
// Resolve ECDHE and compute the handshake secret.
- var ecdheSecret []byte
if !c.config.Bugs.MissingKeyShare && !c.config.Bugs.SecondClientHelloMissingKeyShare {
curve, ok := hs.keyShares[hs.serverHello.keyShare.group]
if !ok {
@@ -657,22 +675,19 @@
}
c.curveID = hs.serverHello.keyShare.group
- var err error
- ecdheSecret, err = curve.finish(hs.serverHello.keyShare.keyExchange)
+ ecdheSecret, err := curve.finish(hs.serverHello.keyShare.keyExchange)
if err != nil {
return err
}
+ hs.finishedHash.addEntropy(ecdheSecret)
} else {
- ecdheSecret = zeroSecret
+ hs.finishedHash.addEntropy(zeroSecret)
}
- // Compute the handshake secret.
- handshakeSecret := hs.finishedHash.extractKey(earlySecret, ecdheSecret)
-
// Switch to handshake traffic keys.
- clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, clientHandshakeTrafficLabel)
+ clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
c.out.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite)
- serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, serverHandshakeTrafficLabel)
+ serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
c.in.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite)
msg, err := c.readHandshake()
@@ -800,9 +815,9 @@
// 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)
- clientTrafficSecret := hs.finishedHash.deriveSecret(masterSecret, clientApplicationTrafficLabel)
- serverTrafficSecret := hs.finishedHash.deriveSecret(masterSecret, serverApplicationTrafficLabel)
+ hs.finishedHash.addEntropy(zeroSecret)
+ clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
+ serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
if certReq != nil && !c.config.Bugs.SkipClientCertificate {
certMsg := &certificateMsg{
@@ -871,6 +886,12 @@
if c.config.Bugs.PartialClientFinishedWithClientHello {
// The first byte has already been sent.
c.writeRecord(recordTypeHandshake, finished.marshal()[1:])
+ } else if c.config.Bugs.InterleaveEarlyData {
+ finishedBytes := finished.marshal()
+ c.sendFakeEarlyData(4)
+ c.writeRecord(recordTypeHandshake, finishedBytes[:1])
+ c.sendFakeEarlyData(4)
+ c.writeRecord(recordTypeHandshake, finishedBytes[1:])
} else {
c.writeRecord(recordTypeHandshake, finished.marshal())
}
@@ -883,8 +904,8 @@
c.out.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite)
c.in.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, serverWrite)
- c.exporterSecret = hs.finishedHash.deriveSecret(masterSecret, exporterLabel)
- c.resumptionSecret = hs.finishedHash.deriveSecret(masterSecret, resumptionLabel)
+ c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
+ c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
return nil
}
@@ -1648,11 +1669,16 @@
binderLen--
}
+ numBinders := 1
+ if config.Bugs.SendExtraPSKBinder {
+ numBinders++
+ }
+
// Fill hello.pskBinders with appropriate length arrays of zeros so the
// length prefixes are correct when computing the binder over the truncated
// ClientHello message.
- hello.pskBinders = make([][]byte, len(hello.pskIdentities))
- for i := range hello.pskIdentities {
+ hello.pskBinders = make([][]byte, numBinders)
+ for i := range hello.pskBinders {
hello.pskBinders[i] = make([]byte, binderLen)
}
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 67950ba..57566c5 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -501,15 +501,12 @@
}
// Resolve PSK and compute the early secret.
- var psk []byte
if hs.sessionState != nil {
- psk = hs.sessionState.masterSecret
+ hs.finishedHash.addEntropy(hs.sessionState.masterSecret)
} else {
- psk = hs.finishedHash.zeroSecret()
+ hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
}
- earlySecret := hs.finishedHash.extractKey(hs.finishedHash.zeroSecret(), psk)
-
hs.hello.hasKeyShare = true
if hs.sessionState != nil && config.Bugs.NegotiatePSKResumption {
hs.hello.hasKeyShare = false
@@ -647,7 +644,6 @@
}
// 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
@@ -672,13 +668,12 @@
peerKey = selectedKeyShare.keyExchange
}
- var publicKey []byte
- var err error
- publicKey, ecdheSecret, err = curve.accept(config.rand(), peerKey)
+ publicKey, ecdheSecret, err := curve.accept(config.rand(), peerKey)
if err != nil {
c.sendAlert(alertHandshakeFailure)
return err
}
+ hs.finishedHash.addEntropy(ecdheSecret)
hs.hello.hasKeyShare = true
curveID := selectedCurve
@@ -702,7 +697,7 @@
}
}
} else {
- ecdheSecret = hs.finishedHash.zeroSecret()
+ hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
}
// Send unencrypted ServerHello.
@@ -718,13 +713,10 @@
}
c.flushHandshake()
- // Compute the handshake secret.
- handshakeSecret := hs.finishedHash.extractKey(earlySecret, ecdheSecret)
-
// Switch to handshake traffic keys.
- serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, serverHandshakeTrafficLabel)
+ serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
c.out.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite)
- clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(handshakeSecret, clientHandshakeTrafficLabel)
+ clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
c.in.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite)
// Send EncryptedExtensions.
@@ -842,10 +834,10 @@
// 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())
- clientTrafficSecret := hs.finishedHash.deriveSecret(masterSecret, clientApplicationTrafficLabel)
- serverTrafficSecret := hs.finishedHash.deriveSecret(masterSecret, serverApplicationTrafficLabel)
- c.exporterSecret = hs.finishedHash.deriveSecret(masterSecret, exporterLabel)
+ hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
+ clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
+ serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
+ c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
// Switch to application data keys on write. In particular, any alerts
// from the client certificate are sent over these keys.
@@ -956,7 +948,7 @@
c.in.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite)
c.cipherSuite = hs.suite
- c.resumptionSecret = hs.finishedHash.deriveSecret(masterSecret, resumptionLabel)
+ c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
// TODO(davidben): Allow configuring the number of tickets sent for
// testing.
diff --git a/src/ssl/test/runner/prf.go b/src/ssl/test/runner/prf.go
index c311e99..cfc383d 100644
--- a/src/ssl/test/runner/prf.go
+++ b/src/ssl/test/runner/prf.go
@@ -129,14 +129,8 @@
return prf30
case VersionTLS10, VersionTLS11:
return prf10
- // TODO(nharper): VersionTLS13 is in the case statement below only to
- // support Fake TLS 1.3. Real TLS 1.3 should never call this function.
- // Once we no longer support Fake TLS 1.3, the VersionTLS13 should be
- // removed from this case statement.
- case VersionTLS12, VersionTLS13:
- if version == VersionTLS12 {
- return prf12(suite.hash().New)
- }
+ case VersionTLS12:
+ return prf12(suite.hash().New)
}
panic("unknown version")
}
@@ -197,6 +191,8 @@
if version == VersionTLS12 {
ret.prf = prf12(ret.hash.New)
+ } else {
+ ret.secret = make([]byte, ret.hash.Size())
}
} else {
ret.hash = crypto.MD5SHA1
@@ -232,6 +228,9 @@
version uint16
prf func(result, secret, label, seed []byte)
+
+ // secret, in TLS 1.3, is the running input secret.
+ secret []byte
}
func (h *finishedHash) Write(msg []byte) (n int, err error) {
@@ -370,10 +369,9 @@
return make([]byte, h.hash.Size())
}
-// extractKey combines two secrets together with HKDF-Expand in the TLS 1.3 key
-// derivation schedule.
-func (h *finishedHash) extractKey(salt, ikm []byte) []byte {
- return hkdfExtract(h.hash.New, salt, ikm)
+// addEntropy incorporates ikm into the running TLS 1.3 secret with HKDF-Expand.
+func (h *finishedHash) addEntropy(ikm []byte) {
+ h.secret = hkdfExtract(h.hash.New, h.secret, ikm)
}
// hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined
@@ -420,8 +418,8 @@
// deriveSecret implements TLS 1.3's Derive-Secret function, as defined in
// section 7.1 of draft ietf-tls-tls13-16.
-func (h *finishedHash) deriveSecret(secret, label []byte) []byte {
- return hkdfExpandLabel(h.hash, secret, label, h.appendContextHashes(nil), h.hash.Size())
+func (h *finishedHash) deriveSecret(label []byte) []byte {
+ return hkdfExpandLabel(h.hash, h.secret, label, h.appendContextHashes(nil), h.hash.Size())
}
// The following are context strings for CertificateVerify in TLS 1.3.
@@ -472,8 +470,8 @@
func computePSKBinder(psk, label []byte, cipherSuite *cipherSuite, transcript, truncatedHello []byte) []byte {
finishedHash := newFinishedHash(VersionTLS13, cipherSuite)
- earlySecret := finishedHash.extractKey(finishedHash.zeroSecret(), psk)
- binderKey := finishedHash.deriveSecret(earlySecret, label)
+ finishedHash.addEntropy(psk)
+ binderKey := finishedHash.deriveSecret(label)
finishedHash.Write(transcript)
finishedHash.Write(truncatedHello)
return finishedHash.clientSum(binderKey)
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 683f07c..15895d6 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -835,6 +835,18 @@
panic("expectResumeRejected without resumeSession in " + test.name)
}
+ for _, ver := range tlsVersions {
+ if !strings.Contains("-"+test.name+"-", "-"+ver.name+"-") {
+ continue
+ }
+
+ if test.config.MaxVersion != 0 || test.config.MinVersion != 0 || test.expectedVersion != 0 {
+ continue
+ }
+
+ panic(fmt.Sprintf("The name of test %q suggests that it's version specific, but min/max version in the Config is %x/%x. One of them should probably be %x", test.name, test.config.MinVersion, test.config.MaxVersion, ver.version))
+ }
+
listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
if err != nil {
panic(err)
@@ -4973,20 +4985,6 @@
shouldFail: true,
expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
})
-
- // Test that NPN can be disabled with SSL_OP_DISABLE_NPN.
- testCases = append(testCases, testCase{
- name: "DisableNPN-" + ver.name,
- config: Config{
- MaxVersion: ver.version,
- NextProtos: []string{"foo"},
- },
- flags: []string{
- "-select-next-proto", "foo",
- "-disable-npn",
- },
- expectNoNextProto: true,
- })
}
// Test ticket behavior.
@@ -5568,7 +5566,7 @@
"-signed-cert-timestamps",
base64.StdEncoding.EncodeToString([]byte{0, 0}),
},
- shouldFail: true,
+ shouldFail: true,
expectedError: ":INVALID_SCT_LIST:",
})
}
@@ -5979,6 +5977,36 @@
testCases = append(testCases, testCase{
testType: serverTest,
+ name: "Resume-Server-ExtraPSKBinder",
+ resumeSession: true,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendExtraPSKBinder: true,
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: illegal parameter",
+ expectedError: ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "Resume-Server-ExtraIdentityNoBinder",
+ resumeSession: true,
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ ExtraPSKIdentity: true,
+ },
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: illegal parameter",
+ expectedError: ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
name: "Resume-Server-InvalidPSKBinder",
resumeSession: true,
config: Config{
@@ -9033,6 +9061,144 @@
})
testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyDataLength: 4,
+ },
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-OmitEarlyDataExtension",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyDataLength: 4,
+ OmitEarlyDataExtension: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-TooMuchData",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyDataLength: 16384 + 1,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-Interleaved",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyDataLength: 4,
+ InterleaveEarlyData: true,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-EarlyDataInTLS12",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyDataLength: 4,
+ },
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-HRR",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyDataLength: 4,
+ },
+ DefaultCurves: []CurveID{},
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-HRR-Interleaved",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyDataLength: 4,
+ InterleaveEarlyData: true,
+ },
+ DefaultCurves: []CurveID{},
+ },
+ shouldFail: true,
+ expectedError: ":UNEXPECTED_RECORD:",
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-HRR-TooMuchData",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyDataLength: 16384 + 1,
+ },
+ DefaultCurves: []CurveID{},
+ },
+ shouldFail: true,
+ expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
+ })
+
+ // Test that skipping early data looking for cleartext correctly
+ // processes an alert record.
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-HRR-FatalAlert",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyAlert: true,
+ SendEarlyDataLength: 4,
+ },
+ DefaultCurves: []CurveID{},
+ },
+ shouldFail: true,
+ expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:",
+ })
+
+ testCases = append(testCases, testCase{
+ testType: serverTest,
+ name: "SkipEarlyData-SecondClientHelloEarlyData",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ Bugs: ProtocolBugs{
+ SendEarlyDataOnSecondClientHello: true,
+ },
+ DefaultCurves: []CurveID{},
+ },
+ shouldFail: true,
+ expectedLocalError: "remote error: bad record MAC",
+ })
+
+ testCases = append(testCases, testCase{
testType: clientTest,
name: "EmptyEncryptedExtensions",
config: Config{
@@ -9364,7 +9530,8 @@
config: Config{
MaxVersion: VersionTLS13,
Bugs: ProtocolBugs{
- ExtraPSKIdentity: true,
+ ExtraPSKIdentity: true,
+ SendExtraPSKBinder: true,
},
},
resumeSession: true,
@@ -9559,6 +9726,8 @@
testType: clientTest,
name: "SendReceiveIntermediate-Client-" + ver.name,
config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
Certificates: []Certificate{rsaChainCertificate},
ClientAuth: RequireAnyClientCert,
},
@@ -9574,6 +9743,8 @@
testType: serverTest,
name: "SendReceiveIntermediate-Server-" + ver.name,
config: Config{
+ MinVersion: ver.version,
+ MaxVersion: ver.version,
Certificates: []Certificate{rsaChainCertificate},
},
expectPeerCertificate: &rsaChainCertificate,
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 940e676..9b9e20c 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -97,7 +97,6 @@
{ "-renegotiate-once", &TestConfig::renegotiate_once },
{ "-renegotiate-freely", &TestConfig::renegotiate_freely },
{ "-renegotiate-ignore", &TestConfig::renegotiate_ignore },
- { "-disable-npn", &TestConfig::disable_npn },
{ "-p384-only", &TestConfig::p384_only },
{ "-enable-all-curves", &TestConfig::enable_all_curves },
{ "-use-sparse-dh-prime", &TestConfig::use_sparse_dh_prime },
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index ed1a47b..76cd5fb 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -102,7 +102,6 @@
bool renegotiate_once = false;
bool renegotiate_freely = false;
bool renegotiate_ignore = false;
- bool disable_npn = false;
int expect_peer_signature_algorithm = 0;
bool p384_only = false;
bool enable_all_curves = false;
diff --git a/src/ssl/tls13_both.c b/src/ssl/tls13_both.c
index 17f7161..ea3eb77 100644
--- a/src/ssl/tls13_both.c
+++ b/src/ssl/tls13_both.c
@@ -34,9 +34,8 @@
* without being able to return application data. */
static const uint8_t kMaxKeyUpdates = 32;
-int tls13_handshake(SSL *ssl) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
-
+int tls13_handshake(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
for (;;) {
/* Resolve the operation the handshake was waiting on. */
switch (hs->wait) {
@@ -95,7 +94,7 @@
}
/* Run the state machine again. */
- hs->wait = hs->do_handshake(ssl);
+ hs->wait = hs->do_tls13_handshake(hs);
if (hs->wait == ssl_hs_error) {
/* Don't loop around to avoid a stray |SSL_R_SSL_HANDSHAKE_FAILURE| the
* first time around. */
@@ -402,10 +401,11 @@
return 1;
}
-int tls13_process_finished(SSL *ssl) {
+int tls13_process_finished(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
uint8_t verify_data[EVP_MAX_MD_SIZE];
size_t verify_data_len;
- if (!tls13_finished_mac(ssl, verify_data, &verify_data_len, !ssl->server)) {
+ if (!tls13_finished_mac(hs, verify_data, &verify_data_len, !ssl->server)) {
return 0;
}
@@ -424,7 +424,8 @@
return 1;
}
-int tls13_prepare_certificate(SSL *ssl) {
+int tls13_prepare_certificate(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
CBB cbb, body, certificate_list;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE) ||
/* The request context is always empty in the handshake. */
@@ -451,7 +452,7 @@
goto err;
}
- if (ssl->s3->hs->scts_requested &&
+ if (hs->scts_requested &&
ssl->ctx->signed_cert_timestamp_list_length != 0) {
CBB contents;
if (!CBB_add_u16(&extensions, TLSEXT_TYPE_certificate_timestamp) ||
@@ -464,7 +465,7 @@
}
}
- if (ssl->s3->hs->ocsp_stapling_requested &&
+ if (hs->ocsp_stapling_requested &&
ssl->ctx->ocsp_response_length != 0) {
CBB contents, ocsp_response;
if (!CBB_add_u16(&extensions, TLSEXT_TYPE_status_request) ||
@@ -501,7 +502,8 @@
}
enum ssl_private_key_result_t tls13_prepare_certificate_verify(
- SSL *ssl, int is_first_run) {
+ SSL_HANDSHAKE *hs, int is_first_run) {
+ SSL *const ssl = hs->ssl;
enum ssl_private_key_result_t ret = ssl_private_key_failure;
uint8_t *msg = NULL;
size_t msg_len;
@@ -509,7 +511,7 @@
CBB_zero(&cbb);
uint16_t signature_algorithm;
- if (!tls1_choose_signature_algorithm(ssl, &signature_algorithm)) {
+ if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) {
goto err;
}
if (!ssl->method->init_message(ssl, &cbb, &body,
@@ -562,11 +564,12 @@
return ret;
}
-int tls13_prepare_finished(SSL *ssl) {
+int tls13_prepare_finished(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
size_t verify_data_len;
uint8_t verify_data[EVP_MAX_MD_SIZE];
- if (!tls13_finished_mac(ssl, verify_data, &verify_data_len, ssl->server)) {
+ if (!tls13_finished_mac(hs, verify_data, &verify_data_len, ssl->server)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
return 0;
diff --git a/src/ssl/tls13_client.c b/src/ssl/tls13_client.c
index 4a30ce3..7a09fb1 100644
--- a/src/ssl/tls13_client.c
+++ b/src/ssl/tls13_client.c
@@ -48,8 +48,10 @@
state_done,
};
-static enum ssl_hs_wait_t do_process_hello_retry_request(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
+
+static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST) {
hs->state = state_process_server_hello;
return ssl_hs_ok;
@@ -140,9 +142,8 @@
return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_send_second_client_hello(SSL *ssl,
- SSL_HANDSHAKE *hs) {
- if (!ssl_write_client_hello(ssl)) {
+static enum ssl_hs_wait_t do_send_second_client_hello(SSL_HANDSHAKE *hs) {
+ if (!ssl_write_client_hello(hs)) {
return ssl_hs_error;
}
@@ -150,13 +151,13 @@
return ssl_hs_write_message;
}
-static enum ssl_hs_wait_t do_flush_second_client_hello(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_flush_second_client_hello(SSL_HANDSHAKE *hs) {
hs->state = state_process_server_hello;
return ssl_hs_flush_and_read_message;
}
-static enum ssl_hs_wait_t do_process_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!tls13_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) {
return ssl_hs_error;
}
@@ -229,7 +230,7 @@
return ssl_hs_error;
}
- if (!ssl_ext_pre_shared_key_parse_serverhello(ssl, &alert,
+ if (!ssl_ext_pre_shared_key_parse_serverhello(hs, &alert,
&pre_shared_key)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
@@ -264,7 +265,7 @@
return ssl_hs_error;
}
ssl_set_session(ssl, NULL);
- } else if (!ssl_get_new_session(ssl, 0)) {
+ } else if (!ssl_get_new_session(hs, 0)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
@@ -275,33 +276,30 @@
/* The PRF hash is now known. Set up the key schedule. */
size_t hash_len =
EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
-
- /* Derive resumption material. */
- uint8_t psk_secret[EVP_MAX_MD_SIZE] = {0};
- if (ssl->s3->session_reused) {
- if (hash_len != (size_t) ssl->s3->new_session->master_key_length) {
- return ssl_hs_error;
- }
- memcpy(psk_secret, ssl->s3->new_session->master_key, hash_len);
+ if (!tls13_init_key_schedule(hs)) {
+ return ssl_hs_error;
}
- /* Set up the key schedule, hash in the ClientHello, and incorporate the PSK
- * into the running secret. */
- if (!tls13_init_key_schedule(ssl) ||
- !tls13_advance_key_schedule(ssl, psk_secret, hash_len)) {
+ /* Incorporate the PSK into the running secret. */
+ if (ssl->s3->session_reused) {
+ if (!tls13_advance_key_schedule(hs, ssl->s3->new_session->master_key,
+ ssl->s3->new_session->master_key_length)) {
+ return ssl_hs_error;
+ }
+ } else if (!tls13_advance_key_schedule(hs, kZeroes, hash_len)) {
return ssl_hs_error;
}
/* Resolve ECDHE and incorporate it into the secret. */
uint8_t *dhe_secret;
size_t dhe_secret_len;
- if (!ssl_ext_key_share_parse_serverhello(ssl, &dhe_secret, &dhe_secret_len,
+ if (!ssl_ext_key_share_parse_serverhello(hs, &dhe_secret, &dhe_secret_len,
&alert, &key_share)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
- if (!tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len)) {
+ if (!tls13_advance_key_schedule(hs, dhe_secret, dhe_secret_len)) {
OPENSSL_free(dhe_secret);
return ssl_hs_error;
}
@@ -314,7 +312,7 @@
return ssl_hs_error;
}
- if (!tls13_set_handshake_traffic(ssl)) {
+ if (!tls13_set_handshake_traffic(hs)) {
return ssl_hs_error;
}
@@ -322,15 +320,15 @@
return ssl_hs_read_message;
}
-static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!tls13_check_message_type(ssl, SSL3_MT_ENCRYPTED_EXTENSIONS)) {
return ssl_hs_error;
}
CBS cbs;
CBS_init(&cbs, ssl->init_msg, ssl->init_num);
- if (!ssl_parse_serverhello_tlsext(ssl, &cbs)) {
+ if (!ssl_parse_serverhello_tlsext(hs, &cbs)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
return ssl_hs_error;
}
@@ -348,8 +346,8 @@
return ssl_hs_read_message;
}
-static enum ssl_hs_wait_t do_process_certificate_request(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
/* CertificateRequest may only be sent in non-resumption handshakes. */
if (ssl->s3->session_reused) {
hs->state = state_process_server_finished;
@@ -369,7 +367,7 @@
CBS_len(&context) != 0 ||
!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) ||
CBS_len(&supported_signature_algorithms) == 0 ||
- !tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) {
+ !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
return ssl_hs_error;
@@ -392,9 +390,9 @@
return ssl_hs_error;
}
- 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;
+ hs->cert_request = 1;
+ sk_X509_NAME_pop_free(hs->ca_names, X509_NAME_free);
+ hs->ca_names = ca_sk;
if (!ssl_hash_current_message(ssl)) {
return ssl_hs_error;
@@ -404,8 +402,8 @@
return ssl_hs_read_message;
}
-static enum ssl_hs_wait_t do_process_server_certificate(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_server_certificate(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
!tls13_process_certificate(ssl, 0 /* certificate required */) ||
!ssl_hash_current_message(ssl)) {
@@ -417,7 +415,8 @@
}
static enum ssl_hs_wait_t do_process_server_certificate_verify(
- SSL *ssl, SSL_HANDSHAKE *hs) {
+ SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!tls13_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
!tls13_process_certificate_verify(ssl) ||
!ssl_hash_current_message(ssl)) {
@@ -428,15 +427,14 @@
return ssl_hs_read_message;
}
-static enum ssl_hs_wait_t do_process_server_finished(SSL *ssl,
- SSL_HANDSHAKE *hs) {
- static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
+static enum ssl_hs_wait_t do_process_server_finished(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
- !tls13_process_finished(ssl) ||
+ !tls13_process_finished(hs) ||
!ssl_hash_current_message(ssl) ||
/* Update the secret to the master secret and derive traffic keys. */
- !tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
- !tls13_derive_application_secrets(ssl)) {
+ !tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) ||
+ !tls13_derive_application_secrets(hs)) {
return ssl_hs_error;
}
@@ -445,9 +443,10 @@
return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_certificate_callback(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_certificate_callback(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
/* The peer didn't request a certificate. */
- if (!ssl->s3->hs->cert_request) {
+ if (!hs->cert_request) {
hs->state = state_send_channel_id;
return ssl_hs_ok;
}
@@ -470,8 +469,8 @@
return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_send_client_certificate(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_client_certificate(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
/* Call client_cert_cb to update the certificate. */
int should_retry;
if (!ssl_do_client_cert_cb(ssl, &should_retry)) {
@@ -482,7 +481,7 @@
return ssl_hs_error;
}
- if (!tls13_prepare_certificate(ssl)) {
+ if (!tls13_prepare_certificate(hs)) {
return ssl_hs_error;
}
@@ -490,16 +489,16 @@
return ssl_hs_write_message;
}
-static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL *ssl,
- SSL_HANDSHAKE *hs,
+static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs,
int is_first_run) {
+ SSL *const ssl = hs->ssl;
/* Don't send CertificateVerify if there is no certificate. */
if (!ssl_has_certificate(ssl)) {
hs->state = state_send_channel_id;
return ssl_hs_ok;
}
- switch (tls13_prepare_certificate_verify(ssl, is_first_run)) {
+ switch (tls13_prepare_certificate_verify(hs, is_first_run)) {
case ssl_private_key_success:
hs->state = state_send_channel_id;
return ssl_hs_write_message;
@@ -516,7 +515,8 @@
return ssl_hs_error;
}
-static enum ssl_hs_wait_t do_send_channel_id(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_channel_id(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!ssl->s3->tlsext_channel_id_valid) {
hs->state = state_send_client_finished;
return ssl_hs_ok;
@@ -542,8 +542,8 @@
return ssl_hs_write_message;
}
-static enum ssl_hs_wait_t do_send_client_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
- if (!tls13_prepare_finished(ssl)) {
+static enum ssl_hs_wait_t do_send_client_finished(SSL_HANDSHAKE *hs) {
+ if (!tls13_prepare_finished(hs)) {
return ssl_hs_error;
}
@@ -551,12 +551,13 @@
return ssl_hs_write_message;
}
-static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_flush(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->server_traffic_secret_0,
hs->hash_len) ||
!tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_traffic_secret_0,
hs->hash_len) ||
- !tls13_derive_resumption_secret(ssl)) {
+ !tls13_derive_resumption_secret(hs)) {
return ssl_hs_error;
}
@@ -564,60 +565,58 @@
return ssl_hs_flush;
}
-enum ssl_hs_wait_t tls13_client_handshake(SSL *ssl) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
-
+enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) {
while (hs->state != state_done) {
enum ssl_hs_wait_t ret = ssl_hs_error;
enum client_hs_state_t state = hs->state;
switch (state) {
case state_process_hello_retry_request:
- ret = do_process_hello_retry_request(ssl, hs);
+ ret = do_process_hello_retry_request(hs);
break;
case state_send_second_client_hello:
- ret = do_send_second_client_hello(ssl, hs);
+ ret = do_send_second_client_hello(hs);
break;
case state_flush_second_client_hello:
- ret = do_flush_second_client_hello(ssl, hs);
+ ret = do_flush_second_client_hello(hs);
break;
case state_process_server_hello:
- ret = do_process_server_hello(ssl, hs);
+ ret = do_process_server_hello(hs);
break;
case state_process_encrypted_extensions:
- ret = do_process_encrypted_extensions(ssl, hs);
+ ret = do_process_encrypted_extensions(hs);
break;
case state_process_certificate_request:
- ret = do_process_certificate_request(ssl, hs);
+ ret = do_process_certificate_request(hs);
break;
case state_process_server_certificate:
- ret = do_process_server_certificate(ssl, hs);
+ ret = do_process_server_certificate(hs);
break;
case state_process_server_certificate_verify:
- ret = do_process_server_certificate_verify(ssl, hs);
+ ret = do_process_server_certificate_verify(hs);
break;
case state_process_server_finished:
- ret = do_process_server_finished(ssl, hs);
+ ret = do_process_server_finished(hs);
break;
case state_certificate_callback:
- ret = do_certificate_callback(ssl, hs);
+ ret = do_certificate_callback(hs);
break;
case state_send_client_certificate:
- ret = do_send_client_certificate(ssl, hs);
+ ret = do_send_client_certificate(hs);
break;
case state_send_client_certificate_verify:
- ret = do_send_client_certificate_verify(ssl, hs, 1 /* first run */);
+ ret = do_send_client_certificate_verify(hs, 1 /* first run */);
break;
case state_complete_client_certificate_verify:
- ret = do_send_client_certificate_verify(ssl, hs, 0 /* complete */);
+ ret = do_send_client_certificate_verify(hs, 0 /* complete */);
break;
case state_send_channel_id:
- ret = do_send_channel_id(ssl, hs);
+ ret = do_send_channel_id(hs);
break;
case state_send_client_finished:
- ret = do_send_client_finished(ssl, hs);
+ ret = do_send_client_finished(hs);
break;
case state_flush:
- ret = do_flush(ssl, hs);
+ ret = do_flush(hs);
break;
case state_done:
ret = ssl_hs_ok;
@@ -669,10 +668,10 @@
return 1;
}
-void ssl_clear_tls13_state(SSL *ssl) {
- SSL_ECDH_CTX_cleanup(&ssl->s3->hs->ecdh_ctx);
+void ssl_clear_tls13_state(SSL_HANDSHAKE *hs) {
+ SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
- OPENSSL_free(ssl->s3->hs->key_share_bytes);
- ssl->s3->hs->key_share_bytes = NULL;
- ssl->s3->hs->key_share_bytes_len = 0;
+ OPENSSL_free(hs->key_share_bytes);
+ hs->key_share_bytes = NULL;
+ hs->key_share_bytes_len = 0;
}
diff --git a/src/ssl/tls13_enc.c b/src/ssl/tls13_enc.c
index d87d8a6..4fca65b 100644
--- a/src/ssl/tls13_enc.c
+++ b/src/ssl/tls13_enc.c
@@ -27,8 +27,8 @@
#include "internal.h"
-int tls13_init_key_schedule(SSL *ssl) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
+int tls13_init_key_schedule(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
hs->hash_len = EVP_MD_size(digest);
@@ -44,9 +44,10 @@
return 1;
}
-int tls13_advance_key_schedule(SSL *ssl, const uint8_t *in, size_t len) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
- const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
+int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
+ size_t len) {
+ const EVP_MD *digest =
+ ssl_get_handshake_digest(ssl_get_algorithm_prf(hs->ssl));
return HKDF_extract(hs->secret, &hs->hash_len, digest, in, len, hs->secret,
hs->hash_len);
@@ -97,9 +98,9 @@
/* derive_secret derives a secret of length |len| and writes the result in |out|
* with the given label and the current base secret and most recently-saved
* handshake context. It returns one on success and zero on error. */
-static int derive_secret(SSL *ssl, uint8_t *out, size_t len,
+static int derive_secret(SSL_HANDSHAKE *hs, uint8_t *out, size_t len,
const uint8_t *label, size_t label_len) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
+ SSL *const ssl = hs->ssl;
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
uint8_t context_hash[EVP_MAX_MD_SIZE];
@@ -184,17 +185,16 @@
static const char kTLS13LabelServerApplicationTraffic[] =
"server application traffic secret";
-int tls13_set_handshake_traffic(SSL *ssl) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
-
+int tls13_set_handshake_traffic(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
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,
+ if (!derive_secret(hs, 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,
+ !derive_secret(hs, server_traffic_secret, hs->hash_len,
(const uint8_t *)kTLS13LabelServerHandshakeTraffic,
strlen(kTLS13LabelServerHandshakeTraffic)) ||
!ssl_log_secret(ssl, "SERVER_HANDSHAKE_TRAFFIC_SECRET",
@@ -222,21 +222,20 @@
static const char kTLS13LabelExporter[] = "exporter master secret";
-int tls13_derive_application_secrets(SSL *ssl) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
-
+int tls13_derive_application_secrets(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
ssl->s3->exporter_secret_len = hs->hash_len;
- return derive_secret(ssl, hs->client_traffic_secret_0, hs->hash_len,
+ return derive_secret(hs, 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,
+ derive_secret(hs, 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) &&
- derive_secret(ssl, ssl->s3->exporter_secret, hs->hash_len,
+ derive_secret(hs, ssl->s3->exporter_secret, hs->hash_len,
(const uint8_t *)kTLS13LabelExporter,
strlen(kTLS13LabelExporter));
}
@@ -269,9 +268,15 @@
static const char kTLS13LabelResumption[] = "resumption master secret";
-int tls13_derive_resumption_secret(SSL *ssl) {
- ssl->s3->new_session->master_key_length = ssl->s3->hs->hash_len;
- return derive_secret(ssl, ssl->s3->new_session->master_key,
+int tls13_derive_resumption_secret(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ if (ssl->s3->hs->hash_len > SSL_MAX_MASTER_KEY_LENGTH) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+
+ ssl->s3->new_session->master_key_length = hs->hash_len;
+ return derive_secret(hs, ssl->s3->new_session->master_key,
ssl->s3->new_session->master_key_length,
(const uint8_t *)kTLS13LabelResumption,
strlen(kTLS13LabelResumption));
@@ -297,8 +302,9 @@
return 1;
}
-int tls13_finished_mac(SSL *ssl, uint8_t *out, size_t *out_len, int is_server) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
+int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len,
+ int is_server) {
+ SSL *const ssl = hs->ssl;
const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
const uint8_t *traffic_secret;
diff --git a/src/ssl/tls13_server.c b/src/ssl/tls13_server.c
index 83ef679..626d2ee 100644
--- a/src/ssl/tls13_server.c
+++ b/src/ssl/tls13_server.c
@@ -53,14 +53,15 @@
static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
-static int resolve_ecdhe_secret(SSL *ssl, int *out_need_retry,
- struct ssl_early_callback_ctx *early_ctx) {
+static int resolve_ecdhe_secret(SSL_HANDSHAKE *hs, int *out_need_retry,
+ SSL_CLIENT_HELLO *client_hello) {
+ SSL *const ssl = hs->ssl;
*out_need_retry = 0;
/* We only support connections that include an ECDHE key exchange. */
CBS key_share;
- if (!ssl_early_callback_get_extension(early_ctx, &key_share,
- TLSEXT_TYPE_key_share)) {
+ if (!ssl_client_hello_get_extension(client_hello, &key_share,
+ TLSEXT_TYPE_key_share)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
return 0;
@@ -70,7 +71,7 @@
uint8_t *dhe_secret;
size_t dhe_secret_len;
uint8_t alert = SSL_AD_DECODE_ERROR;
- if (!ssl_ext_key_share_parse_clienthello(ssl, &found_key_share, &dhe_secret,
+ if (!ssl_ext_key_share_parse_clienthello(hs, &found_key_share, &dhe_secret,
&dhe_secret_len, &alert,
&key_share)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
@@ -82,19 +83,20 @@
return 0;
}
- int ok = tls13_advance_key_schedule(ssl, dhe_secret, dhe_secret_len);
+ int ok = tls13_advance_key_schedule(hs, dhe_secret, dhe_secret_len);
OPENSSL_free(dhe_secret);
return ok;
}
-static enum ssl_hs_wait_t do_process_client_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_client_hello(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
return ssl_hs_error;
}
- struct ssl_early_callback_ctx client_hello;
- if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
- ssl->init_num)) {
+ SSL_CLIENT_HELLO client_hello;
+ if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+ ssl->init_num)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
@@ -118,7 +120,7 @@
}
/* TLS extensions. */
- if (!ssl_parse_clienthello_tlsext(ssl, &client_hello)) {
+ if (!ssl_parse_clienthello_tlsext(hs, &client_hello)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
return ssl_hs_error;
}
@@ -128,7 +130,7 @@
}
static const SSL_CIPHER *choose_tls13_cipher(
- const SSL *ssl, const struct ssl_early_callback_ctx *client_hello) {
+ const SSL *ssl, const SSL_CLIENT_HELLO *client_hello) {
if (client_hello->cipher_suites_len % 2 != 0) {
return NULL;
}
@@ -173,7 +175,8 @@
return best;
}
-static enum ssl_hs_wait_t do_select_parameters(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
/* Call |cert_cb| to update server certificates if required. */
if (ssl->cert->cert_cb != NULL) {
int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
@@ -188,9 +191,9 @@
}
}
- struct ssl_early_callback_ctx client_hello;
- if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
- ssl->init_num)) {
+ SSL_CLIENT_HELLO client_hello;
+ if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+ ssl->init_num)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
@@ -209,8 +212,8 @@
SSL_SESSION *session = NULL;
CBS pre_shared_key, binders;
if (hs->accept_psk_mode &&
- ssl_early_callback_get_extension(&client_hello, &pre_shared_key,
- TLSEXT_TYPE_pre_shared_key)) {
+ ssl_client_hello_get_extension(&client_hello, &pre_shared_key,
+ TLSEXT_TYPE_pre_shared_key)) {
/* Verify that the pre_shared_key extension is the last extension in
* ClientHello. */
if (CBS_data(&pre_shared_key) + CBS_len(&pre_shared_key) !=
@@ -220,7 +223,7 @@
return ssl_hs_error;
}
- if (!ssl_ext_pre_shared_key_parse_clienthello(ssl, &session, &binders,
+ if (!ssl_ext_pre_shared_key_parse_clienthello(hs, &session, &binders,
&alert, &pre_shared_key)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
@@ -236,7 +239,7 @@
/* Set up the new session, either using the original one as a template or
* creating a fresh one. */
if (session == NULL) {
- if (!ssl_get_new_session(ssl, 1 /* server */)) {
+ if (!ssl_get_new_session(hs, 1 /* server */)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
@@ -244,8 +247,8 @@
ssl->s3->new_session->cipher = ssl->s3->tmp.new_cipher;
/* On new sessions, stash the SNI value in the session. */
- if (ssl->s3->hs->hostname != NULL) {
- ssl->s3->new_session->tlsext_hostname = BUF_strdup(ssl->s3->hs->hostname);
+ if (hs->hostname != NULL) {
+ ssl->s3->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
if (ssl->s3->new_session->tlsext_hostname == NULL) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
@@ -279,28 +282,25 @@
/* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was
* deferred. Complete it now. */
- if (!ssl_negotiate_alpn(ssl, &alert, &client_hello)) {
+ if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
return ssl_hs_error;
}
- /* The PRF hash is now known. */
+ /* The PRF hash is now known. Set up the key schedule. */
size_t hash_len =
EVP_MD_size(ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl)));
-
- /* Derive resumption material. */
- uint8_t psk_secret[EVP_MAX_MD_SIZE] = {0};
- if (ssl->s3->session_reused) {
- if (hash_len != (size_t) ssl->s3->new_session->master_key_length) {
- return ssl_hs_error;
- }
- memcpy(psk_secret, ssl->s3->new_session->master_key, hash_len);
+ if (!tls13_init_key_schedule(hs)) {
+ return ssl_hs_error;
}
- /* Set up the key schedule, hash in the ClientHello, and incorporate the PSK
- * into the running secret. */
- if (!tls13_init_key_schedule(ssl) ||
- !tls13_advance_key_schedule(ssl, psk_secret, hash_len)) {
+ /* Incorporate the PSK into the running secret. */
+ if (ssl->s3->session_reused) {
+ if (!tls13_advance_key_schedule(hs, ssl->s3->new_session->master_key,
+ ssl->s3->new_session->master_key_length)) {
+ return ssl_hs_error;
+ }
+ } else if (!tls13_advance_key_schedule(hs, kZeroes, hash_len)) {
return ssl_hs_error;
}
@@ -308,7 +308,7 @@
/* Resolve ECDHE and incorporate it into the secret. */
int need_retry;
- if (!resolve_ecdhe_secret(ssl, &need_retry, &client_hello)) {
+ if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
if (need_retry) {
hs->state = state_send_hello_retry_request;
return ssl_hs_ok;
@@ -320,14 +320,14 @@
return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_send_hello_retry_request(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
CBB cbb, body, extensions;
uint16_t group_id;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_HELLO_RETRY_REQUEST) ||
!CBB_add_u16(&body, ssl->version) ||
- !tls1_get_shared_group(ssl, &group_id) ||
+ !tls1_get_shared_group(hs, &group_id) ||
!CBB_add_u16_length_prefixed(&body, &extensions) ||
!CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
!CBB_add_u16(&extensions, 2 /* length */) ||
@@ -341,28 +341,27 @@
return ssl_hs_write_message;
}
-static enum ssl_hs_wait_t do_flush_hello_retry_request(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_flush_hello_retry_request(SSL_HANDSHAKE *hs) {
hs->state = state_process_second_client_hello;
return ssl_hs_flush_and_read_message;
}
-static enum ssl_hs_wait_t do_process_second_client_hello(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!tls13_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
return ssl_hs_error;
}
- struct ssl_early_callback_ctx client_hello;
- if (!ssl_early_callback_init(ssl, &client_hello, ssl->init_msg,
- ssl->init_num)) {
+ SSL_CLIENT_HELLO client_hello;
+ if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+ ssl->init_num)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
return ssl_hs_error;
}
int need_retry;
- if (!resolve_ecdhe_secret(ssl, &need_retry, &client_hello)) {
+ if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
if (need_retry) {
/* Only send one HelloRetryRequest. */
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
@@ -380,7 +379,8 @@
return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_send_server_hello(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
CBB cbb, body, extensions;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
!CBB_add_u16(&body, ssl->version) ||
@@ -388,8 +388,8 @@
!CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
!CBB_add_u16(&body, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
!CBB_add_u16_length_prefixed(&body, &extensions) ||
- !ssl_ext_pre_shared_key_add_serverhello(ssl, &extensions) ||
- !ssl_ext_key_share_add_serverhello(ssl, &extensions) ||
+ !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) ||
+ !ssl_ext_key_share_add_serverhello(hs, &extensions) ||
!ssl_complete_message(ssl, &cbb)) {
goto err;
}
@@ -402,16 +402,16 @@
return ssl_hs_error;
}
-static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL *ssl,
- SSL_HANDSHAKE *hs) {
- if (!tls13_set_handshake_traffic(ssl)) {
+static enum ssl_hs_wait_t do_send_encrypted_extensions(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ if (!tls13_set_handshake_traffic(hs)) {
return ssl_hs_error;
}
CBB cbb, body;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_ENCRYPTED_EXTENSIONS) ||
- !ssl_add_serverhello_tlsext(ssl, &body) ||
+ !ssl_add_serverhello_tlsext(hs, &body) ||
!ssl_complete_message(ssl, &cbb)) {
CBB_cleanup(&cbb);
return ssl_hs_error;
@@ -421,16 +421,16 @@
return ssl_hs_write_message;
}
-static enum ssl_hs_wait_t do_send_certificate_request(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_certificate_request(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
/* Determine whether to request a client certificate. */
- ssl->s3->hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+ 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->hs->cert_request = 0;
+ hs->cert_request = 0;
}
- if (!ssl->s3->hs->cert_request) {
+ if (!hs->cert_request) {
/* Skip this state. */
hs->state = state_send_server_certificate;
return ssl_hs_ok;
@@ -469,8 +469,8 @@
return ssl_hs_error;
}
-static enum ssl_hs_wait_t do_send_server_certificate(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_server_certificate(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->s3->session_reused) {
hs->state = state_send_server_finished;
return ssl_hs_ok;
@@ -481,7 +481,7 @@
return ssl_hs_error;
}
- if (!tls13_prepare_certificate(ssl)) {
+ if (!tls13_prepare_certificate(hs)) {
return ssl_hs_error;
}
@@ -489,10 +489,9 @@
return ssl_hs_write_message;
}
-static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL *ssl,
- SSL_HANDSHAKE *hs,
+static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs,
int is_first_run) {
- switch (tls13_prepare_certificate_verify(ssl, is_first_run)) {
+ switch (tls13_prepare_certificate_verify(hs, is_first_run)) {
case ssl_private_key_success:
hs->state = state_send_server_finished;
return ssl_hs_write_message;
@@ -509,8 +508,8 @@
return ssl_hs_error;
}
-static enum ssl_hs_wait_t do_send_server_finished(SSL *ssl, SSL_HANDSHAKE *hs) {
- if (!tls13_prepare_finished(ssl)) {
+static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) {
+ if (!tls13_prepare_finished(hs)) {
return ssl_hs_error;
}
@@ -518,10 +517,11 @@
return ssl_hs_write_message;
}
-static enum ssl_hs_wait_t do_flush(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_flush(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
/* Update the secret to the master secret and derive traffic keys. */
- if (!tls13_advance_key_schedule(ssl, kZeroes, hs->hash_len) ||
- !tls13_derive_application_secrets(ssl) ||
+ if (!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) ||
+ !tls13_derive_application_secrets(hs) ||
!tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_traffic_secret_0,
hs->hash_len)) {
return ssl_hs_error;
@@ -531,9 +531,9 @@
return ssl_hs_flush_and_read_message;
}
-static enum ssl_hs_wait_t do_process_client_certificate(SSL *ssl,
- SSL_HANDSHAKE *hs) {
- if (!ssl->s3->hs->cert_request) {
+static enum ssl_hs_wait_t do_process_client_certificate(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ if (!hs->cert_request) {
/* OpenSSL returns X509_V_OK when no certificates are requested. This is
* classed by them as a bug, but it's assumed by at least NGINX. */
ssl->s3->new_session->verify_result = X509_V_OK;
@@ -563,7 +563,8 @@
}
static enum ssl_hs_wait_t do_process_client_certificate_verify(
- SSL *ssl, SSL_HANDSHAKE *hs) {
+ SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (ssl->s3->new_session->x509_peer == NULL) {
/* Skip this state. */
hs->state = state_process_channel_id;
@@ -580,7 +581,8 @@
return ssl_hs_read_message;
}
-static enum ssl_hs_wait_t do_process_channel_id(SSL *ssl, SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_channel_id(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!ssl->s3->tlsext_channel_id_valid) {
hs->state = state_process_client_finished;
return ssl_hs_ok;
@@ -596,15 +598,15 @@
return ssl_hs_read_message;
}
-static enum ssl_hs_wait_t do_process_client_finished(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_process_client_finished(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
if (!tls13_check_message_type(ssl, SSL3_MT_FINISHED) ||
- !tls13_process_finished(ssl) ||
+ !tls13_process_finished(hs) ||
!ssl_hash_current_message(ssl) ||
/* evp_aead_seal keys have already been switched. */
!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_traffic_secret_0,
hs->hash_len) ||
- !tls13_derive_resumption_secret(ssl)) {
+ !tls13_derive_resumption_secret(hs)) {
return ssl_hs_error;
}
@@ -621,8 +623,8 @@
* client makes several connections before getting a renewal. */
static const int kNumTickets = 2;
-static enum ssl_hs_wait_t do_send_new_session_ticket(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_send_new_session_ticket(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
/* If the client doesn't accept resumption with PSK_DHE_KE, don't send a
* session ticket. */
if (!hs->accept_psk_mode) {
@@ -674,75 +676,72 @@
return ssl_hs_error;
}
-static enum ssl_hs_wait_t do_flush_new_session_tickets(SSL *ssl,
- SSL_HANDSHAKE *hs) {
+static enum ssl_hs_wait_t do_flush_new_session_tickets(SSL_HANDSHAKE *hs) {
hs->state = state_done;
return ssl_hs_flush;
}
-enum ssl_hs_wait_t tls13_server_handshake(SSL *ssl) {
- SSL_HANDSHAKE *hs = ssl->s3->hs;
-
+enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) {
while (hs->state != state_done) {
enum ssl_hs_wait_t ret = ssl_hs_error;
enum server_hs_state_t state = hs->state;
switch (state) {
case state_process_client_hello:
- ret = do_process_client_hello(ssl, hs);
+ ret = do_process_client_hello(hs);
break;
case state_select_parameters:
- ret = do_select_parameters(ssl, hs);
+ ret = do_select_parameters(hs);
break;
case state_send_hello_retry_request:
- ret = do_send_hello_retry_request(ssl, hs);
+ ret = do_send_hello_retry_request(hs);
break;
case state_flush_hello_retry_request:
- ret = do_flush_hello_retry_request(ssl, hs);
+ ret = do_flush_hello_retry_request(hs);
break;
case state_process_second_client_hello:
- ret = do_process_second_client_hello(ssl, hs);
+ ret = do_process_second_client_hello(hs);
break;
case state_send_server_hello:
- ret = do_send_server_hello(ssl, hs);
+ ret = do_send_server_hello(hs);
break;
case state_send_encrypted_extensions:
- ret = do_send_encrypted_extensions(ssl, hs);
+ ret = do_send_encrypted_extensions(hs);
break;
case state_send_certificate_request:
- ret = do_send_certificate_request(ssl, hs);
+ ret = do_send_certificate_request(hs);
break;
case state_send_server_certificate:
- ret = do_send_server_certificate(ssl, hs);
+ ret = do_send_server_certificate(hs);
break;
case state_send_server_certificate_verify:
- ret = do_send_server_certificate_verify(ssl, hs, 1 /* first run */);
+ ret = do_send_server_certificate_verify(hs, 1 /* first run */);
break;
case state_complete_server_certificate_verify:
- ret = do_send_server_certificate_verify(ssl, hs, 0 /* complete */);
+ ret = do_send_server_certificate_verify(hs, 0 /* complete */);
break;
case state_send_server_finished:
- ret = do_send_server_finished(ssl, hs);
+ ret = do_send_server_finished(hs);
break;
case state_flush:
- ret = do_flush(ssl, hs);
+ ret = do_flush(hs);
break;
case state_process_client_certificate:
- ret = do_process_client_certificate(ssl, hs);
+ ret = do_process_client_certificate(hs);
break;
case state_process_client_certificate_verify:
- ret = do_process_client_certificate_verify(ssl, hs);
+ ret = do_process_client_certificate_verify(hs);
break;
case state_process_channel_id:
- ret = do_process_channel_id(ssl, hs);
+ ret = do_process_channel_id(hs);
break;
case state_process_client_finished:
- ret = do_process_client_finished(ssl, hs);
+ ret = do_process_client_finished(hs);
break;
case state_send_new_session_ticket:
- ret = do_send_new_session_ticket(ssl, hs);
+ ret = do_send_new_session_ticket(hs);
break;
case state_flush_new_session_tickets:
- ret = do_flush_new_session_tickets(ssl, hs);
+ ret = do_flush_new_session_tickets(hs);
break;
case state_done:
ret = ssl_hs_ok;
diff --git a/src/ssl/tls_method.c b/src/ssl/tls_method.c
index ce42904..9effb36 100644
--- a/src/ssl/tls_method.c
+++ b/src/ssl/tls_method.c
@@ -97,6 +97,12 @@
return 0;
}
+static int ssl3_supports_cipher(const SSL_CIPHER *cipher) { return 1; }
+
+static void ssl3_expect_flight(SSL *ssl) {}
+
+static void ssl3_received_flight(SSL *ssl) {}
+
static int ssl3_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
if (ssl->s3->rrec.length != 0) {
/* There may not be unprocessed record data at a cipher change. */
diff --git a/src/ssl/tls_record.c b/src/ssl/tls_record.c
index 5931922..c52909c 100644
--- a/src/ssl/tls_record.c
+++ b/src/ssl/tls_record.c
@@ -125,6 +125,12 @@
* forever. */
static const uint8_t kMaxEmptyRecords = 32;
+/* kMaxEarlyDataSkipped is the maximum amount of data processed when skipping
+ * over early data. Without this limit an attacker could send records at a
+ * faster rate than we can process and cause trial decryption to loop
+ * forever. */
+static const size_t kMaxEarlyDataSkipped = 16384;
+
/* kMaxWarningAlerts is the number of consecutive warning alerts that will be
* processed. */
static const uint8_t kMaxWarningAlerts = 4;
@@ -246,15 +252,32 @@
ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, in,
SSL3_RT_HEADER_LENGTH);
+ *out_consumed = in_len - CBS_len(&cbs);
+
+ /* Skip early data received when expecting a second ClientHello if we rejected
+ * 0RTT. */
+ if (ssl->s3->skip_early_data &&
+ ssl->s3->aead_read_ctx == NULL &&
+ type == SSL3_RT_APPLICATION_DATA) {
+ goto skipped_data;
+ }
+
/* Decrypt the body in-place. */
if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, type, version,
ssl->s3->read_sequence, (uint8_t *)CBS_data(&body),
CBS_len(&body))) {
+ if (ssl->s3->skip_early_data &&
+ ssl->s3->aead_read_ctx != NULL) {
+ ERR_clear_error();
+ goto skipped_data;
+ }
+
OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
*out_alert = SSL_AD_BAD_RECORD_MAC;
return ssl_open_record_error;
}
- *out_consumed = in_len - CBS_len(&cbs);
+
+ ssl->s3->skip_early_data = 0;
if (!ssl_record_sequence_update(ssl->s3->read_sequence, 8)) {
*out_alert = SSL_AD_INTERNAL_ERROR;
@@ -310,6 +333,20 @@
*out_type = type;
return ssl_open_record_success;
+
+skipped_data:
+ ssl->s3->early_data_skipped += *out_consumed;
+ if (ssl->s3->early_data_skipped < *out_consumed) {
+ ssl->s3->early_data_skipped = kMaxEarlyDataSkipped + 1;
+ }
+
+ if (ssl->s3->early_data_skipped > kMaxEarlyDataSkipped) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MUCH_SKIPPED_EARLY_DATA);
+ *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
+ return ssl_open_record_error;
+ }
+
+ return ssl_open_record_discard;
}
static int do_seal_record(SSL *ssl, uint8_t *out, size_t *out_len,
diff --git a/src/tool/server.cc b/src/tool/server.cc
index d0213e9..a049422 100644
--- a/src/tool/server.cc
+++ b/src/tool/server.cc
@@ -15,6 +15,7 @@
#include <openssl/base.h>
#include <openssl/err.h>
+#include <openssl/rand.h>
#include <openssl/ssl.h>
#include "internal.h"
@@ -40,7 +41,9 @@
},
{
"-key", kOptionalArgument,
- "Private-key file to use (default is server.pem)",
+ "PEM-encoded file containing the private key, leaf certificate and "
+ "optional certificate chain. A self-signed certificate is generated "
+ "at runtime if this argument is not provided.",
},
{
"-ocsp-response", kOptionalArgument,
@@ -91,6 +94,49 @@
return ret;
}
+static bssl::UniquePtr<EVP_PKEY> MakeKeyPairForSelfSignedCert() {
+ bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+ if (!ec_key || !EC_KEY_generate_key(ec_key.get())) {
+ fprintf(stderr, "Failed to generate key pair.\n");
+ return nullptr;
+ }
+ bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
+ if (!evp_pkey || !EVP_PKEY_assign_EC_KEY(evp_pkey.get(), ec_key.release())) {
+ fprintf(stderr, "Failed to assign key pair.\n");
+ return nullptr;
+ }
+ return evp_pkey;
+}
+
+static bssl::UniquePtr<X509> MakeSelfSignedCert(EVP_PKEY *evp_pkey,
+ const int valid_days) {
+ bssl::UniquePtr<X509> x509(X509_new());
+ uint32_t serial;
+ RAND_bytes(reinterpret_cast<uint8_t*>(&serial), sizeof(serial));
+ ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), serial >> 1);
+ X509_gmtime_adj(X509_get_notBefore(x509.get()), 0);
+ X509_gmtime_adj(X509_get_notAfter(x509.get()), 60 * 60 * 24 * valid_days);
+
+ X509_NAME* subject = X509_get_subject_name(x509.get());
+ X509_NAME_add_entry_by_txt(subject, "C", MBSTRING_ASC,
+ reinterpret_cast<const uint8_t *>("US"), -1, -1,
+ 0);
+ X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC,
+ reinterpret_cast<const uint8_t *>("BoringSSL"), -1,
+ -1, 0);
+ X509_set_issuer_name(x509.get(), subject);
+
+ if (!X509_set_pubkey(x509.get(), evp_pkey)) {
+ fprintf(stderr, "Failed to set public key.\n");
+ return nullptr;
+ }
+ if (!X509_sign(x509.get(), evp_pkey, EVP_sha256())) {
+ fprintf(stderr, "Failed to sign certificate.\n");
+ return nullptr;
+ }
+ return x509;
+}
+
bool Server(const std::vector<std::string> &args) {
if (!InitSocketLibrary()) {
return false;
@@ -107,17 +153,34 @@
SSL_CTX_set_options(ctx.get(), SSL_OP_NO_SSLv3);
// Server authentication is required.
- std::string key_file = "server.pem";
if (args_map.count("-key") != 0) {
- key_file = args_map["-key"];
- }
- if (!SSL_CTX_use_PrivateKey_file(ctx.get(), key_file.c_str(), SSL_FILETYPE_PEM)) {
- fprintf(stderr, "Failed to load private key: %s\n", key_file.c_str());
- return false;
- }
- if (!SSL_CTX_use_certificate_chain_file(ctx.get(), key_file.c_str())) {
- fprintf(stderr, "Failed to load cert chain: %s\n", key_file.c_str());
- return false;
+ std::string key_file = args_map["-key"];
+ if (!SSL_CTX_use_PrivateKey_file(ctx.get(), key_file.c_str(), SSL_FILETYPE_PEM)) {
+ fprintf(stderr, "Failed to load private key: %s\n", key_file.c_str());
+ return false;
+ }
+ if (!SSL_CTX_use_certificate_chain_file(ctx.get(), key_file.c_str())) {
+ fprintf(stderr, "Failed to load cert chain: %s\n", key_file.c_str());
+ return false;
+ }
+ } else {
+ bssl::UniquePtr<EVP_PKEY> evp_pkey = MakeKeyPairForSelfSignedCert();
+ if (!evp_pkey) {
+ return false;
+ }
+ bssl::UniquePtr<X509> cert =
+ MakeSelfSignedCert(evp_pkey.get(), 365 /* valid_days */);
+ if (!cert) {
+ return false;
+ }
+ if (!SSL_CTX_use_PrivateKey(ctx.get(), evp_pkey.get())) {
+ fprintf(stderr, "Failed to set private key.\n");
+ return false;
+ }
+ if (!SSL_CTX_use_certificate(ctx.get(), cert.get())) {
+ fprintf(stderr, "Failed to set certificate.\n");
+ return false;
+ }
}
if (args_map.count("-cipher") != 0 &&
diff --git a/src/tool/speed.cc b/src/tool/speed.cc
index f16a9eb..5fd1058 100644
--- a/src/tool/speed.cc
+++ b/src/tool/speed.cc
@@ -654,6 +654,12 @@
kLegacyADLen, selected) ||
!SpeedAEAD(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1",
kLegacyADLen, selected) ||
+#if !defined(OPENSSL_SMALL)
+ !SpeedAEAD(EVP_aead_aes_128_gcm_siv(), "AES-128-GCM-SIV", kTLSADLen,
+ selected) ||
+ !SpeedAEAD(EVP_aead_aes_256_gcm_siv(), "AES-256-GCM-SIV", kTLSADLen,
+ selected) ||
+#endif
!SpeedHash(EVP_sha1(), "SHA-1", selected) ||
!SpeedHash(EVP_sha256(), "SHA-256", selected) ||
!SpeedHash(EVP_sha512(), "SHA-512", selected) ||
diff --git a/src/util/all_tests.json b/src/util/all_tests.json
index d2e39ce..5ffa5e8 100644
--- a/src/util/all_tests.json
+++ b/src/util/all_tests.json
@@ -8,6 +8,8 @@
["crypto/chacha/chacha_test"],
["crypto/cipher/aead_test", "aes-128-gcm", "crypto/cipher/test/aes_128_gcm_tests.txt"],
["crypto/cipher/aead_test", "aes-256-gcm", "crypto/cipher/test/aes_256_gcm_tests.txt"],
+ ["crypto/cipher/aead_test", "aes-128-gcm-siv", "crypto/cipher/test/aes_128_gcm_siv_tests.txt"],
+ ["crypto/cipher/aead_test", "aes-256-gcm-siv", "crypto/cipher/test/aes_256_gcm_siv_tests.txt"],
["crypto/cipher/aead_test", "chacha20-poly1305", "crypto/cipher/test/chacha20_poly1305_tests.txt"],
["crypto/cipher/aead_test", "chacha20-poly1305-old", "crypto/cipher/test/chacha20_poly1305_old_tests.txt"],
["crypto/cipher/aead_test", "aes-128-cbc-sha1-tls", "crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt"],
diff --git a/src/util/bot/DEPS b/src/util/bot/DEPS
index 0452d55..5036c0c 100644
--- a/src/util/bot/DEPS
+++ b/src/util/bot/DEPS
@@ -104,8 +104,6 @@
'boringssl/util/bot/update_clang.py',
],
},
- # TODO(davidben): Only extract archives when they've changed. Extracting perl
- # on Windows is a significant part of the cycle time.
{
'name': 'cmake_linux64_extract',
'pattern': '.',
diff --git a/src/util/bot/extract.py b/src/util/bot/extract.py
index 77603c0..e36ce99 100644
--- a/src/util/bot/extract.py
+++ b/src/util/bot/extract.py
@@ -15,6 +15,7 @@
"""Extracts archives."""
+import hashlib
import optparse
import os
import os.path
@@ -78,6 +79,22 @@
# Skip archives that weren't downloaded.
return 0
+ with open(archive) as f:
+ sha256 = hashlib.sha256()
+ while True:
+ chunk = f.read(1024 * 1024)
+ if not chunk:
+ break
+ sha256.update(chunk)
+ digest = sha256.hexdigest()
+
+ stamp_path = os.path.join(output, ".boringssl_archive_digest")
+ if os.path.exists(stamp_path):
+ with open(stamp_path) as f:
+ if f.read().strip() == digest:
+ print "Already up-to-date."
+ return 0
+
if archive.endswith('.zip'):
entries = IterateZip(archive)
elif archive.endswith('.tar.gz'):
@@ -129,9 +146,10 @@
finally:
entries.close()
- if num_extracted % 100 == 0:
- print "Done. Extracted %d files." % (num_extracted,)
+ with open(stamp_path, 'w') as f:
+ f.write(digest)
+ print "Done. Extracted %d files." % (num_extracted,)
return 0