proxygen
HandshakeTypesTest.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-present, Facebook, Inc.
3  * All rights reserved.
4  *
5  * This source code is licensed under the BSD-style license found in the
6  * LICENSE file in the root directory of this source tree.
7  */
8 
9 #include <gmock/gmock.h>
10 #include <gtest/gtest.h>
11 
12 #include <fizz/record/Extensions.h>
13 #include <folly/String.h>
14 
15 using namespace folly;
16 using namespace folly::io;
17 
18 using testing::_;
19 using namespace testing;
20 
21 // Real client hello captured from
22 // firefox nightly
23 static const std::string chlo =
24  "0304383cd7adc8587"
25  "e3b608ef98f8b47e5f29dd6124a1f258549"
26  "34ad85157dd5a7a400001ac02bc02fcca9c"
27  "ca8c02cc030c00ac009c013c014002f0035"
28  "000a010001d000000014001200000f74726"
29  "9732e66696c6970706f2e696f00170000ff"
30  "01000100000a00080006001700180019000"
31  "b0002010000230000337400000010001700"
32  "1502683208737064792f332e31086874747"
33  "02f312e31000500050100000000ff020002"
34  "000d0033014b014900170041048d5e897c8"
35  "96b17e1679766c14c785dd2c328c3eecc7d"
36  "bfd2e2e817cd35c786aceea79bf1286ab8a"
37  "5c3c464c46f5ba06338b24ea96ce442a4d1"
38  "3356902dfcd1e90100010032c84b9fc5e4f"
39  "12bf1b10da62506105f26d6913eb6a6ca34"
40  "c454963b85d3bbbd9360994db2baa28c217"
41  "e98cb6c40ed5a51246867910b5586dab299"
42  "5cb2c7c6298ab6606906911c08913adabe2"
43  "5901b7907b915b5962ad9e4639475292b18"
44  "0b651929e53b7fb38e7150bae3360aa3a30"
45  "b5a22facff2dd8716ef3239887f1f781757"
46  "b5ef4c68e7ed31e5bfbcb0ebb5d86794322"
47  "c01bd5d456292e8c0276efb05296cd24c10"
48  "cd388cf51ee798cf7e18638c17e44874bc3"
49  "bd1f697424511051f686db6a84b604d1bb4"
50  "0f6041c0c0e28be2a98829c78c7baea2dd3"
51  "49f0219443007e88fb3406dc4d9756e1076"
52  "1ef0eef675b4c4625f5d0aab3d6c7f57747"
53  "f4008d5a5000d0018001604010501060102"
54  "010403050306030203050204020202";
55 
56 static const std::string ssl3chlo =
57  "03005880ff04e8d5e0af70a2fe55fd90a5380a184f78c213aa8a4142010cac742e3600004cc014c00a0039003800880087c00fc00500350084c013c00900330032009a009900450044c00ec004002f00960041c012c00800160013c00dc003000a0007c011c007c00cc0020005000400ff0100";
58 
59 // From https://martinthomson.github.io/tls13-vectors/
60 static const std::string chloPsk =
61  "03034e2d3805200a9433ebdb4f1bf85d0a773c65a7430aa904c13966e49ab96efe2500003e130113031302c02bc02fcca9cca8c00ac009c013c023c027c014009eccaa00330032006700390038006b00160013009c002f003c0035003d000a00050004010001950015003b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b0009000006736572766572ff01000100000a00140012001d00170018001901000101010201030104000b00020100002800260024001d0020621bb90eca697f96d7ddc2966218ae0e7961268d8def400f8d7805172501932f002a0000002b000706030403030302000d0020001e040305030603020308040805080604010501060102010402050206020202002d00020101002900bd009800924e535321db0251332a66d4efd3b0285509fd8a26b801211c72f5f9012b8a6f35005069950156fc02abe56744e7c7d2798675e8372cbba2a93e2436bcd3dbac7662e64e187379bec081051957c0da819d44fafb13d833752c7340a32df5e133e3717566ac66b4cc417a4d0afaa64493997dba0cd6e601bc11a4ce5506236c2c4094d1ea2329d1756ac32783ef158e91a92c44d0a8dc290021202deccf4db1a231fa7359797967c09aa4ea69c29ecd781b41cbae9b1d7e4c0ff9";
62 
63 static const std::string encodedShlo =
64  "03039f2bfbe752cb49bc82303dd32a80cf60483a38e44bfb695ebd0280bcc1c70c5b00130100002e00330024001d00208db235a330ee184b953a981ecfb23b05380768ed12050ec2f0ec62b74ef8f835002b00020304";
65 
66 static const std::string encodedEoed = "";
67 
69  "001c000a00140012001d0017001800190100010101020103010400000000";
70 
72  "000001b50001b0308201ac30820115a003020102020102300d06092a864886f70d01010b0500300e310c300a06035504031303727361301e170d3136303733303031323335395a170d3236303733303031323335395a300e310c300a0603550403130372736130819f300d06092a864886f70d010101050003818d0030818902818100b4bb498f8279303d980836399b36c6988c0c68de55e1bdb826d3901a2461eafd2de49a91d015abbc9a95137ace6c1af19eaa6af98c7ced43120998e187a80ee0ccb0524b1b018c3e0b63264d449a6d38e22a5fda430846748030530ef0461c8ca9d9efbfae8ea6d1d03e2bd193eff0ab9a8002c47428a6d35a8d88d79f7f1e3f0203010001a31a301830090603551d1304023000300b0603551d0f0404030205a0300d06092a864886f70d01010b05000381810085aad2a0e5b9276b908c65f73a7267170618a54c5f8a7b337d2df7a594365417f2eae8f8a58c8f8172f9319cf36b7fd6c55b80f21a03015156726096fd335e5e67f2dbf102702e608ccae6bec1fc63a42a99be5c3eb7107c3c54e9b9eb2bd5203b1c3b84e0a8b2f759409ba3eac9d91d402dcc0cc8f8961229ac9187b42b4de10000";
73 
75  "080400805db9706f9bd41ab01be55f75b136cb89dda63dc6e4510e40c7203cb87f4eba2b122644018640641bde97e03d4caa1d670371b8bf81374d5126f88df68b87ef6c706cf9c0ee04063d8e65cb403433fb006c800e307b79b3a51fbae6089c2f3988ddfe04a760902e0a2141046054bdf807cf48cd3ce83f58a149ba35b7ff6c2f2a";
76 
77 static const std::string nst =
78  "0002a300d0a8dc290000924e535321db0251332a66d4efd3b0285509fd8a26b801211c72f5f9012b8a6f35005069950156fc02abe56744e7c7d2798675e8372cbba2a93e2436bcd3dbac7662e64e187379bec081051957c0da819d44fafb13d833752c7340a32df5e133e3717566ac66b4cc417a4d0afaa64493997dba0cd6e601bc11a4ce5506236c2c4094d1ea2329d1756ac32783ef158e91a92c440008002e000400020000";
79 
80 static const std::string encodedKeyUpdate = "00";
81 
82 static const std::string encodedCertRequest = "00000a000d0006000406030807";
83 
84 static const std::string encodedCompressedCertificate = "000100face000009666f6f62617262617a";
85 
86 namespace fizz {
87 namespace test {
88 
90  protected:
91  template <class T>
92  T decodeHex(const std::string& hex) {
93  auto data = unhexlify(hex);
94  auto buf = IOBuf::copyBuffer(data.data(), data.size());
95  return decode<T>(std::move(buf));
96  }
97 
98  template <class T>
100  auto buf = encode(std::forward<T>(msg));
101  auto str = buf->moveToFbString().toStdString();
102  return hexlify(str);
103  }
104 };
105 
106 TEST_F(HandshakeTypesTest, ChloEncodeDecode) {
107  auto clientHello = decodeHex<ClientHello>(chlo);
108 
109  auto sigAlgs = getExtension<SignatureAlgorithms>(clientHello.extensions);
110  ASSERT_TRUE(sigAlgs);
111  const auto& schemes = sigAlgs->supported_signature_algorithms;
112  ASSERT_EQ(11, schemes.size());
113  ASSERT_FALSE(
114  schemes.end() ==
115  std::find(
116  schemes.begin(),
117  schemes.end(),
118  SignatureScheme::ecdsa_secp256r1_sha256));
119 
120  auto groups = getExtension<SupportedGroups>(clientHello.extensions);
121  const auto& groupNames = groups->named_group_list;
122  ASSERT_EQ(3, groupNames.size());
123  ASSERT_FALSE(
124  groupNames.end() ==
125  std::find(groupNames.begin(), groupNames.end(), NamedGroup::secp256r1));
126 
127  auto clientShares = getExtension<ClientKeyShare>(clientHello.extensions);
128  ASSERT_TRUE(clientShares);
129  ASSERT_EQ(2, clientShares->client_shares.size());
130 
131  ASSERT_FALSE(getExtension<ClientPresharedKey>(clientHello.extensions));
132  ASSERT_FALSE(getExtension<ClientEarlyData>(clientHello.extensions));
133  ASSERT_FALSE(getExtension<Cookie>(clientHello.extensions));
134 
135  auto reencoded = encodeHex(std::move(clientHello));
136  EXPECT_EQ(chlo, reencoded);
137 }
138 
139 TEST_F(HandshakeTypesTest, SSL3ChloDecode) {
140  auto clientHello = decodeHex<ClientHello>(ssl3chlo);
141  EXPECT_TRUE(clientHello.extensions.empty());
142 }
143 
144 TEST_F(HandshakeTypesTest, ChloDecidePsk) {
145  auto clientHello = decodeHex<ClientHello>(chloPsk);
146 
147  EXPECT_EQ(35, getBinderLength(clientHello));
148 }
149 
150 TEST_F(HandshakeTypesTest, ChloEncodeCopy) {
151  auto clientHello = decodeHex<ClientHello>(chlo);
152  EXPECT_EQ(encodeHex(clientHello), chlo);
153  EXPECT_EQ(encodeHex(clientHello), chlo);
154 }
155 
156 TEST_F(HandshakeTypesTest, NstEncodeDecode) {
157  auto ticket = decodeHex<NewSessionTicket>(nst);
158 
159  EXPECT_EQ(ticket.ticket_lifetime, 0x0002a300);
160  EXPECT_EQ(ticket.ticket_age_add, 0xd0a8dc29);
161  EXPECT_TRUE(ticket.ticket_nonce->empty());
162  EXPECT_EQ(ticket.ticket->computeChainDataLength(), 146);
163 
164  auto reencoded = encodeHex(std::move(ticket));
165  EXPECT_EQ(nst, reencoded);
166 }
167 
168 bool extensionsMatch(const Extension& expected, const Extension& actual) {
169  if (expected.extension_type != actual.extension_type) {
170  return false;
171  }
172  return folly::IOBufEqualTo()(
173  *expected.extension_data, *actual.extension_data);
174 }
175 
176 TEST_F(HandshakeTypesTest, EncodeAndDecodeSigAlgs) {
177  auto clientHello = decodeHex<ClientHello>(chlo);
178  auto sigAlgs = getExtension<SignatureAlgorithms>(clientHello.extensions);
179  ASSERT_TRUE(sigAlgs);
180  auto ext = encodeExtension(*sigAlgs);
181  auto original = findExtension(
182  clientHello.extensions, ExtensionType::signature_algorithms);
183  EXPECT_TRUE(extensionsMatch(*original, ext));
184 }
185 
186 TEST_F(HandshakeTypesTest, EncodeAndDecodeClientKeyShare) {
187  auto clientHello = decodeHex<ClientHello>(chlo);
188  auto share = getExtension<ClientKeyShare>(clientHello.extensions);
189  ASSERT_TRUE(share);
190  auto ext = encodeExtension(*share);
191  auto original =
192  findExtension(clientHello.extensions, ExtensionType::key_share);
193  EXPECT_TRUE(extensionsMatch(*original, ext));
194 }
195 
196 TEST_F(HandshakeTypesTest, EncodeAndDecodeServerHello) {
197  auto shlo = decodeHex<ServerHello>(encodedShlo);
198  EXPECT_EQ(shlo.legacy_version, ProtocolVersion::tls_1_2);
199  EXPECT_EQ(shlo.random.front(), 0x9f);
200  EXPECT_EQ(shlo.random.back(), 0x5b);
201  EXPECT_EQ(shlo.cipher_suite, CipherSuite::TLS_AES_128_GCM_SHA256);
202  EXPECT_EQ(shlo.extensions.size(), 2);
203  EXPECT_TRUE(getExtension<ServerKeyShare>(shlo.extensions).hasValue());
204  EXPECT_TRUE(
205  getExtension<ServerSupportedVersions>(shlo.extensions).hasValue());
206  auto reencoded = encodeHex(std::move(shlo));
207  EXPECT_EQ(reencoded, encodedShlo);
208 }
209 
210 TEST_F(HandshakeTypesTest, EncodeAndDecodeEndOfEarlyData) {
211  auto eoed = decodeHex<EndOfEarlyData>(encodedEoed);
212  auto reencoded = encodeHex(std::move(eoed));
213  EXPECT_EQ(reencoded, encodedEoed);
214 }
215 
216 TEST_F(HandshakeTypesTest, EncodeAndDecodeEncryptedExtensions) {
217  auto ee = decodeHex<EncryptedExtensions>(encodedEncryptedExtensions);
218  EXPECT_EQ(ee.extensions.size(), 2);
219  EXPECT_TRUE(getExtension<SupportedGroups>(ee.extensions).hasValue());
220  auto reencoded = encodeHex(std::move(ee));
222 }
223 
224 TEST_F(HandshakeTypesTest, EncodeAndDecodedCertificate) {
225  auto cert = decodeHex<CertificateMsg>(encodedCertificate);
226  EXPECT_EQ(cert.certificate_request_context->computeChainDataLength(), 0);
227  EXPECT_EQ(cert.certificate_list.size(), 1);
228  EXPECT_EQ(cert.certificate_list[0].cert_data->computeChainDataLength(), 432);
229  EXPECT_TRUE(cert.certificate_list[0].extensions.empty());
230  auto reencoded = encodeHex(std::move(cert));
231  EXPECT_EQ(reencoded, encodedCertificate);
232 }
233 
234 TEST_F(HandshakeTypesTest, EncodedAndDecodeCertificateVerify) {
235  auto verify = decodeHex<CertificateVerify>(encodedCertVerify);
236  EXPECT_EQ(verify.algorithm, SignatureScheme::rsa_pss_sha256);
237  EXPECT_EQ(verify.signature->computeChainDataLength(), 128);
238  auto reencoded = encodeHex(std::move(verify));
239  EXPECT_EQ(reencoded, encodedCertVerify);
240 }
241 
242 TEST_F(HandshakeTypesTest, EncodedAndDecodeKeyUpdated) {
243  auto keyUpdate = decodeHex<KeyUpdate>(encodedKeyUpdate);
244  EXPECT_EQ(keyUpdate.request_update, KeyUpdateRequest::update_not_requested);
245  auto reencoded = encodeHex(std::move(keyUpdate));
246  EXPECT_EQ(reencoded, encodedKeyUpdate);
247 }
248 
249 TEST_F(HandshakeTypesTest, EncodedAndDecodeCertificateRequest) {
250  auto cr = decodeHex<CertificateRequest>(encodedCertRequest);
251  EXPECT_TRUE(cr.certificate_request_context->empty());
252  EXPECT_EQ(cr.extensions.size(), 1);
253  EXPECT_TRUE(getExtension<SignatureAlgorithms>(cr.extensions).hasValue());
254  auto reencoded = encodeHex(std::move(cr));
255  EXPECT_EQ(reencoded, encodedCertRequest);
256 }
257 
258 TEST_F(HandshakeTypesTest, EncodeAndDecodeCompressedCertificate) {
259  auto cc = decodeHex<CompressedCertificate>(encodedCompressedCertificate);
260  EXPECT_EQ(cc.algorithm, CertificateCompressionAlgorithm::zlib);
261  EXPECT_EQ(cc.uncompressed_length, 0x00face);
262  EXPECT_EQ(
263  StringPiece(cc.compressed_certificate_message->coalesce()),
264  StringPiece("foobarbaz"));
265  auto reencoded = encodeHex(std::move(cc));
267 }
268 } // namespace test
269 } // namespace fizz
bool unhexlify(const InputString &input, OutputString &output)
Definition: String-inl.h:616
std::vector< Extension >::const_iterator findExtension(const std::vector< Extension > &extensions, ExtensionType type)
size_t getBinderLength(const ClientHello &chlo)
void verify(int extras)
unique_ptr< IOBuf > encode(vector< HPACKHeader > &headers, HPACKEncoder &encoder)
#define ASSERT_EQ(val1, val2)
Definition: gtest.h:1956
static const std::string chlo
static const std::string encodedKeyUpdate
PUSHMI_INLINE_VAR constexpr detail::share_fn< TN... > share
Definition: share.h:53
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
T decodeHex(const std::string &hex)
static const std::string encodedCompressedCertificate
Buf extension_data
Definition: Types.h:175
folly::std T
The non test part of the code is expected to have failures gtest_output_test_ cc
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
static const std::string encodedCertVerify
static const std::string ssl3chlo
static constexpr StringPiece ticket
constexpr bool empty() const
Definition: Range.h:443
static const std::string encodedCertificate
static const std::string encodedEncryptedExtensions
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
Definition: Actions.h:16
TEST_F(AsyncSSLSocketWriteTest, write_coalescing1)
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
static const std::string encodedCertRequest
static const std::string nst
const char * string
Definition: Conv.cpp:212
ExtensionType extension_type
Definition: Types.h:174
const internal::AnythingMatcher _
#define ASSERT_FALSE(condition)
Definition: gtest.h:1868
Extension encodeExtension(const TokenBindingParameters &params)
Definition: Types.cpp:113
Range< const char * > StringPiece
bool hexlify(const InputString &input, OutputString &output, bool append_output)
Definition: String-inl.h:596
static std::unique_ptr< IOBuf > copyBuffer(const void *buf, std::size_t size, std::size_t headroom=0, std::size_t minTailroom=0)
Definition: IOBuf.h:1587
static const std::string chloPsk
static const std::string encodedEoed
#define ASSERT_TRUE(condition)
Definition: gtest.h:1865
bool extensionsMatch(const Extension &expected, const Extension &actual)
static const std::string encodedShlo