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