Home | History | Annotate | Download | only in crypto
      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 
     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
     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.
    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.
    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 
    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 
    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 
    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(NULL, 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