1 /*
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <folly/ssl/OpenSSLHash.h>
18
19 #include <folly/io/IOBufQueue.h>
20 #include <folly/portability/GTest.h>
21
22 using namespace std;
23 using namespace folly;
24 using namespace folly::ssl;
25
26 namespace {
27
28 class OpenSSLHashTest : public testing::Test {};
29 } // namespace
30
TEST_F(OpenSSLHashTest,sha256)31 TEST_F(OpenSSLHashTest, sha256) {
32 IOBuf buf;
33 buf.prependChain(IOBuf::wrapBuffer(ByteRange(StringPiece("foo"))));
34 buf.prependChain(IOBuf::wrapBuffer(ByteRange(StringPiece("bar"))));
35 EXPECT_EQ(3, buf.countChainElements());
36 EXPECT_EQ(6, buf.computeChainDataLength());
37
38 auto expected = vector<uint8_t>(32);
39 auto combined = ByteRange(StringPiece("foobar"));
40 SHA256(combined.data(), combined.size(), expected.data());
41
42 auto out = vector<uint8_t>(32);
43 OpenSSLHash::sha256(range(out), buf);
44 EXPECT_EQ(expected, out);
45 }
46
TEST_F(OpenSSLHashTest,sha256_hashcopy)47 TEST_F(OpenSSLHashTest, sha256_hashcopy) {
48 std::array<uint8_t, 32> expected, actual1, actual2;
49 constexpr StringPiece data{"foobar"};
50
51 OpenSSLHash::hash(range(expected), EVP_sha256(), data);
52
53 OpenSSLHash::Digest digest;
54 digest.hash_init(EVP_sha256());
55 digest.hash_update(ByteRange(data));
56
57 OpenSSLHash::Digest copy1(digest); // copy constructor
58 OpenSSLHash::Digest copy2 = digest; // copy assignment operator
59
60 copy1.hash_final(range(actual1));
61 copy2.hash_final(range(actual2));
62
63 EXPECT_EQ(expected, actual1);
64 EXPECT_EQ(expected, actual2);
65 }
66
TEST_F(OpenSSLHashTest,sha256_hashcopy_self)67 TEST_F(OpenSSLHashTest, sha256_hashcopy_self) {
68 std::array<uint8_t, 32> expected, actual;
69 constexpr StringPiece data{"foobar"};
70
71 OpenSSLHash::hash(range(expected), EVP_sha256(), data);
72
73 OpenSSLHash::Digest digest;
74 digest.hash_init(EVP_sha256());
75 digest.hash_update(ByteRange(data));
76
77 OpenSSLHash::Digest* ptr = &digest;
78 digest = *ptr; // test copy of an object to itself
79
80 digest.hash_final(range(actual));
81
82 EXPECT_EQ(expected, actual);
83 }
84
TEST_F(OpenSSLHashTest,sha256_hashcopy_from_default_constructed)85 TEST_F(OpenSSLHashTest, sha256_hashcopy_from_default_constructed) {
86 std::array<uint8_t, 32> expected, actual1, actual2;
87 constexpr StringPiece data{"foobar"};
88
89 OpenSSLHash::hash(range(expected), EVP_sha256(), data);
90
91 OpenSSLHash::Digest digest;
92 OpenSSLHash::Digest copy1(digest); // copy constructor
93 OpenSSLHash::Digest copy2 = digest; // copy assignment operator
94
95 copy1.hash_init(EVP_sha256());
96 copy1.hash_update(ByteRange(data));
97 copy1.hash_final(range(actual1));
98 EXPECT_EQ(expected, actual1);
99
100 copy2.hash_init(EVP_sha256());
101 copy2.hash_update(ByteRange(data));
102 copy2.hash_final(range(actual2));
103 EXPECT_EQ(expected, actual2);
104 }
105
TEST_F(OpenSSLHashTest,sha256_hashmove)106 TEST_F(OpenSSLHashTest, sha256_hashmove) {
107 std::array<uint8_t, 32> expected, actual1, actual2;
108 constexpr StringPiece data{"foobar"};
109
110 OpenSSLHash::hash(range(expected), EVP_sha256(), data);
111
112 OpenSSLHash::Digest digest;
113 digest.hash_init(EVP_sha256());
114 digest.hash_update(ByteRange(data));
115 OpenSSLHash::Digest copy1(std::move(digest)); // move constructor
116 copy1.hash_final(range(actual1));
117 EXPECT_EQ(expected, actual1);
118
119 digest = OpenSSLHash::Digest{}; // should be safe to reassign to moved object
120 digest.hash_init(EVP_sha256());
121 digest.hash_update(ByteRange(data));
122 OpenSSLHash::Digest copy2 = std::move(digest); // move assignment operator
123 copy2.hash_final(range(actual2));
124 EXPECT_EQ(expected, actual2);
125 }
126
TEST_F(OpenSSLHashTest,sha256_hashmove_self)127 TEST_F(OpenSSLHashTest, sha256_hashmove_self) {
128 std::array<uint8_t, 32> expected, actual;
129 constexpr StringPiece data{"foobar"};
130
131 OpenSSLHash::hash(range(expected), EVP_sha256(), data);
132
133 OpenSSLHash::Digest digest;
134 digest.hash_init(EVP_sha256());
135 digest.hash_update(ByteRange(data));
136
137 OpenSSLHash::Digest* ptr = &digest;
138 digest = std::move(*ptr); // test move of an object to itself
139
140 digest.hash_final(range(actual));
141
142 EXPECT_EQ(expected, actual);
143 }
144
TEST_F(OpenSSLHashTest,sha256_hashmove_from_default_constructed)145 TEST_F(OpenSSLHashTest, sha256_hashmove_from_default_constructed) {
146 std::array<uint8_t, 32> expected, actual1, actual2;
147 constexpr StringPiece data{"foobar"};
148
149 OpenSSLHash::hash(range(expected), EVP_sha256(), data);
150
151 OpenSSLHash::Digest digest1;
152 OpenSSLHash::Digest copy1(std::move(digest1)); // move constructor
153 OpenSSLHash::Digest digest2;
154 OpenSSLHash::Digest copy2 = std::move(digest2); // move assignment operator
155
156 copy1.hash_init(EVP_sha256());
157 copy1.hash_update(ByteRange(data));
158 copy1.hash_final(range(actual1));
159 EXPECT_EQ(expected, actual1);
160
161 copy2.hash_init(EVP_sha256());
162 copy2.hash_update(ByteRange(data));
163 copy2.hash_final(range(actual2));
164 EXPECT_EQ(expected, actual2);
165 }
166
TEST_F(OpenSSLHashTest,sha256_hashcopy_intermediate)167 TEST_F(OpenSSLHashTest, sha256_hashcopy_intermediate) {
168 std::array<uint8_t, 32> expected, actual1, actual2;
169 constexpr StringPiece data1("foo");
170 constexpr StringPiece data2("bar");
171
172 OpenSSLHash::Digest digest;
173 digest.hash_init(EVP_sha256());
174 digest.hash_update(ByteRange(data1));
175
176 OpenSSLHash::Digest copy1(digest); // copy constructor
177 OpenSSLHash::Digest copy2 = digest; // copy assignment operator
178
179 digest.hash_update(ByteRange(data2));
180 digest.hash_final(range(expected));
181
182 copy1.hash_update(ByteRange(data2));
183 copy1.hash_final(range(actual1));
184 EXPECT_EQ(expected, actual1);
185
186 copy2.hash_update(ByteRange(data2));
187 copy2.hash_final(range(actual2));
188 EXPECT_EQ(expected, actual2);
189 }
190
TEST_F(OpenSSLHashTest,sha256_hashmove_intermediate)191 TEST_F(OpenSSLHashTest, sha256_hashmove_intermediate) {
192 std::array<uint8_t, 32> expected, actual1, actual2;
193 constexpr StringPiece fulldata("foobar");
194 constexpr StringPiece data1("foo");
195 constexpr StringPiece data2("bar");
196
197 OpenSSLHash::hash(range(expected), EVP_sha256(), fulldata);
198
199 OpenSSLHash::Digest digest;
200 digest.hash_init(EVP_sha256());
201 digest.hash_update(ByteRange(data1));
202 OpenSSLHash::Digest copy1(std::move(digest)); // move constructor
203 copy1.hash_update(ByteRange(data2));
204 copy1.hash_final(range(actual1));
205 EXPECT_EQ(expected, actual1);
206
207 digest.hash_init(EVP_sha256()); // should be safe to re-init moved object
208 digest.hash_update(ByteRange(data1));
209 OpenSSLHash::Digest copy2 = std::move(digest); // move assignment operator
210 copy2.hash_update(ByteRange(data2));
211 copy2.hash_final(range(actual2));
212 EXPECT_EQ(expected, actual2);
213
214 // Make sure it's safe to re-init moved object after move operator=()
215 digest.hash_init(EVP_sha256());
216 }
217
TEST_F(OpenSSLHashTest,digest_update_without_init_throws)218 TEST_F(OpenSSLHashTest, digest_update_without_init_throws) {
219 OpenSSLHash::Digest digest;
220 EXPECT_THROW(digest.hash_update(ByteRange{}), std::runtime_error);
221 }
222
TEST_F(OpenSSLHashTest,digest_final_without_init_throws)223 TEST_F(OpenSSLHashTest, digest_final_without_init_throws) {
224 OpenSSLHash::Digest digest;
225 std::array<uint8_t, 32> out;
226 EXPECT_THROW(digest.hash_final(range(out)), std::runtime_error);
227 }
228
TEST_F(OpenSSLHashTest,hmac_sha256)229 TEST_F(OpenSSLHashTest, hmac_sha256) {
230 auto key = ByteRange(StringPiece("qwerty"));
231
232 IOBuf buf;
233 buf.prependChain(IOBuf::wrapBuffer(ByteRange(StringPiece("foo"))));
234 buf.prependChain(IOBuf::wrapBuffer(ByteRange(StringPiece("bar"))));
235 EXPECT_EQ(3, buf.countChainElements());
236 EXPECT_EQ(6, buf.computeChainDataLength());
237
238 auto expected = vector<uint8_t>(32);
239 auto combined = ByteRange(StringPiece("foobar"));
240 HMAC(
241 EVP_sha256(),
242 key.data(),
243 int(key.size()),
244 combined.data(),
245 combined.size(),
246 expected.data(),
247 nullptr);
248
249 auto out = vector<uint8_t>(32);
250 OpenSSLHash::hmac_sha256(range(out), key, buf);
251 EXPECT_EQ(expected, out);
252 }
253
TEST_F(OpenSSLHashTest,hmac_sha256_hashcopy)254 TEST_F(OpenSSLHashTest, hmac_sha256_hashcopy) {
255 std::array<uint8_t, 32> expected, actual1, actual2;
256
257 constexpr StringPiece data{"foobar"};
258 constexpr StringPiece key{"qwerty"};
259
260 OpenSSLHash::Hmac hmac;
261 hmac.hash_init(EVP_sha256(), {key});
262 hmac.hash_update({data});
263
264 OpenSSLHash::Hmac copy1{hmac};
265 OpenSSLHash::Hmac copy2 = hmac;
266
267 hmac.hash_final(range(expected));
268 copy1.hash_final(range(actual1));
269 copy2.hash_final(range(actual2));
270
271 EXPECT_EQ(expected, actual1);
272 EXPECT_EQ(expected, actual2);
273 }
274
TEST_F(OpenSSLHashTest,hmac_sha256_hashmove)275 TEST_F(OpenSSLHashTest, hmac_sha256_hashmove) {
276 std::array<uint8_t, 32> expected, actual1, actual2;
277
278 constexpr StringPiece data{"foobar"};
279 constexpr StringPiece key{"qwerty"};
280
281 HMAC(
282 EVP_sha256(),
283 key.data(),
284 int(key.size()),
285 ByteRange{data}.data(),
286 data.size(),
287 expected.data(),
288 nullptr);
289
290 OpenSSLHash::Hmac hmac;
291 hmac.hash_init(EVP_sha256(), {key});
292 hmac.hash_update({data});
293
294 OpenSSLHash::Hmac copy1{std::move(hmac)};
295 copy1.hash_final(range(actual1));
296 EXPECT_EQ(expected, actual1);
297
298 hmac = OpenSSLHash::Hmac{};
299 hmac.hash_init(EVP_sha256(), {key});
300 hmac.hash_update({data});
301
302 OpenSSLHash::Hmac copy2 = std::move(hmac);
303 copy2.hash_final(range(actual2));
304 EXPECT_EQ(expected, actual2);
305 }
306
TEST_F(OpenSSLHashTest,hmac_sha256_hashcopy_self)307 TEST_F(OpenSSLHashTest, hmac_sha256_hashcopy_self) {
308 std::array<uint8_t, 32> expected, actual;
309
310 constexpr StringPiece data{"foobar"};
311 constexpr StringPiece key{"qwerty"};
312
313 HMAC(
314 EVP_sha256(),
315 key.data(),
316 int(key.size()),
317 ByteRange{data}.data(),
318 data.size(),
319 expected.data(),
320 nullptr);
321
322 OpenSSLHash::Hmac hmac;
323 hmac.hash_init(EVP_sha256(), {key});
324 hmac.hash_update({data});
325
326 OpenSSLHash::Hmac* ptr = &hmac;
327 hmac = *ptr;
328
329 hmac.hash_final(range(actual));
330 EXPECT_EQ(expected, actual);
331 }
332
TEST_F(OpenSSLHashTest,hmac_sha256_hashmove_self)333 TEST_F(OpenSSLHashTest, hmac_sha256_hashmove_self) {
334 std::array<uint8_t, 32> expected, actual;
335
336 constexpr StringPiece data{"foobar"};
337 constexpr StringPiece key{"qwerty"};
338
339 HMAC(
340 EVP_sha256(),
341 key.data(),
342 int(key.size()),
343 ByteRange{data}.data(),
344 data.size(),
345 expected.data(),
346 nullptr);
347
348 OpenSSLHash::Hmac hmac;
349 hmac.hash_init(EVP_sha256(), {key});
350 hmac.hash_update({data});
351
352 OpenSSLHash::Hmac* ptr = &hmac;
353 hmac = std::move(*ptr);
354
355 hmac.hash_final(range(actual));
356 EXPECT_EQ(expected, actual);
357 }
358
TEST_F(OpenSSLHashTest,hmac_sha256_hashcopy_from_default_constructed)359 TEST_F(OpenSSLHashTest, hmac_sha256_hashcopy_from_default_constructed) {
360 std::array<uint8_t, 32> expected, actual1, actual2;
361
362 constexpr StringPiece data{"foobar"};
363 constexpr StringPiece key{"qwerty"};
364
365 HMAC(
366 EVP_sha256(),
367 key.data(),
368 int(key.size()),
369 ByteRange{data}.data(),
370 data.size(),
371 expected.data(),
372 nullptr);
373
374 OpenSSLHash::Hmac hmac;
375 OpenSSLHash::Hmac copy1{hmac};
376 OpenSSLHash::Hmac copy2 = hmac;
377
378 copy1.hash_init(EVP_sha256(), {key});
379 copy1.hash_update({data});
380 copy1.hash_final(range(actual1));
381 EXPECT_EQ(expected, actual1);
382
383 copy2.hash_init(EVP_sha256(), {key});
384 copy2.hash_update({data});
385 copy2.hash_final(range(actual2));
386 EXPECT_EQ(expected, actual2);
387 }
388
TEST_F(OpenSSLHashTest,hmac_sha256_hashmove_from_default_constructed)389 TEST_F(OpenSSLHashTest, hmac_sha256_hashmove_from_default_constructed) {
390 std::array<uint8_t, 32> expected, actual1, actual2;
391
392 constexpr StringPiece data{"foobar"};
393 constexpr StringPiece key{"qwerty"};
394
395 HMAC(
396 EVP_sha256(),
397 key.data(),
398 int(key.size()),
399 ByteRange{data}.data(),
400 data.size(),
401 expected.data(),
402 nullptr);
403
404 OpenSSLHash::Hmac hmac1;
405 OpenSSLHash::Hmac copy1{std::move(hmac1)};
406 OpenSSLHash::Hmac hmac2;
407 OpenSSLHash::Hmac copy2 = std::move(hmac2);
408
409 copy1.hash_init(EVP_sha256(), {key});
410 copy1.hash_update({data});
411 copy1.hash_final(range(actual1));
412 EXPECT_EQ(expected, actual1);
413
414 copy2.hash_init(EVP_sha256(), {key});
415 copy2.hash_update({data});
416 copy2.hash_final(range(actual2));
417 EXPECT_EQ(expected, actual2);
418 }
419
TEST_F(OpenSSLHashTest,hmac_sha256_hashcopy_intermediate)420 TEST_F(OpenSSLHashTest, hmac_sha256_hashcopy_intermediate) {
421 std::array<uint8_t, 32> expected, actual1, actual2;
422
423 constexpr StringPiece data1{"foo"};
424 constexpr StringPiece data2{"bar"};
425 constexpr StringPiece key{"qwerty"};
426
427 OpenSSLHash::Hmac hmac;
428 hmac.hash_init(EVP_sha256(), {key});
429 hmac.hash_update({data1});
430
431 OpenSSLHash::Hmac copy1{hmac};
432 OpenSSLHash::Hmac copy2 = hmac;
433 hmac.hash_update({data2});
434 copy1.hash_update({data2});
435 copy2.hash_update({data2});
436
437 hmac.hash_final(range(expected));
438 copy1.hash_final(range(actual1));
439 copy2.hash_final(range(actual2));
440
441 EXPECT_EQ(expected, actual1);
442 EXPECT_EQ(expected, actual2);
443 }
444
TEST_F(OpenSSLHashTest,hmac_sha256_movecopy_intermediate)445 TEST_F(OpenSSLHashTest, hmac_sha256_movecopy_intermediate) {
446 std::array<uint8_t, 32> expected, actual1, actual2;
447
448 constexpr StringPiece data{"foobar"};
449 constexpr StringPiece data1{"foo"};
450 constexpr StringPiece data2{"bar"};
451 constexpr StringPiece key{"qwerty"};
452
453 HMAC(
454 EVP_sha256(),
455 key.data(),
456 int(key.size()),
457 ByteRange{data}.data(),
458 data.size(),
459 expected.data(),
460 nullptr);
461
462 OpenSSLHash::Hmac hmac;
463 hmac.hash_init(EVP_sha256(), {key});
464 hmac.hash_update({data1});
465 OpenSSLHash::Hmac copy1{std::move(hmac)};
466 copy1.hash_update({data2});
467 copy1.hash_final(range(actual1));
468 EXPECT_EQ(expected, actual1);
469
470 hmac.hash_init(EVP_sha256(), {key});
471 hmac.hash_update({data1});
472 OpenSSLHash::Hmac copy2 = std::move(hmac);
473 copy2.hash_update({data2});
474 copy2.hash_final(range(actual2));
475 EXPECT_EQ(expected, actual2);
476
477 hmac.hash_init(EVP_sha256(), {key});
478 }
479
TEST_F(OpenSSLHashTest,hmac_update_without_init_throws)480 TEST_F(OpenSSLHashTest, hmac_update_without_init_throws) {
481 OpenSSLHash::Hmac hmac;
482 EXPECT_THROW(hmac.hash_update(ByteRange{}), std::runtime_error);
483 }
484
TEST_F(OpenSSLHashTest,hmac_final_without_init_throws)485 TEST_F(OpenSSLHashTest, hmac_final_without_init_throws) {
486 OpenSSLHash::Hmac hmac;
487 std::array<uint8_t, 32> out;
488 EXPECT_THROW(hmac.hash_final(range(out)), std::runtime_error);
489 }
490