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