1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "crypto/hmac.h"
6
7 #include <stddef.h>
8 #include <string.h>
9
10 #include <string>
11 #include <string_view>
12
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 static const size_t kSHA1DigestSize = 20;
16 static const size_t kSHA256DigestSize = 32;
17
18 static const char* kSimpleKey =
19 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
20 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
21 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
22 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
23 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA";
24 static const size_t kSimpleKeyLength = 80;
25
26 static const struct {
27 const char *data;
28 const int data_len;
29 const char *digest;
30 } kSimpleHmacCases[] = {
31 { "Test Using Larger Than Block-Size Key - Hash Key First", 54,
32 "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55"
33 "\xED\x40\x21\x12" },
34 { "Test Using Larger Than Block-Size Key and Larger "
35 "Than One Block-Size Data", 73,
36 "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08"
37 "\xBB\xFF\x1A\x91" }
38 };
39
TEST(HMACTest,HmacSafeBrowsingResponseTest)40 TEST(HMACTest, HmacSafeBrowsingResponseTest) {
41 const int kKeySize = 16;
42
43 // Client key.
44 const unsigned char kClientKey[kKeySize] =
45 { 0xbf, 0xf6, 0x83, 0x4b, 0x3e, 0xa3, 0x23, 0xdd,
46 0x96, 0x78, 0x70, 0x8e, 0xa1, 0x9d, 0x3b, 0x40 };
47
48 // Expected HMAC result using kMessage and kClientKey.
49 const unsigned char kReceivedHmac[kSHA1DigestSize] =
50 { 0xb9, 0x3c, 0xd6, 0xf0, 0x49, 0x47, 0xe2, 0x52,
51 0x59, 0x7a, 0xbd, 0x1f, 0x2b, 0x4c, 0x83, 0xad,
52 0x86, 0xd2, 0x48, 0x85 };
53
54 const char kMessage[] =
55 "n:1896\ni:goog-malware-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav"
56 "ar_s_445-450\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_439-444\nu:s"
57 ".ytimg.com/safebrowsing/rd/goog-malware-shavar_s_437\nu:s.ytimg.com/safebrowsi"
58 "ng/rd/goog-malware-shavar_s_436\nu:s.ytimg.com/safebrowsing/rd/goog-malware-sh"
59 "avar_s_433-435\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_431\nu:s.y"
60 "timg.com/safebrowsing/rd/goog-malware-shavar_s_430\nu:s.ytimg.com/safebrowsing"
61 "/rd/goog-malware-shavar_s_429\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav"
62 "ar_s_428\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_426\nu:s.ytimg.c"
63 "om/safebrowsing/rd/goog-malware-shavar_s_424\nu:s.ytimg.com/safebrowsing/rd/go"
64 "og-malware-shavar_s_423\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_4"
65 "22\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_420\nu:s.ytimg.com/saf"
66 "ebrowsing/rd/goog-malware-shavar_s_419\nu:s.ytimg.com/safebrowsing/rd/goog-mal"
67 "ware-shavar_s_414\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_409-411"
68 "\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_405\nu:s.ytimg.com/safeb"
69 "rowsing/rd/goog-malware-shavar_s_404\nu:s.ytimg.com/safebrowsing/rd/goog-malwa"
70 "re-shavar_s_402\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_401\nu:s."
71 "ytimg.com/safebrowsing/rd/goog-malware-shavar_a_973-978\nu:s.ytimg.com/safebro"
72 "wsing/rd/goog-malware-shavar_a_937-972\nu:s.ytimg.com/safebrowsing/rd/goog-mal"
73 "ware-shavar_a_931-936\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_925"
74 "-930\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_a_919-924\ni:goog-phis"
75 "h-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2633\nu:s.ytimg.co"
76 "m/safebrowsing/rd/goog-phish-shavar_a_2632\nu:s.ytimg.com/safebrowsing/rd/goog"
77 "-phish-shavar_a_2629-2631\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2"
78 "626-2628\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2625\n";
79
80 std::string message_data(kMessage);
81
82 crypto::HMAC hmac(crypto::HMAC::SHA1);
83 ASSERT_TRUE(hmac.Init(kClientKey, kKeySize));
84 unsigned char calculated_hmac[kSHA1DigestSize];
85
86 EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize));
87 EXPECT_EQ(0, memcmp(kReceivedHmac, calculated_hmac, kSHA1DigestSize));
88 }
89
90 // Test cases from RFC 2202 section 3
TEST(HMACTest,RFC2202TestCases)91 TEST(HMACTest, RFC2202TestCases) {
92 const struct {
93 const char *key;
94 const int key_len;
95 const char *data;
96 const int data_len;
97 const char *digest;
98 } cases[] = {
99 { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
100 "\x0B\x0B\x0B\x0B", 20,
101 "Hi There", 8,
102 "\xB6\x17\x31\x86\x55\x05\x72\x64\xE2\x8B\xC0\xB6\xFB\x37\x8C\x8E"
103 "\xF1\x46\xBE\x00" },
104 { "Jefe", 4,
105 "what do ya want for nothing?", 28,
106 "\xEF\xFC\xDF\x6A\xE5\xEB\x2F\xA2\xD2\x74\x16\xD5\xF1\x84\xDF\x9C"
107 "\x25\x9A\x7C\x79" },
108 { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
109 "\xAA\xAA\xAA\xAA", 20,
110 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
111 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
112 "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
113 "\xDD\xDD", 50,
114 "\x12\x5D\x73\x42\xB9\xAC\x11\xCD\x91\xA3\x9A\xF4\x8A\xA1\x7B\x4F"
115 "\x63\xF1\x75\xD3" },
116 { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
117 "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
118 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
119 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
120 "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
121 "\xCD\xCD", 50,
122 "\x4C\x90\x07\xF4\x02\x62\x50\xC6\xBC\x84\x14\xF9\xBF\x50\xC8\x6C"
123 "\x2D\x72\x35\xDA" },
124 { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
125 "\x0C\x0C\x0C\x0C", 20,
126 "Test With Truncation", 20,
127 "\x4C\x1A\x03\x42\x4B\x55\xE0\x7F\xE7\xF2\x7B\xE1\xD5\x8B\xB9\x32"
128 "\x4A\x9A\x5A\x04" },
129 { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
130 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
131 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
132 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
133 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
134 80,
135 "Test Using Larger Than Block-Size Key - Hash Key First", 54,
136 "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55"
137 "\xED\x40\x21\x12" },
138 { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
139 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
140 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
141 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
142 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
143 80,
144 "Test Using Larger Than Block-Size Key and Larger "
145 "Than One Block-Size Data", 73,
146 "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08"
147 "\xBB\xFF\x1A\x91" }
148 };
149
150 for (size_t i = 0; i < std::size(cases); ++i) {
151 crypto::HMAC hmac(crypto::HMAC::SHA1);
152 ASSERT_TRUE(hmac.Init(reinterpret_cast<const unsigned char*>(cases[i].key),
153 cases[i].key_len));
154 std::string data_string(cases[i].data, cases[i].data_len);
155 unsigned char digest[kSHA1DigestSize];
156 EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize));
157 EXPECT_EQ(0, memcmp(cases[i].digest, digest, kSHA1DigestSize));
158 }
159 }
160
161 // TODO(wtc): add other test vectors from RFC 4231.
TEST(HMACTest,RFC4231TestCase6)162 TEST(HMACTest, RFC4231TestCase6) {
163 unsigned char key[131];
164 for (size_t i = 0; i < sizeof(key); ++i)
165 key[i] = 0xaa;
166
167 std::string data = "Test Using Larger Than Block-Size Key - Hash Key First";
168 ASSERT_EQ(54U, data.size());
169
170 static unsigned char kKnownHMACSHA256[] = {
171 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f,
172 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f,
173 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14,
174 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54
175 };
176
177 crypto::HMAC hmac(crypto::HMAC::SHA256);
178 ASSERT_TRUE(hmac.Init(key, sizeof(key)));
179 unsigned char calculated_hmac[kSHA256DigestSize];
180
181 EXPECT_EQ(kSHA256DigestSize, hmac.DigestLength());
182 EXPECT_TRUE(hmac.Sign(data, calculated_hmac, kSHA256DigestSize));
183 EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize));
184 }
185
186 // Based on NSS's FIPS HMAC power-up self-test.
TEST(HMACTest,NSSFIPSPowerUpSelfTest)187 TEST(HMACTest, NSSFIPSPowerUpSelfTest) {
188 static const char kKnownMessage[] =
189 "The test message for the MD2, MD5, and SHA-1 hashing algorithms.";
190
191 static const unsigned char kKnownSecretKey[] = {
192 0x46, 0x69, 0x72, 0x65, 0x66, 0x6f, 0x78, 0x20,
193 0x61, 0x6e, 0x64, 0x20, 0x54, 0x68, 0x75, 0x6e,
194 0x64, 0x65, 0x72, 0x42, 0x69, 0x72, 0x64, 0x20,
195 0x61, 0x72, 0x65, 0x20, 0x61, 0x77, 0x65, 0x73,
196 0x6f, 0x6d, 0x65, 0x21, 0x00
197 };
198
199 static const size_t kKnownSecretKeySize = sizeof(kKnownSecretKey);
200
201 // HMAC-SHA-1 known answer (20 bytes).
202 static const unsigned char kKnownHMACSHA1[] = {
203 0xd5, 0x85, 0xf6, 0x5b, 0x39, 0xfa, 0xb9, 0x05,
204 0x3b, 0x57, 0x1d, 0x61, 0xe7, 0xb8, 0x84, 0x1e,
205 0x5d, 0x0e, 0x1e, 0x11
206 };
207
208 // HMAC-SHA-256 known answer (32 bytes).
209 static const unsigned char kKnownHMACSHA256[] = {
210 0x05, 0x75, 0x9a, 0x9e, 0x70, 0x5e, 0xe7, 0x44,
211 0xe2, 0x46, 0x4b, 0x92, 0x22, 0x14, 0x22, 0xe0,
212 0x1b, 0x92, 0x8a, 0x0c, 0xfe, 0xf5, 0x49, 0xe9,
213 0xa7, 0x1b, 0x56, 0x7d, 0x1d, 0x29, 0x40, 0x48
214 };
215
216 std::string message_data(kKnownMessage);
217
218 crypto::HMAC hmac(crypto::HMAC::SHA1);
219 ASSERT_TRUE(hmac.Init(kKnownSecretKey, kKnownSecretKeySize));
220 unsigned char calculated_hmac[kSHA1DigestSize];
221
222 EXPECT_EQ(kSHA1DigestSize, hmac.DigestLength());
223 EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize));
224 EXPECT_EQ(0, memcmp(kKnownHMACSHA1, calculated_hmac, kSHA1DigestSize));
225 EXPECT_TRUE(hmac.Verify(
226 message_data,
227 std::string_view(reinterpret_cast<const char*>(kKnownHMACSHA1),
228 kSHA1DigestSize)));
229 EXPECT_TRUE(hmac.VerifyTruncated(
230 message_data,
231 std::string_view(reinterpret_cast<const char*>(kKnownHMACSHA1),
232 kSHA1DigestSize / 2)));
233
234 crypto::HMAC hmac2(crypto::HMAC::SHA256);
235 ASSERT_TRUE(hmac2.Init(kKnownSecretKey, kKnownSecretKeySize));
236 unsigned char calculated_hmac2[kSHA256DigestSize];
237
238 EXPECT_TRUE(hmac2.Sign(message_data, calculated_hmac2, kSHA256DigestSize));
239 EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac2, kSHA256DigestSize));
240 }
241
TEST(HMACTest,HMACObjectReuse)242 TEST(HMACTest, HMACObjectReuse) {
243 crypto::HMAC hmac(crypto::HMAC::SHA1);
244 ASSERT_TRUE(
245 hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey),
246 kSimpleKeyLength));
247 for (size_t i = 0; i < std::size(kSimpleHmacCases); ++i) {
248 std::string data_string(kSimpleHmacCases[i].data,
249 kSimpleHmacCases[i].data_len);
250 unsigned char digest[kSHA1DigestSize];
251 EXPECT_TRUE(hmac.Sign(data_string, digest, kSHA1DigestSize));
252 EXPECT_EQ(0, memcmp(kSimpleHmacCases[i].digest, digest, kSHA1DigestSize));
253 }
254 }
255
TEST(HMACTest,Verify)256 TEST(HMACTest, Verify) {
257 crypto::HMAC hmac(crypto::HMAC::SHA1);
258 ASSERT_TRUE(
259 hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey),
260 kSimpleKeyLength));
261 const char empty_digest[kSHA1DigestSize] = { 0 };
262 for (size_t i = 0; i < std::size(kSimpleHmacCases); ++i) {
263 // Expected results
264 EXPECT_TRUE(hmac.Verify(
265 std::string_view(kSimpleHmacCases[i].data,
266 kSimpleHmacCases[i].data_len),
267 std::string_view(kSimpleHmacCases[i].digest, kSHA1DigestSize)));
268 // Mismatched size
269 EXPECT_FALSE(hmac.Verify(std::string_view(kSimpleHmacCases[i].data,
270 kSimpleHmacCases[i].data_len),
271 std::string_view(kSimpleHmacCases[i].data,
272 kSimpleHmacCases[i].data_len)));
273
274 // Expected size, mismatched data
275 EXPECT_FALSE(hmac.Verify(std::string_view(kSimpleHmacCases[i].data,
276 kSimpleHmacCases[i].data_len),
277 std::string_view(empty_digest, kSHA1DigestSize)));
278 }
279 }
280
TEST(HMACTest,EmptyKey)281 TEST(HMACTest, EmptyKey) {
282 // Test vector from https://en.wikipedia.org/wiki/HMAC
283 const char* kExpectedDigest =
284 "\xFB\xDB\x1D\x1B\x18\xAA\x6C\x08\x32\x4B\x7D\x64\xB7\x1F\xB7\x63"
285 "\x70\x69\x0E\x1D";
286 std::string_view data("");
287
288 crypto::HMAC hmac(crypto::HMAC::SHA1);
289 ASSERT_TRUE(hmac.Init(nullptr, 0));
290
291 unsigned char digest[kSHA1DigestSize];
292 EXPECT_TRUE(hmac.Sign(data, digest, kSHA1DigestSize));
293 EXPECT_EQ(0, memcmp(kExpectedDigest, digest, kSHA1DigestSize));
294
295 EXPECT_TRUE(
296 hmac.Verify(data, std::string_view(kExpectedDigest, kSHA1DigestSize)));
297 }
298
TEST(HMACTest,TooLong)299 TEST(HMACTest, TooLong) {
300 // See RFC4231, section 4.7.
301 unsigned char key[131];
302 for (size_t i = 0; i < sizeof(key); ++i)
303 key[i] = 0xaa;
304
305 std::string data = "Test Using Larger Than Block-Size Key - Hash Key First";
306 static uint8_t kKnownHMACSHA256[] = {
307 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26,
308 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28,
309 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54};
310
311 crypto::HMAC hmac(crypto::HMAC::SHA256);
312 ASSERT_TRUE(hmac.Init(key, sizeof(key)));
313
314 // Attempting to write too large of an HMAC is an error.
315 uint8_t calculated_hmac[kSHA256DigestSize + 1];
316 EXPECT_FALSE(hmac.Sign(data, calculated_hmac, sizeof(calculated_hmac)));
317
318 // Attempting to verify too large of an HMAC is an error.
319 memcpy(calculated_hmac, kKnownHMACSHA256, kSHA256DigestSize);
320 calculated_hmac[kSHA256DigestSize] = 0;
321 EXPECT_FALSE(hmac.VerifyTruncated(
322 data,
323 std::string(calculated_hmac, calculated_hmac + sizeof(calculated_hmac))));
324 }
325
TEST(HMACTest,Bytes)326 TEST(HMACTest, Bytes) {
327 // See RFC4231, section 4.7.
328 std::vector<uint8_t> key(131, 0xaa);
329 std::string data_str =
330 "Test Using Larger Than Block-Size Key - Hash Key First";
331 std::vector<uint8_t> data(data_str.begin(), data_str.end());
332 static uint8_t kKnownHMACSHA256[] = {
333 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26,
334 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28,
335 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54};
336
337 crypto::HMAC hmac(crypto::HMAC::SHA256);
338 ASSERT_TRUE(hmac.Init(key));
339
340 uint8_t calculated_hmac[kSHA256DigestSize];
341 ASSERT_TRUE(hmac.Sign(data, calculated_hmac));
342 EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize));
343
344 EXPECT_TRUE(hmac.Verify(data, calculated_hmac));
345 EXPECT_TRUE(hmac.VerifyTruncated(
346 data, base::make_span(calculated_hmac, kSHA256DigestSize / 2)));
347
348 data[0]++;
349 EXPECT_FALSE(hmac.Verify(data, calculated_hmac));
350 EXPECT_FALSE(hmac.VerifyTruncated(
351 data, base::make_span(calculated_hmac, kSHA256DigestSize / 2)));
352 }
353