proxygen
EncryptedRecordTest.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 
13 
15 #include <folly/String.h>
16 
17 using namespace folly;
18 using namespace folly::io;
19 
20 using testing::_;
21 using namespace testing;
22 
23 namespace fizz {
24 namespace test {
25 
27  void SetUp() override {
28  auto readAead = std::make_unique<MockAead>();
29  readAead_ = readAead.get();
30  read_.setAead(folly::ByteRange(), std::move(readAead));
31  auto writeAead = std::make_unique<MockAead>();
32  writeAead_ = writeAead.get();
33  write_.setAead(folly::ByteRange(), std::move(writeAead));
34  }
35 
36  protected:
37  EncryptedReadRecordLayer read_{EncryptionLevel::AppTraffic};
38  EncryptedWriteRecordLayer write_{EncryptionLevel::AppTraffic};
41 
43 
45 
46  static Buf
47  getBuf(const std::string& hex, size_t headroom = 0, size_t tailroom = 0) {
48  auto data = unhexlify(hex);
49  return IOBuf::copyBuffer(data.data(), data.size(), headroom, tailroom);
50  }
51 
52  void addToQueue(const std::string& hex) {
53  queue_.append(getBuf(hex));
54  }
55 
56  static void expectSame(const Buf& buf, const std::string& hex) {
57  auto str = buf->moveToFbString().toStdString();
58  EXPECT_EQ(hexlify(str), hex);
59  }
60 };
61 
62 TEST_F(EncryptedRecordTest, TestReadEmpty) {
63  EXPECT_FALSE(read_.read(queue_).hasValue());
64 }
65 
66 TEST_F(EncryptedRecordTest, TestReadHandshake) {
67  addToQueue("17030100050123456789");
68  EXPECT_CALL(*readAead_, _decrypt(_, _, 0))
69  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
70  expectSame(buf, "0123456789");
71  return getBuf("abcdef16");
72  }));
73  auto msg = read_.read(queue_);
74  EXPECT_EQ(msg->type, ContentType::handshake);
75  expectSame(msg->fragment, "abcdef");
76  EXPECT_TRUE(queue_.empty());
77 }
78 
79 TEST_F(EncryptedRecordTest, TestReadAlert) {
80  addToQueue("17030100050123456789");
81  EXPECT_CALL(*readAead_, _decrypt(_, _, 0))
82  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
83  expectSame(buf, "0123456789");
84  return getBuf("020215");
85  }));
86  auto msg = read_.read(queue_);
87  EXPECT_EQ(msg->type, ContentType::alert);
88  expectSame(msg->fragment, "0202");
89  EXPECT_TRUE(queue_.empty());
90 }
91 
92 TEST_F(EncryptedRecordTest, TestReadAppData) {
93  addToQueue("17030100050123456789");
94  EXPECT_CALL(*readAead_, _decrypt(_, _, 0))
95  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
96  expectSame(buf, "0123456789");
97  return getBuf("1234abcd17");
98  }));
99  auto msg = read_.read(queue_);
100  EXPECT_EQ(msg->type, ContentType::application_data);
101  expectSame(msg->fragment, "1234abcd");
102  EXPECT_TRUE(queue_.empty());
103 }
104 
105 TEST_F(EncryptedRecordTest, TestReadUnknown) {
106  addToQueue("17030100050123456789");
107  EXPECT_CALL(*readAead_, _decrypt(_, _, 0))
108  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
109  expectSame(buf, "0123456789");
110  return getBuf("1234abcd20");
111  }));
112  EXPECT_ANY_THROW(read_.read(queue_));
113 }
114 
115 TEST_F(EncryptedRecordTest, TestWaitForData) {
116  addToQueue("1703010010012345");
117  EXPECT_FALSE(read_.read(queue_).hasValue());
118  EXPECT_EQ(queue_.chainLength(), 8);
119 }
120 
121 TEST_F(EncryptedRecordTest, TestWaitForHeader) {
122  addToQueue("16030102");
123  EXPECT_FALSE(read_.read(queue_).hasValue());
124  EXPECT_EQ(queue_.chainLength(), 4);
125 }
126 
128  addToQueue("1603014100");
129  EXPECT_FALSE(read_.read(queue_).hasValue());
130  EXPECT_EQ(queue_.chainLength(), 5);
131 }
132 
133 TEST_F(EncryptedRecordTest, TestOverSize) {
134  addToQueue("1603015000");
135  EXPECT_ANY_THROW(read_.read(queue_));
136 }
137 
138 TEST_F(EncryptedRecordTest, TestDataRemaining) {
139  addToQueue("17030100050123456789aa");
140  EXPECT_CALL(*readAead_, _decrypt(_, _, 0))
141  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
142  expectSame(buf, "0123456789");
143  return getBuf("abcdef16");
144  }));
145  read_.read(queue_);
146  EXPECT_EQ(queue_.chainLength(), 1);
147 }
148 
150  addToQueue("17030100050123456789");
151  EXPECT_CALL(*readAead_, _decrypt(_, _, 0))
152  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
153  expectSame(buf, "0123456789");
154  return getBuf("1234abcd17000000");
155  }));
156  auto msg = read_.read(queue_);
157  EXPECT_EQ(msg->type, ContentType::application_data);
158  expectSame(msg->fragment, "1234abcd");
159  EXPECT_TRUE(queue_.empty());
160 }
161 
162 TEST_F(EncryptedRecordTest, TestAllPaddingAppData) {
163  addToQueue("17030100050123456789");
164  EXPECT_CALL(*readAead_, _decrypt(_, _, 0))
165  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
166  expectSame(buf, "0123456789");
167  return getBuf("17000000");
168  }));
169  auto msg = read_.read(queue_);
170  EXPECT_EQ(msg->type, ContentType::application_data);
171  EXPECT_TRUE(msg->fragment->empty());
172  EXPECT_TRUE(queue_.empty());
173 }
174 
175 TEST_F(EncryptedRecordTest, TestAllPaddingHandshake) {
176  addToQueue("17030100050123456789");
177  EXPECT_CALL(*readAead_, _decrypt(_, _, 0))
178  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
179  expectSame(buf, "0123456789");
180  return getBuf("16000000");
181  }));
182  EXPECT_ANY_THROW(read_.read(queue_));
183 }
184 
185 TEST_F(EncryptedRecordTest, TestNoContentType) {
186  addToQueue("17030100050123456789");
187  EXPECT_CALL(*readAead_, _decrypt(_, _, 0))
188  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
189  expectSame(buf, "0123456789");
190  return getBuf("00000000");
191  }));
192  EXPECT_ANY_THROW(read_.read(queue_));
193 }
194 
195 TEST_F(EncryptedRecordTest, TestReadSeqNum) {
196  for (int i = 0; i < 10; i++) {
197  addToQueue("17030100050123456789");
198  EXPECT_CALL(*readAead_, _decrypt(_, _, i))
199  .WillOnce(
200  Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
201  expectSame(buf, "0123456789");
202  return getBuf("1234abcd17");
203  }));
204  read_.read(queue_);
205  }
206 }
207 
208 TEST_F(EncryptedRecordTest, TestSkipAndWait) {
209  read_.setSkipFailedDecryption(true);
210  addToQueue("17030100050123456789");
211  EXPECT_CALL(*readAead_, _tryDecrypt(_, _, 0))
212  .WillOnce(
213  Invoke([](std::unique_ptr<IOBuf>& /*buf*/, const IOBuf*, uint64_t) {
214  return folly::none;
215  }));
216  EXPECT_FALSE(read_.read(queue_).hasValue());
217  EXPECT_TRUE(queue_.empty());
218 }
219 
220 TEST_F(EncryptedRecordTest, TestSkipAndRead) {
221  Sequence s;
222  read_.setSkipFailedDecryption(true);
223  addToQueue("1703010005012345678917030100050123456789170301000501234567aa");
224  EXPECT_CALL(*readAead_, _tryDecrypt(_, _, 0))
225  .InSequence(s)
226  .WillOnce(
227  Invoke([](std::unique_ptr<IOBuf>& /*buf*/, const IOBuf*, uint64_t) {
228  return folly::none;
229  }));
230  EXPECT_CALL(*readAead_, _tryDecrypt(_, _, 0))
231  .InSequence(s)
232  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
233  expectSame(buf, "0123456789");
234  return getBuf("1234abcd17");
235  }));
236  auto msg = read_.read(queue_);
237  EXPECT_EQ(msg->type, ContentType::application_data);
238  expectSame(msg->fragment, "1234abcd");
239  EXPECT_EQ(queue_.chainLength(), 10);
240  EXPECT_CALL(*readAead_, _decrypt(_, _, 1))
241  .InSequence(s)
242  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
243  expectSame(buf, "01234567aa");
244  return getBuf("1234abaa17");
245  }));
246  msg = read_.read(queue_);
247  EXPECT_EQ(msg->type, ContentType::application_data);
248  expectSame(msg->fragment, "1234abaa");
249  EXPECT_TRUE(queue_.empty());
250 }
251 
252 TEST_F(EncryptedRecordTest, TestWriteHandshake) {
253  TLSMessage msg{ContentType::handshake, getBuf("1234567890")};
254  EXPECT_CALL(*writeAead_, _encrypt(_, _, 0))
255  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
256  expectSame(buf, "123456789016");
257  return getBuf("abcd1234abcd");
258  }));
259  auto buf = write_.write(std::move(msg));
260  expectSame(buf.data, "1703030006abcd1234abcd");
261 }
262 
263 TEST_F(EncryptedRecordTest, TestWriteAppData) {
264  TLSMessage msg{ContentType::application_data, getBuf("1234567890")};
265  EXPECT_CALL(*writeAead_, _encrypt(_, _, 0))
266  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
267  expectSame(buf, "123456789017");
268  return getBuf("abcd1234abcd");
269  }));
270  auto buf = write_.write(std::move(msg));
271  expectSame(buf.data, "1703030006abcd1234abcd");
272 }
273 
274 TEST_F(EncryptedRecordTest, TestWriteAppDataInPlace) {
275  TLSMessage msg{ContentType::application_data, getBuf("1234567890", 5, 17)};
276  EXPECT_CALL(*writeAead_, _encrypt(_, _, 0))
277  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
278  // footer should have been written w/o chaining
279  EXPECT_FALSE(buf->isChained());
280  expectSame(buf, "123456789017");
281  // we need to return room for the header
282  return getBuf("abcd1234abcd", 5, 0);
283  }));
284  auto buf = write_.write(std::move(msg));
285  EXPECT_FALSE(buf.data->isChained());
286  expectSame(buf.data, "1703030006abcd1234abcd");
287 }
288 
289 TEST_F(EncryptedRecordTest, TestFragmentedWrite) {
290  TLSMessage msg{ContentType::application_data, IOBuf::create(0x4a00)};
291  msg.fragment->append(0x4a00);
292  memset(msg.fragment->writableData(), 0x1, msg.fragment->length());
293 
294  Sequence s;
295  EXPECT_CALL(*writeAead_, _encrypt(_, _, 0))
296  .InSequence(s)
297  .WillOnce(
298  Invoke([](std::unique_ptr<IOBuf>& /*buf*/, const IOBuf*, uint64_t) {
299  return getBuf("aaaa");
300  }));
301  EXPECT_CALL(*writeAead_, _encrypt(_, _, 1))
302  .InSequence(s)
303  .WillOnce(
304  Invoke([](std::unique_ptr<IOBuf>& /*buf*/, const IOBuf*, uint64_t) {
305  return getBuf("bbbb");
306  }));
307  auto outBuf = write_.write(std::move(msg));
308  expectSame(outBuf.data, "1703034001aaaa1703030a01bbbb");
309 }
310 
311 TEST_F(EncryptedRecordTest, TestWriteSplittingWholeBuf) {
312  TLSMessage msg{ContentType::application_data, IOBuf::create(2000)};
313  msg.fragment->append(2000);
314  memset(msg.fragment->writableData(), 0x1, msg.fragment->length());
315  msg.fragment->prependChain(IOBuf::copyBuffer("moredata"));
316 
317  Sequence s;
318  EXPECT_CALL(*writeAead_, _encrypt(_, _, _))
319  .Times(2)
320  .WillRepeatedly(
321  Invoke([](std::unique_ptr<IOBuf>& /*buf*/, const IOBuf*, uint64_t) {
322  return getBuf("aaaa");
323  }));
324  write_.write(std::move(msg));
325 }
326 
327 TEST_F(EncryptedRecordTest, TestWriteSplittingCombineSmall) {
328  TLSMessage msg{ContentType::application_data, IOBuf::create(500)};
329  msg.fragment->append(500);
330  memset(msg.fragment->writableData(), 0x1, msg.fragment->length());
331  msg.fragment->prependChain(IOBuf::copyBuffer("moredata"));
332 
333  Sequence s;
334  EXPECT_CALL(*writeAead_, _encrypt(_, _, _))
335  .Times(1)
336  .WillRepeatedly(
337  Invoke([](std::unique_ptr<IOBuf>& /*buf*/, const IOBuf*, uint64_t) {
338  return getBuf("aaaa");
339  }));
340  write_.write(std::move(msg));
341 }
342 
343 TEST_F(EncryptedRecordTest, TestWriteSeqNum) {
344  for (int i = 0; i < 10; i++) {
345  TLSMessage msg{ContentType::application_data, getBuf("1234567890")};
346  EXPECT_CALL(*writeAead_, _encrypt(_, _, i))
347  .WillOnce(
348  Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
349  expectSame(buf, "123456789017");
350  return getBuf("abcd1234abcd");
351  }));
352  write_.write(std::move(msg));
353  }
354 }
355 
356 TEST_F(EncryptedRecordTest, TestWriteEmpty) {
357  TLSMessage msg{ContentType::application_data, folly::IOBuf::create(0)};
358  auto outBuf = write_.write(std::move(msg));
359  EXPECT_TRUE(outBuf.data->empty());
360 }
361 
362 TEST_F(EncryptedRecordTest, TestWriteMaxSize) {
363  write_.setMaxRecord(1900);
364 
365  TLSMessage msg{ContentType::application_data, IOBuf::create(2000)};
366  msg.fragment->append(2000);
367  memset(msg.fragment->writableData(), 0x1, msg.fragment->length());
368 
369  Sequence s;
370  EXPECT_CALL(*writeAead_, _encrypt(_, _, _))
371  .Times(2)
372  .WillRepeatedly(
373  Invoke([](std::unique_ptr<IOBuf>& /*buf*/, const IOBuf*, uint64_t) {
374  return getBuf("aaaa");
375  }));
376  write_.write(std::move(msg));
377 }
378 
379 TEST_F(EncryptedRecordTest, TestWriteMinSize) {
380  write_.setMinDesiredRecord(1700);
381  TLSMessage msg{ContentType::application_data, IOBuf::create(1000)};
382  msg.fragment->append(1000);
383  memset(msg.fragment->writableData(), 0x1, msg.fragment->length());
384  auto next = IOBuf::create(1000);
385  next->append(1000);
386  memset(next->writableData(), 0x2, next->length());
387  msg.fragment->prependChain(std::move(next));
388 
389  Sequence s;
390  EXPECT_CALL(*writeAead_, _encrypt(_, _, _))
391  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
392  // one byte for footer
393  EXPECT_EQ(buf->computeChainDataLength(), 1701);
394  return getBuf("aaaa");
395  }))
396  .WillOnce(Invoke([](std::unique_ptr<IOBuf>& buf, const IOBuf*, uint64_t) {
397  // one byte for footer
398  EXPECT_EQ(buf->computeChainDataLength(), 301);
399  return getBuf("bbbb");
400  }));
401  write_.write(std::move(msg));
402 }
403 } // namespace test
404 } // namespace fizz
#define EXPECT_ANY_THROW(statement)
Definition: gtest.h:1847
bool unhexlify(const InputString &input, OutputString &output)
Definition: String-inl.h:616
static void expectSame(const Buf &buf, const std::string &hex)
static std::unique_ptr< IOBuf > create(std::size_t capacity)
Definition: IOBuf.cpp:229
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:1922
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
bool isChained() const
Definition: IOBuf.h:760
static Options cacheChainLength()
Definition: IOBufQueue.h:83
static Buf getBuf(const std::string &hex, size_t headroom=0, size_t tailroom=0)
PolymorphicAction< internal::InvokeAction< FunctionImpl > > Invoke(FunctionImpl function_impl)
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
Definition: Actions.h:16
TEST_F(AsyncSSLSocketWriteTest, write_coalescing1)
std::size_t computeChainDataLength() const
Definition: IOBuf.cpp:501
#define EXPECT_TRUE(condition)
Definition: gtest.h:1859
const char * string
Definition: Conv.cpp:212
std::unique_ptr< folly::IOBuf > Buf
Definition: Types.h:22
static set< string > s
void addToQueue(const std::string &hex)
#define EXPECT_CALL(obj, call)
const internal::AnythingMatcher _
#define EXPECT_FALSE(condition)
Definition: gtest.h:1862
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
constexpr None none
Definition: Optional.h:87
def next(obj)
Definition: ast.py:58