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