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