diff options
author | Robert Sloan <varomodt@google.com> | 2017-06-27 17:45:33 +0000 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2017-06-27 17:45:33 +0000 |
commit | 9e1a4fab0a96032a30fcc78eb76a572be404e7ea (patch) | |
tree | 1d6a9aba1ee43af8b0c6f01252195eb23d62cb45 | |
parent | 845287ed18ff98235290e565f14109f6a971b0a9 (diff) | |
parent | 8ad267508423079ed3e4df6ffbde0557a0484f2c (diff) | |
download | boringssl-9e1a4fab0a96032a30fcc78eb76a572be404e7ea.tar.gz |
external/boringssl: Sync to 3120950b1e27635ee9b9d167052ce11ce9c96fd4. am: e56da3e0a1 am: b2737a239d
am: 8ad2675084
Change-Id: Ibd002c2a949a198067c712f9a591a70787b1aabf
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 @@ -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(¶meter), CBS_len(¶meter)) || !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 |