summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Sloan <varomodt@google.com>2017-06-27 17:41:42 +0000
committerandroid-build-merger <android-build-merger@google.com>2017-06-27 17:41:42 +0000
commit8ad267508423079ed3e4df6ffbde0557a0484f2c (patch)
tree8748d2e9bcbf9c92e85f8610584df6dbbc52c6a5
parentaa3f4e316b2fcec0f088e72d2932114d911003a7 (diff)
parentb2737a239d086eb6ce131a148d0d6ad870cb34c7 (diff)
downloadboringssl-8ad267508423079ed3e4df6ffbde0557a0484f2c.tar.gz
external/boringssl: Sync to 3120950b1e27635ee9b9d167052ce11ce9c96fd4. am: e56da3e0a1
am: b2737a239d Change-Id: I5474e24d62345d1ec1edba2ca6169d88494454ba
-rw-r--r--BORINGSSL_REVISION2
-rw-r--r--err_data.c590
-rw-r--r--src/CMakeLists.txt7
-rw-r--r--src/crypto/ec_extra/ec_asn1.c16
-rw-r--r--src/crypto/err/ssl.errordata3
-rw-r--r--src/crypto/evp/evp_extra_test.cc6
-rw-r--r--src/crypto/fipsmodule/ec/ec.c309
-rw-r--r--src/crypto/fipsmodule/ec/internal.h17
-rw-r--r--src/crypto/fipsmodule/rsa/rsa_impl.c5
-rw-r--r--src/crypto/rand_extra/fuchsia.c2
-rw-r--r--src/crypto/rsa_extra/rsa_test.cc16
-rw-r--r--src/include/openssl/aead.h17
-rw-r--r--src/include/openssl/ec_key.h4
-rw-r--r--src/include/openssl/rsa.h30
-rw-r--r--src/include/openssl/ssl.h206
-rw-r--r--src/include/openssl/ssl3.h8
-rw-r--r--src/ssl/d1_pkt.c4
-rw-r--r--src/ssl/handshake_client.c239
-rw-r--r--src/ssl/handshake_server.c572
-rw-r--r--src/ssl/internal.h85
-rw-r--r--src/ssl/s3_both.c15
-rw-r--r--src/ssl/s3_pkt.c38
-rw-r--r--src/ssl/ssl_buffer.c68
-rw-r--r--src/ssl/ssl_cipher.c110
-rw-r--r--src/ssl/ssl_ecdh.c1
-rw-r--r--src/ssl/ssl_lib.c164
-rw-r--r--src/ssl/ssl_privkey.c78
-rw-r--r--src/ssl/ssl_session.c8
-rw-r--r--src/ssl/ssl_stat.c20
-rw-r--r--src/ssl/ssl_test.cc215
-rw-r--r--src/ssl/t1_lib.c76
-rw-r--r--src/ssl/test/bssl_shim.cc165
-rw-r--r--src/ssl/test/runner/common.go8
-rw-r--r--src/ssl/test/runner/conn.go13
-rw-r--r--src/ssl/test/runner/fuzzer_mode.json7
-rw-r--r--src/ssl/test/runner/handshake_server.go14
-rw-r--r--src/ssl/test/runner/runner.go224
-rw-r--r--src/ssl/test/test_config.cc188
-rw-r--r--src/ssl/test/test_config.h4
-rw-r--r--src/ssl/tls13_both.c34
-rw-r--r--src/ssl/tls13_client.c55
-rw-r--r--src/ssl/tls13_server.c14
-rw-r--r--src/ssl/tls_record.c12
-rw-r--r--src/tool/ciphers.cc2
-rw-r--r--src/tool/client.cc16
-rw-r--r--src/tool/transport_common.cc2
-rw-r--r--src/util/bot/DEPS2
-rwxr-xr-xsrc/util/bot/go/bootstrap.py2
-rw-r--r--src/util/bot/update_clang.py2
-rw-r--r--src/util/fipstools/delocate.go41
-rw-r--r--src/util/fipstools/testdata/ppc64le-Sample/out.s24
-rw-r--r--src/util/fipstools/testdata/ppc64le-Sample2/out.s30
52 files changed, 2051 insertions, 1739 deletions
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index cab901e2..5833838f 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-5e578c9dba73460c3eb17f771c77fc8e36f7812e
+3120950b1e27635ee9b9d167052ce11ce9c96fd4
diff --git a/err_data.c b/err_data.c
index d476d955..44c1882c 100644
--- a/err_data.c
+++ b/err_data.c
@@ -184,43 +184,43 @@ const uint32_t kOpenSSLReasonValues[] = {
0x28340c5e,
0x283480ac,
0x283500ea,
- 0x2c322c00,
+ 0x2c322c26,
0x2c329283,
- 0x2c332c0e,
- 0x2c33ac20,
- 0x2c342c34,
- 0x2c34ac46,
- 0x2c352c61,
- 0x2c35ac73,
- 0x2c362c86,
+ 0x2c332c34,
+ 0x2c33ac46,
+ 0x2c342c5a,
+ 0x2c34ac6c,
+ 0x2c352c87,
+ 0x2c35ac99,
+ 0x2c362cac,
0x2c36832d,
- 0x2c372c93,
- 0x2c37aca5,
- 0x2c382cca,
- 0x2c38ace1,
- 0x2c392cef,
- 0x2c39acff,
- 0x2c3a2d11,
- 0x2c3aad25,
- 0x2c3b2d36,
- 0x2c3bad55,
+ 0x2c372cb9,
+ 0x2c37accb,
+ 0x2c382cf0,
+ 0x2c38ad07,
+ 0x2c392d15,
+ 0x2c39ad25,
+ 0x2c3a2d37,
+ 0x2c3aad4b,
+ 0x2c3b2d5c,
+ 0x2c3bad7b,
0x2c3c1295,
0x2c3c92ab,
- 0x2c3d2d69,
+ 0x2c3d2d8f,
0x2c3d92c4,
- 0x2c3e2d86,
- 0x2c3ead94,
- 0x2c3f2dac,
- 0x2c3fadc4,
- 0x2c402dd1,
+ 0x2c3e2dac,
+ 0x2c3eadba,
+ 0x2c3f2dd2,
+ 0x2c3fadea,
+ 0x2c402df7,
0x2c409196,
- 0x2c412de2,
- 0x2c41adf5,
+ 0x2c412e08,
+ 0x2c41ae1b,
0x2c42116f,
- 0x2c42ae06,
+ 0x2c42ae2c,
0x2c430720,
- 0x2c43ad47,
- 0x2c442cb8,
+ 0x2c43ad6d,
+ 0x2c442cde,
0x30320000,
0x30328015,
0x3033001f,
@@ -353,219 +353,220 @@ const uint32_t kOpenSSLReasonValues[] = {
0x3c410d13,
0x3c418d52,
0x3c420e4f,
- 0x4032187e,
- 0x40329894,
- 0x403318c2,
- 0x403398cc,
- 0x403418e3,
- 0x40349901,
- 0x40351911,
- 0x40359923,
- 0x40361930,
- 0x4036993c,
- 0x40371951,
- 0x40379963,
- 0x4038196e,
- 0x40389980,
+ 0x403218a4,
+ 0x403298ba,
+ 0x403318e8,
+ 0x403398f2,
+ 0x40341909,
+ 0x40349927,
+ 0x40351937,
+ 0x40359949,
+ 0x40361956,
+ 0x40369962,
+ 0x40371977,
+ 0x40379989,
+ 0x40381994,
+ 0x403899a6,
0x40390eed,
- 0x40399990,
- 0x403a19a3,
- 0x403a99c4,
- 0x403b19d5,
- 0x403b99e5,
+ 0x403999b6,
+ 0x403a19c9,
+ 0x403a99ea,
+ 0x403b19fb,
+ 0x403b9a0b,
0x403c0064,
0x403c8083,
- 0x403d1a69,
- 0x403d9a7f,
- 0x403e1a8e,
- 0x403e9ac6,
- 0x403f1ae0,
- 0x403f9aee,
- 0x40401b03,
- 0x40409b30,
- 0x40411b4d,
- 0x40419b68,
- 0x40421b81,
- 0x40429b94,
- 0x40431ba8,
- 0x40439bc0,
- 0x40441bd7,
+ 0x403d1a8f,
+ 0x403d9aa5,
+ 0x403e1ab4,
+ 0x403e9aec,
+ 0x403f1b06,
+ 0x403f9b14,
+ 0x40401b29,
+ 0x40409b56,
+ 0x40411b73,
+ 0x40419b8e,
+ 0x40421ba7,
+ 0x40429bba,
+ 0x40431bce,
+ 0x40439be6,
+ 0x40441bfd,
0x404480ac,
- 0x40451bec,
- 0x40459bfe,
- 0x40461c22,
- 0x40469c42,
- 0x40471c50,
- 0x40479c77,
- 0x40481cb4,
- 0x40489ccd,
- 0x40491ce4,
- 0x40499cfe,
- 0x404a1d15,
- 0x404a9d33,
- 0x404b1d4b,
- 0x404b9d62,
- 0x404c1d78,
- 0x404c9d8a,
- 0x404d1dab,
- 0x404d9dcd,
- 0x404e1de1,
- 0x404e9dee,
- 0x404f1e1b,
- 0x404f9e44,
- 0x40501e7f,
- 0x40509e93,
- 0x40511eae,
- 0x40521ebe,
- 0x40529ee2,
- 0x40531efa,
- 0x40539f0d,
- 0x40541f22,
- 0x40549f45,
- 0x40551f53,
- 0x40559f70,
- 0x40561f7d,
- 0x40569f96,
- 0x40571fae,
- 0x40579fc1,
- 0x40581fd6,
- 0x40589ffd,
- 0x4059202c,
- 0x4059a059,
- 0x405a206d,
- 0x405aa07d,
- 0x405b2095,
- 0x405ba0a6,
- 0x405c20b9,
- 0x405ca0f8,
- 0x405d2105,
- 0x405da11c,
- 0x405e215a,
+ 0x40451c12,
+ 0x40459c24,
+ 0x40461c48,
+ 0x40469c68,
+ 0x40471c76,
+ 0x40479c9d,
+ 0x40481cda,
+ 0x40489cf3,
+ 0x40491d0a,
+ 0x40499d24,
+ 0x404a1d3b,
+ 0x404a9d59,
+ 0x404b1d71,
+ 0x404b9d88,
+ 0x404c1d9e,
+ 0x404c9db0,
+ 0x404d1dd1,
+ 0x404d9df3,
+ 0x404e1e07,
+ 0x404e9e14,
+ 0x404f1e41,
+ 0x404f9e6a,
+ 0x40501ea5,
+ 0x40509eb9,
+ 0x40511ed4,
+ 0x40521ee4,
+ 0x40529f08,
+ 0x40531f20,
+ 0x40539f33,
+ 0x40541f48,
+ 0x40549f6b,
+ 0x40551f79,
+ 0x40559f96,
+ 0x40561fa3,
+ 0x40569fbc,
+ 0x40571fd4,
+ 0x40579fe7,
+ 0x40581ffc,
+ 0x4058a023,
+ 0x40592052,
+ 0x4059a07f,
+ 0x405a2093,
+ 0x405aa0a3,
+ 0x405b20bb,
+ 0x405ba0cc,
+ 0x405c20df,
+ 0x405ca11e,
+ 0x405d212b,
+ 0x405da142,
+ 0x405e2180,
0x405e8ab1,
- 0x405f217b,
- 0x405fa188,
- 0x40602196,
- 0x4060a1b8,
- 0x406121fc,
- 0x4061a234,
- 0x4062224b,
- 0x4062a25c,
- 0x4063226d,
- 0x4063a282,
- 0x40642299,
- 0x4064a2c5,
- 0x406522e0,
- 0x4065a2f7,
- 0x4066230f,
- 0x4066a339,
- 0x40672364,
- 0x4067a385,
- 0x406823ac,
- 0x4068a3cd,
- 0x406923ff,
- 0x4069a42d,
- 0x406a244e,
- 0x406aa46e,
- 0x406b25f6,
- 0x406ba619,
- 0x406c262f,
- 0x406ca8aa,
- 0x406d28d9,
- 0x406da901,
- 0x406e292f,
- 0x406ea963,
- 0x406f2982,
- 0x406fa997,
- 0x407029aa,
- 0x4070a9c7,
+ 0x405f21a1,
+ 0x405fa1ae,
+ 0x406021bc,
+ 0x4060a1de,
+ 0x40612222,
+ 0x4061a25a,
+ 0x40622271,
+ 0x4062a282,
+ 0x40632293,
+ 0x4063a2a8,
+ 0x406422bf,
+ 0x4064a2eb,
+ 0x40652306,
+ 0x4065a31d,
+ 0x40662335,
+ 0x4066a35f,
+ 0x4067238a,
+ 0x4067a3ab,
+ 0x406823d2,
+ 0x4068a3f3,
+ 0x40692425,
+ 0x4069a453,
+ 0x406a2474,
+ 0x406aa494,
+ 0x406b261c,
+ 0x406ba63f,
+ 0x406c2655,
+ 0x406ca8d0,
+ 0x406d28ff,
+ 0x406da927,
+ 0x406e2955,
+ 0x406ea9a2,
+ 0x406f29c1,
+ 0x406fa9d6,
+ 0x407029e9,
+ 0x4070aa06,
0x40710800,
- 0x4071a9d9,
- 0x407229ec,
- 0x4072aa05,
- 0x40732a1d,
+ 0x4071aa18,
+ 0x40722a2b,
+ 0x4072aa44,
+ 0x40732a5c,
0x40739482,
- 0x40742a31,
- 0x4074aa4b,
- 0x40752a5c,
- 0x4075aa70,
- 0x40762a7e,
+ 0x40742a70,
+ 0x4074aa8a,
+ 0x40752a9b,
+ 0x4075aaaf,
+ 0x40762abd,
0x40769259,
- 0x40772aa3,
- 0x4077aac5,
- 0x40782ae0,
- 0x4078ab19,
- 0x40792b30,
- 0x4079ab46,
- 0x407a2b52,
- 0x407aab65,
- 0x407b2b7a,
- 0x407bab8c,
- 0x407c2bbd,
- 0x407cabc6,
- 0x407d23e8,
- 0x407d9e54,
- 0x407e2af5,
- 0x407ea00d,
- 0x407f1c64,
- 0x407f9a0b,
- 0x40801e2b,
- 0x40809c8c,
- 0x40811ed0,
- 0x40819e05,
- 0x4082291a,
- 0x408299f1,
- 0x40831fe8,
- 0x4083a2aa,
- 0x40841ca0,
- 0x4084a045,
- 0x408520ca,
- 0x4085a1e0,
- 0x4086213c,
- 0x40869e6e,
- 0x40872947,
- 0x4087a211,
- 0x40881a52,
- 0x4088a398,
- 0x40891aa1,
- 0x40899a2e,
- 0x408a264f,
+ 0x40772ae2,
+ 0x4077ab04,
+ 0x40782b1f,
+ 0x4078ab58,
+ 0x40792b6f,
+ 0x4079ab85,
+ 0x407a2b91,
+ 0x407aaba4,
+ 0x407b2bb9,
+ 0x407babcb,
+ 0x407c2bfc,
+ 0x407cac05,
+ 0x407d240e,
+ 0x407d9e7a,
+ 0x407e2b34,
+ 0x407ea033,
+ 0x407f1c8a,
+ 0x407f9a31,
+ 0x40801e51,
+ 0x40809cb2,
+ 0x40811ef6,
+ 0x40819e2b,
+ 0x40822940,
+ 0x40829a17,
+ 0x4083200e,
+ 0x4083a2d0,
+ 0x40841cc6,
+ 0x4084a06b,
+ 0x408520f0,
+ 0x4085a206,
+ 0x40862162,
+ 0x40869e94,
+ 0x40872986,
+ 0x4087a237,
+ 0x40881a78,
+ 0x4088a3be,
+ 0x40891ac7,
+ 0x40899a54,
+ 0x408a2675,
0x408a9862,
- 0x408b2ba1,
- 0x408b9b17,
- 0x408c20da,
- 0x41f42521,
- 0x41f925b3,
- 0x41fe24a6,
- 0x41fea69b,
- 0x41ff278c,
- 0x4203253a,
- 0x4208255c,
- 0x4208a598,
- 0x4209248a,
- 0x4209a5d2,
- 0x420a24e1,
- 0x420aa4c1,
- 0x420b2501,
- 0x420ba57a,
- 0x420c27a8,
- 0x420ca668,
- 0x420d2682,
- 0x420da6b9,
- 0x421226d3,
- 0x4217276f,
- 0x4217a715,
- 0x421c2737,
- 0x421f26f2,
- 0x422127bf,
- 0x42262752,
- 0x422b288e,
- 0x422ba83c,
- 0x422c2876,
- 0x422ca7fb,
- 0x422d27da,
- 0x422da85b,
- 0x422e2821,
- 0x422eabe7,
+ 0x408b2be0,
+ 0x408b9b3d,
+ 0x408c2100,
+ 0x408c987e,
+ 0x41f42547,
+ 0x41f925d9,
+ 0x41fe24cc,
+ 0x41fea6c1,
+ 0x41ff27b2,
+ 0x42032560,
+ 0x42082582,
+ 0x4208a5be,
+ 0x420924b0,
+ 0x4209a5f8,
+ 0x420a2507,
+ 0x420aa4e7,
+ 0x420b2527,
+ 0x420ba5a0,
+ 0x420c27ce,
+ 0x420ca68e,
+ 0x420d26a8,
+ 0x420da6df,
+ 0x421226f9,
+ 0x42172795,
+ 0x4217a73b,
+ 0x421c275d,
+ 0x421f2718,
+ 0x422127e5,
+ 0x42262778,
+ 0x422b28b4,
+ 0x422ba862,
+ 0x422c289c,
+ 0x422ca821,
+ 0x422d2800,
+ 0x422da881,
+ 0x422e2847,
+ 0x422ea96d,
0x4432072b,
0x4432873a,
0x44330746,
@@ -618,69 +619,69 @@ const uint32_t kOpenSSLReasonValues[] = {
0x4c4014a7,
0x4c4092d5,
0x4c4114cb,
- 0x50322e18,
- 0x5032ae27,
- 0x50332e32,
- 0x5033ae42,
- 0x50342e5b,
- 0x5034ae75,
- 0x50352e83,
- 0x5035ae99,
- 0x50362eab,
- 0x5036aec1,
- 0x50372eda,
- 0x5037aeed,
- 0x50382f05,
- 0x5038af16,
- 0x50392f2b,
- 0x5039af3f,
- 0x503a2f5f,
- 0x503aaf75,
- 0x503b2f8d,
- 0x503baf9f,
- 0x503c2fbb,
- 0x503cafd2,
- 0x503d2feb,
- 0x503db001,
- 0x503e300e,
- 0x503eb024,
- 0x503f3036,
+ 0x50322e3e,
+ 0x5032ae4d,
+ 0x50332e58,
+ 0x5033ae68,
+ 0x50342e81,
+ 0x5034ae9b,
+ 0x50352ea9,
+ 0x5035aebf,
+ 0x50362ed1,
+ 0x5036aee7,
+ 0x50372f00,
+ 0x5037af13,
+ 0x50382f2b,
+ 0x5038af3c,
+ 0x50392f51,
+ 0x5039af65,
+ 0x503a2f85,
+ 0x503aaf9b,
+ 0x503b2fb3,
+ 0x503bafc5,
+ 0x503c2fe1,
+ 0x503caff8,
+ 0x503d3011,
+ 0x503db027,
+ 0x503e3034,
+ 0x503eb04a,
+ 0x503f305c,
0x503f8382,
- 0x50403049,
- 0x5040b059,
- 0x50413073,
- 0x5041b082,
- 0x5042309c,
- 0x5042b0b9,
- 0x504330c9,
- 0x5043b0d9,
- 0x504430e8,
+ 0x5040306f,
+ 0x5040b07f,
+ 0x50413099,
+ 0x5041b0a8,
+ 0x504230c2,
+ 0x5042b0df,
+ 0x504330ef,
+ 0x5043b0ff,
+ 0x5044310e,
0x5044843f,
- 0x504530fc,
- 0x5045b11a,
- 0x5046312d,
- 0x5046b143,
- 0x50473155,
- 0x5047b16a,
- 0x50483190,
- 0x5048b19e,
- 0x504931b1,
- 0x5049b1c6,
- 0x504a31dc,
- 0x504ab1ec,
- 0x504b320c,
- 0x504bb21f,
- 0x504c3242,
- 0x504cb270,
- 0x504d3282,
- 0x504db29f,
- 0x504e32ba,
- 0x504eb2d6,
- 0x504f32e8,
- 0x504fb2ff,
- 0x5050330e,
+ 0x50453122,
+ 0x5045b140,
+ 0x50463153,
+ 0x5046b169,
+ 0x5047317b,
+ 0x5047b190,
+ 0x504831b6,
+ 0x5048b1c4,
+ 0x504931d7,
+ 0x5049b1ec,
+ 0x504a3202,
+ 0x504ab212,
+ 0x504b3232,
+ 0x504bb245,
+ 0x504c3268,
+ 0x504cb296,
+ 0x504d32a8,
+ 0x504db2c5,
+ 0x504e32e0,
+ 0x504eb2fc,
+ 0x504f330e,
+ 0x504fb325,
+ 0x50503334,
0x505086ef,
- 0x50513321,
+ 0x50513347,
0x58320f2b,
0x68320eed,
0x68328c6a,
@@ -1043,6 +1044,7 @@ const char kOpenSSLReasonStringData[] =
"VALUE_MISSING\0"
"WRONG_SIGNATURE_LENGTH\0"
"ALPN_MISMATCH_ON_EARLY_DATA\0"
+ "APPLICATION_DATA_INSTEAD_OF_HANDSHAKE\0"
"APP_DATA_IN_HANDSHAKE\0"
"ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\0"
"BAD_ALERT\0"
@@ -1217,6 +1219,7 @@ const char kOpenSSLReasonStringData[] =
"TOO_MANY_EMPTY_FRAGMENTS\0"
"TOO_MANY_KEY_UPDATES\0"
"TOO_MANY_WARNING_ALERTS\0"
+ "TOO_MUCH_READ_EARLY_DATA\0"
"TOO_MUCH_SKIPPED_EARLY_DATA\0"
"UNABLE_TO_FIND_ECDH_PARAMETERS\0"
"UNEXPECTED_EXTENSION\0"
@@ -1246,7 +1249,6 @@ const char kOpenSSLReasonStringData[] =
"WRONG_VERSION_ON_EARLY_DATA\0"
"X509_LIB\0"
"X509_VERIFICATION_SETUP_PROBLEMS\0"
- "TOO_MUCH_READ_EARLY_DATA\0"
"AKID_MISMATCH\0"
"BAD_X509_FILETYPE\0"
"BASE64_DECODE_ERROR\0"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 3898ac87..deab75ba 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -89,11 +89,9 @@ elseif(MSVC)
"C4706" # assignment within conditional expression
"C4710" # 'function': function not inlined
"C4711" # function 'function' selected for inline expansion
- "C4774" # format string is not a string literal
"C4800" # 'int' : forcing value to bool 'true' or 'false'
# (performance warning)
"C4820" # 'bytes' bytes padding added after construct 'member_name'
- "C4987" # nonstandard extension used: 'throw (...)'
"C5026" # move constructor was implicitly defined as deleted
"C5027" # move assignment operator was implicitly defined as deleted
)
@@ -111,7 +109,10 @@ elseif(MSVC)
add_definitions(-D_HAS_EXCEPTIONS=0)
add_definitions(-DWIN32_LEAN_AND_MEAN)
add_definitions(-DNOMINMAX)
- add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Allow use of fopen
+ # Allow use of fopen.
+ add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+ # VS 2017 and higher supports STL-only warning suppressions.
+ add_definitions("-D_STL_EXTRA_DISABLED_WARNINGS=4774 4987")
endif()
if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.7.99") OR
diff --git a/src/crypto/ec_extra/ec_asn1.c b/src/crypto/ec_extra/ec_asn1.c
index 76210455..0772506b 100644
--- a/src/crypto/ec_extra/ec_asn1.c
+++ b/src/crypto/ec_extra/ec_asn1.c
@@ -388,18 +388,18 @@ EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) {
const struct built_in_curves *const curves = OPENSSL_built_in_curves();
for (size_t i = 0; i < OPENSSL_NUM_BUILT_IN_CURVES; i++) {
const struct built_in_curve *curve = &curves->curves[i];
- const unsigned param_len = curve->data->param_len;
- /* |curve->data->data| is ordered p, a, b, x, y, order, each component
+ const unsigned param_len = curve->param_len;
+ /* |curve->params| is ordered p, a, b, x, y, order, each component
* zero-padded up to the field length. Although SEC 1 states that the
* Field-Element-to-Octet-String conversion also pads, OpenSSL mis-encodes
* |a| and |b|, so this comparison must allow omitting leading zeros. (This
* is relevant for P-521 whose |b| has a leading 0.) */
- if (integers_equal(&prime, curve->data->data, param_len) &&
- integers_equal(&a, curve->data->data + param_len, param_len) &&
- integers_equal(&b, curve->data->data + param_len * 2, param_len) &&
- integers_equal(&base_x, curve->data->data + param_len * 3, param_len) &&
- integers_equal(&base_y, curve->data->data + param_len * 4, param_len) &&
- integers_equal(&order, curve->data->data + param_len * 5, param_len)) {
+ if (integers_equal(&prime, curve->params, param_len) &&
+ integers_equal(&a, curve->params + param_len, param_len) &&
+ integers_equal(&b, curve->params + param_len * 2, param_len) &&
+ integers_equal(&base_x, curve->params + param_len * 3, param_len) &&
+ integers_equal(&base_y, curve->params + param_len * 4, param_len) &&
+ integers_equal(&order, curve->params + param_len * 5, param_len)) {
return EC_GROUP_new_by_curve_name(curve->nid);
}
}
diff --git a/src/crypto/err/ssl.errordata b/src/crypto/err/ssl.errordata
index 641d873d..7949cc7d 100644
--- a/src/crypto/err/ssl.errordata
+++ b/src/crypto/err/ssl.errordata
@@ -1,4 +1,5 @@
SSL,277,ALPN_MISMATCH_ON_EARLY_DATA
+SSL,281,APPLICATION_DATA_INSTEAD_OF_HANDSHAKE
SSL,100,APP_DATA_IN_HANDSHAKE
SSL,101,ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT
SSL,102,BAD_ALERT
@@ -178,6 +179,7 @@ SSL,218,TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG
SSL,219,TOO_MANY_EMPTY_FRAGMENTS
SSL,260,TOO_MANY_KEY_UPDATES
SSL,220,TOO_MANY_WARNING_ALERTS
+SSL,1117,TOO_MUCH_READ_EARLY_DATA
SSL,270,TOO_MUCH_SKIPPED_EARLY_DATA
SSL,221,UNABLE_TO_FIND_ECDH_PARAMETERS
SSL,222,UNEXPECTED_EXTENSION
@@ -210,4 +212,3 @@ SSL,247,WRONG_VERSION_NUMBER
SSL,278,WRONG_VERSION_ON_EARLY_DATA
SSL,248,X509_LIB
SSL,249,X509_VERIFICATION_SETUP_PROBLEMS
-SSL,1117,TOO_MUCH_READ_EARLY_DATA
diff --git a/src/crypto/evp/evp_extra_test.cc b/src/crypto/evp/evp_extra_test.cc
index 26986630..f12650ef 100644
--- a/src/crypto/evp/evp_extra_test.cc
+++ b/src/crypto/evp/evp_extra_test.cc
@@ -614,13 +614,13 @@ TEST(EVPExtraTest, Ed25519) {
EXPECT_EQ(Bytes(kPrivateKeyPKCS8), Bytes(der, der_len));
// Test EVP_PKEY_cmp.
- EXPECT_TRUE(EVP_PKEY_cmp(pubkey.get(), privkey.get()));
+ EXPECT_EQ(1, EVP_PKEY_cmp(pubkey.get(), privkey.get()));
static const uint8_t kZeros[32] = {0};
bssl::UniquePtr<EVP_PKEY> pubkey2(EVP_PKEY_new_ed25519_public(kZeros));
ASSERT_TRUE(pubkey2);
- EXPECT_FALSE(EVP_PKEY_cmp(pubkey.get(), pubkey2.get()));
- EXPECT_FALSE(EVP_PKEY_cmp(privkey.get(), pubkey2.get()));
+ EXPECT_EQ(0, EVP_PKEY_cmp(pubkey.get(), pubkey2.get()));
+ EXPECT_EQ(0, EVP_PKEY_cmp(privkey.get(), pubkey2.get()));
// Ed25519 may not be used streaming.
bssl::ScopedEVP_MD_CTX ctx;
diff --git a/src/crypto/fipsmodule/ec/ec.c b/src/crypto/fipsmodule/ec/ec.c
index 7e6eecc9..ef816344 100644
--- a/src/crypto/fipsmodule/ec/ec.c
+++ b/src/crypto/fipsmodule/ec/ec.c
@@ -80,161 +80,137 @@
#include "../delocate.h"
-DEFINE_LOCAL_DATA(struct curve_data, P224_data) {
- static const uint8_t kData[6 * 28] = {
- /* p */
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01,
- /* a */
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFE,
- /* b */
- 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
- 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
- 0x23, 0x55, 0xFF, 0xB4,
- /* x */
- 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
- 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
- 0x11, 0x5C, 0x1D, 0x21,
- /* y */
- 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
- 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
- 0x85, 0x00, 0x7e, 0x34,
- /* order */
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
- 0x5C, 0x5C, 0x2A, 0x3D,
- };
-
- out->comment = "NIST P-224";
- out->param_len = 28;
- out->data = kData;
+static const uint8_t kP224Params[6 * 28] = {
+ /* p */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01,
+ /* a */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFE,
+ /* b */
+ 0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, 0x32, 0x56,
+ 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B, 0x39, 0x43,
+ 0x23, 0x55, 0xFF, 0xB4,
+ /* x */
+ 0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, 0x90, 0xB9,
+ 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32, 0x80, 0xD6,
+ 0x11, 0x5C, 0x1D, 0x21,
+ /* y */
+ 0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, 0xdf, 0xe6,
+ 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5, 0x81, 0x99,
+ 0x85, 0x00, 0x7e, 0x34,
+ /* order */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x16, 0xA2, 0xE0, 0xB8, 0xF0, 0x3E, 0x13, 0xDD, 0x29, 0x45,
+ 0x5C, 0x5C, 0x2A, 0x3D,
};
-DEFINE_LOCAL_DATA(struct curve_data, P256_data) {
- static const uint8_t kData[6 * 32] = {
- /* p */
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- /* a */
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
- /* b */
- 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
- 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
- 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B,
- /* x */
- 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
- 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
- 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
- /* y */
- 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
- 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
- 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
- /* order */
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
- 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51
- };
-
- out->comment = "NIST P-256";
- out->param_len = 32;
- out->data = kData;
-}
-
-DEFINE_LOCAL_DATA(struct curve_data, P384_data) {
- static const uint8_t kData[6 * 48] = {
- /* p */
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
- /* a */
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC,
- /* b */
- 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
- 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
- 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
- 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF,
- /* x */
- 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
- 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
- 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
- 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
- /* y */
- 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
- 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
- 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
- 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f,
- /* order */
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
- 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73
- };
-
- out->comment = "NIST P-384";
- out->param_len = 48;
- out->data = kData;
-}
-
-DEFINE_LOCAL_DATA(struct curve_data, P521_data) {
- static const uint8_t kData[6 * 66] = {
- /* p */
- 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- /* a */
- 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
- /* b */
- 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
- 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
- 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
- 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
- 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
- 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,
- /* x */
- 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
- 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
- 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
- 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
- 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
- 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
- /* y */
- 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
- 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
- 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
- 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
- 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
- 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
- /* order */
- 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
- 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
- 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
- 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09
- };
-
- out->comment = "NIST P-521";
- out->param_len = 66;
- out->data = kData;
-}
+static const uint8_t kP256Params[6 * 32] = {
+ /* p */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ /* a */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
+ /* b */
+ 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
+ 0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
+ 0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B,
+ /* x */
+ 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
+ 0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
+ 0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
+ /* y */
+ 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a,
+ 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce,
+ 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
+ /* order */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
+ 0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51,
+};
+
+static const uint8_t kP384Params[6 * 48] = {
+ /* p */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+ /* a */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC,
+ /* b */
+ 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
+ 0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
+ 0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
+ 0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF,
+ /* x */
+ 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
+ 0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
+ 0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
+ 0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
+ /* y */
+ 0x36, 0x17, 0xde, 0x4a, 0x96, 0x26, 0x2c, 0x6f, 0x5d, 0x9e, 0x98, 0xbf,
+ 0x92, 0x92, 0xdc, 0x29, 0xf8, 0xf4, 0x1d, 0xbd, 0x28, 0x9a, 0x14, 0x7c,
+ 0xe9, 0xda, 0x31, 0x13, 0xb5, 0xf0, 0xb8, 0xc0, 0x0a, 0x60, 0xb1, 0xce,
+ 0x1d, 0x7e, 0x81, 0x9d, 0x7a, 0x43, 0x1d, 0x7c, 0x90, 0xea, 0x0e, 0x5f,
+ /* order */
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
+ 0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73,
+};
+
+static const uint8_t kP521Params[6 * 66] = {
+ /* p */
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ /* a */
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
+ /* b */
+ 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
+ 0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
+ 0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
+ 0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
+ 0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
+ 0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00,
+ /* x */
+ 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
+ 0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
+ 0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
+ 0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
+ 0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
+ 0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
+ /* y */
+ 0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, 0xc0, 0x04, 0x5c, 0x8a,
+ 0x5f, 0xb4, 0x2c, 0x7d, 0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
+ 0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e, 0x66, 0x2c, 0x97, 0xee,
+ 0x72, 0x99, 0x5e, 0xf4, 0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
+ 0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72, 0xc2, 0x40, 0x88, 0xbe,
+ 0x94, 0x76, 0x9f, 0xd1, 0x66, 0x50,
+ /* order */
+ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
+ 0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
+ 0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
+ 0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09,
+};
/* MSan appears to have a bug that causes code to be miscompiled in opt mode.
* While that is being looked at, don't run the uint128_t code under MSan. */
@@ -249,7 +225,9 @@ DEFINE_METHOD_FUNCTION(struct built_in_curves, OPENSSL_built_in_curves) {
out->curves[0].nid = NID_secp521r1;
out->curves[0].oid = kOIDP521;
out->curves[0].oid_len = sizeof(kOIDP521);
- out->curves[0].data = P521_data();
+ out->curves[0].comment = "NIST P-521";
+ out->curves[0].param_len = 66;
+ out->curves[0].params = kP521Params;
out->curves[0].method = EC_GFp_mont_method();
/* 1.3.132.0.34 */
@@ -257,7 +235,9 @@ DEFINE_METHOD_FUNCTION(struct built_in_curves, OPENSSL_built_in_curves) {
out->curves[1].nid = NID_secp384r1;
out->curves[1].oid = kOIDP384;
out->curves[1].oid_len = sizeof(kOIDP384);
- out->curves[1].data = P384_data();
+ out->curves[1].comment = "NIST P-384";
+ out->curves[1].param_len = 48;
+ out->curves[1].params = kP384Params;
out->curves[1].method = EC_GFp_mont_method();
/* 1.2.840.10045.3.1.7 */
@@ -266,7 +246,9 @@ DEFINE_METHOD_FUNCTION(struct built_in_curves, OPENSSL_built_in_curves) {
out->curves[2].nid = NID_X9_62_prime256v1;
out->curves[2].oid = kOIDP256;
out->curves[2].oid_len = sizeof(kOIDP256);
- out->curves[2].data = P256_data();
+ out->curves[2].comment = "NIST P-256";
+ out->curves[2].param_len = 32;
+ out->curves[2].params = kP256Params;
out->curves[2].method =
#if defined(BORINGSSL_USE_INT128_CODE)
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
@@ -284,7 +266,9 @@ DEFINE_METHOD_FUNCTION(struct built_in_curves, OPENSSL_built_in_curves) {
out->curves[3].nid = NID_secp224r1;
out->curves[3].oid = kOIDP224;
out->curves[3].oid_len = sizeof(kOIDP224);
- out->curves[3].data = P224_data();
+ out->curves[3].comment = "NIST P-224";
+ out->curves[3].param_len = 28;
+ out->curves[3].params = kP224Params;
out->curves[3].method =
#if defined(BORINGSSL_USE_INT128_CODE) && !defined(OPENSSL_SMALL)
EC_GFp_nistp224_method();
@@ -317,9 +301,9 @@ DEFINE_LOCAL_DATA(BN_MONT_CTX **, built_in_curve_scalar_field_monts) {
}
for (size_t i = 0; i < OPENSSL_NUM_BUILT_IN_CURVES; i++) {
- const struct curve_data *curve = curves->curves[i].data;
+ const struct built_in_curve *curve = &curves->curves[i];
const unsigned param_len = curve->param_len;
- const uint8_t *params = curve->data;
+ const uint8_t *params = curve->params;
mont_ctx = BN_MONT_CTX_new();
if (mont_ctx == NULL) {
@@ -433,9 +417,8 @@ static EC_GROUP *ec_group_new_from_data(unsigned built_in_index) {
goto err;
}
- const struct curve_data *data = curve->data;
- const unsigned param_len = data->param_len;
- const uint8_t *params = data->data;
+ const unsigned param_len = curve->param_len;
+ const uint8_t *params = curve->params;
if (!(p = BN_bin2bn(params + 0 * param_len, param_len, NULL)) ||
!(a = BN_bin2bn(params + 1 * param_len, param_len, NULL)) ||
@@ -852,7 +835,7 @@ size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
for (size_t i = 0; i < max_num_curves && i < OPENSSL_NUM_BUILT_IN_CURVES;
i++) {
- out_curves[i].comment = curves->curves[i].data->comment;
+ out_curves[i].comment = curves->curves[i].comment;
out_curves[i].nid = curves->curves[i].nid;
}
diff --git a/src/crypto/fipsmodule/ec/internal.h b/src/crypto/fipsmodule/ec/internal.h
index d14fec66..de91e2b6 100644
--- a/src/crypto/fipsmodule/ec/internal.h
+++ b/src/crypto/fipsmodule/ec/internal.h
@@ -249,23 +249,18 @@ struct ec_key_st {
CRYPTO_EX_DATA ex_data;
} /* EC_KEY */;
-/* curve_data contains data about a built-in elliptic curve. */
-struct curve_data {
+struct built_in_curve {
+ int nid;
+ const uint8_t *oid;
+ uint8_t oid_len;
/* comment is a human-readable string describing the curve. */
const char *comment;
/* param_len is the number of bytes needed to store a field element. */
uint8_t param_len;
- /* data points to an array of 6*|param_len| bytes which hold the field
+ /* params points to an array of 6*|param_len| bytes which hold the field
* elements of the following (in big-endian order): prime, a, b, generator x,
* generator y, order. */
- const uint8_t *data;
-};
-
-struct built_in_curve {
- int nid;
- const uint8_t *oid;
- uint8_t oid_len;
- const struct curve_data *data;
+ const uint8_t *params;
const EC_METHOD *method;
};
diff --git a/src/crypto/fipsmodule/rsa/rsa_impl.c b/src/crypto/fipsmodule/rsa/rsa_impl.c
index 342f1c2c..c79f8649 100644
--- a/src/crypto/fipsmodule/rsa/rsa_impl.c
+++ b/src/crypto/fipsmodule/rsa/rsa_impl.c
@@ -533,6 +533,11 @@ err:
int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
size_t len) {
+ if (rsa->n == NULL || rsa->d == NULL) {
+ OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
+ return 0;
+ }
+
BIGNUM *f, *result;
BN_CTX *ctx = NULL;
unsigned blinding_index = 0;
diff --git a/src/crypto/rand_extra/fuchsia.c b/src/crypto/rand_extra/fuchsia.c
index fae29894..9711c1db 100644
--- a/src/crypto/rand_extra/fuchsia.c
+++ b/src/crypto/rand_extra/fuchsia.c
@@ -32,7 +32,7 @@ void CRYPTO_sysrand(uint8_t *out, size_t requested) {
size_t bytes_drawn;
mx_status_t status =
mx_cprng_draw(out, output_bytes_this_pass, &bytes_drawn);
- if (status != NO_ERROR) {
+ if (status != MX_OK) {
abort();
}
requested -= bytes_drawn;
diff --git a/src/crypto/rsa_extra/rsa_test.cc b/src/crypto/rsa_extra/rsa_test.cc
index 162ac055..1cc71eab 100644
--- a/src/crypto/rsa_extra/rsa_test.cc
+++ b/src/crypto/rsa_extra/rsa_test.cc
@@ -697,6 +697,22 @@ TEST(RSATest, BlindingDisabled) {
RSA_verify(NID_sha256, kZeros, sizeof(kZeros), sig, sig_len, rsa.get()));
}
+// Test that decrypting with a public key fails gracefully rather than crashing.
+TEST(RSATest, DecryptPublic) {
+ bssl::UniquePtr<RSA> pub(
+ RSA_public_key_from_bytes(kFIPSPublicKey, sizeof(kFIPSPublicKey) - 1));
+ ASSERT_TRUE(pub);
+ ASSERT_EQ(1024u / 8u, RSA_size(pub.get()));
+
+ size_t len;
+ uint8_t in[1024 / 8] = {0}, out[1024 / 8];
+ EXPECT_FALSE(RSA_decrypt(pub.get(), &len, out, sizeof(out), in, sizeof(in),
+ RSA_PKCS1_PADDING));
+ uint32_t err = ERR_get_error();
+ EXPECT_EQ(ERR_LIB_RSA, ERR_GET_LIB(err));
+ EXPECT_EQ(RSA_R_VALUE_MISSING, ERR_GET_REASON(err));
+}
+
#if !defined(BORINGSSL_SHARED_LIBRARY)
TEST(RSATest, SqrtTwo) {
bssl::UniquePtr<BIGNUM> sqrt(BN_new()), pow2(BN_new());
diff --git a/src/include/openssl/aead.h b/src/include/openssl/aead.h
index 29944384..e0d64325 100644
--- a/src/include/openssl/aead.h
+++ b/src/include/openssl/aead.h
@@ -223,8 +223,8 @@ OPENSSL_EXPORT void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx);
* |EVP_AEAD_nonce_length| for this AEAD.
*
* |EVP_AEAD_CTX_seal| never results in a partial output. If |max_out_len| is
- * insufficient, zero will be returned. (In this case, |*out_len| is set to
- * zero.)
+ * insufficient, zero will be returned. If any error occurs, |out| will be
+ * filled with zero bytes and |*out_len| set to zero.
*
* If |in| and |out| alias then |out| must be == |in|. */
OPENSSL_EXPORT int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
@@ -232,6 +232,7 @@ OPENSSL_EXPORT int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
const uint8_t *ad, size_t ad_len);
+
/* EVP_AEAD_CTX_open authenticates |in_len| bytes from |in| and |ad_len| bytes
* from |ad| and decrypts at most |in_len| bytes into |out|. It returns one on
* success and zero otherwise.
@@ -247,8 +248,8 @@ OPENSSL_EXPORT int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
* |EVP_AEAD_nonce_length| for this AEAD.
*
* |EVP_AEAD_CTX_open| never results in a partial output. If |max_out_len| is
- * insufficient, zero will be returned. (In this case, |*out_len| is set to
- * zero.)
+ * insufficient, zero will be returned. If any error occurs, |out| will be
+ * filled with zero bytes and |*out_len| set to zero.
*
* If |in| and |out| alias then |out| must be == |in|. */
OPENSSL_EXPORT int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
@@ -273,8 +274,9 @@ OPENSSL_EXPORT int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
* |EVP_AEAD_nonce_length| for this AEAD.
*
* |EVP_AEAD_CTX_seal_scatter| never results in a partial output. If
- * |max_out_tag_len| is insufficient, zero will be returned. (In this case,
- * |*out_tag_len| is set to zero.)
+ * |max_out_tag_len| is insufficient, zero will be returned. If any error
+ * occurs, |out| and |out_tag| will be filled with zero bytes and |*out_tag_len|
+ * set to zero.
*
* If |in| and |out| alias then |out| must be == |in|. |out_tag| may not alias
* any other argument. */
@@ -295,7 +297,8 @@ OPENSSL_EXPORT int EVP_AEAD_CTX_seal_scatter(
* The length of |nonce|, |nonce_len|, must be equal to the result of
* |EVP_AEAD_nonce_length| for this AEAD.
*
- * |EVP_AEAD_CTX_open_gather| never results in a partial output.
+ * |EVP_AEAD_CTX_open_gather| never results in a partial output. If any error
+ * occurs, |out| will be filled with zero bytes.
*
* If |in| and |out| alias then |out| must be == |in|. */
OPENSSL_EXPORT int EVP_AEAD_CTX_open_gather(
diff --git a/src/include/openssl/ec_key.h b/src/include/openssl/ec_key.h
index 3aeaa780..7c2957e8 100644
--- a/src/include/openssl/ec_key.h
+++ b/src/include/openssl/ec_key.h
@@ -255,10 +255,6 @@ struct ecdsa_method_st {
int (*sign)(const uint8_t *digest, size_t digest_len, uint8_t *sig,
unsigned int *sig_len, EC_KEY *eckey);
- /* Ignored. Set this to NULL. */
- int (*verify)(const uint8_t *digest, size_t digest_len, const uint8_t *sig,
- size_t sig_len, EC_KEY *eckey);
-
int flags;
};
diff --git a/src/include/openssl/rsa.h b/src/include/openssl/rsa.h
index caf4a428..a580f974 100644
--- a/src/include/openssl/rsa.h
+++ b/src/include/openssl/rsa.h
@@ -577,11 +577,10 @@ struct rsa_meth_st {
int (*sign)(int type, const uint8_t *m, unsigned int m_length,
uint8_t *sigret, unsigned int *siglen, const RSA *rsa);
- /* Ignored. Set this to NULL. */
- int (*verify)(int dtype, const uint8_t *m, unsigned int m_length,
- const uint8_t *sigbuf, unsigned int siglen, const RSA *rsa);
-
- /* Ignored. Set this to NULL. */
+ /* Ignored. Set this to NULL.
+ * TODO(davidben): Remove this when
+ * https://github.com/google/conscrypt/commit/bb0571e358e95e1c70ac7a6984fc4d7236cac72f
+ * is in all BoringSSL consumers. */
int (*encrypt)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
const uint8_t *in, size_t in_len, int padding);
@@ -590,9 +589,6 @@ struct rsa_meth_st {
const uint8_t *in, size_t in_len, int padding);
int (*decrypt)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
const uint8_t *in, size_t in_len, int padding);
- /* Ignored. Set this to NULL. */
- int (*verify_raw)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
- const uint8_t *in, size_t in_len, int padding);
/* private_transform takes a big-endian integer from |in|, calculates the
* d'th power of it, modulo the RSA modulus and writes the result as a
@@ -609,25 +605,7 @@ struct rsa_meth_st {
int (*private_transform)(RSA *rsa, uint8_t *out, const uint8_t *in,
size_t len);
- /* mod_exp is deprecated and ignored. Set it to NULL. */
- int (*mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
-
- /* bn_mod_exp is deprecated and ignored. Set it to NULL. */
- int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
- const BIGNUM *m, BN_CTX *ctx,
- const BN_MONT_CTX *mont);
-
int flags;
-
- /* Ignored. Set this to NULL. */
- int (*keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
-
- /* Ignored. Set this to NULL. */
- int (*multi_prime_keygen)(RSA *rsa, int bits, int num_primes, BIGNUM *e,
- BN_GENCB *cb);
-
- /* supports_digest is deprecated and ignored. Set it to NULL. */
- int (*supports_digest)(const RSA *rsa, const EVP_MD *md);
};
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index 55e53dac..b5f1c574 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -512,6 +512,12 @@ OPENSSL_EXPORT int SSL_get_error(const SSL *ssl, int ret_code);
* See also |SSL_CTX_set_ticket_aead_method|. */
#define SSL_ERROR_PENDING_TICKET 14
+/* SSL_ERROR_EARLY_DATA_REJECTED indicates that early data was rejected. The
+ * caller should treat this as a connection failure and retry any operations
+ * associated with the rejected early data. |SSL_reset_early_data_reject| may be
+ * used to reuse the underlying connection for the retry. */
+#define SSL_ERROR_EARLY_DATA_REJECTED 15
+
/* SSL_set_mtu sets the |ssl|'s MTU in DTLS to |mtu|. It returns one on success
* and zero on failure. */
OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu);
@@ -1240,7 +1246,12 @@ OPENSSL_EXPORT uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher);
* supports |cipher|. */
OPENSSL_EXPORT uint16_t SSL_CIPHER_get_max_version(const SSL_CIPHER *cipher);
-/* SSL_CIPHER_get_name returns the OpenSSL name of |cipher|. */
+/* SSL_CIPHER_standard_name returns the standard IETF name for |cipher|. For
+ * example, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256". */
+OPENSSL_EXPORT const char *SSL_CIPHER_standard_name(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_get_name returns the OpenSSL name of |cipher|. For example,
+ * "ECDHE-RSA-AES128-GCM-SHA256". */
OPENSSL_EXPORT const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher);
/* SSL_CIPHER_get_kx_name returns a string that describes the key-exchange
@@ -1248,12 +1259,6 @@ OPENSSL_EXPORT const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher);
* ciphers return the string "GENERIC". */
OPENSSL_EXPORT const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher);
-/* SSL_CIPHER_get_rfc_name returns a newly-allocated string with the standard
- * name for |cipher| or NULL on error. For example,
- * "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256". The caller is responsible for
- * calling |OPENSSL_free| on the result. */
-OPENSSL_EXPORT char *SSL_CIPHER_get_rfc_name(const SSL_CIPHER *cipher);
-
/* SSL_CIPHER_get_bits returns the strength, in bits, of |cipher|. If
* |out_alg_bits| is not NULL, it writes the number of bits consumed by the
* symmetric algorithm to |*out_alg_bits|. */
@@ -1289,10 +1294,10 @@ OPENSSL_EXPORT int SSL_CIPHER_get_bits(const SSL_CIPHER *cipher,
* |!| deletes all matching ciphers, enabled or not, from either list. Deleted
* ciphers will not matched by future operations.
*
- * A selector may be a specific cipher (using the OpenSSL name for the cipher)
- * or one or more rules separated by |+|. The final selector matches the
- * intersection of each rule. For instance, |AESGCM+aECDSA| matches
- * ECDSA-authenticated AES-GCM ciphers.
+ * A selector may be a specific cipher (using either the standard or OpenSSL
+ * name for the cipher) or one or more rules separated by |+|. The final
+ * selector matches the intersection of each rule. For instance, |AESGCM+aECDSA|
+ * matches ECDSA-authenticated AES-GCM ciphers.
*
* Available cipher rules are:
*
@@ -2620,35 +2625,21 @@ OPENSSL_EXPORT void SSL_get0_next_proto_negotiated(const SSL *ssl,
* expected that this function is called from the callback set by
* |SSL_CTX_set_next_proto_select_cb|.
*
- * The protocol data is assumed to be a vector of 8-bit, length prefixed byte
- * strings. The length byte itself is not included in the length. A byte
- * string of length 0 is invalid. No byte string may be truncated.
- *
- * The current, but experimental algorithm for selecting the protocol is:
- *
- * 1) If the server doesn't support NPN then this is indicated to the
- * callback. In this case, the client application has to abort the connection
- * or have a default application level protocol.
- *
- * 2) If the server supports NPN, but advertises an empty list then the
- * client selects the first protocol in its list, but indicates via the
- * API that this fallback case was enacted.
- *
- * 3) Otherwise, the client finds the first protocol in the server's list
- * that it supports and selects this protocol. This is because it's
- * assumed that the server has better information about which protocol
- * a client should use.
- *
- * 4) If the client doesn't support any of the server's advertised
- * protocols, then this is treated the same as case 2.
- *
- * It returns either |OPENSSL_NPN_NEGOTIATED| if a common protocol was found, or
- * |OPENSSL_NPN_NO_OVERLAP| if the fallback case was reached. */
+ * |peer| and |supported| must be vectors of 8-bit, length-prefixed byte strings
+ * containing the peer and locally-configured protocols, respectively. The
+ * length byte itself is not included in the length. A byte string of length 0
+ * is invalid. No byte string may be truncated. |supported| is assumed to be
+ * non-empty.
+ *
+ * This function finds the first protocol in |peer| which is also in
+ * |supported|. If one was found, it sets |*out| and |*out_len| to point to it
+ * and returns |OPENSSL_NPN_NEGOTIATED|. Otherwise, it returns
+ * |OPENSSL_NPN_NO_OVERLAP| and sets |*out| and |*out_len| to the first
+ * supported protocol. */
OPENSSL_EXPORT int SSL_select_next_proto(uint8_t **out, uint8_t *out_len,
- const uint8_t *server,
- unsigned server_len,
- const uint8_t *client,
- unsigned client_len);
+ const uint8_t *peer, unsigned peer_len,
+ const uint8_t *supported,
+ unsigned supported_len);
#define OPENSSL_NPN_UNSUPPORTED 0
#define OPENSSL_NPN_NEGOTIATED 1
@@ -2833,6 +2824,86 @@ OPENSSL_EXPORT const char *SSL_get_psk_identity_hint(const SSL *ssl);
OPENSSL_EXPORT const char *SSL_get_psk_identity(const SSL *ssl);
+/* Early data.
+ *
+ * WARNING: 0-RTT support in BoringSSL is currently experimental and not fully
+ * implemented. It may cause interoperability or security failures when used.
+ *
+ * Early data, or 0-RTT, is a feature in TLS 1.3 which allows clients to send
+ * data on the first flight during a resumption handshake. This can save a
+ * round-trip in some application protocols.
+ *
+ * WARNING: A 0-RTT handshake has different security properties from normal
+ * handshake, so it is off by default unless opted in. In particular, early data
+ * is replayable by a network attacker. Callers must account for this when
+ * sending or processing data before the handshake is confirmed. See
+ * draft-ietf-tls-tls13-18 for more information.
+ *
+ * As a server, if early data is accepted, |SSL_do_handshake| will complete as
+ * soon as the ClientHello is processed and server flight sent. |SSL_write| may
+ * be used to send half-RTT data. |SSL_read| will consume early data and
+ * transition to 1-RTT data as appropriate. Prior to the transition,
+ * |SSL_in_init| will report the handshake is still in progress. Callers may use
+ * it or |SSL_in_early_data| to defer or reject requests as needed.
+ *
+ * Early data as a client is more complex. If the offered session (see
+ * |SSL_set_session|) is 0-RTT-capable, the handshake will return after sending
+ * the ClientHello. The predicted peer certificate and ALPN protocol will be
+ * available via the usual APIs. |SSL_write| will write early data, up to the
+ * session's limit. Writes past this limit and |SSL_read| will complete the
+ * handshake before continuing. Callers may also call |SSL_do_handshake| again
+ * to complete the handshake sooner.
+ *
+ * If the server accepts early data, the handshake will succeed. |SSL_read| and
+ * |SSL_write| will then act as in a 1-RTT handshake. The peer certificate and
+ * ALPN protocol will be as predicted and need not be re-queried.
+ *
+ * If the server rejects early data, |SSL_do_handshake| (and thus |SSL_read| and
+ * |SSL_write|) will then fail with |SSL_get_error| returning
+ * |SSL_ERROR_EARLY_DATA_REJECTED|. The caller should treat this as a connection
+ * error and most likely perform a high-level retry. Note the server may still
+ * have processed the early data due to attacker replays.
+ *
+ * To then continue the handshake on the original connection, use
+ * |SSL_reset_early_data_reject|. This allows a faster retry than making a fresh
+ * connection. |SSL_do_handshake| will the complete the full handshake as in a
+ * fresh connection. Once reset, the peer certificate, ALPN protocol, and other
+ * properties may change so the caller must query them again.
+ *
+ * Finally, to implement the fallback described in draft-ietf-tls-tls13-18
+ * appendix C.3, retry on a fresh connection without 0-RTT if the handshake
+ * fails with |SSL_R_WRONG_VERSION_ON_EARLY_DATA|. */
+
+/* SSL_CTX_set_early_data_enabled sets whether early data is allowed to be used
+ * with resumptions using |ctx|. */
+OPENSSL_EXPORT void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled);
+
+/* SSL_set_early_data_enabled sets whether early data is allowed to be used
+ * with resumptions using |ssl|. See |SSL_CTX_set_early_data_enabled| for more
+ * information. */
+OPENSSL_EXPORT void SSL_set_early_data_enabled(SSL *ssl, int enabled);
+
+/* SSL_in_early_data returns one if |ssl| has a pending handshake that has
+ * progressed enough to send or receive early data. Clients may call |SSL_write|
+ * to send early data, but |SSL_read| will complete the handshake before
+ * accepting application data. Servers may call |SSL_read| to read early data
+ * and |SSL_write| to send half-RTT data. */
+OPENSSL_EXPORT int SSL_in_early_data(const SSL *ssl);
+
+/* SSL_early_data_accepted returns whether early data was accepted on the
+ * handshake performed by |ssl|. */
+OPENSSL_EXPORT int SSL_early_data_accepted(const SSL *ssl);
+
+/* SSL_reset_early_data_reject resets |ssl| after an early data reject. All
+ * 0-RTT state is discarded, including any pending |SSL_write| calls. The caller
+ * should treat |ssl| as a logically fresh connection, usually by driving the
+ * handshake to completion using |SSL_do_handshake|.
+ *
+ * It is an error to call this function on an |SSL| object that is not signaling
+ * |SSL_ERROR_EARLY_DATA_REJECTED|. */
+OPENSSL_EXPORT void SSL_reset_early_data_reject(SSL *ssl);
+
+
/* Alerts.
*
* TLS and SSL 3.0 use alerts to signal error conditions. Alerts have a type
@@ -3061,32 +3132,6 @@ OPENSSL_EXPORT int SSL_renegotiate_pending(SSL *ssl);
* performed by |ssl|. This includes the pending renegotiation, if any. */
OPENSSL_EXPORT int SSL_total_renegotiations(const SSL *ssl);
-/* SSL_CTX_set_early_data_enabled sets whether early data is allowed to be used
- * with resumptions using |ctx|.
- *
- * As a server, if the client's early data is accepted, |SSL_do_handshake| will
- * complete as soon as the ClientHello is processed and server flight sent.
- * |SSL_write| may be used to send half-RTT data. |SSL_read| will consume early
- * data and transition to 1-RTT data as appropriate.
- *
- * Note early data is replayable by a network attacker. |SSL_in_init| and
- * |SSL_is_init_finished| will report the handshake is still in progress until
- * the client's Finished message is received. Callers may use these functions
- * to defer some processing if desired.
- *
- * WARNING: This is experimental and may cause interoperability failures until
- * fully implemented. */
-OPENSSL_EXPORT void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled);
-
-/* SSL_set_early_data_enabled sets whether early data is allowed to be used
- * with resumptions using |ssl|. See |SSL_CTX_set_early_data_enabled| for more
- * information. */
-OPENSSL_EXPORT void SSL_set_early_data_enabled(SSL *ssl, int enabled);
-
-/* SSL_early_data_accepted returns whether early data was accepted on the
- * handshake performed by |ssl|. */
-OPENSSL_EXPORT int SSL_early_data_accepted(const SSL *ssl);
-
/* SSL_MAX_CERT_LIST_DEFAULT is the default maximum length, in bytes, of a peer
* certificate chain. */
#define SSL_MAX_CERT_LIST_DEFAULT (1024 * 100)
@@ -3124,10 +3169,6 @@ OPENSSL_EXPORT int SSL_CTX_set_max_send_fragment(SSL_CTX *ctx,
OPENSSL_EXPORT int SSL_set_max_send_fragment(SSL *ssl,
size_t max_send_fragment);
-/* SSL_get_v2clienthello_count returns the total number of V2ClientHellos that
- * are accepted. */
-OPENSSL_EXPORT uint64_t SSL_get_v2clienthello_count(void);
-
/* 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
@@ -3344,13 +3385,20 @@ OPENSSL_EXPORT int SSL_library_init(void);
* The description includes a trailing newline and has the form:
* AES128-SHA Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1
*
- * Consider |SSL_CIPHER_get_name| or |SSL_CIPHER_get_rfc_name| instead. */
+ * Consider |SSL_CIPHER_standard_name| or |SSL_CIPHER_get_name| instead. */
OPENSSL_EXPORT const char *SSL_CIPHER_description(const SSL_CIPHER *cipher,
char *buf, int len);
/* SSL_CIPHER_get_version returns the string "TLSv1/SSLv3". */
OPENSSL_EXPORT const char *SSL_CIPHER_get_version(const SSL_CIPHER *cipher);
+/* SSL_CIPHER_get_rfc_name returns a newly-allocated string containing the
+ * result of |SSL_CIPHER_standard_name| or NULL on error. The caller is
+ * responsible for calling |OPENSSL_free| on the result.
+ *
+ * Use |SSL_CIPHER_standard_name| instead. */
+OPENSSL_EXPORT char *SSL_CIPHER_get_rfc_name(const SSL_CIPHER *cipher);
+
typedef void COMP_METHOD;
/* SSL_COMP_get_compression_methods returns NULL. */
@@ -3676,6 +3724,7 @@ OPENSSL_EXPORT void SSL_CTX_set_client_cert_cb(
#define SSL_CERTIFICATE_SELECTION_PENDING 8
#define SSL_PRIVATE_KEY_OPERATION 9
#define SSL_PENDING_TICKET 10
+#define SSL_EARLY_DATA_REJECTED 11
/* SSL_want returns one of the above values to determine what the most recent
* operation on |ssl| was blocked on. Use |SSL_get_error| instead. */
@@ -3847,6 +3896,8 @@ typedef struct ssl_x509_method_st SSL_X509_METHOD;
struct ssl_cipher_st {
/* name is the OpenSSL name for the cipher. */
const char *name;
+ /* standard_name is the IETF name for the cipher. */
+ const char *standard_name;
/* id is the cipher suite value bitwise OR-d with 0x03000000. */
uint32_t id;
@@ -4036,13 +4087,15 @@ struct ssl_ctx_st {
/* lock is used to protect various operations on this object. */
CRYPTO_MUTEX lock;
- /* max_version is the maximum acceptable protocol version. Note this version
- * is normalized in DTLS. */
- uint16_t max_version;
+ /* conf_max_version is the maximum acceptable protocol version configured by
+ * |SSL_CTX_set_max_proto_version|. Note this version is normalized in DTLS
+ * and is further constrainted by |SSL_OP_NO_*|. */
+ uint16_t conf_max_version;
- /* min_version is the minimum acceptable protocol version. Note this version
- * is normalized in DTLS. */
- uint16_t min_version;
+ /* conf_min_version is the minimum acceptable protocol version configured by
+ * |SSL_CTX_set_min_proto_version|. Note this version is normalized in DTLS
+ * and is further constrainted by |SSL_OP_NO_*|. */
+ uint16_t conf_min_version;
struct ssl_cipher_preference_list_st *cipher_list;
@@ -4625,6 +4678,7 @@ BORINGSSL_MAKE_DELETER(SSL_SESSION, SSL_SESSION_free)
#define SSL_R_WRONG_VERSION_ON_EARLY_DATA 278
#define SSL_R_CHANNEL_ID_ON_EARLY_DATA 279
#define SSL_R_NO_SUPPORTED_VERSIONS_ENABLED 280
+#define SSL_R_APPLICATION_DATA_INSTEAD_OF_HANDSHAKE 281
#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/ssl3.h b/src/include/openssl/ssl3.h
index b5f5d6ad..98648c4c 100644
--- a/src/include/openssl/ssl3.h
+++ b/src/include/openssl/ssl3.h
@@ -302,6 +302,7 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_ST_FALSE_START (0x101 | SSL_ST_CONNECT)
#define SSL3_ST_VERIFY_SERVER_CERT (0x102 | SSL_ST_CONNECT)
#define SSL3_ST_FINISH_CLIENT_HANDSHAKE (0x103 | SSL_ST_CONNECT)
+#define SSL3_ST_WRITE_EARLY_DATA (0x104 | SSL_ST_CONNECT)
/* write to server */
#define SSL3_ST_CW_CLNT_HELLO_A (0x110 | SSL_ST_CONNECT)
/* read from server */
@@ -309,14 +310,12 @@ OPENSSL_COMPILE_ASSERT(
#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126 | SSL_ST_CONNECT)
#define SSL3_ST_CR_CERT_A (0x130 | SSL_ST_CONNECT)
#define SSL3_ST_CR_KEY_EXCH_A (0x140 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_KEY_EXCH_B (0x141 | SSL_ST_CONNECT)
#define SSL3_ST_CR_CERT_REQ_A (0x150 | SSL_ST_CONNECT)
#define SSL3_ST_CR_SRVR_DONE_A (0x160 | SSL_ST_CONNECT)
/* write to server */
#define SSL3_ST_CW_CERT_A (0x170 | SSL_ST_CONNECT)
#define SSL3_ST_CW_KEY_EXCH_A (0x180 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CERT_VRFY_A (0x190 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_CERT_VRFY_B (0x191 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CHANGE (0x1A0 | SSL_ST_CONNECT)
#define SSL3_ST_CW_NEXT_PROTO_A (0x200 | SSL_ST_CONNECT)
#define SSL3_ST_CW_CHANNEL_ID_A (0x220 | SSL_ST_CONNECT)
@@ -343,8 +342,6 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_ST_SW_SRVR_HELLO_A (0x130 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_CERT_A (0x140 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_KEY_EXCH_A (0x150 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_KEY_EXCH_B (0x151 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_CERT_REQ_A (0x160 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_SRVR_DONE_A (0x170 | SSL_ST_ACCEPT)
/* read from client */
#define SSL3_ST_SR_CERT_A (0x180 | SSL_ST_ACCEPT)
@@ -357,10 +354,7 @@ OPENSSL_COMPILE_ASSERT(
#define SSL3_ST_SR_FINISHED_A (0x1C0 | SSL_ST_ACCEPT)
/* write to client */
-#define SSL3_ST_SW_CHANGE (0x1D0 | SSL_ST_ACCEPT)
#define SSL3_ST_SW_FINISHED_A (0x1E0 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_SESSION_TICKET_A (0x1F0 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_CERT_STATUS_A (0x200 | SSL_ST_ACCEPT)
#define SSL3_MT_HELLO_REQUEST 0
#define SSL3_MT_CLIENT_HELLO 1
diff --git a/src/ssl/d1_pkt.c b/src/ssl/d1_pkt.c
index 34448259..e2c7315d 100644
--- a/src/ssl/d1_pkt.c
+++ b/src/ssl/d1_pkt.c
@@ -335,8 +335,10 @@ void dtls1_read_close_notify(SSL *ssl) {
}
}
-int dtls1_write_app_data(SSL *ssl, const uint8_t *buf, int len) {
+int dtls1_write_app_data(SSL *ssl, int *out_needs_handshake, const uint8_t *buf,
+ int len) {
assert(!SSL_in_init(ssl));
+ *out_needs_handshake = 0;
if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DTLS_MESSAGE_TOO_BIG);
diff --git a/src/ssl/handshake_client.c b/src/ssl/handshake_client.c
index f204286f..dddf6029 100644
--- a/src/ssl/handshake_client.c
+++ b/src/ssl/handshake_client.c
@@ -169,7 +169,7 @@
static int ssl3_send_client_hello(SSL_HANDSHAKE *hs);
-static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs);
+static int dtls1_get_hello_verify_request(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);
@@ -218,8 +218,10 @@ int ssl3_connect(SSL_HANDSHAKE *hs) {
ret = -1;
goto end;
}
+ hs->next_state = SSL3_ST_WRITE_EARLY_DATA;
+ } else {
+ hs->next_state = SSL3_ST_CR_SRVR_HELLO_A;
}
- hs->next_state = SSL3_ST_CR_SRVR_HELLO_A;
} else {
hs->next_state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
}
@@ -228,7 +230,7 @@ int ssl3_connect(SSL_HANDSHAKE *hs) {
case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
assert(SSL_is_dtls(ssl));
- ret = dtls1_get_hello_verify(hs);
+ ret = dtls1_get_hello_verify_request(hs);
if (ret <= 0) {
goto end;
}
@@ -240,6 +242,18 @@ int ssl3_connect(SSL_HANDSHAKE *hs) {
}
break;
+ case SSL3_ST_WRITE_EARLY_DATA:
+ /* Stash the early data session, so connection properties may be queried
+ * out of it. */
+ hs->in_early_data = 1;
+ hs->early_session = ssl->session;
+ SSL_SESSION_up_ref(ssl->session);
+
+ hs->state = SSL3_ST_CR_SRVR_HELLO_A;
+ hs->can_early_write = 1;
+ ret = 1;
+ goto end;
+
case SSL3_ST_CR_SRVR_HELLO_A:
ret = ssl3_get_server_hello(hs);
if (hs->state == SSL_ST_TLS13) {
@@ -332,7 +346,6 @@ int ssl3_connect(SSL_HANDSHAKE *hs) {
break;
case SSL3_ST_CW_CERT_VRFY_A:
- case SSL3_ST_CW_CERT_VRFY_B:
if (hs->cert_request && ssl_has_certificate(ssl)) {
ret = ssl3_send_cert_verify(hs);
if (ret <= 0) {
@@ -554,9 +567,8 @@ static void ssl_get_client_disabled(SSL *ssl, uint32_t *out_mask_a,
}
}
-static int ssl_write_client_cipher_list(SSL *ssl, CBB *out,
- uint16_t min_version,
- uint16_t max_version) {
+static int ssl_write_client_cipher_list(SSL_HANDSHAKE *hs, CBB *out) {
+ SSL *const ssl = hs->ssl;
uint32_t mask_a, mask_k;
ssl_get_client_disabled(ssl, &mask_a, &mask_k);
@@ -573,7 +585,7 @@ static int ssl_write_client_cipher_list(SSL *ssl, CBB *out,
/* Add TLS 1.3 ciphers. Order ChaCha20-Poly1305 relative to AES-GCM based on
* hardware support. */
- if (max_version >= TLS1_3_VERSION) {
+ if (hs->max_version >= TLS1_3_VERSION) {
if (!EVP_has_aes_hardware() &&
!CBB_add_u16(&child, TLS1_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) {
return 0;
@@ -588,7 +600,7 @@ static int ssl_write_client_cipher_list(SSL *ssl, CBB *out,
}
}
- if (min_version < TLS1_3_VERSION) {
+ if (hs->min_version < TLS1_3_VERSION) {
STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl);
int any_enabled = 0;
for (size_t i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
@@ -598,8 +610,8 @@ static int ssl_write_client_cipher_list(SSL *ssl, CBB *out,
(cipher->algorithm_auth & mask_a)) {
continue;
}
- if (SSL_CIPHER_get_min_version(cipher) > max_version ||
- SSL_CIPHER_get_max_version(cipher) < min_version) {
+ if (SSL_CIPHER_get_min_version(cipher) > hs->max_version ||
+ SSL_CIPHER_get_max_version(cipher) < hs->min_version) {
continue;
}
any_enabled = 1;
@@ -609,7 +621,7 @@ static int ssl_write_client_cipher_list(SSL *ssl, CBB *out,
}
/* If all ciphers were disabled, return the error to the caller. */
- if (!any_enabled && max_version < TLS1_3_VERSION) {
+ if (!any_enabled && hs->max_version < TLS1_3_VERSION) {
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_AVAILABLE);
return 0;
}
@@ -617,7 +629,7 @@ static int ssl_write_client_cipher_list(SSL *ssl, CBB *out,
/* For SSLv3, the SCSV is added. Otherwise the renegotiation extension is
* added. */
- if (max_version == SSL3_VERSION &&
+ if (hs->max_version == SSL3_VERSION &&
!ssl->s3->initial_handshake_complete) {
if (!CBB_add_u16(&child, SSL3_CK_SCSV & 0xffff)) {
return 0;
@@ -635,11 +647,6 @@ static int ssl_write_client_cipher_list(SSL *ssl, CBB *out,
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;
- }
-
CBB cbb, body;
if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CLIENT_HELLO)) {
goto err;
@@ -668,7 +675,7 @@ int ssl_write_client_hello(SSL_HANDSHAKE *hs) {
size_t header_len =
SSL_is_dtls(ssl) ? DTLS1_HM_HEADER_LENGTH : SSL3_HM_HEADER_LENGTH;
- if (!ssl_write_client_cipher_list(ssl, &body, min_version, max_version) ||
+ if (!ssl_write_client_cipher_list(hs, &body) ||
!CBB_add_u8(&body, 1 /* one compression method */) ||
!CBB_add_u8(&body, 0 /* null compression */) ||
!ssl_add_clienthello_tlsext(hs, &body, header_len + CBB_len(&body))) {
@@ -705,12 +712,12 @@ static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
return -1;
}
- uint16_t min_version, max_version;
- if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+ /* Freeze the version range. */
+ if (!ssl_get_version_range(ssl, &hs->min_version, &hs->max_version)) {
return -1;
}
- uint16_t max_wire_version = ssl->method->version_to_wire(max_version);
+ uint16_t max_wire_version = ssl->method->version_to_wire(hs->max_version);
assert(hs->state == SSL3_ST_CW_CLNT_HELLO_A);
if (!ssl->s3->have_version) {
ssl->version = max_wire_version;
@@ -720,7 +727,7 @@ static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
* 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) {
+ if (hs->max_version >= TLS1_3_VERSION) {
hs->client_version = ssl->method->version_to_wire(TLS1_2_VERSION);
}
@@ -735,7 +742,8 @@ static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
ssl->session->session_id_length == 0) ||
ssl->session->not_resumable ||
!ssl_session_is_time_valid(ssl, ssl->session) ||
- session_version < min_version || session_version > max_version) {
+ session_version < hs->min_version ||
+ session_version > hs->max_version) {
ssl_set_session(ssl, NULL);
}
}
@@ -754,9 +762,8 @@ static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
return 1;
}
-static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs) {
+static int dtls1_get_hello_verify_request(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int al;
CBS hello_verify_request, cookie;
uint16_t server_version;
@@ -774,15 +781,11 @@ static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs) {
CBS_init(&hello_verify_request, ssl->init_msg, ssl->init_num);
if (!CBS_get_u16(&hello_verify_request, &server_version) ||
!CBS_get_u8_length_prefixed(&hello_verify_request, &cookie) ||
+ CBS_len(&cookie) > sizeof(ssl->d1->cookie) ||
CBS_len(&hello_verify_request) != 0) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
- }
-
- if (CBS_len(&cookie) > sizeof(ssl->d1->cookie)) {
- al = SSL_AD_ILLEGAL_PARAMETER;
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ return -1;
}
OPENSSL_memcpy(ssl->d1->cookie, CBS_data(&cookie), CBS_len(&cookie));
@@ -790,10 +793,6 @@ static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs) {
ssl->d1->send_cookie = 1;
return 1;
-
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- return -1;
}
static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
@@ -833,10 +832,9 @@ static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
return -1;
}
- uint16_t min_version, max_version, server_version;
- if (!ssl_get_version_range(ssl, &min_version, &max_version) ||
- !ssl->method->version_from_wire(&server_version, server_wire_version) ||
- server_version < min_version || server_version > max_version) {
+ uint16_t server_version;
+ if (!ssl->method->version_from_wire(&server_version, server_wire_version) ||
+ server_version < hs->min_version || server_version > hs->max_version) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_PROTOCOL_VERSION);
return -1;
@@ -1076,10 +1074,6 @@ static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) {
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;
-
int ret = ssl->method->ssl_get_message(ssl);
if (ret <= 0) {
return ret;
@@ -1096,28 +1090,27 @@ static int ssl3_get_cert_status(SSL_HANDSHAKE *hs) {
return -1;
}
+ CBS certificate_status, ocsp_response;
+ uint8_t status_type;
CBS_init(&certificate_status, ssl->init_msg, ssl->init_num);
if (!CBS_get_u8(&certificate_status, &status_type) ||
status_type != TLSEXT_STATUSTYPE_ocsp ||
!CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
CBS_len(&ocsp_response) == 0 ||
CBS_len(&certificate_status) != 0) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ return -1;
}
if (!CBS_stow(&ocsp_response, &hs->new_session->ocsp_response,
&hs->new_session->ocsp_response_length)) {
- al = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ return -1;
}
- return 1;
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- return -1;
+ return 1;
}
static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs) {
@@ -1131,7 +1124,6 @@ static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs) {
static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int al;
EC_KEY *ecdh = NULL;
EC_POINT *srvr_ecpoint = NULL;
@@ -1170,9 +1162,9 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
/* Each of the PSK key exchanges begins with a psk_identity_hint. */
if (!CBS_get_u16_length_prefixed(&server_key_exchange,
&psk_identity_hint)) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ goto err;
}
/* Store PSK identity hint for later use, hint is used in
@@ -1184,9 +1176,9 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
* a specific identity. */
if (CBS_len(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN ||
CBS_contains_zero_byte(&psk_identity_hint)) {
- al = SSL_AD_HANDSHAKE_FAILURE;
OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
}
/* Save non-empty identity hints as a C string. Empty identity hints we
@@ -1196,9 +1188,9 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
* and missing as identical. */
if (CBS_len(&psk_identity_hint) != 0 &&
!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;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
}
}
@@ -1211,17 +1203,17 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
group_type != NAMED_CURVE_TYPE ||
!CBS_get_u16(&server_key_exchange, &group_id) ||
!CBS_get_u8_length_prefixed(&server_key_exchange, &point)) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ goto err;
}
hs->new_session->group_id = group_id;
/* Ensure the group is consistent with preferences. */
if (!tls1_check_group_id(ssl, group_id)) {
- al = SSL_AD_ILLEGAL_PARAMETER;
OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ goto err;
}
/* Initialize ECDH and save the peer public key for later. */
@@ -1230,9 +1222,9 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
goto err;
}
} else if (!(alg_k & SSL_kPSK)) {
- al = SSL_AD_UNEXPECTED_MESSAGE;
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ goto err;
}
/* At this point, |server_key_exchange| contains the signature, if any, while
@@ -1247,28 +1239,30 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
uint16_t signature_algorithm = 0;
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
if (!CBS_get_u16(&server_key_exchange, &signature_algorithm)) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ goto err;
}
- if (!tls12_check_peer_sigalg(ssl, &al, signature_algorithm)) {
- goto f_err;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
+ if (!tls12_check_peer_sigalg(ssl, &alert, signature_algorithm)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+ goto err;
}
hs->new_session->peer_signature_algorithm = signature_algorithm;
} else if (!tls1_get_legacy_signature_algorithm(&signature_algorithm,
hs->peer_pubkey)) {
- al = SSL_AD_UNSUPPORTED_CERTIFICATE;
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_CERTIFICATE);
+ goto err;
}
/* The last field in |server_key_exchange| is the signature. */
CBS signature;
if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) ||
CBS_len(&server_key_exchange) != 0) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ goto err;
}
CBB transcript;
@@ -1280,9 +1274,9 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
!CBB_add_bytes(&transcript, CBS_data(&parameter), CBS_len(&parameter)) ||
!CBB_finish(&transcript, &transcript_data, &transcript_len)) {
CBB_cleanup(&transcript);
- al = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
}
int sig_ok = ssl_public_key_verify(
@@ -1296,24 +1290,22 @@ static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
#endif
if (!sig_ok) {
/* bad signature */
- al = SSL_AD_DECRYPT_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
+ goto err;
}
} else {
/* PSK ciphers are the only supported certificate-less ciphers. */
assert(alg_a == SSL_aPSK);
if (CBS_len(&server_key_exchange) > 0) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_EXTRA_DATA_IN_MESSAGE);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ goto err;
}
}
return 1;
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
err:
EC_POINT_free(srvr_ecpoint);
EC_KEY_free(ecdh);
@@ -1661,58 +1653,43 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
}
size_t sig_len = max_sig_len;
- enum ssl_private_key_result_t sign_result;
- if (hs->state == SSL3_ST_CW_CERT_VRFY_A) {
- /* The SSL3 construction for CertificateVerify does not decompose into a
- * single final digest and signature, and must be special-cased. */
- if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
- if (ssl->cert->key_method != NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
- goto err;
- }
-
- uint8_t digest[EVP_MAX_MD_SIZE];
- size_t digest_len;
- if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
- &digest_len, hs->new_session,
- signature_algorithm)) {
- goto err;
- }
-
- sign_result = ssl_private_key_success;
-
- EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
- if (pctx == NULL ||
- !EVP_PKEY_sign_init(pctx) ||
- !EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len)) {
- EVP_PKEY_CTX_free(pctx);
- sign_result = ssl_private_key_failure;
- goto err;
- }
- EVP_PKEY_CTX_free(pctx);
- } else {
- sign_result = ssl_private_key_sign(
- ssl, ptr, &sig_len, max_sig_len, signature_algorithm,
- (const uint8_t *)hs->transcript.buffer->data,
- hs->transcript.buffer->length);
+ /* The SSL3 construction for CertificateVerify does not decompose into a
+ * single final digest and signature, and must be special-cased. */
+ if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+ if (ssl->cert->key_method != NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
+ goto err;
}
- /* The handshake buffer is no longer necessary. */
- SSL_TRANSCRIPT_free_buffer(&hs->transcript);
- } else {
- assert(hs->state == SSL3_ST_CW_CERT_VRFY_B);
- sign_result = ssl_private_key_complete(ssl, ptr, &sig_len, max_sig_len);
- }
-
- switch (sign_result) {
- case ssl_private_key_success:
- break;
- case ssl_private_key_failure:
+ uint8_t digest[EVP_MAX_MD_SIZE];
+ size_t digest_len;
+ if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
+ &digest_len, hs->new_session,
+ signature_algorithm)) {
goto err;
- case ssl_private_key_retry:
- ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
- hs->state = SSL3_ST_CW_CERT_VRFY_B;
+ }
+
+ EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
+ int ok = pctx != NULL &&
+ EVP_PKEY_sign_init(pctx) &&
+ EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len);
+ EVP_PKEY_CTX_free(pctx);
+ if (!ok) {
goto err;
+ }
+ } else {
+ switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
+ signature_algorithm,
+ (const uint8_t *)hs->transcript.buffer->data,
+ hs->transcript.buffer->length)) {
+ case ssl_private_key_success:
+ break;
+ case ssl_private_key_failure:
+ goto err;
+ case ssl_private_key_retry:
+ ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
+ goto err;
+ }
}
if (!CBB_did_write(&child, sig_len) ||
@@ -1720,6 +1697,8 @@ static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
goto err;
}
+ /* The handshake buffer is no longer necessary. */
+ SSL_TRANSCRIPT_free_buffer(&hs->transcript);
return 1;
err:
diff --git a/src/ssl/handshake_server.c b/src/ssl/handshake_server.c
index 4eaf3cb0..d591c805 100644
--- a/src/ssl/handshake_server.c
+++ b/src/ssl/handshake_server.c
@@ -175,31 +175,17 @@ static int ssl3_select_certificate(SSL_HANDSHAKE *hs);
static int ssl3_select_parameters(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);
-
-static struct CRYPTO_STATIC_MUTEX g_v2clienthello_lock =
- CRYPTO_STATIC_MUTEX_INIT;
-static uint64_t g_v2clienthello_count = 0;
-
-uint64_t SSL_get_v2clienthello_count(void) {
- CRYPTO_STATIC_MUTEX_lock_read(&g_v2clienthello_lock);
- uint64_t ret = g_v2clienthello_count;
- CRYPTO_STATIC_MUTEX_unlock_read(&g_v2clienthello_lock);
- return ret;
-}
+static int ssl3_send_server_finished(SSL_HANDSHAKE *hs);
int ssl3_accept(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- uint32_t alg_a;
int ret = -1;
assert(ssl->handshake_func == ssl3_accept);
@@ -255,55 +241,28 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
goto end;
}
if (ssl->session != NULL) {
- hs->state = SSL3_ST_SW_SESSION_TICKET_A;
+ hs->state = SSL3_ST_SW_FINISHED_A;
} else {
hs->state = SSL3_ST_SW_CERT_A;
}
break;
case SSL3_ST_SW_CERT_A:
- if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
- ret = ssl3_send_server_certificate(hs);
- if (ret <= 0) {
- goto end;
- }
- }
- hs->state = SSL3_ST_SW_CERT_STATUS_A;
- break;
-
- case SSL3_ST_SW_CERT_STATUS_A:
- if (hs->certificate_status_expected) {
- ret = ssl3_send_certificate_status(hs);
- if (ret <= 0) {
- goto end;
- }
+ ret = ssl3_send_server_certificate(hs);
+ if (ret <= 0) {
+ goto end;
}
hs->state = SSL3_ST_SW_KEY_EXCH_A;
break;
case SSL3_ST_SW_KEY_EXCH_A:
- case SSL3_ST_SW_KEY_EXCH_B:
- alg_a = hs->new_cipher->algorithm_auth;
-
- /* PSK ciphers send ServerKeyExchange if there is an identity hint. */
- if (ssl_cipher_requires_server_key_exchange(hs->new_cipher) ||
- ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
+ if (hs->server_params_len > 0) {
ret = ssl3_send_server_key_exchange(hs);
if (ret <= 0) {
goto end;
}
}
- hs->state = SSL3_ST_SW_CERT_REQ_A;
- break;
-
- case SSL3_ST_SW_CERT_REQ_A:
- if (hs->cert_request) {
- ret = ssl3_send_certificate_request(hs);
- if (ret <= 0) {
- goto end;
- }
- }
hs->state = SSL3_ST_SW_SRVR_DONE_A;
break;
@@ -388,7 +347,7 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
if (ssl->session != NULL) {
hs->state = SSL_ST_OK;
} else {
- hs->state = SSL3_ST_SW_SESSION_TICKET_A;
+ hs->state = SSL3_ST_SW_FINISHED_A;
}
/* If this is a full handshake with ChannelID then record the handshake
@@ -402,28 +361,8 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
}
break;
- case SSL3_ST_SW_SESSION_TICKET_A:
- if (hs->ticket_expected) {
- ret = ssl3_send_new_session_ticket(hs);
- if (ret <= 0) {
- goto end;
- }
- }
- hs->state = SSL3_ST_SW_CHANGE;
- break;
-
- case SSL3_ST_SW_CHANGE:
- if (!ssl->method->add_change_cipher_spec(ssl) ||
- !tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
- ret = -1;
- goto end;
- }
-
- hs->state = SSL3_ST_SW_FINISHED_A;
- break;
-
case SSL3_ST_SW_FINISHED_A:
- ret = ssl3_send_finished(hs);
+ ret = ssl3_send_server_finished(hs);
if (ret <= 0) {
goto end;
}
@@ -485,12 +424,6 @@ int ssl3_accept(SSL_HANDSHAKE *hs) {
hs->new_session = NULL;
}
- if (hs->v2_clienthello) {
- CRYPTO_STATIC_MUTEX_lock_write(&g_v2clienthello_lock);
- g_v2clienthello_count++;
- CRYPTO_STATIC_MUTEX_unlock_write(&g_v2clienthello_lock);
- }
-
ssl->s3->initial_handshake_complete = 1;
ssl_update_cache(hs, SSL_SESS_CACHE_SERVER);
@@ -538,12 +471,6 @@ static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
const SSL_CLIENT_HELLO *client_hello) {
SSL *const ssl = hs->ssl;
assert(!ssl->s3->have_version);
- uint16_t min_version, max_version;
- if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
- *out_alert = SSL_AD_PROTOCOL_VERSION;
- return 0;
- }
-
uint16_t version = 0;
/* Check supported_versions extension if it is present. */
CBS supported_versions;
@@ -572,8 +499,8 @@ static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
if (!ssl->method->version_from_wire(&ext_version, ext_version)) {
continue;
}
- if (min_version <= ext_version &&
- ext_version <= max_version &&
+ if (hs->min_version <= ext_version &&
+ ext_version <= hs->max_version &&
(!found_version || version < ext_version)) {
version = ext_version;
found_version = 1;
@@ -609,11 +536,11 @@ static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
}
/* Apply our minimum and maximum version. */
- if (version > max_version) {
- version = max_version;
+ if (version > hs->max_version) {
+ version = hs->max_version;
}
- if (version < min_version) {
+ if (version < hs->min_version) {
goto unsupported_protocol;
}
}
@@ -621,7 +548,7 @@ static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
/* Handle FALLBACK_SCSV. */
if (ssl_client_cipher_list_contains_cipher(client_hello,
SSL3_CK_FALLBACK_SCSV & 0xffff) &&
- version < max_version) {
+ version < hs->max_version) {
OPENSSL_PUT_ERROR(SSL, SSL_R_INAPPROPRIATE_FALLBACK);
*out_alert = SSL3_AD_INAPPROPRIATE_FALLBACK;
return 0;
@@ -821,6 +748,11 @@ static int ssl3_process_client_hello(SSL_HANDSHAKE *hs) {
}
}
+ /* Freeze the version range after the early callback. */
+ if (!ssl_get_version_range(ssl, &hs->min_version, &hs->max_version)) {
+ return -1;
+ }
+
uint8_t alert = SSL_AD_DECODE_ERROR;
if (!negotiate_version(hs, &alert, &client_hello)) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
@@ -903,7 +835,6 @@ static int ssl3_select_certificate(SSL_HANDSHAKE *hs) {
static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- uint8_t al = SSL_AD_INTERNAL_ERROR;
int ret = -1;
SSL_SESSION *session = NULL;
@@ -933,9 +864,9 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
if (session->extended_master_secret && !hs->extended_master_secret) {
/* A ClientHello without EMS that attempts to resume a session with EMS
* is fatal to the connection. */
- al = SSL_AD_HANDSHAKE_FAILURE;
OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
}
if (!ssl_session_is_resumable(hs, session) ||
@@ -969,9 +900,9 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
if (ssl->ctx->dos_protection_cb != NULL &&
ssl->ctx->dos_protection_cb(&client_hello) == 0) {
/* Connection rejected for DOS reasons. */
- al = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
}
if (ssl->session == NULL) {
@@ -982,8 +913,8 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
OPENSSL_free(hs->new_session->tlsext_hostname);
hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
if (hs->new_session->tlsext_hostname == NULL) {
- al = SSL_AD_INTERNAL_ERROR;
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
}
}
@@ -1008,8 +939,10 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
/* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was
* deferred. Complete it now. */
- if (!ssl_negotiate_alpn(hs, &al, &client_hello)) {
- goto f_err;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
+ if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+ goto err;
}
/* Now that all parameters are known, initialize the handshake hash and hash
@@ -1017,7 +950,8 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(ssl),
hs->new_cipher->algorithm_prf) ||
!ssl_hash_current_message(hs)) {
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
}
/* Release the handshake buffer if client authentication isn't required. */
@@ -1027,11 +961,6 @@ static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
ret = 1;
- if (0) {
- f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
- }
-
err:
SSL_SESSION_free(session);
return ret;
@@ -1094,48 +1023,48 @@ static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) {
static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- if (!ssl_has_certificate(ssl)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
- return -1;
- }
-
- if (!ssl3_output_cert_chain(ssl)) {
- return -1;
- }
- return 1;
-}
+ int ret = -1;
+ CBB cbb;
+ CBB_zero(&cbb);
-static int ssl3_send_certificate_status(SSL_HANDSHAKE *hs) {
- SSL *const ssl = hs->ssl;
- CBB cbb, body, ocsp_response;
- if (!ssl->method->init_message(ssl, &cbb, &body,
- SSL3_MT_CERTIFICATE_STATUS) ||
- !CBB_add_u8(&body, TLSEXT_STATUSTYPE_ocsp) ||
- !CBB_add_u24_length_prefixed(&body, &ocsp_response) ||
- !CBB_add_bytes(&ocsp_response,
- CRYPTO_BUFFER_data(ssl->cert->ocsp_response),
- CRYPTO_BUFFER_len(ssl->cert->ocsp_response)) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
- return -1;
- }
+ if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+ if (!ssl_has_certificate(ssl)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
+ goto err;
+ }
- return 1;
-}
+ if (!ssl3_output_cert_chain(ssl)) {
+ goto err;
+ }
-static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
- SSL *const ssl = hs->ssl;
- CBB cbb, child;
- CBB_zero(&cbb);
+ if (hs->certificate_status_expected) {
+ CBB body, ocsp_response;
+ if (!ssl->method->init_message(ssl, &cbb, &body,
+ SSL3_MT_CERTIFICATE_STATUS) ||
+ !CBB_add_u8(&body, TLSEXT_STATUSTYPE_ocsp) ||
+ !CBB_add_u24_length_prefixed(&body, &ocsp_response) ||
+ !CBB_add_bytes(&ocsp_response,
+ CRYPTO_BUFFER_data(ssl->cert->ocsp_response),
+ CRYPTO_BUFFER_len(ssl->cert->ocsp_response)) ||
+ !ssl_add_message_cbb(ssl, &cbb)) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+ }
- /* Put together the parameters. */
- if (hs->state == SSL3_ST_SW_KEY_EXCH_A) {
- uint32_t alg_k = hs->new_cipher->algorithm_mkey;
- uint32_t alg_a = hs->new_cipher->algorithm_auth;
+ /* Assemble ServerKeyExchange parameters if needed. */
+ uint32_t alg_k = hs->new_cipher->algorithm_mkey;
+ uint32_t alg_a = hs->new_cipher->algorithm_auth;
+ if (ssl_cipher_requires_server_key_exchange(hs->new_cipher) ||
+ ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
- /* Pre-allocate enough room to comfortably fit an ECDHE public key. */
- if (!CBB_init(&cbb, 128)) {
+ /* Pre-allocate enough room to comfortably fit an ECDHE public key. Prepend
+ * the client and server randoms for the signing transcript. */
+ CBB child;
+ if (!CBB_init(&cbb, SSL3_RANDOM_SIZE * 2 + 128) ||
+ !CBB_add_bytes(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
+ !CBB_add_bytes(&cbb, ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
goto err;
}
@@ -1177,11 +1106,22 @@ static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
}
}
- /* Assemble the message. */
- CBB body;
+ ret = 1;
+
+err:
+ CBB_cleanup(&cbb);
+ return ret;
+}
+
+static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
+ SSL *const ssl = hs->ssl;
+ CBB cbb, body, child;
if (!ssl->method->init_message(ssl, &cbb, &body,
SSL3_MT_SERVER_KEY_EXCHANGE) ||
- !CBB_add_bytes(&body, hs->server_params, hs->server_params_len)) {
+ /* |hs->server_params| contains a prefix for signing. */
+ hs->server_params_len < 2 * SSL3_RANDOM_SIZE ||
+ !CBB_add_bytes(&body, hs->server_params + 2 * SSL3_RANDOM_SIZE,
+ hs->server_params_len - 2 * SSL3_RANDOM_SIZE)) {
goto err;
}
@@ -1214,36 +1154,9 @@ static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
}
size_t sig_len;
- enum ssl_private_key_result_t sign_result;
- if (hs->state == SSL3_ST_SW_KEY_EXCH_A) {
- CBB transcript;
- uint8_t *transcript_data;
- size_t transcript_len;
- if (!CBB_init(&transcript,
- 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);
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
- }
-
- sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len,
- signature_algorithm, transcript_data,
- transcript_len);
- OPENSSL_free(transcript_data);
- } else {
- assert(hs->state == SSL3_ST_SW_KEY_EXCH_B);
- sign_result = ssl_private_key_complete(ssl, ptr, &sig_len, max_sig_len);
- }
-
- switch (sign_result) {
+ switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len,
+ signature_algorithm, hs->server_params,
+ hs->server_params_len)) {
case ssl_private_key_success:
if (!CBB_did_write(&child, sig_len)) {
goto err;
@@ -1253,7 +1166,6 @@ static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
goto err;
case ssl_private_key_retry:
ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
- hs->state = SSL3_ST_SW_KEY_EXCH_B;
goto err;
}
}
@@ -1273,26 +1185,28 @@ err:
return -1;
}
-static int ssl3_send_certificate_request(SSL_HANDSHAKE *hs) {
+static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- CBB cbb, body, cert_types, sigalgs_cbb;
- if (!ssl->method->init_message(ssl, &cbb, &body,
- SSL3_MT_CERTIFICATE_REQUEST) ||
- !CBB_add_u8_length_prefixed(&body, &cert_types) ||
- !CBB_add_u8(&cert_types, SSL3_CT_RSA_SIGN) ||
- (ssl->version >= TLS1_VERSION &&
- !CBB_add_u8(&cert_types, TLS_CT_ECDSA_SIGN))) {
- goto err;
- }
+ CBB cbb, body;
- if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
- if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
- !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb)) {
+ if (hs->cert_request) {
+ CBB cert_types, sigalgs_cbb;
+ if (!ssl->method->init_message(ssl, &cbb, &body,
+ SSL3_MT_CERTIFICATE_REQUEST) ||
+ !CBB_add_u8_length_prefixed(&body, &cert_types) ||
+ !CBB_add_u8(&cert_types, SSL3_CT_RSA_SIGN) ||
+ (ssl3_protocol_version(ssl) >= TLS1_VERSION &&
+ !CBB_add_u8(&cert_types, TLS_CT_ECDSA_SIGN)) ||
+ (ssl3_protocol_version(ssl) >= TLS1_2_VERSION &&
+ (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb) ||
+ !tls12_add_verify_sigalgs(ssl, &sigalgs_cbb))) ||
+ !ssl_add_client_CA_list(ssl, &body) ||
+ !ssl_add_message_cbb(ssl, &cbb)) {
goto err;
}
}
- if (!ssl_add_client_CA_list(ssl, &body) ||
+ if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO_DONE) ||
!ssl_add_message_cbb(ssl, &cbb)) {
goto err;
}
@@ -1305,19 +1219,6 @@ err:
return -1;
}
-static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs) {
- SSL *const ssl = hs->ssl;
- CBB cbb, body;
- if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO_DONE) ||
- !ssl_add_message_cbb(ssl, &cbb)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- CBB_cleanup(&cbb);
- return -1;
- }
-
- return 1;
-}
-
static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
assert(hs->cert_request);
@@ -1417,34 +1318,27 @@ static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
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;
- uint32_t alg_a;
uint8_t *premaster_secret = NULL;
size_t premaster_secret_len = 0;
uint8_t *decrypt_buf = NULL;
- unsigned psk_len = 0;
- uint8_t psk[PSK_MAX_PSK_LEN];
-
if (hs->state == SSL3_ST_SR_KEY_EXCH_A) {
int ret = ssl->method->ssl_get_message(ssl);
if (ret <= 0) {
return ret;
}
+ }
- if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE) ||
- !ssl_hash_current_message(hs)) {
- return -1;
- }
+ if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE)) {
+ return -1;
}
CBS_init(&client_key_exchange, ssl->init_msg, ssl->init_num);
- alg_k = hs->new_cipher->algorithm_mkey;
- alg_a = hs->new_cipher->algorithm_auth;
+ uint32_t alg_k = hs->new_cipher->algorithm_mkey;
+ uint32_t alg_a = hs->new_cipher->algorithm_auth;
- /* If using a PSK key exchange, prepare the pre-shared key. */
+ /* If using a PSK key exchange, parse the PSK identity. */
if (alg_a & SSL_aPSK) {
CBS psk_identity;
@@ -1453,47 +1347,40 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) ||
((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- al = SSL_AD_DECODE_ERROR;
- goto f_err;
- }
-
- if (ssl->psk_server_callback == NULL) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_SERVER_CB);
- al = SSL_AD_INTERNAL_ERROR;
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ goto err;
}
if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN ||
CBS_contains_zero_byte(&psk_identity)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
- al = SSL_AD_ILLEGAL_PARAMETER;
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+ goto err;
}
if (!CBS_strdup(&psk_identity, &hs->new_session->psk_identity)) {
- al = SSL_AD_INTERNAL_ERROR;
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto f_err;
- }
-
- /* Look up the key for the identity. */
- psk_len = ssl->psk_server_callback(ssl, hs->new_session->psk_identity, psk,
- sizeof(psk));
- if (psk_len > PSK_MAX_PSK_LEN) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- al = SSL_AD_INTERNAL_ERROR;
- goto f_err;
- } else if (psk_len == 0) {
- /* PSK related to the given identity not found */
- OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
- al = SSL_AD_UNKNOWN_PSK_IDENTITY;
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
}
}
/* Depending on the key exchange method, compute |premaster_secret| and
* |premaster_secret_len|. */
if (alg_k & SSL_kRSA) {
+ CBS encrypted_premaster_secret;
+ if (ssl->version > SSL3_VERSION) {
+ if (!CBS_get_u16_length_prefixed(&client_key_exchange,
+ &encrypted_premaster_secret) ||
+ CBS_len(&client_key_exchange) != 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ goto err;
+ }
+ } else {
+ encrypted_premaster_secret = client_key_exchange;
+ }
+
/* Allocate a buffer large enough for an RSA decryption. */
const size_t rsa_size = EVP_PKEY_size(hs->local_pubkey);
decrypt_buf = OPENSSL_malloc(rsa_size);
@@ -1502,43 +1389,12 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
goto err;
}
- enum ssl_private_key_result_t decrypt_result;
+ /* Decrypt with no padding. PKCS#1 padding will be removed as part of the
+ * timing-sensitive code below. */
size_t decrypt_len;
- if (hs->state == SSL3_ST_SR_KEY_EXCH_A) {
- if (!ssl_has_private_key(ssl) ||
- EVP_PKEY_id(hs->local_pubkey) != EVP_PKEY_RSA) {
- al = SSL_AD_HANDSHAKE_FAILURE;
- OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_RSA_CERTIFICATE);
- goto f_err;
- }
- CBS encrypted_premaster_secret;
- if (ssl->version > SSL3_VERSION) {
- if (!CBS_get_u16_length_prefixed(&client_key_exchange,
- &encrypted_premaster_secret) ||
- CBS_len(&client_key_exchange) != 0) {
- al = SSL_AD_DECODE_ERROR;
- OPENSSL_PUT_ERROR(SSL,
- SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
- goto f_err;
- }
- } else {
- encrypted_premaster_secret = client_key_exchange;
- }
-
- /* Decrypt with no padding. PKCS#1 padding will be removed as part of the
- * timing-sensitive code below. */
- decrypt_result = ssl_private_key_decrypt(
- ssl, decrypt_buf, &decrypt_len, rsa_size,
- CBS_data(&encrypted_premaster_secret),
- CBS_len(&encrypted_premaster_secret));
- } else {
- assert(hs->state == SSL3_ST_SR_KEY_EXCH_B);
- /* Complete async decrypt. */
- decrypt_result =
- ssl_private_key_complete(ssl, decrypt_buf, &decrypt_len, rsa_size);
- }
-
- switch (decrypt_result) {
+ switch (ssl_private_key_decrypt(hs, decrypt_buf, &decrypt_len, rsa_size,
+ CBS_data(&encrypted_premaster_secret),
+ CBS_len(&encrypted_premaster_secret))) {
case ssl_private_key_success:
break;
case ssl_private_key_failure:
@@ -1550,9 +1406,9 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
}
if (decrypt_len != rsa_size) {
- al = SSL_AD_DECRYPT_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
+ goto err;
}
/* Prepare a random premaster, to be used on invalid padding. See RFC 5246,
@@ -1570,9 +1426,9 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
/* The smallest padded premaster is 11 bytes of overhead. Small keys are
* publicly invalid. */
if (decrypt_len < 11 + premaster_secret_len) {
- al = SSL_AD_DECRYPT_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
+ goto err;
}
/* Check the padding. See RFC 3447, section 7.2.2. */
@@ -1605,9 +1461,9 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
CBS peer_key;
if (!CBS_get_u8_length_prefixed(&client_key_exchange, &peer_key) ||
CBS_len(&client_key_exchange) != 0) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ goto err;
}
/* Compute the premaster. */
@@ -1615,35 +1471,57 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
if (!SSL_ECDH_CTX_finish(&hs->ecdh_ctx, &premaster_secret,
&premaster_secret_len, &alert, CBS_data(&peer_key),
CBS_len(&peer_key))) {
- al = alert;
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+ goto err;
}
/* The key exchange state may now be discarded. */
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. */
- premaster_secret_len = psk_len;
- premaster_secret = OPENSSL_malloc(premaster_secret_len);
- if (premaster_secret == NULL) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- OPENSSL_memset(premaster_secret, 0, premaster_secret_len);
- } else {
- al = SSL_AD_HANDSHAKE_FAILURE;
+ } else if (!(alg_k & SSL_kPSK)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_TYPE);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+ goto err;
}
/* For a PSK cipher suite, the actual pre-master secret is combined with the
* pre-shared key. */
if (alg_a & SSL_aPSK) {
+ if (ssl->psk_server_callback == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_SERVER_CB);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /* Look up the key for the identity. */
+ uint8_t psk[PSK_MAX_PSK_LEN];
+ unsigned psk_len = ssl->psk_server_callback(
+ ssl, hs->new_session->psk_identity, psk, sizeof(psk));
+ if (psk_len > PSK_MAX_PSK_LEN) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
+ } else if (psk_len == 0) {
+ /* PSK related to the given identity not found */
+ OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNKNOWN_PSK_IDENTITY);
+ goto err;
+ }
+
+ if (alg_k & SSL_kPSK) {
+ /* In plain PSK, other_secret is a block of 0s with the same length as the
+ * pre-shared key. */
+ premaster_secret_len = psk_len;
+ premaster_secret = OPENSSL_malloc(premaster_secret_len);
+ if (premaster_secret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ OPENSSL_memset(premaster_secret, 0, premaster_secret_len);
+ }
+
CBB new_premaster, child;
uint8_t *new_data;
size_t new_len;
-
CBB_zero(&new_premaster);
if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len) ||
!CBB_add_u16_length_prefixed(&new_premaster, &child) ||
@@ -1662,6 +1540,10 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
premaster_secret_len = new_len;
}
+ if (!ssl_hash_current_message(hs)) {
+ goto err;
+ }
+
/* Compute the master secret */
hs->new_session->master_key_length = tls1_generate_master_secret(
hs, hs->new_session->master_key, premaster_secret, premaster_secret_len);
@@ -1674,8 +1556,6 @@ static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
OPENSSL_free(premaster_secret);
return 1;
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
err:
if (premaster_secret != NULL) {
OPENSSL_cleanse(premaster_secret, premaster_secret_len);
@@ -1688,7 +1568,6 @@ err:
static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- int al;
CBS certificate_verify, signature;
/* Only RSA and ECDSA client certificates are supported, so a
@@ -1714,27 +1593,29 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
uint16_t signature_algorithm = 0;
if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
if (!CBS_get_u16(&certificate_verify, &signature_algorithm)) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ return -1;
}
- if (!tls12_check_peer_sigalg(ssl, &al, signature_algorithm)) {
- goto f_err;
+ uint8_t alert = SSL_AD_DECODE_ERROR;
+ if (!tls12_check_peer_sigalg(ssl, &alert, signature_algorithm)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+ return -1;
}
hs->new_session->peer_signature_algorithm = signature_algorithm;
} else if (!tls1_get_legacy_signature_algorithm(&signature_algorithm,
hs->peer_pubkey)) {
- al = SSL_AD_UNSUPPORTED_CERTIFICATE;
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_CERTIFICATE);
+ return -1;
}
/* Parse and verify the signature. */
if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) ||
CBS_len(&certificate_verify) != 0) {
- al = SSL_AD_DECODE_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+ return -1;
}
int sig_ok;
@@ -1746,7 +1627,7 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
&digest_len, hs->new_session,
signature_algorithm)) {
- goto err;
+ return -1;
}
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(hs->peer_pubkey, NULL);
@@ -1767,24 +1648,19 @@ static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
ERR_clear_error();
#endif
if (!sig_ok) {
- al = SSL_AD_DECRYPT_ERROR;
OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
- goto f_err;
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
+ return -1;
}
/* The handshake buffer is no longer necessary, and we may hash the current
* message.*/
SSL_TRANSCRIPT_free_buffer(&hs->transcript);
if (!ssl_hash_current_message(hs)) {
- goto err;
+ return -1;
}
return 1;
-
-f_err:
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
- return 0;
}
/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
@@ -1835,40 +1711,46 @@ static int ssl3_get_channel_id(SSL_HANDSHAKE *hs) {
return 1;
}
-static int ssl3_send_new_session_ticket(SSL_HANDSHAKE *hs) {
+static int ssl3_send_server_finished(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- const SSL_SESSION *session;
- SSL_SESSION *session_copy = NULL;
- if (ssl->session == NULL) {
- /* Fix the timeout to measure from the ticket issuance time. */
- ssl_session_rebase_time(ssl, hs->new_session);
- session = hs->new_session;
- } else {
- /* We are renewing an existing session. Duplicate the session to adjust the
- * timeout. */
- session_copy = SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH);
- if (session_copy == NULL) {
- return -1;
- }
- ssl_session_rebase_time(ssl, session_copy);
- session = session_copy;
- }
+ if (hs->ticket_expected) {
+ const SSL_SESSION *session;
+ SSL_SESSION *session_copy = NULL;
+ if (ssl->session == NULL) {
+ /* Fix the timeout to measure from the ticket issuance time. */
+ ssl_session_rebase_time(ssl, hs->new_session);
+ session = hs->new_session;
+ } else {
+ /* We are renewing an existing session. Duplicate the session to adjust
+ * the timeout. */
+ session_copy = SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH);
+ if (session_copy == NULL) {
+ return -1;
+ }
- CBB cbb, body, ticket;
- int ok =
- ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_NEW_SESSION_TICKET) &&
- CBB_add_u32(&body, session->timeout) &&
- CBB_add_u16_length_prefixed(&body, &ticket) &&
- ssl_encrypt_ticket(ssl, &ticket, session) &&
- ssl_add_message_cbb(ssl, &cbb);
+ ssl_session_rebase_time(ssl, session_copy);
+ session = session_copy;
+ }
- SSL_SESSION_free(session_copy);
- CBB_cleanup(&cbb);
+ CBB cbb, body, ticket;
+ int ok = ssl->method->init_message(ssl, &cbb, &body,
+ SSL3_MT_NEW_SESSION_TICKET) &&
+ CBB_add_u32(&body, session->timeout) &&
+ CBB_add_u16_length_prefixed(&body, &ticket) &&
+ ssl_encrypt_ticket(ssl, &ticket, session) &&
+ ssl_add_message_cbb(ssl, &cbb);
+ SSL_SESSION_free(session_copy);
+ CBB_cleanup(&cbb);
+ if (!ok) {
+ return -1;
+ }
+ }
- if (!ok) {
+ if (!ssl->method->add_change_cipher_spec(ssl) ||
+ !tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
return -1;
}
- return 1;
+ return ssl3_send_finished(hs);
}
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index bf0ef029..d56c73ba 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -548,22 +548,20 @@ typedef struct ssl_handshake_st SSL_HANDSHAKE;
* configured and zero otherwise. */
int ssl_has_private_key(const SSL *ssl);
-/* ssl_private_key_* call the corresponding function on the
- * |SSL_PRIVATE_KEY_METHOD| for |ssl|, if configured. Otherwise, they implement
- * the operation with |EVP_PKEY|. */
+/* ssl_private_key_* perform the corresponding operation on
+ * |SSL_PRIVATE_KEY_METHOD|. If there is a custom private key configured, they
+ * call the corresponding function or |complete| depending on whether there is a
+ * pending operation. Otherwise, they implement the operation with
+ * |EVP_PKEY|. */
enum ssl_private_key_result_t ssl_private_key_sign(
- SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
+ SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
uint16_t signature_algorithm, const uint8_t *in, size_t in_len);
enum ssl_private_key_result_t ssl_private_key_decrypt(
- SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
+ SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
const uint8_t *in, size_t in_len);
-enum ssl_private_key_result_t ssl_private_key_complete(SSL *ssl, uint8_t *out,
- size_t *out_len,
- size_t max_out);
-
/* ssl_private_key_supports_signature_algorithm returns one if |hs|'s private
* key supports |sigalg| and zero otherwise. */
int ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
@@ -925,6 +923,7 @@ enum ssl_hs_wait_t {
ssl_hs_channel_id_lookup,
ssl_hs_private_key_operation,
ssl_hs_pending_ticket,
+ ssl_hs_early_data_rejected,
ssl_hs_read_end_of_early_data,
};
@@ -951,6 +950,14 @@ struct ssl_handshake_st {
* depend on |do_tls13_handshake| but the starting state is always zero. */
int tls13_state;
+ /* min_version is the minimum accepted protocol version, taking account both
+ * |SSL_OP_NO_*| and |SSL_CTX_set_min_proto_version| APIs. */
+ uint16_t min_version;
+
+ /* max_version is the maximum accepted protocol version, taking account both
+ * |SSL_OP_NO_*| and |SSL_CTX_set_max_proto_version| APIs. */
+ uint16_t max_version;
+
size_t hash_len;
uint8_t secret[EVP_MAX_MD_SIZE];
uint8_t early_traffic_secret[EVP_MAX_MD_SIZE];
@@ -1022,8 +1029,9 @@ struct ssl_handshake_st {
uint8_t *peer_key;
size_t peer_key_len;
- /* server_params, in TLS 1.2, stores the ServerKeyExchange parameters to be
- * signed while the signature is being computed. */
+ /* server_params, in a TLS 1.2 server, stores the ServerKeyExchange
+ * parameters. It has client and server randoms prepended for signing
+ * convenience. */
uint8_t *server_params;
size_t server_params_len;
@@ -1057,6 +1065,10 @@ struct ssl_handshake_st {
* handshake. It should not be cached. */
SSL_SESSION *new_session;
+ /* early_session is the session corresponding to the current 0-RTT state on
+ * the client if |in_early_data| is true. */
+ SSL_SESSION *early_session;
+
/* new_cipher is the cipher being negotiated in this handshake. */
const SSL_CIPHER *new_cipher;
@@ -1097,6 +1109,10 @@ struct ssl_handshake_st {
* Start. The client may write data at this point. */
unsigned in_false_start:1;
+ /* in_early_data is one if there is a pending handshake that has progressed
+ * enough to send and receive early data. */
+ unsigned in_early_data:1;
+
/* early_data_offered is one if the client sent the early_data extension. */
unsigned early_data_offered:1;
@@ -1115,19 +1131,24 @@ struct ssl_handshake_st {
* or received. */
unsigned ticket_expected:1;
- /* v2_clienthello is one if we received a V2ClientHello. */
- unsigned v2_clienthello:1;
-
/* extended_master_secret is one if the extended master secret extension is
* negotiated in this handshake. */
unsigned extended_master_secret:1;
+ /* pending_private_key_op is one if there is a pending private key operation
+ * in progress. */
+ unsigned pending_private_key_op:1;
+
/* client_version is the value sent or received in the ClientHello version. */
uint16_t client_version;
/* early_data_read is the amount of early data that has been read by the
* record layer. */
uint16_t early_data_read;
+
+ /* early_data_written is the amount of early data that has been written by the
+ * record layer. */
+ uint16_t early_data_written;
} /* SSL_HANDSHAKE */;
SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl);
@@ -1162,8 +1183,12 @@ int tls13_process_certificate_verify(SSL_HANDSHAKE *hs);
int tls13_process_finished(SSL_HANDSHAKE *hs, int use_saved_value);
int tls13_add_certificate(SSL_HANDSHAKE *hs);
-enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs,
- int is_first_run);
+
+/* tls13_add_certificate_verify adds a TLS 1.3 CertificateVerify message to the
+ * handshake. If it returns |ssl_private_key_retry|, it should be called again
+ * to retry when the signing operation is completed. */
+enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs);
+
int tls13_add_finished(SSL_HANDSHAKE *hs);
int tls13_process_new_session_ticket(SSL *ssl);
@@ -1292,7 +1317,7 @@ int tls12_add_verify_sigalgs(const SSL *ssl, CBB *out);
/* tls12_check_peer_sigalg checks if |sigalg| is acceptable for the peer
* signature. It returns one on success and zero on error, setting |*out_alert|
* to an alert to send. */
-int tls12_check_peer_sigalg(SSL *ssl, int *out_alert, uint16_t sigalg);
+int tls12_check_peer_sigalg(SSL *ssl, uint8_t *out_alert, uint16_t sigalg);
/* Underdocumented functions.
@@ -1421,7 +1446,8 @@ struct ssl_protocol_method_st {
int peek);
int (*read_change_cipher_spec)(SSL *ssl);
void (*read_close_notify)(SSL *ssl);
- int (*write_app_data)(SSL *ssl, const uint8_t *buf, int len);
+ int (*write_app_data)(SSL *ssl, int *out_needs_handshake, const uint8_t *buf,
+ int len);
int (*dispatch_alert)(SSL *ssl);
/* supports_cipher returns one if |cipher| is supported by this protocol and
* zero otherwise. */
@@ -1632,6 +1658,9 @@ typedef struct ssl3_state_st {
* outstanding. */
unsigned key_update_pending:1;
+ /* wpend_pending is one if we have a pending write outstanding. */
+ unsigned wpend_pending:1;
+
uint8_t send_alert[2];
/* pending_flight is the pending outgoing flight. This is used to flush each
@@ -1819,13 +1848,15 @@ struct ssl_st {
/* version is the protocol version. */
int version;
- /* max_version is the maximum acceptable protocol version. Note this version
- * is normalized in DTLS. */
- uint16_t max_version;
+ /* conf_max_version is the maximum acceptable protocol version configured by
+ * |SSL_set_max_proto_version|. Note this version is normalized in DTLS and is
+ * further constrainted by |SSL_OP_NO_*|. */
+ uint16_t conf_max_version;
- /* min_version is the minimum acceptable protocol version. Note this version
- * is normalized in DTLS. */
- uint16_t min_version;
+ /* conf_min_version is the minimum acceptable protocol version configured by
+ * |SSL_set_min_proto_version|. Note this version is normalized in DTLS and is
+ * further constrainted by |SSL_OP_NO_*|. */
+ uint16_t conf_min_version;
uint16_t max_send_fragment;
@@ -2088,7 +2119,8 @@ int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
int ssl3_read_change_cipher_spec(SSL *ssl);
void ssl3_read_close_notify(SSL *ssl);
int ssl3_read_handshake_bytes(SSL *ssl, uint8_t *buf, int len);
-int ssl3_write_app_data(SSL *ssl, const uint8_t *buf, int len);
+int ssl3_write_app_data(SSL *ssl, int *out_needs_handshake, const uint8_t *buf,
+ int len);
int ssl3_output_cert_chain(SSL *ssl);
int ssl3_new(SSL *ssl);
@@ -2129,7 +2161,8 @@ int dtls1_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
int dtls1_read_change_cipher_spec(SSL *ssl);
void dtls1_read_close_notify(SSL *ssl);
-int dtls1_write_app_data(SSL *ssl, const uint8_t *buf, int len);
+int dtls1_write_app_data(SSL *ssl, int *out_needs_handshake, const uint8_t *buf,
+ int len);
/* dtls1_write_record sends a record. It returns one on success and <= 0 on
* error. */
diff --git a/src/ssl/s3_both.c b/src/ssl/s3_both.c
index e05a16e1..65d438a1 100644
--- a/src/ssl/s3_both.c
+++ b/src/ssl/s3_both.c
@@ -168,6 +168,7 @@ void ssl_handshake_free(SSL_HANDSHAKE *hs) {
OPENSSL_free(hs->key_share_bytes);
OPENSSL_free(hs->ecdh_public_key);
SSL_SESSION_free(hs->new_session);
+ SSL_SESSION_free(hs->early_session);
OPENSSL_free(hs->peer_sigalgs);
OPENSSL_free(hs->peer_supported_group_list);
OPENSSL_free(hs->peer_key);
@@ -331,12 +332,14 @@ int ssl3_flush_flight(SSL *ssl) {
return -1;
}
- /* The handshake flight buffer is mutually exclusive with application data.
- *
- * TODO(davidben): This will not be true when closure alerts use this. */
+ /* If there is pending data in the write buffer, it must be flushed out before
+ * any new data in pending_flight. */
if (ssl_write_buffer_is_pending(ssl)) {
- OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
- return -1;
+ int ret = ssl_write_buffer_flush(ssl);
+ if (ret <= 0) {
+ ssl->rwstate = SSL_WRITING;
+ return ret;
+ }
}
/* Write the pending flight. */
@@ -675,8 +678,6 @@ static int read_v2_client_hello(SSL *ssl) {
ssl_read_buffer_discard(ssl);
ssl->s3->is_v2_hello = 1;
- /* This is the first message, so hs must be non-NULL. */
- ssl->s3->hs->v2_clienthello = 1;
return 1;
}
diff --git a/src/ssl/s3_pkt.c b/src/ssl/s3_pkt.c
index 23b39f23..445f8826 100644
--- a/src/ssl/s3_pkt.c
+++ b/src/ssl/s3_pkt.c
@@ -188,10 +188,13 @@ again:
return -1;
}
-int ssl3_write_app_data(SSL *ssl, const uint8_t *buf, int len) {
+int ssl3_write_app_data(SSL *ssl, int *out_needs_handshake, const uint8_t *buf,
+ int len) {
assert(ssl_can_write(ssl));
assert(ssl->s3->aead_write_ctx != NULL);
+ *out_needs_handshake = 0;
+
unsigned tot, n, nw;
assert(ssl->s3->wnum <= INT_MAX);
@@ -210,11 +213,25 @@ int ssl3_write_app_data(SSL *ssl, const uint8_t *buf, int len) {
return -1;
}
+ const int is_early_data_write =
+ !ssl->server && SSL_in_early_data(ssl) && ssl->s3->hs->can_early_write;
+
n = len - tot;
for (;;) {
/* max contains the maximum number of bytes that we can put into a
* record. */
unsigned max = ssl->max_send_fragment;
+ if (is_early_data_write && max > ssl->session->ticket_max_early_data -
+ ssl->s3->hs->early_data_written) {
+ max = ssl->session->ticket_max_early_data - ssl->s3->hs->early_data_written;
+ if (max == 0) {
+ ssl->s3->wnum = tot;
+ ssl->s3->hs->can_early_write = 0;
+ *out_needs_handshake = 1;
+ return -1;
+ }
+ }
+
if (n > max) {
nw = max;
} else {
@@ -227,6 +244,10 @@ int ssl3_write_app_data(SSL *ssl, const uint8_t *buf, int len) {
return ret;
}
+ if (is_early_data_write) {
+ ssl->s3->hs->early_data_written += ret;
+ }
+
if (ret == (int)n || (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE)) {
return tot + ret;
}
@@ -250,13 +271,14 @@ static int ssl3_write_pending(SSL *ssl, int type, const uint8_t *buf,
if (ret <= 0) {
return ret;
}
+ ssl->s3->wpend_pending = 0;
return ssl->s3->wpend_ret;
}
/* do_ssl3_write writes an SSL record of the given type. */
static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len) {
/* If there is still data from the previous record, flush it. */
- if (ssl_write_buffer_is_pending(ssl)) {
+ if (ssl->s3->wpend_pending) {
return ssl3_write_pending(ssl, type, buf, len);
}
@@ -317,6 +339,7 @@ static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len) {
ssl->s3->wpend_buf = buf;
ssl->s3->wpend_type = type;
ssl->s3->wpend_ret = len;
+ ssl->s3->wpend_pending = 1;
/* we now just need to write the buffer */
return ssl3_write_pending(ssl, type, buf, len);
@@ -488,6 +511,17 @@ int ssl3_read_handshake_bytes(SSL *ssl, uint8_t *buf, int len) {
}
}
+ /* WatchGuard's TLS 1.3 interference bug is very distinctive: they drop the
+ * ServerHello and send the remaining encrypted application data records
+ * as-is. This manifests as an application data record when we expect
+ * handshake. Report a dedicated error code for this case. */
+ if (!ssl->server && rr->type == SSL3_RT_APPLICATION_DATA &&
+ ssl->s3->aead_read_ctx == NULL) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_APPLICATION_DATA_INSTEAD_OF_HANDSHAKE);
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+ return -1;
+ }
+
if (rr->type != SSL3_RT_HANDSHAKE) {
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
diff --git a/src/ssl/ssl_buffer.c b/src/ssl/ssl_buffer.c
index aefc0443..9ea5c68c 100644
--- a/src/ssl/ssl_buffer.c
+++ b/src/ssl/ssl_buffer.c
@@ -33,26 +33,37 @@ OPENSSL_COMPILE_ASSERT(0xffff <= INT_MAX, uint16_fits_in_int);
OPENSSL_COMPILE_ASSERT((SSL3_ALIGN_PAYLOAD & (SSL3_ALIGN_PAYLOAD - 1)) == 0,
align_to_a_power_of_two);
-/* setup_buffer initializes |buf| with capacity |cap|, aligned such that data
- * written after |header_len| is aligned to a |SSL3_ALIGN_PAYLOAD|-byte
+/* ensure_buffer ensures |buf| has capacity at least |cap|, aligned such that
+ * data written after |header_len| is aligned to a |SSL3_ALIGN_PAYLOAD|-byte
* boundary. It returns one on success and zero on error. */
-static int setup_buffer(SSL3_BUFFER *buf, size_t header_len, size_t cap) {
- if (buf->buf != NULL || cap > 0xffff) {
+static int ensure_buffer(SSL3_BUFFER *buf, size_t header_len, size_t cap) {
+ if (cap > 0xffff) {
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
return 0;
}
+ if (buf->cap >= cap) {
+ return 1;
+ }
+
/* Add up to |SSL3_ALIGN_PAYLOAD| - 1 bytes of slack for alignment. */
- buf->buf = OPENSSL_malloc(cap + SSL3_ALIGN_PAYLOAD - 1);
- if (buf->buf == NULL) {
+ uint8_t *new_buf = OPENSSL_malloc(cap + SSL3_ALIGN_PAYLOAD - 1);
+ if (new_buf == NULL) {
OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
- /* Arrange the buffer such that the record body is aligned. */
- buf->offset = (0 - header_len - (uintptr_t)buf->buf) &
- (SSL3_ALIGN_PAYLOAD - 1);
- buf->len = 0;
+ /* Offset the buffer such that the record body is aligned. */
+ size_t new_offset =
+ (0 - header_len - (uintptr_t)new_buf) & (SSL3_ALIGN_PAYLOAD - 1);
+
+ if (buf->buf != NULL) {
+ OPENSSL_memcpy(new_buf + new_offset, buf->buf + buf->offset, buf->len);
+ OPENSSL_free(buf->buf);
+ }
+
+ buf->buf = new_buf;
+ buf->offset = new_offset;
buf->cap = cap;
return 1;
}
@@ -71,30 +82,6 @@ static void clear_buffer(SSL3_BUFFER *buf) {
OPENSSL_memset(buf, 0, sizeof(SSL3_BUFFER));
}
-OPENSSL_COMPILE_ASSERT(DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH <=
- 0xffff,
- maximum_read_buffer_too_large);
-
-/* setup_read_buffer initializes the read buffer if not already initialized. It
- * returns one on success and zero on failure. */
-static int setup_read_buffer(SSL *ssl) {
- SSL3_BUFFER *buf = &ssl->s3->read_buffer;
-
- if (buf->buf != NULL) {
- return 1;
- }
-
- size_t header_len = ssl_record_prefix_len(ssl);
- size_t cap = SSL3_RT_MAX_ENCRYPTED_LENGTH;
- if (SSL_is_dtls(ssl)) {
- cap += DTLS1_RT_HEADER_LENGTH;
- } else {
- cap += SSL3_RT_HEADER_LENGTH;
- }
-
- return setup_buffer(buf, header_len, cap);
-}
-
uint8_t *ssl_read_buffer(SSL *ssl) {
return ssl->s3->read_buffer.buf + ssl->s3->read_buffer.offset;
}
@@ -154,7 +141,16 @@ int ssl_read_buffer_extend_to(SSL *ssl, size_t len) {
/* |ssl_read_buffer_extend_to| implicitly discards any consumed data. */
ssl_read_buffer_discard(ssl);
- if (!setup_read_buffer(ssl)) {
+ if (SSL_is_dtls(ssl)) {
+ OPENSSL_COMPILE_ASSERT(
+ DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH <= 0xffff,
+ dtls_read_buffer_too_large);
+
+ /* The |len| parameter is ignored in DTLS. */
+ len = DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
+ }
+
+ if (!ensure_buffer(&ssl->s3->read_buffer, ssl_record_prefix_len(ssl), len)) {
return -1;
}
@@ -225,7 +221,7 @@ int ssl_write_buffer_init(SSL *ssl, uint8_t **out_ptr, size_t max_len) {
return 0;
}
- if (!setup_buffer(buf, ssl_seal_align_prefix_len(ssl), max_len)) {
+ if (!ensure_buffer(buf, ssl_seal_align_prefix_len(ssl), max_len)) {
return 0;
}
*out_ptr = buf->buf + buf->offset;
diff --git a/src/ssl/ssl_cipher.c b/src/ssl/ssl_cipher.c
index 01bb8726..562c1f30 100644
--- a/src/ssl/ssl_cipher.c
+++ b/src/ssl/ssl_cipher.c
@@ -160,6 +160,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 02 */
{
SSL3_TXT_RSA_NULL_SHA,
+ "TLS_RSA_WITH_NULL_SHA",
SSL3_CK_RSA_NULL_SHA,
SSL_kRSA,
SSL_aRSA,
@@ -171,6 +172,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 0A */
{
SSL3_TXT_RSA_DES_192_CBC3_SHA,
+ "TLS_RSA_WITH_3DES_EDE_CBC_SHA",
SSL3_CK_RSA_DES_192_CBC3_SHA,
SSL_kRSA,
SSL_aRSA,
@@ -185,6 +187,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 2F */
{
TLS1_TXT_RSA_WITH_AES_128_SHA,
+ "TLS_RSA_WITH_AES_128_CBC_SHA",
TLS1_CK_RSA_WITH_AES_128_SHA,
SSL_kRSA,
SSL_aRSA,
@@ -196,6 +199,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 35 */
{
TLS1_TXT_RSA_WITH_AES_256_SHA,
+ "TLS_RSA_WITH_AES_256_CBC_SHA",
TLS1_CK_RSA_WITH_AES_256_SHA,
SSL_kRSA,
SSL_aRSA,
@@ -210,6 +214,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 3C */
{
TLS1_TXT_RSA_WITH_AES_128_SHA256,
+ "TLS_RSA_WITH_AES_128_CBC_SHA256",
TLS1_CK_RSA_WITH_AES_128_SHA256,
SSL_kRSA,
SSL_aRSA,
@@ -221,6 +226,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 3D */
{
TLS1_TXT_RSA_WITH_AES_256_SHA256,
+ "TLS_RSA_WITH_AES_256_CBC_SHA256",
TLS1_CK_RSA_WITH_AES_256_SHA256,
SSL_kRSA,
SSL_aRSA,
@@ -234,6 +240,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 8C */
{
TLS1_TXT_PSK_WITH_AES_128_CBC_SHA,
+ "TLS_PSK_WITH_AES_128_CBC_SHA",
TLS1_CK_PSK_WITH_AES_128_CBC_SHA,
SSL_kPSK,
SSL_aPSK,
@@ -245,6 +252,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 8D */
{
TLS1_TXT_PSK_WITH_AES_256_CBC_SHA,
+ "TLS_PSK_WITH_AES_256_CBC_SHA",
TLS1_CK_PSK_WITH_AES_256_CBC_SHA,
SSL_kPSK,
SSL_aPSK,
@@ -258,6 +266,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 9C */
{
TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256,
+ "TLS_RSA_WITH_AES_128_GCM_SHA256",
TLS1_CK_RSA_WITH_AES_128_GCM_SHA256,
SSL_kRSA,
SSL_aRSA,
@@ -269,6 +278,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 9D */
{
TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384,
+ "TLS_RSA_WITH_AES_256_GCM_SHA384",
TLS1_CK_RSA_WITH_AES_256_GCM_SHA384,
SSL_kRSA,
SSL_aRSA,
@@ -282,6 +292,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 1301 */
{
TLS1_TXT_AES_128_GCM_SHA256,
+ "TLS_AES_128_GCM_SHA256",
TLS1_CK_AES_128_GCM_SHA256,
SSL_kGENERIC,
SSL_aGENERIC,
@@ -293,6 +304,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 1302 */
{
TLS1_TXT_AES_256_GCM_SHA384,
+ "TLS_AES_256_GCM_SHA384",
TLS1_CK_AES_256_GCM_SHA384,
SSL_kGENERIC,
SSL_aGENERIC,
@@ -304,6 +316,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher 1303 */
{
TLS1_TXT_CHACHA20_POLY1305_SHA256,
+ "TLS_CHACHA20_POLY1305_SHA256",
TLS1_CK_CHACHA20_POLY1305_SHA256,
SSL_kGENERIC,
SSL_aGENERIC,
@@ -315,6 +328,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C009 */
{
TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
SSL_kECDHE,
SSL_aECDSA,
@@ -326,6 +340,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C00A */
{
TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
SSL_kECDHE,
SSL_aECDSA,
@@ -337,6 +352,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C013 */
{
TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA,
SSL_kECDHE,
SSL_aRSA,
@@ -348,6 +364,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C014 */
{
TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA,
SSL_kECDHE,
SSL_aRSA,
@@ -362,6 +379,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C023 */
{
TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256,
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256,
SSL_kECDHE,
SSL_aECDSA,
@@ -373,6 +391,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C024 */
{
TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_SHA384,
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384,
SSL_kECDHE,
SSL_aECDSA,
@@ -384,6 +403,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C027 */
{
TLS1_TXT_ECDHE_RSA_WITH_AES_128_SHA256,
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
SSL_kECDHE,
SSL_aRSA,
@@ -395,6 +415,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C028 */
{
TLS1_TXT_ECDHE_RSA_WITH_AES_256_SHA384,
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",
TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
SSL_kECDHE,
SSL_aRSA,
@@ -409,6 +430,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C02B */
{
TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
SSL_kECDHE,
SSL_aECDSA,
@@ -420,6 +442,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C02C */
{
TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
SSL_kECDHE,
SSL_aECDSA,
@@ -431,6 +454,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C02F */
{
TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
SSL_kECDHE,
SSL_aRSA,
@@ -442,6 +466,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C030 */
{
TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+ "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
SSL_kECDHE,
SSL_aRSA,
@@ -455,6 +480,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C035 */
{
TLS1_TXT_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA",
TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
SSL_kECDHE,
SSL_aPSK,
@@ -466,6 +492,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher C036 */
{
TLS1_TXT_ECDHE_PSK_WITH_AES_256_CBC_SHA,
+ "TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA",
TLS1_CK_ECDHE_PSK_WITH_AES_256_CBC_SHA,
SSL_kECDHE,
SSL_aPSK,
@@ -479,6 +506,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher CCA8 */
{
TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
SSL_kECDHE,
SSL_aRSA,
@@ -490,6 +518,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher CCA9 */
{
TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
SSL_kECDHE,
SSL_aECDSA,
@@ -501,6 +530,7 @@ static const SSL_CIPHER kCiphers[] = {
/* Cipher CCAB */
{
TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",
TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
SSL_kECDHE,
SSL_aPSK,
@@ -1089,8 +1119,8 @@ static int ssl_cipher_process_rulestr(const SSL_PROTOCOL_METHOD *ssl_method,
ch = *l;
buf = l;
buf_len = 0;
- while (((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) ||
- ((ch >= 'a') && (ch <= 'z')) || (ch == '-') || (ch == '.')) {
+ while ((ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') ||
+ (ch >= 'a' && ch <= 'z') || ch == '-' || ch == '.' || ch == '_') {
ch = *(++l);
buf_len++;
}
@@ -1111,7 +1141,8 @@ static int ssl_cipher_process_rulestr(const SSL_PROTOCOL_METHOD *ssl_method,
if (!multi && ch != '+') {
for (j = 0; j < kCiphersLen; j++) {
const SSL_CIPHER *cipher = &kCiphers[j];
- if (rule_equals(cipher->name, buf, buf_len)) {
+ if (rule_equals(cipher->name, buf, buf_len) ||
+ rule_equals(cipher->standard_name, buf, buf_len)) {
cipher_id = cipher->id;
break;
}
@@ -1447,6 +1478,10 @@ const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher) {
return "(NONE)";
}
+const char *SSL_CIPHER_standard_name(const SSL_CIPHER *cipher) {
+ return cipher->standard_name;
+}
+
const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher) {
if (cipher == NULL) {
return "";
@@ -1483,79 +1518,12 @@ const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher) {
}
}
-static const char *ssl_cipher_get_enc_name(const SSL_CIPHER *cipher) {
- switch (cipher->algorithm_enc) {
- case SSL_3DES:
- return "3DES_EDE_CBC";
- case SSL_AES128:
- return "AES_128_CBC";
- case SSL_AES256:
- return "AES_256_CBC";
- case SSL_AES128GCM:
- return "AES_128_GCM";
- case SSL_AES256GCM:
- return "AES_256_GCM";
- case SSL_CHACHA20POLY1305:
- return "CHACHA20_POLY1305";
- break;
- default:
- assert(0);
- return "UNKNOWN";
- }
-}
-
-static const char *ssl_cipher_get_prf_name(const SSL_CIPHER *cipher) {
- switch (cipher->algorithm_prf) {
- case SSL_HANDSHAKE_MAC_DEFAULT:
- /* Before TLS 1.2, the PRF component is the hash used in the HMAC, which
- * is SHA-1 for all supported ciphers. */
- assert(cipher->algorithm_mac == SSL_SHA1);
- return "SHA";
- case SSL_HANDSHAKE_MAC_SHA256:
- return "SHA256";
- case SSL_HANDSHAKE_MAC_SHA384:
- return "SHA384";
- }
- assert(0);
- return "UNKNOWN";
-}
-
char *SSL_CIPHER_get_rfc_name(const SSL_CIPHER *cipher) {
if (cipher == NULL) {
return NULL;
}
- const char *kx_name = SSL_CIPHER_get_kx_name(cipher);
- const char *enc_name = ssl_cipher_get_enc_name(cipher);
- const char *prf_name = ssl_cipher_get_prf_name(cipher);
-
- /* The final name is TLS_{kx_name}_WITH_{enc_name}_{prf_name} or
- * TLS_{enc_name}_{prf_name} depending on whether the cipher is AEAD-only. */
- size_t len = 4 + strlen(enc_name) + 1 + strlen(prf_name) + 1;
-
- if (cipher->algorithm_mkey != SSL_kGENERIC) {
- len += strlen(kx_name) + 6;
- }
-
- char *ret = OPENSSL_malloc(len);
- if (ret == NULL) {
- return NULL;
- }
-
- if (BUF_strlcpy(ret, "TLS_", len) >= len ||
- (cipher->algorithm_mkey != SSL_kGENERIC &&
- (BUF_strlcat(ret, kx_name, len) >= len ||
- BUF_strlcat(ret, "_WITH_", len) >= len)) ||
- BUF_strlcat(ret, enc_name, len) >= len ||
- BUF_strlcat(ret, "_", len) >= len ||
- BUF_strlcat(ret, prf_name, len) >= len) {
- assert(0);
- OPENSSL_free(ret);
- return NULL;
- }
-
- assert(strlen(ret) + 1 == len);
- return ret;
+ return OPENSSL_strdup(SSL_CIPHER_standard_name(cipher));
}
int SSL_CIPHER_get_bits(const SSL_CIPHER *cipher, int *out_alg_bits) {
diff --git a/src/ssl/ssl_ecdh.c b/src/ssl/ssl_ecdh.c
index 30fe7e4f..49652f2e 100644
--- a/src/ssl/ssl_ecdh.c
+++ b/src/ssl/ssl_ecdh.c
@@ -189,6 +189,7 @@ static int ssl_x25519_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
uint8_t *secret = OPENSSL_malloc(32);
if (secret == NULL) {
+ OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
return 0;
}
diff --git a/src/ssl/ssl_lib.c b/src/ssl/ssl_lib.c
index b3e397d1..1b002a5e 100644
--- a/src/ssl/ssl_lib.c
+++ b/src/ssl/ssl_lib.c
@@ -371,8 +371,8 @@ SSL *SSL_new(SSL_CTX *ctx) {
}
OPENSSL_memset(ssl, 0, sizeof(SSL));
- ssl->min_version = ctx->min_version;
- ssl->max_version = ctx->max_version;
+ ssl->conf_min_version = ctx->conf_min_version;
+ ssl->conf_max_version = ctx->conf_max_version;
/* RFC 6347 states that implementations SHOULD use an initial timer value of
* 1 second. */
@@ -467,7 +467,10 @@ void SSL_free(SSL *ssl) {
return;
}
- ssl->ctx->x509_method->ssl_free(ssl);
+ if (ssl->ctx != NULL) {
+ ssl->ctx->x509_method->ssl_free(ssl);
+ }
+
CRYPTO_free_ex_data(&g_ex_data_class_ssl, ssl, &ssl->ex_data);
BIO_free_all(ssl->rbio);
@@ -757,19 +760,23 @@ int SSL_write(SSL *ssl, const void *buf, int num) {
return -1;
}
- /* If necessary, complete the handshake implicitly. */
- if (!ssl_can_write(ssl)) {
- int ret = SSL_do_handshake(ssl);
- if (ret < 0) {
- return ret;
- }
- if (ret == 0) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
- return -1;
+ int ret = 0, needs_handshake = 0;
+ do {
+ /* If necessary, complete the handshake implicitly. */
+ if (!ssl_can_write(ssl)) {
+ ret = SSL_do_handshake(ssl);
+ if (ret < 0) {
+ return ret;
+ }
+ if (ret == 0) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
+ return -1;
+ }
}
- }
- return ssl->method->write_app_data(ssl, buf, num);
+ ret = ssl->method->write_app_data(ssl, &needs_handshake, buf, num);
+ } while (needs_handshake);
+ return ret;
}
int SSL_shutdown(SSL *ssl) {
@@ -842,10 +849,35 @@ void SSL_set_early_data_enabled(SSL *ssl, int enabled) {
ssl->cert->enable_early_data = !!enabled;
}
+int SSL_in_early_data(const SSL *ssl) {
+ if (ssl->s3->hs == NULL) {
+ return 0;
+ }
+ return ssl->s3->hs->in_early_data;
+}
+
int SSL_early_data_accepted(const SSL *ssl) {
return ssl->early_data_accepted;
}
+void SSL_reset_early_data_reject(SSL *ssl) {
+ SSL_HANDSHAKE *hs = ssl->s3->hs;
+ if (hs == NULL ||
+ hs->wait != ssl_hs_early_data_rejected) {
+ abort();
+ }
+
+ hs->wait = ssl_hs_ok;
+ hs->in_early_data = 0;
+ SSL_SESSION_free(hs->early_session);
+ hs->early_session = NULL;
+
+ /* Discard any unfinished writes from the perspective of |SSL_write|'s
+ * retry. The handshake will transparently flush out the pending record
+ * (discarded by the server) to keep the framing correct. */
+ ssl->s3->wpend_pending = 0;
+}
+
static int bio_retry_reason_to_error(int reason) {
switch (reason) {
case BIO_RR_CONNECT:
@@ -938,6 +970,9 @@ int SSL_get_error(const SSL *ssl, int ret_code) {
case SSL_PENDING_TICKET:
return SSL_ERROR_PENDING_TICKET;
+
+ case SSL_EARLY_DATA_REJECTED:
+ return SSL_ERROR_EARLY_DATA_REJECTED;
}
return SSL_ERROR_SYSCALL;
@@ -982,19 +1017,19 @@ static int set_max_version(const SSL_PROTOCOL_METHOD *method, uint16_t *out,
}
int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, uint16_t version) {
- return set_min_version(ctx->method, &ctx->min_version, version);
+ return set_min_version(ctx->method, &ctx->conf_min_version, version);
}
int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, uint16_t version) {
- return set_max_version(ctx->method, &ctx->max_version, version);
+ return set_max_version(ctx->method, &ctx->conf_max_version, version);
}
int SSL_set_min_proto_version(SSL *ssl, uint16_t version) {
- return set_min_version(ssl->method, &ssl->min_version, version);
+ return set_min_version(ssl->method, &ssl->conf_min_version, version);
}
int SSL_set_max_proto_version(SSL *ssl, uint16_t version) {
- return set_max_version(ssl->method, &ssl->max_version, version);
+ return set_max_version(ssl->method, &ssl->conf_max_version, version);
}
uint32_t SSL_CTX_set_options(SSL_CTX *ctx, uint32_t options) {
@@ -1643,32 +1678,31 @@ int SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg) {
return 1;
}
-int SSL_select_next_proto(uint8_t **out, uint8_t *out_len,
- const uint8_t *server, unsigned server_len,
- const uint8_t *client, unsigned client_len) {
- unsigned int i, j;
+int SSL_select_next_proto(uint8_t **out, uint8_t *out_len, const uint8_t *peer,
+ unsigned peer_len, const uint8_t *supported,
+ unsigned supported_len) {
const uint8_t *result;
- int status = OPENSSL_NPN_UNSUPPORTED;
+ int status;
- /* For each protocol in server preference order, see if we support it. */
- for (i = 0; i < server_len;) {
- for (j = 0; j < client_len;) {
- if (server[i] == client[j] &&
- OPENSSL_memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) {
+ /* For each protocol in peer preference order, see if we support it. */
+ for (unsigned i = 0; i < peer_len;) {
+ for (unsigned j = 0; j < supported_len;) {
+ if (peer[i] == supported[j] &&
+ OPENSSL_memcmp(&peer[i + 1], &supported[j + 1], peer[i]) == 0) {
/* We found a match */
- result = &server[i];
+ result = &peer[i];
status = OPENSSL_NPN_NEGOTIATED;
goto found;
}
- j += client[j];
+ j += supported[j];
j++;
}
- i += server[i];
+ i += peer[i];
i++;
}
- /* There's no overlap between our protocols and the server's list. */
- result = client;
+ /* There's no overlap between our protocols and the peer's list. */
+ result = supported;
status = OPENSSL_NPN_NO_OVERLAP;
found:
@@ -1680,11 +1714,7 @@ found:
void SSL_get0_next_proto_negotiated(const SSL *ssl, const uint8_t **out_data,
unsigned *out_len) {
*out_data = ssl->s3->next_proto_negotiated;
- if (*out_data == NULL) {
- *out_len = 0;
- } else {
- *out_len = ssl->s3->next_proto_negotiated_len;
- }
+ *out_len = ssl->s3->next_proto_negotiated_len;
}
void SSL_CTX_set_next_protos_advertised_cb(
@@ -1737,13 +1767,11 @@ void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
void SSL_get0_alpn_selected(const SSL *ssl, const uint8_t **out_data,
unsigned *out_len) {
- *out_data = NULL;
- if (ssl->s3) {
- *out_data = ssl->s3->alpn_selected;
- }
- if (*out_data == NULL) {
- *out_len = 0;
+ if (SSL_in_early_data(ssl) && !ssl->server) {
+ *out_data = ssl->s3->hs->early_session->early_alpn;
+ *out_len = ssl->s3->hs->early_session->early_alpn_len;
} else {
+ *out_data = ssl->s3->alpn_selected;
*out_len = ssl->s3->alpn_selected_len;
}
}
@@ -1934,7 +1962,7 @@ const SSL_CIPHER *SSL_get_current_cipher(const SSL *ssl) {
}
int SSL_session_reused(const SSL *ssl) {
- return ssl->s3->session_reused;
+ return ssl->s3->session_reused || SSL_in_early_data(ssl);
}
const COMP_METHOD *SSL_get_current_compression(SSL *ssl) { return NULL; }
@@ -2104,47 +2132,23 @@ void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*callback)(SSL *ssl, int is_export,
int keylength)) {
}
-int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) {
- if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
- return 0;
- }
-
- OPENSSL_free(ctx->psk_identity_hint);
-
- if (identity_hint != NULL) {
- ctx->psk_identity_hint = BUF_strdup(identity_hint);
- if (ctx->psk_identity_hint == NULL) {
- return 0;
- }
- } else {
- ctx->psk_identity_hint = NULL;
- }
-
- return 1;
-}
-
-int SSL_use_psk_identity_hint(SSL *ssl, const char *identity_hint) {
- if (ssl == NULL) {
- return 0;
- }
-
+static int use_psk_identity_hint(char **out, const char *identity_hint) {
if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
/* Clear currently configured hint, if any. */
- OPENSSL_free(ssl->psk_identity_hint);
- ssl->psk_identity_hint = NULL;
+ OPENSSL_free(*out);
+ *out = NULL;
/* Treat the empty hint as not supplying one. Plain PSK makes it possible to
* send either no hint (omit ServerKeyExchange) or an empty hint, while
* ECDHE_PSK can only spell empty hint. Having different capabilities is odd,
* so we interpret empty and missing as identical. */
if (identity_hint != NULL && identity_hint[0] != '\0') {
- ssl->psk_identity_hint = BUF_strdup(identity_hint);
- if (ssl->psk_identity_hint == NULL) {
+ *out = BUF_strdup(identity_hint);
+ if (*out == NULL) {
return 0;
}
}
@@ -2152,6 +2156,14 @@ int SSL_use_psk_identity_hint(SSL *ssl, const char *identity_hint) {
return 1;
}
+int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint) {
+ return use_psk_identity_hint(&ctx->psk_identity_hint, identity_hint);
+}
+
+int SSL_use_psk_identity_hint(SSL *ssl, const char *identity_hint) {
+ return use_psk_identity_hint(&ssl->psk_identity_hint, identity_hint);
+}
+
const char *SSL_get_psk_identity_hint(const SSL *ssl) {
if (ssl == NULL) {
return NULL;
@@ -2342,8 +2354,8 @@ int ssl_get_version_range(const SSL *ssl, uint16_t *out_min_version,
}
}
- uint16_t min_version = ssl->min_version;
- uint16_t max_version = ssl->max_version;
+ uint16_t min_version = ssl->conf_min_version;
+ uint16_t max_version = ssl->conf_max_version;
/* Bound the range to only those implemented in this protocol. */
if (min_version < ssl->method->min_version) {
diff --git a/src/ssl/ssl_privkey.c b/src/ssl/ssl_privkey.c
index 84927487..257d03e4 100644
--- a/src/ssl/ssl_privkey.c
+++ b/src/ssl/ssl_privkey.c
@@ -56,6 +56,7 @@
#include <openssl/ssl.h>
+#include <assert.h>
#include <limits.h>
#include <openssl/ec.h>
@@ -406,33 +407,43 @@ static int legacy_sign_digest_supported(const SSL_SIGNATURE_ALGORITHM *alg) {
!alg->is_rsa_pss;
}
+static enum ssl_private_key_result_t legacy_sign(
+ SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, uint16_t sigalg,
+ const uint8_t *in, size_t in_len) {
+ /* TODO(davidben): Remove support for |sign_digest|-only
+ * |SSL_PRIVATE_KEY_METHOD|s. */
+ const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
+ if (alg == NULL || !legacy_sign_digest_supported(alg)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
+ return ssl_private_key_failure;
+ }
+
+ const EVP_MD *md = alg->digest_func();
+ uint8_t hash[EVP_MAX_MD_SIZE];
+ unsigned hash_len;
+ if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
+ return ssl_private_key_failure;
+ }
+
+ return ssl->cert->key_method->sign_digest(ssl, out, out_len, max_out, md,
+ hash, hash_len);
+}
+
enum ssl_private_key_result_t ssl_private_key_sign(
- SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
+ SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
uint16_t sigalg, const uint8_t *in, size_t in_len) {
+ SSL *const ssl = hs->ssl;
if (ssl->cert->key_method != NULL) {
- if (ssl->cert->key_method->sign != NULL) {
- return ssl->cert->key_method->sign(ssl, out, out_len, max_out, sigalg, in,
- in_len);
- }
-
- /* TODO(davidben): Remove support for |sign_digest|-only
- * |SSL_PRIVATE_KEY_METHOD|s. */
- const SSL_SIGNATURE_ALGORITHM *alg = get_signature_algorithm(sigalg);
- if (alg == NULL ||
- !legacy_sign_digest_supported(alg)) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
- return ssl_private_key_failure;
- }
-
- const EVP_MD *md = alg->digest_func();
- uint8_t hash[EVP_MAX_MD_SIZE];
- unsigned hash_len;
- if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
- return ssl_private_key_failure;
+ enum ssl_private_key_result_t ret;
+ if (hs->pending_private_key_op) {
+ ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
+ } else {
+ ret = (ssl->cert->key_method->sign != NULL
+ ? ssl->cert->key_method->sign
+ : legacy_sign)(ssl, out, out_len, max_out, sigalg, in, in_len);
}
-
- return ssl->cert->key_method->sign_digest(ssl, out, out_len, max_out, md,
- hash, hash_len);
+ hs->pending_private_key_op = ret == ssl_private_key_retry;
+ return ret;
}
*out_len = max_out;
@@ -456,11 +467,19 @@ int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
}
enum ssl_private_key_result_t ssl_private_key_decrypt(
- SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
+ SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len, size_t max_out,
const uint8_t *in, size_t in_len) {
+ SSL *const ssl = hs->ssl;
if (ssl->cert->key_method != NULL) {
- return ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
- in_len);
+ enum ssl_private_key_result_t ret;
+ if (hs->pending_private_key_op) {
+ ret = ssl->cert->key_method->complete(ssl, out, out_len, max_out);
+ } else {
+ ret = ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
+ in_len);
+ }
+ hs->pending_private_key_op = ret == ssl_private_key_retry;
+ return ret;
}
RSA *rsa = EVP_PKEY_get0_RSA(ssl->cert->privatekey);
@@ -478,13 +497,6 @@ enum ssl_private_key_result_t ssl_private_key_decrypt(
return ssl_private_key_success;
}
-enum ssl_private_key_result_t ssl_private_key_complete(SSL *ssl, uint8_t *out,
- size_t *out_len,
- size_t max_out) {
- /* Only custom keys may be asynchronous. */
- return ssl->cert->key_method->complete(ssl, out, out_len, max_out);
-}
-
int ssl_private_key_supports_signature_algorithm(SSL_HANDSHAKE *hs,
uint16_t sigalg) {
SSL *const ssl = hs->ssl;
diff --git a/src/ssl/ssl_session.c b/src/ssl/ssl_session.c
index b105cd01..f025364b 100644
--- a/src/ssl/ssl_session.c
+++ b/src/ssl/ssl_session.c
@@ -467,8 +467,12 @@ SSL_SESSION *SSL_get_session(const SSL *ssl) {
if (!SSL_in_init(ssl)) {
return ssl->s3->established_session;
}
- if (ssl->s3->hs->new_session != NULL) {
- return ssl->s3->hs->new_session;
+ SSL_HANDSHAKE *hs = ssl->s3->hs;
+ if (hs->early_session != NULL) {
+ return hs->early_session;
+ }
+ if (hs->new_session != NULL) {
+ return hs->new_session;
}
return ssl->session;
}
diff --git a/src/ssl/ssl_stat.c b/src/ssl/ssl_stat.c
index 571b4a9a..22149e25 100644
--- a/src/ssl/ssl_stat.c
+++ b/src/ssl/ssl_stat.c
@@ -142,11 +142,7 @@ const char *SSL_state_string_long(const SSL *ssl) {
case SSL3_ST_CW_CERT_VRFY_A:
return "SSLv3 write certificate verify A";
- case SSL3_ST_CW_CERT_VRFY_B:
- return "SSLv3 write certificate verify B";
-
case SSL3_ST_CW_CHANGE:
- case SSL3_ST_SW_CHANGE:
return "SSLv3 write change cipher spec";
case SSL3_ST_CW_FINISHED_A:
@@ -183,12 +179,6 @@ const char *SSL_state_string_long(const SSL *ssl) {
case SSL3_ST_SW_KEY_EXCH_A:
return "SSLv3 write key exchange A";
- case SSL3_ST_SW_CERT_REQ_A:
- return "SSLv3 write certificate request A";
-
- case SSL3_ST_SW_SESSION_TICKET_A:
- return "SSLv3 write session ticket A";
-
case SSL3_ST_SW_SRVR_DONE_A:
return "SSLv3 write server done A";
@@ -256,10 +246,6 @@ const char *SSL_state_string(const SSL *ssl) {
case SSL3_ST_CW_CERT_VRFY_A:
return "3WCV_A";
- case SSL3_ST_CW_CERT_VRFY_B:
- return "3WCV_B";
-
- case SSL3_ST_SW_CHANGE:
case SSL3_ST_CW_CHANGE:
return "3WCCS_";
@@ -293,12 +279,6 @@ const char *SSL_state_string(const SSL *ssl) {
case SSL3_ST_SW_KEY_EXCH_A:
return "3WSKEA";
- case SSL3_ST_SW_KEY_EXCH_B:
- return "3WSKEB";
-
- case SSL3_ST_SW_CERT_REQ_A:
- return "3WCR_A";
-
case SSL3_ST_SW_SRVR_DONE_A:
return "3WSD_A";
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 80465cea..84b7496d 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -177,6 +177,20 @@ static const CipherTest kCipherTests[] = {
},
false,
},
+ // Standard names may be used instead of OpenSSL names.
+ {
+ "[TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256|"
+ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256]:"
+ "[TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256]:"
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+ {
+ {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1},
+ {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+ {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+ {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+ },
+ false,
+ },
// @STRENGTH performs a stable strength-sort of the selected ciphers and
// only the selected ciphers.
{
@@ -715,8 +729,8 @@ static void ExpectDefaultVersion(uint16_t min_version, uint16_t max_version,
const SSL_METHOD *(*method)(void)) {
bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method()));
ASSERT_TRUE(ctx);
- EXPECT_EQ(min_version, ctx->min_version);
- EXPECT_EQ(max_version, ctx->max_version);
+ EXPECT_EQ(min_version, ctx->conf_min_version);
+ EXPECT_EQ(max_version, ctx->conf_max_version);
}
TEST(SSLTest, DefaultVersion) {
@@ -730,43 +744,42 @@ TEST(SSLTest, DefaultVersion) {
ExpectDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &DTLSv1_2_method);
}
-typedef struct {
- int id;
- const char *rfc_name;
-} CIPHER_RFC_NAME_TEST;
-
-static const CIPHER_RFC_NAME_TEST kCipherRFCNameTests[] = {
- {SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
- {TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"},
- {TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
- "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"},
- {TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
- "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"},
- {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
- "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"},
- {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
- "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"},
- {TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
- "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"},
- {TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
- "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"},
- {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
- "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"},
- {TLS1_CK_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384"},
- {TLS1_CK_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256"},
- {TLS1_CK_CHACHA20_POLY1305_SHA256, "TLS_CHACHA20_POLY1305_SHA256"},
-};
+TEST(SSLTest, CipherGetStandardName) {
+ static const struct {
+ int id;
+ const char *standard_name;
+ } kTests[] = {
+ {SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
+ {TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"},
+ {TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"},
+ {TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"},
+ {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+ "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"},
+ {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+ "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"},
+ {TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"},
+ {TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"},
+ {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+ "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"},
+ {TLS1_CK_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384"},
+ {TLS1_CK_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256"},
+ {TLS1_CK_CHACHA20_POLY1305_SHA256, "TLS_CHACHA20_POLY1305_SHA256"},
+ };
-TEST(SSLTest, CipherGetRFCName) {
- for (const CIPHER_RFC_NAME_TEST &t : kCipherRFCNameTests) {
- SCOPED_TRACE(t.rfc_name);
+ for (const auto &t : kTests) {
+ SCOPED_TRACE(t.standard_name);
const SSL_CIPHER *cipher = SSL_get_cipher_by_value(t.id & 0xffff);
ASSERT_TRUE(cipher);
+ EXPECT_STREQ(t.standard_name, SSL_CIPHER_standard_name(cipher));
+
bssl::UniquePtr<char> rfc_name(SSL_CIPHER_get_rfc_name(cipher));
ASSERT_TRUE(rfc_name);
-
- EXPECT_STREQ(t.rfc_name, rfc_name.get());
+ EXPECT_STREQ(t.standard_name, rfc_name.get());
}
}
@@ -1497,6 +1510,7 @@ TEST(SSLTest, SessionDuplication) {
}
static void ExpectFDs(const SSL *ssl, int rfd, int wfd) {
+ EXPECT_EQ(rfd, SSL_get_fd(ssl));
EXPECT_EQ(rfd, SSL_get_rfd(ssl));
EXPECT_EQ(wfd, SSL_get_wfd(ssl));
@@ -1945,7 +1959,7 @@ static int SaveLastSession(SSL *ssl, SSL_SESSION *session) {
}
static bssl::UniquePtr<SSL_SESSION> CreateClientSession(SSL_CTX *client_ctx,
- SSL_CTX *server_ctx) {
+ SSL_CTX *server_ctx) {
g_last_session = nullptr;
SSL_CTX_sess_set_new_cb(client_ctx, SaveLastSession);
@@ -2543,15 +2557,15 @@ TEST(SSLTest, SetVersion) {
// Zero is the default version.
EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), 0));
- EXPECT_EQ(TLS1_2_VERSION, ctx->max_version);
+ EXPECT_EQ(TLS1_2_VERSION, ctx->conf_max_version);
EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), 0));
- EXPECT_EQ(TLS1_VERSION, ctx->min_version);
+ EXPECT_EQ(TLS1_VERSION, ctx->conf_min_version);
// SSL 3.0 and TLS 1.3 are available, but not by default.
EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), SSL3_VERSION));
- EXPECT_EQ(SSL3_VERSION, ctx->min_version);
+ EXPECT_EQ(SSL3_VERSION, ctx->conf_min_version);
EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_VERSION));
- EXPECT_EQ(TLS1_3_VERSION, ctx->max_version);
+ EXPECT_EQ(TLS1_3_VERSION, ctx->conf_max_version);
ctx.reset(SSL_CTX_new(DTLS_method()));
ASSERT_TRUE(ctx);
@@ -2571,9 +2585,9 @@ TEST(SSLTest, SetVersion) {
EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0x1234));
EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), 0));
- EXPECT_EQ(TLS1_2_VERSION, ctx->max_version);
+ EXPECT_EQ(TLS1_2_VERSION, ctx->conf_max_version);
EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), 0));
- EXPECT_EQ(TLS1_1_VERSION, ctx->min_version);
+ EXPECT_EQ(TLS1_1_VERSION, ctx->conf_min_version);
}
static const char *GetVersionName(uint16_t version) {
@@ -3032,6 +3046,81 @@ static bool TestSSLWriteRetry(bool is_dtls, const SSL_METHOD *method,
return true;
}
+static bool TestRecordCallback(bool is_dtls, const SSL_METHOD *method,
+ uint16_t version) {
+ bssl::UniquePtr<X509> cert = GetChainTestCertificate();
+ bssl::UniquePtr<X509> intermediate = GetChainTestIntermediate();
+ bssl::UniquePtr<EVP_PKEY> key = GetChainTestKey();
+ if (!cert || !intermediate || !key) {
+ return false;
+ }
+
+ bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method));
+ if (!ctx ||
+ !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
+ !SSL_CTX_use_PrivateKey(ctx.get(), key.get()) ||
+ !SSL_CTX_set_min_proto_version(ctx.get(), version) ||
+ !SSL_CTX_set_max_proto_version(ctx.get(), version)) {
+ return false;
+ }
+
+ bool read_seen = false;
+ bool write_seen = false;
+ auto cb = [&](int is_write, int cb_version, int cb_type, const void *buf,
+ size_t len, SSL *ssl) {
+ if (cb_type != SSL3_RT_HEADER) {
+ return;
+ }
+
+ // The callback does not report a version for records.
+ EXPECT_EQ(0, cb_version);
+
+ if (is_write) {
+ write_seen = true;
+ } else {
+ read_seen = true;
+ }
+
+ // Sanity-check that the record header is plausible.
+ CBS cbs;
+ CBS_init(&cbs, reinterpret_cast<const uint8_t *>(buf), len);
+ uint8_t type;
+ uint16_t record_version, length;
+ ASSERT_TRUE(CBS_get_u8(&cbs, &type));
+ ASSERT_TRUE(CBS_get_u16(&cbs, &record_version));
+ EXPECT_TRUE(record_version == version ||
+ record_version == (is_dtls ? DTLS1_VERSION : TLS1_VERSION))
+ << "Invalid record version: " << record_version;
+ if (is_dtls) {
+ uint16_t epoch;
+ ASSERT_TRUE(CBS_get_u16(&cbs, &epoch));
+ EXPECT_TRUE(epoch == 0 || epoch == 1) << "Invalid epoch: " << epoch;
+ ASSERT_TRUE(CBS_skip(&cbs, 6));
+ }
+ ASSERT_TRUE(CBS_get_u16(&cbs, &length));
+ EXPECT_EQ(0u, CBS_len(&cbs));
+ };
+ using CallbackType = decltype(cb);
+ SSL_CTX_set_msg_callback(
+ ctx.get(), [](int is_write, int cb_version, int cb_type, const void *buf,
+ size_t len, SSL *ssl, void *arg) {
+ CallbackType *cb_ptr = reinterpret_cast<CallbackType *>(arg);
+ (*cb_ptr)(is_write, cb_version, cb_type, buf, len, ssl);
+ });
+ SSL_CTX_set_msg_callback_arg(ctx.get(), &cb);
+
+ bssl::UniquePtr<SSL> client, server;
+ if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+ nullptr /* no session */)) {
+ return false;
+ }
+
+ EXPECT_TRUE(read_seen);
+ EXPECT_TRUE(write_seen);
+ return true;
+}
+
+
static bool ForEachVersion(bool (*test_func)(bool is_dtls,
const SSL_METHOD *method,
uint16_t version)) {
@@ -3454,6 +3543,49 @@ TEST(SSLTest, SSL3Method) {
EXPECT_EQ(SSL_R_NO_SUPPORTED_VERSIONS_ENABLED, ERR_GET_REASON(err));
}
+TEST(SSLTest, SelectNextProto) {
+ uint8_t *result;
+ uint8_t result_len;
+
+ // If there is an overlap, it should be returned.
+ EXPECT_EQ(OPENSSL_NPN_NEGOTIATED,
+ SSL_select_next_proto(&result, &result_len,
+ (const uint8_t *)"\1a\2bb\3ccc", 9,
+ (const uint8_t *)"\1x\1y\1a\1z", 8));
+ EXPECT_EQ(Bytes("a"), Bytes(result, result_len));
+
+ EXPECT_EQ(OPENSSL_NPN_NEGOTIATED,
+ SSL_select_next_proto(&result, &result_len,
+ (const uint8_t *)"\1a\2bb\3ccc", 9,
+ (const uint8_t *)"\1x\1y\2bb\1z", 9));
+ EXPECT_EQ(Bytes("bb"), Bytes(result, result_len));
+
+ EXPECT_EQ(OPENSSL_NPN_NEGOTIATED,
+ SSL_select_next_proto(&result, &result_len,
+ (const uint8_t *)"\1a\2bb\3ccc", 9,
+ (const uint8_t *)"\1x\1y\3ccc\1z", 10));
+ EXPECT_EQ(Bytes("ccc"), Bytes(result, result_len));
+
+ // Peer preference order takes precedence over local.
+ EXPECT_EQ(OPENSSL_NPN_NEGOTIATED,
+ SSL_select_next_proto(&result, &result_len,
+ (const uint8_t *)"\1a\2bb\3ccc", 9,
+ (const uint8_t *)"\3ccc\2bb\1a", 9));
+ EXPECT_EQ(Bytes("a"), Bytes(result, result_len));
+
+ // If there is no overlap, return the first local protocol.
+ EXPECT_EQ(OPENSSL_NPN_NO_OVERLAP,
+ SSL_select_next_proto(&result, &result_len,
+ (const uint8_t *)"\1a\2bb\3ccc", 9,
+ (const uint8_t *)"\1x\2yy\3zzz", 9));
+ EXPECT_EQ(Bytes("x"), Bytes(result, result_len));
+
+ EXPECT_EQ(OPENSSL_NPN_NO_OVERLAP,
+ SSL_select_next_proto(&result, &result_len, nullptr, 0,
+ (const uint8_t *)"\1x\2yy\3zzz", 9));
+ EXPECT_EQ(Bytes("x"), Bytes(result, result_len));
+}
+
// TODO(davidben): Convert this file to GTest properly.
TEST(SSLTest, AllTests) {
if (!TestSSL_SESSIONEncoding(kOpenSSLSession) ||
@@ -3482,7 +3614,8 @@ TEST(SSLTest, AllTests) {
!ForEachVersion(TestALPNCipherAvailable) ||
!ForEachVersion(TestSSLClearSessionResumption) ||
!ForEachVersion(TestAutoChain) ||
- !ForEachVersion(TestSSLWriteRetry)) {
+ !ForEachVersion(TestSSLWriteRetry) ||
+ !ForEachVersion(TestRecordCallback)) {
ADD_FAILURE() << "Tests failed";
}
}
diff --git a/src/ssl/t1_lib.c b/src/ssl/t1_lib.c
index 000a8cdf..1b143711 100644
--- a/src/ssl/t1_lib.c
+++ b/src/ssl/t1_lib.c
@@ -536,7 +536,7 @@ int tls12_add_verify_sigalgs(const SSL *ssl, CBB *out) {
return 1;
}
-int tls12_check_peer_sigalg(SSL *ssl, int *out_alert, uint16_t sigalg) {
+int tls12_check_peer_sigalg(SSL *ssl, uint8_t *out_alert, uint16_t sigalg) {
const uint16_t *sigalgs = kVerifySignatureAlgorithms;
size_t num_sigalgs = OPENSSL_ARRAY_SIZE(kVerifySignatureAlgorithms);
if (ssl->ctx->num_verify_sigalgs != 0) {
@@ -722,13 +722,8 @@ static int ext_sni_add_serverhello(SSL_HANDSHAKE *hs, 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;
- }
-
/* Renegotiation indication is not necessary in TLS 1.3. */
- if (min_version >= TLS1_3_VERSION) {
+ if (hs->min_version >= TLS1_3_VERSION) {
return 1;
}
@@ -883,13 +878,8 @@ static int ext_ri_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
* https://tools.ietf.org/html/rfc7627 */
static int ext_ems_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
- uint16_t min_version, max_version;
- if (!ssl_get_version_range(hs->ssl, &min_version, &max_version)) {
- return 0;
- }
-
/* Extended master secret is not necessary in TLS 1.3. */
- if (min_version >= TLS1_3_VERSION || max_version <= SSL3_VERSION) {
+ if (hs->min_version >= TLS1_3_VERSION || hs->max_version <= SSL3_VERSION) {
return 1;
}
@@ -967,13 +957,8 @@ static int ext_ems_add_serverhello(SSL_HANDSHAKE *hs, 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;
- }
-
/* TLS 1.3 uses a different ticket extension. */
- if (min_version >= TLS1_3_VERSION ||
+ if (hs->min_version >= TLS1_3_VERSION ||
SSL_get_options(ssl) & SSL_OP_NO_TICKET) {
return 1;
}
@@ -1055,12 +1040,7 @@ static int ext_ticket_add_serverhello(SSL_HANDSHAKE *hs, 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;
- }
-
- if (max_version < TLS1_2_VERSION) {
+ if (hs->max_version < TLS1_2_VERSION) {
return 1;
}
@@ -1814,13 +1794,8 @@ static int ext_ec_point_add_extension(SSL_HANDSHAKE *hs, 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(hs->ssl, &min_version, &max_version)) {
- return 0;
- }
-
/* The point format extension is unneccessary in TLS 1.3. */
- if (min_version >= TLS1_3_VERSION) {
+ if (hs->min_version >= TLS1_3_VERSION) {
return 1;
}
@@ -1888,13 +1863,8 @@ static int ext_ec_point_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
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;
- }
-
uint16_t session_version;
- if (max_version < TLS1_3_VERSION || ssl->session == NULL ||
+ if (hs->max_version < TLS1_3_VERSION || ssl->session == NULL ||
!ssl->method->version_from_wire(&session_version,
ssl->session->ssl_version) ||
session_version < TLS1_3_VERSION) {
@@ -1913,13 +1883,8 @@ static size_t ext_pre_shared_key_clienthello_length(SSL_HANDSHAKE *hs) {
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;
- }
-
uint16_t session_version;
- if (max_version < TLS1_3_VERSION || ssl->session == NULL ||
+ if (hs->max_version < TLS1_3_VERSION || ssl->session == NULL ||
!ssl->method->version_from_wire(&session_version,
ssl->session->ssl_version) ||
session_version < TLS1_3_VERSION) {
@@ -2062,13 +2027,7 @@ int ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE *hs, 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;
- }
-
- if (max_version < TLS1_3_VERSION) {
+ if (hs->max_version < TLS1_3_VERSION) {
return 1;
}
@@ -2194,12 +2153,7 @@ static int ext_early_data_add_serverhello(SSL_HANDSHAKE *hs, 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;
- }
-
- if (max_version < TLS1_3_VERSION) {
+ if (hs->max_version < TLS1_3_VERSION) {
return 1;
}
@@ -2404,12 +2358,7 @@ int ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, 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;
- }
-
- if (max_version <= TLS1_2_VERSION) {
+ if (hs->max_version <= TLS1_2_VERSION) {
return 1;
}
@@ -2426,7 +2375,8 @@ static int ext_supported_versions_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
return 0;
}
- for (uint16_t version = max_version; version >= min_version; version--) {
+ for (uint16_t version = hs->max_version; version >= hs->min_version;
+ version--) {
if (!CBB_add_u16(&versions, ssl->method->version_to_wire(version))) {
return 0;
}
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index f9b6553f..3cb2856d 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -265,6 +265,9 @@ static bssl::UniquePtr<STACK_OF(X509_NAME)> DecodeHexX509Names(
const std::string &hex_names) {
const std::vector<std::string> der_names = DecodeHexStrings(hex_names);
bssl::UniquePtr<STACK_OF(X509_NAME)> ret(sk_X509_NAME_new_null());
+ if (!ret) {
+ return nullptr;
+ }
for (const auto &der_name : der_names) {
const uint8_t *const data =
@@ -1361,24 +1364,23 @@ static uint16_t GetProtocolVersion(const SSL *ssl) {
// CheckHandshakeProperties checks, immediately after |ssl| completes its
// initial handshake (or False Starts), whether all the properties are
// consistent with the test configuration and invariants.
-static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
- const TestConfig *config = GetTestConfig(ssl);
-
+static bool CheckHandshakeProperties(SSL *ssl, bool is_resume,
+ const TestConfig *config) {
if (SSL_get_current_cipher(ssl) == nullptr) {
fprintf(stderr, "null cipher after handshake\n");
return false;
}
- if (is_resume &&
- (!!SSL_session_reused(ssl) == config->expect_session_miss)) {
- fprintf(stderr, "session was%s reused\n",
+ bool expect_resume =
+ is_resume && (!config->expect_session_miss || SSL_in_early_data(ssl));
+ if (!!SSL_session_reused(ssl) != expect_resume) {
+ fprintf(stderr, "session unexpectedly was%s reused\n",
SSL_session_reused(ssl) ? "" : " not");
return false;
}
bool expect_handshake_done =
- (is_resume || !config->false_start) &&
- !(config->is_server && SSL_early_data_accepted(ssl));
+ (is_resume || !config->false_start) && !SSL_in_early_data(ssl);
if (expect_handshake_done != GetTestState(ssl)->handshake_done) {
fprintf(stderr, "handshake was%s completed\n",
GetTestState(ssl)->handshake_done ? "" : " not");
@@ -1552,7 +1554,7 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
return false;
}
- if (is_resume) {
+ if (is_resume && !SSL_in_early_data(ssl)) {
if ((config->expect_accept_early_data && !SSL_early_data_accepted(ssl)) ||
(config->expect_reject_early_data && SSL_early_data_accepted(ssl))) {
fprintf(stderr,
@@ -1643,13 +1645,17 @@ static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
return true;
}
-// DoExchange runs a test SSL exchange against the peer. On success, it returns
+static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session, SSL *ssl,
+ const TestConfig *config, bool is_resume, bool is_retry);
+
+// DoConnection tests an SSL connection against the peer. On success, it returns
// true and sets |*out_session| to the negotiated SSL session. If the test is a
// resumption attempt, |is_resume| is true and |session| is the session from the
// previous exchange.
-static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
- SSL_CTX *ssl_ctx, const TestConfig *config,
- bool is_resume, SSL_SESSION *session) {
+static bool DoConnection(bssl::UniquePtr<SSL_SESSION> *out_session,
+ SSL_CTX *ssl_ctx, const TestConfig *config,
+ const TestConfig *retry_config, bool is_resume,
+ SSL_SESSION *session) {
bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
if (!ssl) {
return false;
@@ -1865,20 +1871,62 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
SSL_set_connect_state(ssl.get());
}
+ bool ret = DoExchange(out_session, ssl.get(), config, is_resume, false);
+ if (!config->is_server && is_resume && config->expect_reject_early_data) {
+ // We must have failed due to an early data rejection.
+ if (ret) {
+ fprintf(stderr, "0-RTT exchange unexpected succeeded.\n");
+ return false;
+ }
+ if (SSL_get_error(ssl.get(), -1) != SSL_ERROR_EARLY_DATA_REJECTED) {
+ fprintf(stderr,
+ "SSL_get_error did not signal SSL_ERROR_EARLY_DATA_REJECTED.\n");
+ return false;
+ }
+
+ // Before reseting, early state should still be available.
+ if (!SSL_in_early_data(ssl.get()) ||
+ !CheckHandshakeProperties(ssl.get(), is_resume, config)) {
+ fprintf(stderr, "SSL_in_early_data returned false before reset.\n");
+ return false;
+ }
+
+ // Reset the connection and try again at 1-RTT.
+ SSL_reset_early_data_reject(ssl.get());
+
+ // After reseting, the socket should report it is no longer in an early data
+ // state.
+ if (SSL_in_early_data(ssl.get())) {
+ fprintf(stderr, "SSL_in_early_data returned true after reset.\n");
+ return false;
+ }
+
+ if (!SetTestConfig(ssl.get(), retry_config)) {
+ return false;
+ }
+
+ ret = DoExchange(out_session, ssl.get(), retry_config, is_resume, true);
+ }
+ return ret;
+}
+
+static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session, SSL *ssl,
+ const TestConfig *config, bool is_resume,
+ bool is_retry) {
int ret;
if (!config->implicit_handshake) {
do {
- ret = SSL_do_handshake(ssl.get());
- } while (config->async && RetryAsync(ssl.get(), ret));
+ ret = SSL_do_handshake(ssl);
+ } while (config->async && RetryAsync(ssl, ret));
if (ret != 1 ||
- !CheckHandshakeProperties(ssl.get(), is_resume)) {
+ !CheckHandshakeProperties(ssl, is_resume, config)) {
return false;
}
if (config->handshake_twice) {
do {
- ret = SSL_do_handshake(ssl.get());
- } while (config->async && RetryAsync(ssl.get(), ret));
+ ret = SSL_do_handshake(ssl);
+ } while (config->async && RetryAsync(ssl, ret));
if (ret != 1) {
return false;
}
@@ -1886,28 +1934,28 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
// Skip the |config->async| logic as this should be a no-op.
if (config->no_op_extra_handshake &&
- SSL_do_handshake(ssl.get()) != 1) {
+ SSL_do_handshake(ssl) != 1) {
fprintf(stderr, "Extra SSL_do_handshake was not a no-op.\n");
return false;
}
// Reset the state to assert later that the callback isn't called in
// renegotations.
- GetTestState(ssl.get())->got_new_session = false;
+ GetTestState(ssl)->got_new_session = false;
}
if (config->export_keying_material > 0) {
std::vector<uint8_t> result(
static_cast<size_t>(config->export_keying_material));
if (!SSL_export_keying_material(
- ssl.get(), result.data(), result.size(),
- config->export_label.data(), config->export_label.size(),
- reinterpret_cast<const uint8_t*>(config->export_context.data()),
+ ssl, result.data(), result.size(), config->export_label.data(),
+ config->export_label.size(),
+ reinterpret_cast<const uint8_t *>(config->export_context.data()),
config->export_context.size(), config->use_export_context)) {
fprintf(stderr, "failed to export keying material\n");
return false;
}
- if (WriteAll(ssl.get(), result.data(), result.size()) < 0) {
+ if (WriteAll(ssl, result.data(), result.size()) < 0) {
return false;
}
}
@@ -1915,7 +1963,7 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
if (config->tls_unique) {
uint8_t tls_unique[16];
size_t tls_unique_len;
- if (!SSL_get_tls_unique(ssl.get(), tls_unique, &tls_unique_len,
+ if (!SSL_get_tls_unique(ssl, tls_unique, &tls_unique_len,
sizeof(tls_unique))) {
fprintf(stderr, "failed to get tls-unique\n");
return false;
@@ -1927,13 +1975,13 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
return false;
}
- if (WriteAll(ssl.get(), tls_unique, tls_unique_len) < 0) {
+ if (WriteAll(ssl, tls_unique, tls_unique_len) < 0) {
return false;
}
}
if (config->send_alert) {
- if (DoSendFatalAlert(ssl.get(), SSL_AD_DECOMPRESSION_FAILURE) < 0) {
+ if (DoSendFatalAlert(ssl, SSL_AD_DECOMPRESSION_FAILURE) < 0) {
return false;
}
return true;
@@ -1957,7 +2005,7 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
fprintf(stderr, "Bad kRecordSizes value.\n");
return false;
}
- if (WriteAll(ssl.get(), buf.get(), len) < 0) {
+ if (WriteAll(ssl, buf.get(), len) < 0) {
return false;
}
}
@@ -1970,15 +2018,17 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
return false;
}
+ // Let only one byte of the record through.
+ AsyncBioAllowWrite(GetTestState(ssl)->async_bio, 1);
int write_ret =
- SSL_write(ssl.get(), kInitialWrite, strlen(kInitialWrite));
- if (SSL_get_error(ssl.get(), write_ret) != SSL_ERROR_WANT_WRITE) {
+ SSL_write(ssl, kInitialWrite, strlen(kInitialWrite));
+ if (SSL_get_error(ssl, write_ret) != SSL_ERROR_WANT_WRITE) {
fprintf(stderr, "Failed to leave unfinished write.\n");
return false;
}
pending_initial_write = true;
} else if (config->shim_writes_first) {
- if (WriteAll(ssl.get(), kInitialWrite, strlen(kInitialWrite)) < 0) {
+ if (WriteAll(ssl, kInitialWrite, strlen(kInitialWrite)) < 0) {
return false;
}
}
@@ -1992,8 +2042,8 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
}
std::unique_ptr<uint8_t[]> buf(new uint8_t[read_size]);
- int n = DoRead(ssl.get(), buf.get(), read_size);
- int err = SSL_get_error(ssl.get(), n);
+ int n = DoRead(ssl, buf.get(), read_size);
+ int err = SSL_get_error(ssl, n);
if (err == SSL_ERROR_ZERO_RETURN ||
(n == 0 && err == SSL_ERROR_SYSCALL)) {
if (n != 0) {
@@ -2015,17 +2065,24 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
return false;
}
+ if (!config->is_server && is_resume && !is_retry &&
+ config->expect_reject_early_data) {
+ fprintf(stderr,
+ "Unexpectedly received data instead of 0-RTT reject.\n");
+ return false;
+ }
+
// After a successful read, with or without False Start, the handshake
// must be complete unless we are doing early data.
- if (!GetTestState(ssl.get())->handshake_done &&
- !SSL_early_data_accepted(ssl.get())) {
+ if (!GetTestState(ssl)->handshake_done &&
+ !SSL_early_data_accepted(ssl)) {
fprintf(stderr, "handshake was not completed after SSL_read\n");
return false;
}
// Clear the initial write, if unfinished.
if (pending_initial_write) {
- if (WriteAll(ssl.get(), kInitialWrite, strlen(kInitialWrite)) < 0) {
+ if (WriteAll(ssl, kInitialWrite, strlen(kInitialWrite)) < 0) {
return false;
}
pending_initial_write = false;
@@ -2034,7 +2091,7 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
for (int i = 0; i < n; i++) {
buf[i] ^= 0xff;
}
- if (WriteAll(ssl.get(), buf.get(), n) < 0) {
+ if (WriteAll(ssl, buf.get(), n) < 0) {
return false;
}
}
@@ -2044,25 +2101,25 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
if (!config->is_server && !config->false_start &&
!config->implicit_handshake &&
// Session tickets are sent post-handshake in TLS 1.3.
- GetProtocolVersion(ssl.get()) < TLS1_3_VERSION &&
- GetTestState(ssl.get())->got_new_session) {
+ GetProtocolVersion(ssl) < TLS1_3_VERSION &&
+ GetTestState(ssl)->got_new_session) {
fprintf(stderr, "new session was established after the handshake\n");
return false;
}
- if (GetProtocolVersion(ssl.get()) >= TLS1_3_VERSION && !config->is_server) {
+ if (GetProtocolVersion(ssl) >= TLS1_3_VERSION && !config->is_server) {
bool expect_new_session =
!config->expect_no_session && !config->shim_shuts_down;
- if (expect_new_session != GetTestState(ssl.get())->got_new_session) {
+ if (expect_new_session != GetTestState(ssl)->got_new_session) {
fprintf(stderr,
"new session was%s cached, but we expected the opposite\n",
- GetTestState(ssl.get())->got_new_session ? "" : " not");
+ GetTestState(ssl)->got_new_session ? "" : " not");
return false;
}
if (expect_new_session) {
bool got_early_data_info =
- GetTestState(ssl.get())->new_session->ticket_max_early_data != 0;
+ GetTestState(ssl)->new_session->ticket_max_early_data != 0;
if (config->expect_early_data_info != got_early_data_info) {
fprintf(
stderr,
@@ -2075,10 +2132,10 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
}
if (out_session) {
- *out_session = std::move(GetTestState(ssl.get())->new_session);
+ *out_session = std::move(GetTestState(ssl)->new_session);
}
- ret = DoShutdown(ssl.get());
+ ret = DoShutdown(ssl);
if (config->shim_shuts_down && config->check_close_notify) {
// We initiate shutdown, so |SSL_shutdown| will return in two stages. First
@@ -2088,7 +2145,7 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
fprintf(stderr, "Unexpected SSL_shutdown result: %d != 0\n", ret);
return false;
}
- ret = DoShutdown(ssl.get());
+ ret = DoShutdown(ssl);
}
if (ret != 1) {
@@ -2096,11 +2153,9 @@ static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
return false;
}
- if (SSL_total_renegotiations(ssl.get()) !=
- config->expect_total_renegotiations) {
+ if (SSL_total_renegotiations(ssl) != config->expect_total_renegotiations) {
fprintf(stderr, "Expected %d renegotiations, got %d\n",
- config->expect_total_renegotiations,
- SSL_total_renegotiations(ssl.get()));
+ config->expect_total_renegotiations, SSL_total_renegotiations(ssl));
return false;
}
@@ -2141,9 +2196,9 @@ int main(int argc, char **argv) {
return 1;
}
- TestConfig initial_config, resume_config;
- if (!ParseConfig(argc - 1, argv + 1, false, &initial_config) ||
- !ParseConfig(argc - 1, argv + 1, true, &resume_config)) {
+ TestConfig initial_config, resume_config, retry_config;
+ if (!ParseConfig(argc - 1, argv + 1, &initial_config, &resume_config,
+ &retry_config)) {
return Usage(argv[0]);
}
@@ -2172,8 +2227,8 @@ int main(int argc, char **argv) {
}
bssl::UniquePtr<SSL_SESSION> offer_session = std::move(session);
- if (!DoExchange(&session, ssl_ctx.get(), config, is_resume,
- offer_session.get())) {
+ if (!DoConnection(&session, ssl_ctx.get(), config, &retry_config, is_resume,
+ offer_session.get())) {
fprintf(stderr, "Connection %d failed.\n", i + 1);
ERR_print_errors_fp(stderr);
return 1;
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index 052f879d..0a6648ff 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -1175,6 +1175,14 @@ type ProtocolBugs struct {
// the number of records or their content do not match.
ExpectEarlyData [][]byte
+ // ExpectLateEarlyData causes a TLS 1.3 server to read application
+ // data after the ServerFinished (assuming the server is able to
+ // derive the key under which the data is encrypted) before it
+ // sends the ClientFinished. It checks that the application data it
+ // reads matches what is provided in ExpectLateEarlyData and errors if
+ // the number of records or their content do not match.
+ ExpectLateEarlyData [][]byte
+
// SendHalfRTTData causes a TLS 1.3 server to send the provided
// data in application data records before reading the client's
// Finished message.
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index 0eb64e71..fce00495 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -857,17 +857,8 @@ func (c *Conn) readRecord(want recordType) error {
c.sendAlert(alertInternalError)
return c.in.setErrorLocked(errors.New("tls: ChangeCipherSpec requested after handshake complete"))
}
- case recordTypeApplicationData:
- if !c.handshakeComplete && !c.config.Bugs.ExpectFalseStart && len(c.config.Bugs.ExpectHalfRTTData) == 0 && len(c.config.Bugs.ExpectEarlyData) == 0 {
- c.sendAlert(alertInternalError)
- return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete"))
- }
- case recordTypeAlert, recordTypeHandshake:
- // Looking for a close_notify or handshake message. Note: unlike
- // a real implementation, this is not tolerant of additional
- // records. See the documentation for ExpectCloseNotify.
- // Post-handshake requests for handshake messages are allowed if
- // the caller used ReadKeyUpdateACK.
+ case recordTypeApplicationData, recordTypeAlert, recordTypeHandshake:
+ break
}
Again:
diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json
index 603ca243..fd819f96 100644
--- a/src/ssl/test/runner/fuzzer_mode.json
+++ b/src/ssl/test/runner/fuzzer_mode.json
@@ -40,7 +40,12 @@
"TLS13-EarlyData-NonZeroRTTSession-Server": "Trial decryption does not work with the NULL cipher.",
"TLS13-EarlyData-SkipEndOfEarlyData": "Trial decryption does not work with the NULL cipher.",
"TLS13-EarlyData-ALPNMismatch-Server": "Trial decryption does not work with the NULL cipher.",
+ "TLS13-EarlyData-ALPNOmitted1-Client": "Trial decryption does not work with the NULL cipher.",
+ "TLS13-EarlyData-ALPNOmitted2-Client": "Trial decryption does not work with the NULL cipher.",
"TLS13-EarlyData-ALPNOmitted1-Server": "Trial decryption does not work with the NULL cipher.",
- "TLS13-EarlyData-ALPNOmitted2-Server": "Trial decryption does not work with the NULL cipher."
+ "TLS13-EarlyData-ALPNOmitted2-Server": "Trial decryption does not work with the NULL cipher.",
+ "TLS13-EarlyData-RejectUnfinishedWrite-Client-*": "Trial decryption does not work with the NULL cipher.",
+ "TLS13-EarlyData-Reject-Client": "Trial decryption does not work with the NULL cipher.",
+ "TLS13-EarlyData-RejectTicket-Client": "Trial decryption does not work with the NULL cipher."
}
}
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 8dc04462..3a182ecf 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -680,7 +680,6 @@ ResendHelloRetryRequest:
}
c.in.freeBlock(c.input)
c.input = nil
-
}
} else {
c.skipEarlyData = true
@@ -880,6 +879,19 @@ ResendHelloRetryRequest:
}
c.flushHandshake()
+ if encryptedExtensions.extensions.hasEarlyData && !c.skipEarlyData {
+ for _, expectedMsg := range config.Bugs.ExpectLateEarlyData {
+ if err := c.readRecord(recordTypeApplicationData); err != nil {
+ return err
+ }
+ if !bytes.Equal(c.input.data[c.input.off:], expectedMsg) {
+ return errors.New("ExpectLateEarlyData: did not get expected message")
+ }
+ c.in.freeBlock(c.input)
+ c.input = nil
+ }
+ }
+
// The various secrets do not incorporate the client's final leg, so
// derive them now before updating the handshake context.
hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 10e728eb..d9218f26 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -412,11 +412,14 @@ type testCase struct {
// which will be compared against the expected value.
testTLSUnique bool
// sendEmptyRecords is the number of consecutive empty records to send
- // before and after the test message.
+ // before each test message.
sendEmptyRecords int
// sendWarningAlerts is the number of consecutive warning alerts to send
- // before and after the test message.
+ // before each test message.
sendWarningAlerts int
+ // sendBogusAlertType, if true, causes a bogus alert of invalid type to
+ // be sent before each test message.
+ sendBogusAlertType bool
// sendKeyUpdates is the number of consecutive key updates to send
// before and after the test message.
sendKeyUpdates int
@@ -428,6 +431,11 @@ type testCase struct {
// expectPeerCertificate, if not nil, is the certificate chain the peer
// is expected to send.
expectPeerCertificate *Certificate
+ // shimPrefix is the prefix that the shim will send to the server.
+ shimPrefix string
+ // resumeShimPrefix is the prefix that the shim will send to the server on a
+ // resumption.
+ resumeShimPrefix string
}
var testCases []testCase
@@ -685,20 +693,26 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, nu
tlsConn.SendHalfHelloRequest()
}
- shimPrefixPending := test.shimWritesFirst || test.readWithUnfinishedWrite
+ shimPrefix := test.shimPrefix
+ if isResume {
+ shimPrefix = test.resumeShimPrefix
+ }
+ if test.shimWritesFirst || test.readWithUnfinishedWrite {
+ shimPrefix = "hello"
+ }
if test.renegotiate > 0 {
// If readWithUnfinishedWrite is set, the shim prefix will be
// available later.
- if shimPrefixPending && !test.readWithUnfinishedWrite {
- var buf [5]byte
- _, err := io.ReadFull(tlsConn, buf[:])
+ if shimPrefix != "" && !test.readWithUnfinishedWrite {
+ var buf = make([]byte, len(shimPrefix))
+ _, err := io.ReadFull(tlsConn, buf)
if err != nil {
return err
}
- if string(buf[:]) != "hello" {
- return fmt.Errorf("bad initial message")
+ if string(buf) != shimPrefix {
+ return fmt.Errorf("bad initial message %v vs %v", string(buf), shimPrefix)
}
- shimPrefixPending = false
+ shimPrefix = ""
}
if test.renegotiateCiphers != nil {
@@ -750,6 +764,10 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, nu
tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
}
+ if test.sendBogusAlertType {
+ tlsConn.SendAlert(0x42, alertUnexpectedMessage)
+ }
+
testMessage := make([]byte, messageLen)
for i := range testMessage {
testMessage[i] = 0x42 ^ byte(j)
@@ -757,16 +775,16 @@ func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, nu
tlsConn.Write(testMessage)
// Consume the shim prefix if needed.
- if shimPrefixPending {
- var buf [5]byte
- _, err := io.ReadFull(tlsConn, buf[:])
+ if shimPrefix != "" {
+ var buf = make([]byte, len(shimPrefix))
+ _, err := io.ReadFull(tlsConn, buf)
if err != nil {
return err
}
- if string(buf[:]) != "hello" {
- return fmt.Errorf("bad initial message")
+ if string(buf) != shimPrefix {
+ return fmt.Errorf("bad initial message %v vs %v", string(buf), shimPrefix)
}
- shimPrefixPending = false
+ shimPrefix = ""
}
if test.shimShutsDown || test.expectMessageDropped {
@@ -1559,7 +1577,7 @@ func addBasicTests() {
},
},
shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
+ expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
},
{
name: "AppDataBeforeHandshake-Empty",
@@ -1569,7 +1587,7 @@ func addBasicTests() {
},
},
shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
+ expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
},
{
protocol: dtls,
@@ -1739,7 +1757,7 @@ func addBasicTests() {
},
shimWritesFirst: true,
shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
+ expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
},
{
name: "FalseStart-SkipServerSecondLeg-Implicit",
@@ -1760,7 +1778,7 @@ func addBasicTests() {
"-advertise-alpn", "\x03foo",
},
shouldFail: true,
- expectedError: ":UNEXPECTED_RECORD:",
+ expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
},
{
testType: serverTest,
@@ -2097,6 +2115,21 @@ func addBasicTests() {
expectedError: ":TOO_MANY_WARNING_ALERTS:",
},
{
+ name: "SendBogusAlertType",
+ sendBogusAlertType: true,
+ shouldFail: true,
+ expectedError: ":UNKNOWN_ALERT_TYPE:",
+ expectedLocalError: "remote error: illegal parameter",
+ },
+ {
+ protocol: dtls,
+ name: "SendBogusAlertType-DTLS",
+ sendBogusAlertType: true,
+ shouldFail: true,
+ expectedError: ":UNKNOWN_ALERT_TYPE:",
+ expectedLocalError: "remote error: illegal parameter",
+ },
+ {
name: "TooManyKeyUpdates",
config: Config{
MaxVersion: VersionTLS13,
@@ -3617,7 +3650,6 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
resumeSession: true,
})
- // TODO(svaldez): Send data on early data once implemented.
tests = append(tests, testCase{
testType: clientTest,
name: "TLS13-EarlyData-Client",
@@ -3626,15 +3658,110 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) {
MinVersion: VersionTLS13,
MaxEarlyDataSize: 16384,
},
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ ExpectEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
+ },
+ },
resumeSession: true,
flags: []string{
"-enable-early-data",
"-expect-early-data-info",
"-expect-accept-early-data",
+ "-on-resume-shim-writes-first",
},
})
tests = append(tests, testCase{
+ testType: clientTest,
+ name: "TLS13-EarlyData-TooMuchData-Client",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 2,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 2,
+ Bugs: ProtocolBugs{
+ ExpectEarlyData: [][]byte{{'h', 'e'}},
+ },
+ },
+ resumeShimPrefix: "llo",
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-early-data-info",
+ "-expect-accept-early-data",
+ "-on-resume-shim-writes-first",
+ },
+ })
+
+ // Unfinished writes can only be tested when operations are async. EarlyData
+ // can't be tested as part of an ImplicitHandshake in this case since
+ // otherwise the early data will be sent as normal data.
+ if config.async && !config.implicitHandshake {
+ tests = append(tests, testCase{
+ testType: clientTest,
+ name: "TLS13-EarlyData-UnfinishedWrite-Client",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ ExpectLateEarlyData: [][]byte{{'h', 'e', 'l', 'l', 'o'}},
+ },
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-early-data-info",
+ "-expect-accept-early-data",
+ "-on-resume-read-with-unfinished-write",
+ "-on-resume-shim-writes-first",
+ },
+ })
+
+ // Rejected unfinished writes are discarded (from the
+ // perspective of the calling application) on 0-RTT
+ // reject.
+ tests = append(tests, testCase{
+ testType: clientTest,
+ name: "TLS13-EarlyData-RejectUnfinishedWrite-Client",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MinVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Bugs: ProtocolBugs{
+ AlwaysRejectEarlyData: true,
+ },
+ },
+ resumeSession: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-early-data-info",
+ "-expect-reject-early-data",
+ "-on-resume-read-with-unfinished-write",
+ "-on-resume-shim-writes-first",
+ },
+ })
+ }
+
+ tests = append(tests, testCase{
testType: serverTest,
name: "TLS13-EarlyData-Server",
config: Config{
@@ -10264,7 +10391,7 @@ func addTLS13HandshakeTests() {
testCases = append(testCases, testCase{
testType: clientTest,
- name: "TLS13-DataLessEarlyData-Reject-Client",
+ name: "TLS13-EarlyData-Reject-Client",
config: Config{
MaxVersion: VersionTLS13,
MaxEarlyDataSize: 16384,
@@ -10281,12 +10408,42 @@ func addTLS13HandshakeTests() {
"-enable-early-data",
"-expect-early-data-info",
"-expect-reject-early-data",
+ "-on-resume-shim-writes-first",
},
})
testCases = append(testCases, testCase{
testType: clientTest,
- name: "TLS13-DataLessEarlyData-HRR-Client",
+ name: "TLS13-EarlyData-RejectTicket-Client",
+ config: Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Certificates: []Certificate{rsaCertificate},
+ },
+ resumeConfig: &Config{
+ MaxVersion: VersionTLS13,
+ MaxEarlyDataSize: 16384,
+ Certificates: []Certificate{ecdsaP256Certificate},
+ SessionTicketsDisabled: true,
+ },
+ resumeSession: true,
+ expectResumeRejected: true,
+ flags: []string{
+ "-enable-early-data",
+ "-expect-early-data-info",
+ "-expect-reject-early-data",
+ "-on-resume-shim-writes-first",
+ "-on-initial-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-on-resume-expect-peer-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+ "-on-retry-expect-peer-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+ // Session tickets are disabled, so the runner will not send a ticket.
+ "-on-retry-expect-no-session",
+ },
+ })
+
+ testCases = append(testCases, testCase{
+ testType: clientTest,
+ name: "TLS13-EarlyData-HRR-Client",
config: Config{
MaxVersion: VersionTLS13,
MaxEarlyDataSize: 16384,
@@ -10373,6 +10530,7 @@ func addTLS13HandshakeTests() {
flags: []string{
"-enable-early-data",
"-expect-early-data-info",
+ "-expect-reject-early-data",
},
shouldFail: true,
expectedError: ":UNEXPECTED_EXTENSION:",
@@ -10385,7 +10543,7 @@ func addTLS13HandshakeTests() {
// that changed it.
testCases = append(testCases, testCase{
testType: clientTest,
- name: "TLS13-DataLessEarlyData-ALPNMismatch-Client",
+ name: "TLS13-EarlyData-ALPNMismatch-Client",
config: Config{
MaxVersion: VersionTLS13,
MaxEarlyDataSize: 16384,
@@ -10407,7 +10565,8 @@ func addTLS13HandshakeTests() {
"-expect-early-data-info",
"-expect-reject-early-data",
"-on-initial-expect-alpn", "foo",
- "-on-resume-expect-alpn", "bar",
+ "-on-resume-expect-alpn", "foo",
+ "-on-retry-expect-alpn", "bar",
},
})
@@ -10415,7 +10574,7 @@ func addTLS13HandshakeTests() {
// ALPN was omitted from the first connection.
testCases = append(testCases, testCase{
testType: clientTest,
- name: "TLS13-DataLessEarlyData-ALPNOmitted1-Client",
+ name: "TLS13-EarlyData-ALPNOmitted1-Client",
config: Config{
MaxVersion: VersionTLS13,
MaxEarlyDataSize: 16384,
@@ -10432,7 +10591,9 @@ func addTLS13HandshakeTests() {
"-expect-early-data-info",
"-expect-reject-early-data",
"-on-initial-expect-alpn", "",
- "-on-resume-expect-alpn", "foo",
+ "-on-resume-expect-alpn", "",
+ "-on-retry-expect-alpn", "foo",
+ "-on-resume-shim-writes-first",
},
})
@@ -10440,7 +10601,7 @@ func addTLS13HandshakeTests() {
// ALPN was omitted from the second connection.
testCases = append(testCases, testCase{
testType: clientTest,
- name: "TLS13-DataLessEarlyData-ALPNOmitted2-Client",
+ name: "TLS13-EarlyData-ALPNOmitted2-Client",
config: Config{
MaxVersion: VersionTLS13,
MaxEarlyDataSize: 16384,
@@ -10457,14 +10618,16 @@ func addTLS13HandshakeTests() {
"-expect-early-data-info",
"-expect-reject-early-data",
"-on-initial-expect-alpn", "foo",
- "-on-resume-expect-alpn", "",
+ "-on-resume-expect-alpn", "foo",
+ "-on-retry-expect-alpn", "",
+ "-on-resume-shim-writes-first",
},
})
// Test that the client enforces ALPN match on 0-RTT accept.
testCases = append(testCases, testCase{
testType: clientTest,
- name: "TLS13-DataLessEarlyData-BadALPNMismatch-Client",
+ name: "TLS13-EarlyData-BadALPNMismatch-Client",
config: Config{
MaxVersion: VersionTLS13,
MaxEarlyDataSize: 16384,
@@ -10486,7 +10649,8 @@ func addTLS13HandshakeTests() {
"-enable-early-data",
"-expect-early-data-info",
"-on-initial-expect-alpn", "foo",
- "-on-resume-expect-alpn", "bar",
+ "-on-resume-expect-alpn", "foo",
+ "-on-retry-expect-alpn", "bar",
},
shouldFail: true,
expectedError: ":ALPN_MISMATCH_ON_EARLY_DATA:",
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index d7c32398..960240e1 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -142,6 +142,7 @@ const Flag<std::string> kStringFlags[] = {
{ "-host-name", &TestConfig::host_name },
{ "-advertise-alpn", &TestConfig::advertise_alpn },
{ "-expect-alpn", &TestConfig::expected_alpn },
+ { "-expect-late-alpn", &TestConfig::expected_late_alpn },
{ "-expect-advertised-alpn", &TestConfig::expected_advertised_alpn },
{ "-select-alpn", &TestConfig::select_alpn },
{ "-psk", &TestConfig::psk },
@@ -192,110 +193,123 @@ const Flag<std::vector<int>> kIntVectorFlags[] = {
{ "-verify-prefs", &TestConfig::verify_prefs },
};
-const char kInit[] = "-on-initial";
-const char kResume[] = "-on-resume";
+bool ParseFlag(char *flag, int argc, char **argv, int *i,
+ bool skip, TestConfig *out_config) {
+ bool *bool_field = FindField(out_config, kBoolFlags, flag);
+ if (bool_field != NULL) {
+ if (!skip) {
+ *bool_field = true;
+ }
+ return true;
+ }
-} // namespace
+ std::string *string_field = FindField(out_config, kStringFlags, flag);
+ if (string_field != NULL) {
+ *i = *i + 1;
+ if (*i >= argc) {
+ fprintf(stderr, "Missing parameter\n");
+ return false;
+ }
+ if (!skip) {
+ string_field->assign(argv[*i]);
+ }
+ return true;
+ }
-bool ParseConfig(int argc, char **argv, bool is_resume,
- TestConfig *out_config) {
- for (int i = 0; i < argc; i++) {
- bool skip = false;
- char *flag = argv[i];
- const char *prefix = is_resume ? kResume : kInit;
- const char *opposite = is_resume ? kInit : kResume;
- if (strncmp(flag, prefix, strlen(prefix)) == 0) {
- flag = flag + strlen(prefix);
- for (int j = 0; j < argc; j++) {
- if (strcmp(argv[j], flag) == 0) {
- fprintf(stderr, "Can't use default and prefixed arguments: %s\n",
- flag);
- return false;
- }
- }
- } else if (strncmp(flag, opposite, strlen(opposite)) == 0) {
- flag = flag + strlen(opposite);
- skip = true;
+ std::string *base64_field = FindField(out_config, kBase64Flags, flag);
+ if (base64_field != NULL) {
+ *i = *i + 1;
+ if (*i >= argc) {
+ fprintf(stderr, "Missing parameter\n");
+ return false;
}
+ size_t len;
+ if (!EVP_DecodedLength(&len, strlen(argv[*i]))) {
+ fprintf(stderr, "Invalid base64: %s\n", argv[*i]);
+ return false;
+ }
+ std::unique_ptr<uint8_t[]> decoded(new uint8_t[len]);
+ if (!EVP_DecodeBase64(decoded.get(), &len, len,
+ reinterpret_cast<const uint8_t *>(argv[*i]),
+ strlen(argv[*i]))) {
+ fprintf(stderr, "Invalid base64: %s\n", argv[*i]);
+ return false;
+ }
+ if (!skip) {
+ base64_field->assign(reinterpret_cast<const char *>(decoded.get()),
+ len);
+ }
+ return true;
+ }
- bool *bool_field = FindField(out_config, kBoolFlags, flag);
- if (bool_field != NULL) {
- if (!skip) {
- *bool_field = true;
- }
- continue;
+ int *int_field = FindField(out_config, kIntFlags, flag);
+ if (int_field) {
+ *i = *i + 1;
+ if (*i >= argc) {
+ fprintf(stderr, "Missing parameter\n");
+ return false;
+ }
+ if (!skip) {
+ *int_field = atoi(argv[*i]);
}
+ return true;
+ }
- std::string *string_field = FindField(out_config, kStringFlags, flag);
- if (string_field != NULL) {
- i++;
- if (i >= argc) {
- fprintf(stderr, "Missing parameter\n");
- return false;
- }
- if (!skip) {
- string_field->assign(argv[i]);
- }
- continue;
+ std::vector<int> *int_vector_field =
+ FindField(out_config, kIntVectorFlags, flag);
+ if (int_vector_field) {
+ *i = *i + 1;
+ if (*i >= argc) {
+ fprintf(stderr, "Missing parameter\n");
+ return false;
}
- std::string *base64_field = FindField(out_config, kBase64Flags, flag);
- if (base64_field != NULL) {
- i++;
- if (i >= argc) {
- fprintf(stderr, "Missing parameter\n");
- return false;
- }
- size_t len;
- if (!EVP_DecodedLength(&len, strlen(argv[i]))) {
- fprintf(stderr, "Invalid base64: %s\n", argv[i]);
- return false;
- }
- std::unique_ptr<uint8_t[]> decoded(new uint8_t[len]);
- if (!EVP_DecodeBase64(decoded.get(), &len, len,
- reinterpret_cast<const uint8_t *>(argv[i]),
- strlen(argv[i]))) {
- fprintf(stderr, "Invalid base64: %s\n", argv[i]);
- return false;
- }
- if (!skip) {
- base64_field->assign(reinterpret_cast<const char *>(decoded.get()),
- len);
- }
- continue;
+ // Each instance of the flag adds to the list.
+ if (!skip) {
+ int_vector_field->push_back(atoi(argv[*i]));
}
+ return true;
+ }
+
+ fprintf(stderr, "Unknown argument: %s\n", flag);
+ return false;
+}
+
+const char kInit[] = "-on-initial";
+const char kResume[] = "-on-resume";
+const char kRetry[] = "-on-retry";
- int *int_field = FindField(out_config, kIntFlags, flag);
- if (int_field) {
- i++;
- if (i >= argc) {
- fprintf(stderr, "Missing parameter\n");
+} // namespace
+
+bool ParseConfig(int argc, char **argv,
+ TestConfig *out_initial,
+ TestConfig *out_resume,
+ TestConfig *out_retry) {
+ for (int i = 0; i < argc; i++) {
+ bool skip = false;
+ char *flag = argv[i];
+ if (strncmp(flag, kInit, strlen(kInit)) == 0) {
+ if (!ParseFlag(flag + strlen(kInit), argc, argv, &i, skip, out_initial)) {
return false;
}
- if (!skip) {
- *int_field = atoi(argv[i]);
+ } else if (strncmp(flag, kResume, strlen(kResume)) == 0) {
+ if (!ParseFlag(flag + strlen(kResume), argc, argv, &i, skip,
+ out_resume)) {
+ return false;
}
- continue;
- }
-
- std::vector<int> *int_vector_field =
- FindField(out_config, kIntVectorFlags, flag);
- if (int_vector_field) {
- i++;
- if (i >= argc) {
- fprintf(stderr, "Missing parameter\n");
+ } else if (strncmp(flag, kRetry, strlen(kRetry)) == 0) {
+ if (!ParseFlag(flag + strlen(kRetry), argc, argv, &i, skip, out_retry)) {
return false;
}
-
- // Each instance of the flag adds to the list.
- if (!skip) {
- int_vector_field->push_back(atoi(argv[i]));
+ } else {
+ int i_init = i;
+ int i_resume = i;
+ if (!ParseFlag(flag, argc, argv, &i_init, skip, out_initial) ||
+ !ParseFlag(flag, argc, argv, &i_resume, skip, out_resume) ||
+ !ParseFlag(flag, argc, argv, &i, skip, out_retry)) {
+ return false;
}
- continue;
}
-
- fprintf(stderr, "Unknown argument: %s\n", flag);
- return false;
}
return true;
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index c63a1cb3..8bc8892e 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -53,6 +53,7 @@ struct TestConfig {
std::string host_name;
std::string advertise_alpn;
std::string expected_alpn;
+ std::string expected_late_alpn;
std::string expected_advertised_alpn;
std::string select_alpn;
bool decline_alpn = false;
@@ -141,7 +142,8 @@ struct TestConfig {
bool enable_ed25519 = false;
};
-bool ParseConfig(int argc, char **argv, bool is_resume, TestConfig *out_config);
+bool ParseConfig(int argc, char **argv, TestConfig *out_initial,
+ TestConfig *out_resume, TestConfig *out_retry);
#endif // HEADER_TEST_CONFIG
diff --git a/src/ssl/tls13_both.c b/src/ssl/tls13_both.c
index f44933ff..6fdfb269 100644
--- a/src/ssl/tls13_both.c
+++ b/src/ssl/tls13_both.c
@@ -94,6 +94,12 @@ int tls13_handshake(SSL_HANDSHAKE *hs, int *out_early_return) {
hs->wait = ssl_hs_ok;
return -1;
+ case ssl_hs_early_data_rejected:
+ ssl->rwstate = SSL_EARLY_DATA_REJECTED;
+ /* Cause |SSL_write| to start failing immediately. */
+ hs->can_early_write = 0;
+ return -1;
+
case ssl_hs_ok:
break;
}
@@ -378,9 +384,9 @@ int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) {
goto err;
}
- int al;
- if (!tls12_check_peer_sigalg(ssl, &al, signature_algorithm)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+ uint8_t alert = SSL_AD_DECODE_ERROR;
+ if (!tls12_check_peer_sigalg(ssl, &alert, signature_algorithm)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
goto err;
}
hs->new_session->peer_signature_algorithm = signature_algorithm;
@@ -527,8 +533,7 @@ err:
return 0;
}
-enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs,
- int is_first_run) {
+enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
enum ssl_private_key_result_t ret = ssl_private_key_failure;
uint8_t *msg = NULL;
@@ -558,20 +563,15 @@ enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs,
goto err;
}
- enum ssl_private_key_result_t sign_result;
- if (is_first_run) {
- if (!tls13_get_cert_verify_signature_input(
- hs, &msg, &msg_len,
- ssl->server ? ssl_cert_verify_server : ssl_cert_verify_client)) {
- ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
- goto err;
- }
- sign_result = ssl_private_key_sign(ssl, sig, &sig_len, max_sig_len,
- signature_algorithm, msg, msg_len);
- } else {
- sign_result = ssl_private_key_complete(ssl, sig, &sig_len, max_sig_len);
+ if (!tls13_get_cert_verify_signature_input(
+ hs, &msg, &msg_len,
+ ssl->server ? ssl_cert_verify_server : ssl_cert_verify_client)) {
+ ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+ goto err;
}
+ enum ssl_private_key_result_t sign_result = ssl_private_key_sign(
+ hs, sig, &sig_len, max_sig_len, signature_algorithm, msg, msg_len);
if (sign_result != ssl_private_key_success) {
ret = sign_result;
goto err;
diff --git a/src/ssl/tls13_client.c b/src/ssl/tls13_client.c
index 6de51e5b..92ea4f87 100644
--- a/src/ssl/tls13_client.c
+++ b/src/ssl/tls13_client.c
@@ -33,6 +33,7 @@ enum client_hs_state_t {
state_send_second_client_hello,
state_process_server_hello,
state_process_encrypted_extensions,
+ state_continue_second_server_flight,
state_process_certificate_request,
state_process_server_certificate,
state_process_server_certificate_verify,
@@ -40,7 +41,6 @@ enum client_hs_state_t {
state_send_end_of_early_data,
state_send_client_certificate,
state_send_client_certificate_verify,
- state_complete_client_certificate_verify,
state_complete_second_flight,
state_done,
};
@@ -141,13 +141,15 @@ static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) {
hs->received_hello_retry_request = 1;
hs->tls13_state = state_send_second_client_hello;
+ /* 0-RTT is rejected if we receive a HelloRetryRequest. */
+ if (hs->in_early_data) {
+ return ssl_hs_early_data_rejected;
+ }
return ssl_hs_ok;
}
static enum ssl_hs_wait_t do_send_second_client_hello(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- /* TODO(svaldez): Ensure that we set can_early_write to false since 0-RTT is
- * rejected if we receive a HelloRetryRequest. */
if (!ssl->method->set_write_state(ssl, NULL) ||
!ssl_write_client_hello(hs)) {
return ssl_hs_error;
@@ -259,6 +261,7 @@ static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
return ssl_hs_error;
}
+ ssl_set_session(ssl, NULL);
/* Resumption incorporates fresh key material, so refresh the timeout. */
ssl_session_renew_timeout(ssl, hs->new_session,
@@ -358,9 +361,9 @@ static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL_HANDSHAKE *hs) {
}
if (ssl->early_data_accepted) {
- if (ssl->session->cipher != hs->new_session->cipher ||
- ssl->session->early_alpn_len != ssl->s3->alpn_selected_len ||
- OPENSSL_memcmp(ssl->session->early_alpn, ssl->s3->alpn_selected,
+ if (hs->early_session->cipher != hs->new_session->cipher ||
+ hs->early_session->early_alpn_len != ssl->s3->alpn_selected_len ||
+ OPENSSL_memcmp(hs->early_session->early_alpn, ssl->s3->alpn_selected,
ssl->s3->alpn_selected_len) != 0) {
OPENSSL_PUT_ERROR(SSL, SSL_R_ALPN_MISMATCH_ON_EARLY_DATA);
return ssl_hs_error;
@@ -371,15 +374,18 @@ static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL_HANDSHAKE *hs) {
}
}
- /* Release offered session now that it is no longer needed. */
- if (ssl->s3->session_reused) {
- ssl_set_session(ssl, NULL);
- }
-
if (!ssl_hash_current_message(hs)) {
return ssl_hs_error;
}
+ hs->tls13_state = state_continue_second_server_flight;
+ if (hs->in_early_data && !ssl->early_data_accepted) {
+ return ssl_hs_early_data_rejected;
+ }
+ return ssl_hs_ok;
+}
+
+static enum ssl_hs_wait_t do_continue_second_server_flight(SSL_HANDSHAKE *hs) {
hs->tls13_state = state_process_certificate_request;
return ssl_hs_read_message;
}
@@ -485,11 +491,13 @@ static enum ssl_hs_wait_t do_process_server_finished(SSL_HANDSHAKE *hs) {
static enum ssl_hs_wait_t do_send_end_of_early_data(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
- /* TODO(svaldez): Stop sending early data. */
- if (ssl->early_data_accepted &&
- !ssl->method->add_alert(ssl, SSL3_AL_WARNING,
- TLS1_AD_END_OF_EARLY_DATA)) {
- return ssl_hs_error;
+
+ if (ssl->early_data_accepted) {
+ hs->can_early_write = 0;
+ if (!ssl->method->add_alert(ssl, SSL3_AL_WARNING,
+ TLS1_AD_END_OF_EARLY_DATA)) {
+ return ssl_hs_error;
+ }
}
if (hs->early_data_offered &&
@@ -534,8 +542,7 @@ static enum ssl_hs_wait_t do_send_client_certificate(SSL_HANDSHAKE *hs) {
return ssl_hs_ok;
}
-static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs,
- int is_first_run) {
+static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs) {
SSL *const ssl = hs->ssl;
/* Don't send CertificateVerify if there is no certificate. */
if (!ssl_has_certificate(ssl)) {
@@ -543,13 +550,13 @@ static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs,
return ssl_hs_ok;
}
- switch (tls13_add_certificate_verify(hs, is_first_run)) {
+ switch (tls13_add_certificate_verify(hs)) {
case ssl_private_key_success:
hs->tls13_state = state_complete_second_flight;
return ssl_hs_ok;
case ssl_private_key_retry:
- hs->tls13_state = state_complete_client_certificate_verify;
+ hs->tls13_state = state_send_client_certificate_verify;
return ssl_hs_private_key_operation;
case ssl_private_key_failure:
@@ -618,6 +625,9 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) {
case state_process_encrypted_extensions:
ret = do_process_encrypted_extensions(hs);
break;
+ case state_continue_second_server_flight:
+ ret = do_continue_second_server_flight(hs);
+ break;
case state_process_certificate_request:
ret = do_process_certificate_request(hs);
break;
@@ -637,10 +647,7 @@ enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) {
ret = do_send_client_certificate(hs);
break;
case state_send_client_certificate_verify:
- ret = do_send_client_certificate_verify(hs, 1 /* first run */);
- break;
- case state_complete_client_certificate_verify:
- ret = do_send_client_certificate_verify(hs, 0 /* complete */);
+ ret = do_send_client_certificate_verify(hs);
break;
case state_complete_second_flight:
ret = do_complete_second_flight(hs);
diff --git a/src/ssl/tls13_server.c b/src/ssl/tls13_server.c
index 9e8513ce..0a5e1a2b 100644
--- a/src/ssl/tls13_server.c
+++ b/src/ssl/tls13_server.c
@@ -36,7 +36,6 @@ enum server_hs_state_t {
state_process_second_client_hello,
state_send_server_hello,
state_send_server_certificate_verify,
- state_complete_server_certificate_verify,
state_send_server_finished,
state_read_second_client_flight,
state_process_end_of_early_data,
@@ -583,15 +582,14 @@ err:
return ssl_hs_error;
}
-static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs,
- int is_first_run) {
- switch (tls13_add_certificate_verify(hs, is_first_run)) {
+static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs) {
+ switch (tls13_add_certificate_verify(hs)) {
case ssl_private_key_success:
hs->tls13_state = state_send_server_finished;
return ssl_hs_ok;
case ssl_private_key_retry:
- hs->tls13_state = state_complete_server_certificate_verify;
+ hs->tls13_state = state_send_server_certificate_verify;
return ssl_hs_private_key_operation;
case ssl_private_key_failure:
@@ -657,6 +655,7 @@ static enum ssl_hs_wait_t do_read_second_client_flight(SSL_HANDSHAKE *hs) {
}
hs->can_early_write = 1;
hs->can_early_read = 1;
+ hs->in_early_data = 1;
hs->tls13_state = state_process_end_of_early_data;
return ssl_hs_read_end_of_early_data;
}
@@ -801,10 +800,7 @@ enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) {
ret = do_send_server_hello(hs);
break;
case state_send_server_certificate_verify:
- ret = do_send_server_certificate_verify(hs, 1 /* first run */);
- break;
- case state_complete_server_certificate_verify:
- ret = do_send_server_certificate_verify(hs, 0 /* complete */);
+ ret = do_send_server_certificate_verify(hs);
break;
case state_send_server_finished:
ret = do_send_server_finished(hs);
diff --git a/src/ssl/tls_record.c b/src/ssl/tls_record.c
index e67e0b46..a5bbe933 100644
--- a/src/ssl/tls_record.c
+++ b/src/ssl/tls_record.c
@@ -398,14 +398,12 @@ static int do_seal_record(SSL *ssl, uint8_t *out, size_t *out_len,
out[0] = type;
out[1] = wire_version >> 8;
out[2] = wire_version & 0xff;
- out += 3;
- max_out -= 3;
/* Write the ciphertext, leaving two bytes for the length. */
size_t ciphertext_len;
- if (!SSL_AEAD_CTX_seal(ssl->s3->aead_write_ctx, out + 2, &ciphertext_len,
- max_out - 2, type, wire_version,
- ssl->s3->write_sequence, in, in_len) ||
+ if (!SSL_AEAD_CTX_seal(ssl->s3->aead_write_ctx, out + SSL3_RT_HEADER_LENGTH,
+ &ciphertext_len, max_out - SSL3_RT_HEADER_LENGTH, type,
+ wire_version, ssl->s3->write_sequence, in, in_len) ||
!ssl_record_sequence_update(ssl->s3->write_sequence, 8)) {
return 0;
}
@@ -415,8 +413,8 @@ static int do_seal_record(SSL *ssl, uint8_t *out, size_t *out_len,
OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
return 0;
}
- out[0] = ciphertext_len >> 8;
- out[1] = ciphertext_len & 0xff;
+ out[3] = ciphertext_len >> 8;
+ out[4] = ciphertext_len & 0xff;
*out_len = SSL3_RT_HEADER_LENGTH + ciphertext_len;
diff --git a/src/tool/ciphers.cc b/src/tool/ciphers.cc
index 6370b783..3a7e23d9 100644
--- a/src/tool/ciphers.cc
+++ b/src/tool/ciphers.cc
@@ -52,7 +52,7 @@ bool Ciphers(const std::vector<std::string> &args) {
printf(" ");
}
- printf("%s\n", SSL_CIPHER_get_name(cipher));
+ printf("%s\n", SSL_CIPHER_standard_name(cipher));
if (!in_group && last_in_group) {
printf("]\n");
diff --git a/src/tool/client.cc b/src/tool/client.cc
index 005afa85..c4a071de 100644
--- a/src/tool/client.cc
+++ b/src/tool/client.cc
@@ -121,7 +121,7 @@ static const struct argument kArguments[] = {
"verification is required.",
},
{
- "-early-data", kBooleanArgument, "Allow early data",
+ "-early-data", kOptionalArgument, "Allow early data",
},
{
"-ed25519", kBooleanArgument, "Advertise Ed25519 support",
@@ -264,6 +264,20 @@ static bool DoConnection(SSL_CTX *ctx,
return false;
}
+ if (args_map.count("-early-data") != 0 && SSL_in_early_data(ssl.get())) {
+ int ed_size = args_map["-early-data"].size();
+ int ssl_ret = SSL_write(ssl.get(), args_map["-early-data"].data(), ed_size);
+ if (ssl_ret <= 0) {
+ int ssl_err = SSL_get_error(ssl.get(), ssl_ret);
+ fprintf(stderr, "Error while writing: %d\n", ssl_err);
+ ERR_print_errors_cb(PrintErrorCallback, stderr);
+ return false;
+ } else if (ssl_ret != ed_size) {
+ fprintf(stderr, "Short write from SSL_write.\n");
+ return false;
+ }
+ }
+
fprintf(stderr, "Connected.\n");
PrintConnectionInfo(ssl.get());
diff --git a/src/tool/transport_common.cc b/src/tool/transport_common.cc
index b7ad5ffa..cf1d5f8b 100644
--- a/src/tool/transport_common.cc
+++ b/src/tool/transport_common.cc
@@ -251,7 +251,7 @@ void PrintConnectionInfo(const SSL *ssl) {
fprintf(stderr, " Version: %s\n", SSL_get_version(ssl));
fprintf(stderr, " Resumed session: %s\n",
SSL_session_reused(ssl) ? "yes" : "no");
- fprintf(stderr, " Cipher: %s\n", SSL_CIPHER_get_name(cipher));
+ fprintf(stderr, " Cipher: %s\n", SSL_CIPHER_standard_name(cipher));
uint16_t curve = SSL_get_curve_id(ssl);
if (curve != 0) {
fprintf(stderr, " ECDHE curve: %s\n", SSL_get_curve_name(curve));
diff --git a/src/util/bot/DEPS b/src/util/bot/DEPS
index 3047f145..0e1b7dc7 100644
--- a/src/util/bot/DEPS
+++ b/src/util/bot/DEPS
@@ -24,7 +24,7 @@ deps = {
deps_os = {
'android': {
'boringssl/util/bot/android_tools':
- Var('chromium_git') + '/android_tools.git' + '@' + 'cb6bc21107001e2f2eeee2707b482b2b755baf51',
+ Var('chromium_git') + '/android_tools.git' + '@' + '023e2f65409a2b7886b8d644d6a88542ead6cd0a',
},
'unix': {
'boringssl/util/bot/libFuzzer':
diff --git a/src/util/bot/go/bootstrap.py b/src/util/bot/go/bootstrap.py
index 3b82ab2e..407d3067 100755
--- a/src/util/bot/go/bootstrap.py
+++ b/src/util/bot/go/bootstrap.py
@@ -45,7 +45,7 @@ WORKSPACE = os.path.join(ROOT, 'go')
EXE_SFX = '.exe' if sys.platform == 'win32' else ''
# Pinned version of Go toolset to download.
-TOOLSET_VERSION = 'go1.8.1'
+TOOLSET_VERSION = 'go1.8.3'
# Platform dependent portion of a download URL. See http://golang.org/dl/.
TOOLSET_VARIANTS = {
diff --git a/src/util/bot/update_clang.py b/src/util/bot/update_clang.py
index d23abfcc..3fd59a30 100644
--- a/src/util/bot/update_clang.py
+++ b/src/util/bot/update_clang.py
@@ -22,7 +22,7 @@ import urllib
# CLANG_REVISION and CLANG_SUB_REVISION determine the build of clang
# to use. These should be synced with tools/clang/scripts/update.py in
# Chromium.
-CLANG_REVISION = "300839"
+CLANG_REVISION = "305281"
CLANG_SUB_REVISION = "1"
PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION)
diff --git a/src/util/fipstools/delocate.go b/src/util/fipstools/delocate.go
index a4799290..07a260b2 100644
--- a/src/util/fipstools/delocate.go
+++ b/src/util/fipstools/delocate.go
@@ -339,7 +339,7 @@ func instructionArgs(node *node32) (argNodes []*node32) {
/* ppc64le
-[PABI]: “64-bit ELF v2 ABI Specification. Power Architechture.” March 21st,
+[PABI]: “64-Bit ELF V2 ABI Specification. Power Architecture.” March 21st,
2017
(Also useful is “Power ISA Version 2.07 B”. Note that version three of that
@@ -639,6 +639,14 @@ Args:
changed = true
d.redirectors[symbol] = redirectorName(symbol)
symbol = redirectorName(symbol)
+ // TODO(davidben): This should sanity-check the next
+ // instruction is a nop and ideally remove it.
+ wrappers = append(wrappers, func(k func()) {
+ k()
+ // Like the linker's PLT stubs, redirector functions
+ // expect callers to restore r2.
+ d.output.WriteString("\tld 2, 24(1)\n")
+ })
}
}
@@ -715,12 +723,12 @@ Args:
// Avoid it by spilling and using r3 instead.
baseReg = "3"
wrappers = append(wrappers, func(k func()) {
- d.output.WriteString("\taddi 1, 1, -288\n") // Clear the red zone.
+ d.output.WriteString("\taddi 1, 1, -288\n") // Clear the red zone.
d.output.WriteString("\tstd " + baseReg + ", -8(1)\n")
d.output.WriteString("\tmr " + baseReg + ", " + destReg + "\n")
k()
d.output.WriteString("\tld " + baseReg + ", -8(1)\n")
- d.output.WriteString("\taddi 1, 1, 288\n") // Clear the red zone.
+ d.output.WriteString("\taddi 1, 1, 288\n") // Clear the red zone.
})
}
@@ -1190,19 +1198,24 @@ func transform(w stringWriter, inputs []inputFile) error {
for _, name := range redirectorNames {
redirector := d.redirectors[name]
- w.WriteString(".type " + redirector + ", @function\n")
- w.WriteString(redirector + ":\n")
if d.processor == ppc64le {
- w.WriteString("\tmflr 0\n")
- w.WriteString("\tstd 0,16(1)\n")
- w.WriteString("\tstdu 1,-32(1)\n")
- w.WriteString("\tbl\t" + name + "\n")
- w.WriteString("\tnop\n")
- w.WriteString("\taddi 1,1,32\n")
- w.WriteString("\tld 0,16(1)\n")
- w.WriteString("\tmtlr 0\n")
- w.WriteString("\tblr\n")
+ w.WriteString(".section \".toc\", \"aw\"\n")
+ w.WriteString(".Lredirector_toc_" + name + ":\n")
+ w.WriteString(".quad " + name + "\n")
+ w.WriteString(".text\n")
+ w.WriteString(".type " + redirector + ", @function\n")
+ w.WriteString(redirector + ":\n")
+ // |name| will clobber r2, so save it. This is matched by a restore in
+ // redirector calls.
+ w.WriteString("\tstd 2, 24(1)\n")
+ // Load and call |name|'s global entry point.
+ w.WriteString("\taddis 12, 2, .Lredirector_toc_" + name + "@toc@ha\n")
+ w.WriteString("\tld 12, .Lredirector_toc_" + name + "@toc@l(12)\n")
+ w.WriteString("\tmtctr 12\n")
+ w.WriteString("\tbctr\n")
} else {
+ w.WriteString(".type " + redirector + ", @function\n")
+ w.WriteString(redirector + ":\n")
w.WriteString("\tjmp\t" + name + "\n")
}
}
diff --git a/src/util/fipstools/testdata/ppc64le-Sample/out.s b/src/util/fipstools/testdata/ppc64le-Sample/out.s
index 929d80fd..5823d623 100644
--- a/src/util/fipstools/testdata/ppc64le-Sample/out.s
+++ b/src/util/fipstools/testdata/ppc64le-Sample/out.s
@@ -134,6 +134,7 @@ function:
addi 1, 1, 288
# WAS bl fprintf
bl bcm_redirector_fprintf
+ ld 2, 24(1)
nop
# WAS addis 10,2,.LC0@toc@ha
# WAS ld 9,.LC0@toc@l(10)
@@ -180,6 +181,7 @@ function:
ld 5, 0(5)
# WAS bl fprintf
bl bcm_redirector_fprintf
+ ld 2, 24(1)
nop
# WAS addis 10,2,.LC0@toc@ha
# WAS ld 9,.LC0@toc@l(10)
@@ -225,6 +227,7 @@ function:
addi 1, 1, 288
# WAS bl fprintf
bl bcm_redirector_fprintf
+ ld 2, 24(1)
nop
# WAS addis 10,2,.LC0@toc@ha
# WAS ld 9,.LC0@toc@l(10)
@@ -271,6 +274,7 @@ function:
ld 5, 0(5)
# WAS bl fprintf
bl bcm_redirector_fprintf
+ ld 2, 24(1)
nop
# WAS addis 10,2,.LC0@toc@ha
# WAS ld 9,.LC0@toc@l(10)
@@ -317,6 +321,7 @@ function:
ld 5, 0(5)
# WAS bl fprintf
bl bcm_redirector_fprintf
+ ld 2, 24(1)
nop
# WAS addis 10,2,.LC0@toc@ha
# WAS ld 9,.LC0@toc@l(10)
@@ -363,6 +368,7 @@ function:
ld 5, 0(5)
# WAS bl fprintf
bl bcm_redirector_fprintf
+ ld 2, 24(1)
nop
# WAS bl exported_function
bl .Lexported_function_local_entry
@@ -410,17 +416,17 @@ exported_function:
.section .note.GNU-stack,"",@progbits
.text
BORINGSSL_bcm_text_end:
+.section ".toc", "aw"
+.Lredirector_toc_fprintf:
+.quad fprintf
+.text
.type bcm_redirector_fprintf, @function
bcm_redirector_fprintf:
- mflr 0
- std 0,16(1)
- stdu 1,-32(1)
- bl fprintf
- nop
- addi 1,1,32
- ld 0,16(1)
- mtlr 0
- blr
+ std 2, 24(1)
+ addis 12, 2, .Lredirector_toc_fprintf@toc@ha
+ ld 12, .Lredirector_toc_fprintf@toc@l(12)
+ mtctr 12
+ bctr
.type bss_bss_get, @function
bss_bss_get:
addis 3, 2, bss@toc@ha
diff --git a/src/util/fipstools/testdata/ppc64le-Sample2/out.s b/src/util/fipstools/testdata/ppc64le-Sample2/out.s
index 29291dc8..3e9c3cb9 100644
--- a/src/util/fipstools/testdata/ppc64le-Sample2/out.s
+++ b/src/util/fipstools/testdata/ppc64le-Sample2/out.s
@@ -206,6 +206,7 @@ exported_function:
li 4,1
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
ld 3,0(31)
mr 5,22
@@ -213,6 +214,7 @@ exported_function:
li 4,1
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
ld 3,0(31)
mr 5,23
@@ -220,6 +222,7 @@ exported_function:
li 4,1
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
ld 3,0(31)
mr 5,25
@@ -227,6 +230,7 @@ exported_function:
li 4,1
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
ld 3,0(31)
mr 5,26
@@ -234,6 +238,7 @@ exported_function:
li 4,1
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
ld 3,0(31)
li 4,1
@@ -241,6 +246,7 @@ exported_function:
mr 6,30
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
b .L2
.long 0
@@ -316,6 +322,7 @@ function:
ld 3,0(31)
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
# WAS addis 6,2,.LC12@toc@ha # gpr load fusion, type long
# WAS ld 6,.LC12@toc@l(6)
@@ -348,6 +355,7 @@ function:
addi 1, 1, 288
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
ld 3,0(31)
# WAS addis 5,2,.LC4@toc@ha
@@ -379,6 +387,7 @@ function:
li 4,1
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
# WAS addis 6,2,.LC13@toc@ha # gpr load fusion, type long
# WAS ld 6,.LC13@toc@l(6)
@@ -411,6 +420,7 @@ function:
addi 1, 1, 288
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
ld 3,0(31)
# WAS addis 5,2,.LC7@toc@ha
@@ -430,6 +440,7 @@ function:
li 4,1
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
ld 3,0(31)
addis 6,30,0x5
@@ -450,6 +461,7 @@ function:
addi 6,6,-29404
# WAS bl __fprintf_chk
bl bcm_redirector___fprintf_chk
+ ld 2, 24(1)
nop
# WAS bl exported_function
bl .Lexported_function_local_entry
@@ -523,17 +535,17 @@ bss:
.section .note.GNU-stack,"",@progbits
.text
BORINGSSL_bcm_text_end:
+.section ".toc", "aw"
+.Lredirector_toc___fprintf_chk:
+.quad __fprintf_chk
+.text
.type bcm_redirector___fprintf_chk, @function
bcm_redirector___fprintf_chk:
- mflr 0
- std 0,16(1)
- stdu 1,-32(1)
- bl __fprintf_chk
- nop
- addi 1,1,32
- ld 0,16(1)
- mtlr 0
- blr
+ std 2, 24(1)
+ addis 12, 2, .Lredirector_toc___fprintf_chk@toc@ha
+ ld 12, .Lredirector_toc___fprintf_chk@toc@l(12)
+ mtctr 12
+ bctr
.type bss_bss_get, @function
bss_bss_get:
addis 3, 2, .Lbss_local_target@toc@ha