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