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.
5 #include "crypto/hmac.h"
11 #include <string_view>
13 #include "testing/gtest/include/gtest/gtest.h"
15 static const size_t kSHA1DigestSize = 20;
16 static const size_t kSHA256DigestSize = 32;
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;
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"
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"
40 TEST(HMACTest, HmacSafeBrowsingResponseTest) {
41 const int kKeySize = 16;
44 const unsigned char kClientKey[kKeySize] =
45 { 0xbf, 0xf6, 0x83, 0x4b, 0x3e, 0xa3, 0x23, 0xdd,
46 0x96, 0x78, 0x70, 0x8e, 0xa1, 0x9d, 0x3b, 0x40 };
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 };
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";
80 std::string message_data(kMessage);
82 crypto::HMAC hmac(crypto::HMAC::SHA1);
83 ASSERT_TRUE(hmac.Init(kClientKey, kKeySize));
84 unsigned char calculated_hmac[kSHA1DigestSize];
86 EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kSHA1DigestSize));
87 EXPECT_EQ(0, memcmp(kReceivedHmac, calculated_hmac, kSHA1DigestSize));
90 // Test cases from RFC 2202 section 3
91 TEST(HMACTest, RFC2202TestCases) {
99 { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
100 "\x0B\x0B\x0B\x0B", 20,
102 "\xB6\x17\x31\x86\x55\x05\x72\x64\xE2\x8B\xC0\xB6\xFB\x37\x8C\x8E"
103 "\xF1\x46\xBE\x00" },
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"
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"
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",
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",
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"
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),
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));
161 // TODO(wtc): add other test vectors from RFC 4231.
162 TEST(HMACTest, RFC4231TestCase6) {
163 unsigned char key[131];
164 for (size_t i = 0; i < sizeof(key); ++i)
167 std::string data = "Test Using Larger Than Block-Size Key - Hash Key First";
168 ASSERT_EQ(54U, data.size());
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
177 crypto::HMAC hmac(crypto::HMAC::SHA256);
178 ASSERT_TRUE(hmac.Init(key, sizeof(key)));
179 unsigned char calculated_hmac[kSHA256DigestSize];
181 EXPECT_EQ(kSHA256DigestSize, hmac.DigestLength());
182 EXPECT_TRUE(hmac.Sign(data, calculated_hmac, kSHA256DigestSize));
183 EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize));
186 // Based on NSS's FIPS HMAC power-up self-test.
187 TEST(HMACTest, NSSFIPSPowerUpSelfTest) {
188 static const char kKnownMessage[] =
189 "The test message for the MD2, MD5, and SHA-1 hashing algorithms.";
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
199 static const size_t kKnownSecretKeySize = sizeof(kKnownSecretKey);
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
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
216 std::string message_data(kKnownMessage);
218 crypto::HMAC hmac(crypto::HMAC::SHA1);
219 ASSERT_TRUE(hmac.Init(kKnownSecretKey, kKnownSecretKeySize));
220 unsigned char calculated_hmac[kSHA1DigestSize];
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(
227 std::string_view(reinterpret_cast<const char*>(kKnownHMACSHA1),
229 EXPECT_TRUE(hmac.VerifyTruncated(
231 std::string_view(reinterpret_cast<const char*>(kKnownHMACSHA1),
232 kSHA1DigestSize / 2)));
234 crypto::HMAC hmac2(crypto::HMAC::SHA256);
235 ASSERT_TRUE(hmac2.Init(kKnownSecretKey, kKnownSecretKeySize));
236 unsigned char calculated_hmac2[kSHA256DigestSize];
238 EXPECT_TRUE(hmac2.Sign(message_data, calculated_hmac2, kSHA256DigestSize));
239 EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac2, kSHA256DigestSize));
242 TEST(HMACTest, HMACObjectReuse) {
243 crypto::HMAC hmac(crypto::HMAC::SHA1);
245 hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey),
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));
256 TEST(HMACTest, Verify) {
257 crypto::HMAC hmac(crypto::HMAC::SHA1);
259 hmac.Init(reinterpret_cast<const unsigned char*>(kSimpleKey),
261 const char empty_digest[kSHA1DigestSize] = { 0 };
262 for (size_t i = 0; i < std::size(kSimpleHmacCases); ++i) {
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)));
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)));
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)));
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"
286 std::string_view data("");
288 crypto::HMAC hmac(crypto::HMAC::SHA1);
289 ASSERT_TRUE(hmac.Init(nullptr, 0));
291 unsigned char digest[kSHA1DigestSize];
292 EXPECT_TRUE(hmac.Sign(data, digest, kSHA1DigestSize));
293 EXPECT_EQ(0, memcmp(kExpectedDigest, digest, kSHA1DigestSize));
296 hmac.Verify(data, std::string_view(kExpectedDigest, kSHA1DigestSize)));
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)
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};
311 crypto::HMAC hmac(crypto::HMAC::SHA256);
312 ASSERT_TRUE(hmac.Init(key, sizeof(key)));
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)));
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(
323 std::string(calculated_hmac, calculated_hmac + sizeof(calculated_hmac))));
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};
337 crypto::HMAC hmac(crypto::HMAC::SHA256);
338 ASSERT_TRUE(hmac.Init(key));
340 uint8_t calculated_hmac[kSHA256DigestSize];
341 ASSERT_TRUE(hmac.Sign(data, calculated_hmac));
342 EXPECT_EQ(0, memcmp(kKnownHMACSHA256, calculated_hmac, kSHA256DigestSize));
344 EXPECT_TRUE(hmac.Verify(data, calculated_hmac));
345 EXPECT_TRUE(hmac.VerifyTruncated(
346 data, base::make_span(calculated_hmac, kSHA256DigestSize / 2)));
349 EXPECT_FALSE(hmac.Verify(data, calculated_hmac));
350 EXPECT_FALSE(hmac.VerifyTruncated(
351 data, base::make_span(calculated_hmac, kSHA256DigestSize / 2)));