summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/SConscript2
-rw-r--r--base/base.xcodeproj/project.pbxproj10
-rw-r--r--base/build/base.vcproj4
-rw-r--r--base/hmac.h36
-rw-r--r--base/hmac_mac.cc52
-rw-r--r--base/hmac_unittest.cc131
-rw-r--r--base/hmac_win.cc (renamed from base/hmac.cc)51
-rw-r--r--chrome/browser/safe_browsing/safe_browsing_util.cc6
8 files changed, 238 insertions, 54 deletions
diff --git a/base/SConscript b/base/SConscript
index d9b1c8f..05b9ed1 100644
--- a/base/SConscript
+++ b/base/SConscript
@@ -80,7 +80,7 @@ if env['PLATFORM'] == 'win32':
'clipboard_util.cc',
'event_recorder.cc',
'file_version_info.cc',
- 'hmac.cc', # Depends on OpenSSL; Mac team will investigate.
+ 'hmac_win.cc',
# This group all depends on MessageLoop.
'idle_timer.cc',
diff --git a/base/base.xcodeproj/project.pbxproj b/base/base.xcodeproj/project.pbxproj
index 56fda9d..0a43e64 100644
--- a/base/base.xcodeproj/project.pbxproj
+++ b/base/base.xcodeproj/project.pbxproj
@@ -81,6 +81,8 @@
7BAE30E70E6D93A300C3F750 /* simple_thread.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BAE30E20E6D939800C3F750 /* simple_thread.cc */; };
7BAE38AC0E6EFDBA00C3F750 /* thread_local_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BAE38A90E6EFD9900C3F750 /* thread_local_posix.cc */; };
7BAE38AF0E6EFDC300C3F750 /* thread_local_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BAE38AB0E6EFD9900C3F750 /* thread_local_unittest.cc */; };
+ 7BAE392A0E6F4EEF00C3F750 /* hmac_mac.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BAE39220E6F4EEC00C3F750 /* hmac_mac.cc */; };
+ 7BAE392B0E6F4EF200C3F750 /* hmac_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BAE39240E6F4EEC00C3F750 /* hmac_unittest.cc */; };
7BAF501C0E50B84200CA8A07 /* base_paths.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF501B0E50B84200CA8A07 /* base_paths.cc */; };
7BAF50760E50B8F100CA8A07 /* file_version_info_mac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF50740E50B8F100CA8A07 /* file_version_info_mac.mm */; };
7BD8F4A10E65AA4600034DE9 /* process_util_posix.cc in Sources */ = {isa = PBXBuildFile; fileRef = 7BD8F49F0E65AA2400034DE9 /* process_util_posix.cc */; };
@@ -351,6 +353,9 @@
7BAE38A90E6EFD9900C3F750 /* thread_local_posix.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_local_posix.cc; sourceTree = "<group>"; };
7BAE38AA0E6EFD9900C3F750 /* thread_local_storage_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_local_storage_unittest.cc; sourceTree = "<group>"; };
7BAE38AB0E6EFD9900C3F750 /* thread_local_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thread_local_unittest.cc; sourceTree = "<group>"; };
+ 7BAE39220E6F4EEC00C3F750 /* hmac_mac.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hmac_mac.cc; sourceTree = "<group>"; };
+ 7BAE39240E6F4EEC00C3F750 /* hmac_unittest.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hmac_unittest.cc; sourceTree = "<group>"; };
+ 7BAE39BA0E6F576200C3F750 /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hmac.h; sourceTree = "<group>"; };
7BAF4F7B0E50A3BD00CA8A07 /* logging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logging.h; sourceTree = "<group>"; };
7BAF501B0E50B84200CA8A07 /* base_paths.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = base_paths.cc; sourceTree = "<group>"; };
7BAF50740E50B8F100CA8A07 /* file_version_info_mac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = file_version_info_mac.mm; sourceTree = "<group>"; };
@@ -768,6 +773,9 @@
93611B160E5A875D00F9405D /* histogram.cc */,
93611B170E5A875D00F9405D /* histogram.h */,
93611B190E5A878400F9405D /* histogram_unittest.cc */,
+ 7BAE39BA0E6F576200C3F750 /* hmac.h */,
+ 7BAE39220E6F4EEC00C3F750 /* hmac_mac.cc */,
+ 7BAE39240E6F4EEC00C3F750 /* hmac_unittest.cc */,
8254030F0D92D1E80006B936 /* iat_patch.cc */,
825403100D92D1E80006B936 /* iat_patch.h */,
825403110D92D1E80006B936 /* icu_util.cc */,
@@ -1210,6 +1218,7 @@
A5A0268E0E4A2BDC00498DA9 /* file_util_posix.cc in Sources */,
7BAF50760E50B8F100CA8A07 /* file_version_info_mac.mm in Sources */,
93611B180E5A875D00F9405D /* histogram.cc in Sources */,
+ 7BAE392A0E6F4EEF00C3F750 /* hmac_mac.cc in Sources */,
8216A5060E34DBDD00EE374C /* icu_util.cc in Sources */,
ABF4B9AF0DC2BC6200A6E319 /* json_reader.cc in Sources */,
ABF4B9B00DC2BC6500A6E319 /* json_writer.cc in Sources */,
@@ -1284,6 +1293,7 @@
A5CE1D2B0E55F4D800AD0606 /* file_util_unittest.cc in Sources */,
7B78D3910E54FE0100609465 /* file_version_info_unittest.cc in Sources */,
93611B1A0E5A878400F9405D /* histogram_unittest.cc in Sources */,
+ 7BAE392B0E6F4EF200C3F750 /* hmac_unittest.cc in Sources */,
AB956E0A0E5DDC0900BBE9D8 /* image_operations_unittest.cc in Sources */,
7B78D3920E54FE0100609465 /* json_reader_unittest.cc in Sources */,
7B78D3930E54FE0100609465 /* json_writer_unittest.cc in Sources */,
diff --git a/base/build/base.vcproj b/base/build/base.vcproj
index add54fe..27d7e3c 100644
--- a/base/build/base.vcproj
+++ b/base/build/base.vcproj
@@ -310,11 +310,11 @@
>
</File>
<File
- RelativePath="..\hmac.cc"
+ RelativePath="..\hmac.h"
>
</File>
<File
- RelativePath="..\hmac.h"
+ RelativePath="..\hmac_win.cc"
>
</File>
<File
diff --git a/base/hmac.h b/base/hmac.h
index dac4e82..f9c0e604 100644
--- a/base/hmac.h
+++ b/base/hmac.h
@@ -1,20 +1,26 @@
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-//
+
// Utility class for calculating the HMAC for a given message. We currently
// only support SHA1 for the hash algorithm, but this can be extended easily.
-#ifndef BASE_HMAC_H__
-#define BASE_HMAC_H__
+#ifndef BASE_HMAC_H_
+#define BASE_HMAC_H_
+
+#include "build/build_config.h"
+#if defined(OS_WIN)
#include <windows.h>
#include <wincrypt.h>
+#endif
#include <string>
#include "base/basictypes.h"
+namespace base {
+
class HMAC {
public:
// The set of supported hash functions. Extend as required.
@@ -25,16 +31,17 @@ class HMAC {
HMAC(HashAlgorithm hash_alg, const unsigned char* key, int key_length);
~HMAC();
- // Returns the HMAC in 'digest' for the message in 'data' and the key
- // specified in the contructor.
+ // Calculates the HMAC for the message in |data| using the algorithm and key
+ // supplied to the constructor. The HMAC is returned in |digest|, which
+ // has |digest_length| bytes of storage available.
bool Sign(const std::string& data, unsigned char* digest, int digest_length);
private:
+#if defined(OS_POSIX)
+ HashAlgorithm hash_alg_;
+ std::string key_;
+#elif defined(OS_WIN)
// Import the key so that we don't have to store it ourself.
- // TODO(paulg): Bug: http://b/1084719, 'ImportKey' will not currently work on
- // Windows 2000 since it requires special handling for importing
- // keys. See this link for details:
- // http://www.derkeiler.com/Newsgroups/microsoft.public.platformsdk.security/2004-06/0270.html
void ImportKey(const unsigned char* key, int key_length);
// Returns the SHA1 hash of 'data' and 'key' in 'digest'. If there was any
@@ -43,10 +50,6 @@ class HMAC {
unsigned char* digest,
int digest_length);
- // Required for the SHA1 key_blob struct. We limit this to 16 bytes since
- // Windows 2000 doesn't support keys larger than that.
- static const int kMaxKeySize = 16;
-
// The hash algorithm to use.
HashAlgorithm hash_alg_;
@@ -54,10 +57,11 @@ class HMAC {
HCRYPTPROV provider_;
HCRYPTHASH hash_;
HCRYPTKEY hkey_;
+#endif // OS_WIN
- DISALLOW_EVIL_CONSTRUCTORS(HMAC);
+ DISALLOW_COPY_AND_ASSIGN(HMAC);
};
+} // namespace base
-#endif // BASE_HMAC_H__
-
+#endif // BASE_HMAC_H_
diff --git a/base/hmac_mac.cc b/base/hmac_mac.cc
new file mode 100644
index 0000000..0542a70
--- /dev/null
+++ b/base/hmac_mac.cc
@@ -0,0 +1,52 @@
+// Copyright (c) 2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/hmac.h"
+
+#include <CommonCrypto/CommonHMAC.h>
+
+#include "base/logging.h"
+
+namespace base {
+
+HMAC::HMAC(HashAlgorithm hash_alg, const unsigned char* key, int key_length)
+ : hash_alg_(hash_alg),
+ key_(reinterpret_cast<const char*>(key), key_length) {
+}
+
+HMAC::~HMAC() {
+ // Zero out key copy.
+ key_.assign(key_.length(), std::string::value_type());
+ key_.clear();
+ key_.reserve(0);
+}
+
+bool HMAC::Sign(const std::string& data,
+ unsigned char* digest,
+ int digest_length) {
+ CCHmacAlgorithm algorithm;
+ int algorithm_digest_length;
+ switch (hash_alg_) {
+ case SHA1:
+ algorithm = kCCHmacAlgSHA1;
+ algorithm_digest_length = CC_SHA1_DIGEST_LENGTH;
+ break;
+ default:
+ NOTREACHED();
+ return false;
+ }
+
+ if (digest_length < algorithm_digest_length) {
+ NOTREACHED();
+ return false;
+ }
+
+ CCHmac(algorithm,
+ key_.data(), key_.length(), data.data(), data.length(),
+ digest);
+
+ return true;
+}
+
+} // namespace base
diff --git a/base/hmac_unittest.cc b/base/hmac_unittest.cc
index 3ff2f9f..9881369 100644
--- a/base/hmac_unittest.cc
+++ b/base/hmac_unittest.cc
@@ -7,21 +7,23 @@
#include "base/hmac.h"
#include "testing/gtest/include/gtest/gtest.h"
-static const int kKeySize = 16;
static const int kDigestSize = 20;
-// Client key.
-const unsigned char kClientKey[kKeySize] =
- { 0xbf, 0xf6, 0x83, 0x4b, 0x3e, 0xa3, 0x23, 0xdd,
- 0x96, 0x78, 0x70, 0x8e, 0xa1, 0x9d, 0x3b, 0x40 };
+TEST(HMACTest, HmacSafeBrowsingResponseTest) {
+ const int kKeySize = 16;
+
+ // Client key.
+ const unsigned char kClientKey[kKeySize] =
+ { 0xbf, 0xf6, 0x83, 0x4b, 0x3e, 0xa3, 0x23, 0xdd,
+ 0x96, 0x78, 0x70, 0x8e, 0xa1, 0x9d, 0x3b, 0x40 };
-// Expected HMAC result using kMessage and kClientKey.
-const unsigned char kReceivedHmac[kDigestSize] =
- { 0xb9, 0x3c, 0xd6, 0xf0, 0x49, 0x47, 0xe2, 0x52,
- 0x59, 0x7a, 0xbd, 0x1f, 0x2b, 0x4c, 0x83, 0xad,
- 0x86, 0xd2, 0x48, 0x85 };
+ // Expected HMAC result using kMessage and kClientKey.
+ const unsigned char kReceivedHmac[kDigestSize] =
+ { 0xb9, 0x3c, 0xd6, 0xf0, 0x49, 0x47, 0xe2, 0x52,
+ 0x59, 0x7a, 0xbd, 0x1f, 0x2b, 0x4c, 0x83, 0xad,
+ 0x86, 0xd2, 0x48, 0x85 };
-const char kMessage[] =
+ const char kMessage[] =
"n:1896\ni:goog-malware-shavar\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shav"
"ar_s_445-450\nu:s.ytimg.com/safebrowsing/rd/goog-malware-shavar_s_439-444\nu:s"
".ytimg.com/safebrowsing/rd/goog-malware-shavar_s_437\nu:s.ytimg.com/safebrowsi"
@@ -47,12 +49,115 @@ const char kMessage[] =
"-phish-shavar_a_2629-2631\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2"
"626-2628\nu:s.ytimg.com/safebrowsing/rd/goog-phish-shavar_a_2625\n";
-TEST(HMACTest, HmacSafeBrowsingResponseTest) {
std::string message_data(kMessage);
- HMAC hmac(HMAC::SHA1, kClientKey, kKeySize);
+ base::HMAC hmac(base::HMAC::SHA1, kClientKey, kKeySize);
unsigned char calculated_hmac[kDigestSize];
EXPECT_TRUE(hmac.Sign(message_data, calculated_hmac, kDigestSize));
EXPECT_EQ(memcmp(kReceivedHmac, calculated_hmac, kDigestSize), 0);
}
+
+// Test cases from RFC 2202 section 3
+TEST(HMACTest, RFC2202TestCases) {
+ const struct {
+ const char *key;
+ const int key_len;
+ const char *data;
+ const int data_len;
+ const char *digest;
+ } cases[] = {
+ { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
+ "\x0B\x0B\x0B\x0B", 20,
+ "Hi There", 8,
+ "\xB6\x17\x31\x86\x55\x05\x72\x64\xE2\x8B\xC0\xB6\xFB\x37\x8C\x8E"
+ "\xF1\x46\xBE\x00" },
+ { "Jefe", 4,
+ "what do ya want for nothing?", 28,
+ "\xEF\xFC\xDF\x6A\xE5\xEB\x2F\xA2\xD2\x74\x16\xD5\xF1\x84\xDF\x9C"
+ "\x25\x9A\x7C\x79" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA", 20,
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
+ "\xDD\xDD", 50,
+ "\x12\x5D\x73\x42\xB9\xAC\x11\xCD\x91\xA3\x9A\xF4\x8A\xA1\x7B\x4F"
+ "\x63\xF1\x75\xD3" },
+ { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
+ "\xCD\xCD", 50,
+ "\x4C\x90\x07\xF4\x02\x62\x50\xC6\xBC\x84\x14\xF9\xBF\x50\xC8\x6C"
+ "\x2D\x72\x35\xDA" },
+ { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
+ "\x0C\x0C\x0C\x0C", 20,
+ "Test With Truncation", 20,
+ "\x4C\x1A\x03\x42\x4B\x55\xE0\x7F\xE7\xF2\x7B\xE1\xD5\x8B\xB9\x32"
+ "\x4A\x9A\x5A\x04" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
+ 80,
+ "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+ "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55"
+ "\xED\x40\x21\x12" },
+ { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA",
+ 80,
+ "Test Using Larger Than Block-Size Key and Larger "
+ "Than One Block-Size Data", 73,
+ "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08"
+ "\xBB\xFF\x1A\x91" }
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
+ base::HMAC hmac(base::HMAC::SHA1,
+ reinterpret_cast<const unsigned char*>(cases[i].key),
+ cases[i].key_len);
+ std::string data_string(cases[i].data, cases[i].data_len);
+ unsigned char digest[kDigestSize];
+ EXPECT_TRUE(hmac.Sign(data_string, digest, kDigestSize));
+ EXPECT_EQ(memcmp(cases[i].digest, digest, kDigestSize), 0);
+ }
+}
+
+TEST(HMACTest, HMACObjectReuse) {
+ const char *key =
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
+ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA";
+ const int key_len = 80;
+
+ const struct {
+ const char *data;
+ const int data_len;
+ const char *digest;
+ } cases[] = {
+ { "Test Using Larger Than Block-Size Key - Hash Key First", 54,
+ "\xAA\x4A\xE5\xE1\x52\x72\xD0\x0E\x95\x70\x56\x37\xCE\x8A\x3B\x55"
+ "\xED\x40\x21\x12" },
+ { "Test Using Larger Than Block-Size Key and Larger "
+ "Than One Block-Size Data", 73,
+ "\xE8\xE9\x9D\x0F\x45\x23\x7D\x78\x6D\x6B\xBA\xA7\x96\x5C\x78\x08"
+ "\xBB\xFF\x1A\x91" }
+ };
+
+ base::HMAC hmac(base::HMAC::SHA1,
+ reinterpret_cast<const unsigned char*>(key), key_len);
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
+ std::string data_string(cases[i].data, cases[i].data_len);
+ unsigned char digest[kDigestSize];
+ EXPECT_TRUE(hmac.Sign(data_string, digest, kDigestSize));
+ EXPECT_EQ(memcmp(cases[i].digest, digest, kDigestSize), 0);
+ }
+}
diff --git a/base/hmac.cc b/base/hmac_win.cc
index 074491d..83ec26b 100644
--- a/base/hmac.cc
+++ b/base/hmac_win.cc
@@ -3,8 +3,14 @@
// found in the LICENSE file.
#include "base/hmac.h"
+
+#include <algorithm>
+#include <vector>
+
#include "base/logging.h"
+namespace base {
+
HMAC::HMAC(HashAlgorithm hash_alg, const unsigned char* key, int key_length)
: hash_alg_(hash_alg),
provider_(NULL),
@@ -41,30 +47,36 @@ bool HMAC::Sign(const std::string& data,
}
void HMAC::ImportKey(const unsigned char* key, int key_length) {
- if (key_length > kMaxKeySize) {
- NOTREACHED();
- return;
- }
-
- struct {
+ // This code doesn't work on Win2k because PLAINTEXTKEYBLOB and
+ // CRYPT_IPSEC_HMAC_KEY are not supported on Windows 2000. PLAINTEXTKEYBLOB
+ // allows the import of an unencrypted key. For Win2k support, a cubmbersome
+ // exponent-of-one key procedure must be used:
+ // http://support.microsoft.com/kb/228786/en-us
+ // CRYPT_IPSEC_HMAC_KEY allows keys longer than 16 bytes.
+
+ struct KeyBlob {
BLOBHEADER header;
DWORD key_size;
- BYTE key_data[kMaxKeySize];
- } key_blob;
- key_blob.header.bType = PLAINTEXTKEYBLOB;
- key_blob.header.bVersion = CUR_BLOB_VERSION;
- key_blob.header.reserved = 0;
- key_blob.header.aiKeyAlg = CALG_RC2;
- key_blob.key_size = key_length;
- memcpy(key_blob.key_data, key, key_length);
-
- if (!CryptImportKey(provider_,
- reinterpret_cast<const BYTE *>(&key_blob),
- sizeof(key_blob), 0, 0, &hkey_))
+ BYTE key_data[1];
+ };
+ size_t key_blob_size = std::max(offsetof(KeyBlob, key_data) + key_length,
+ sizeof(KeyBlob));
+ std::vector<BYTE> key_blob_storage = std::vector<BYTE>(key_blob_size);
+ KeyBlob* key_blob = reinterpret_cast<KeyBlob*>(&key_blob_storage[0]);
+ key_blob->header.bType = PLAINTEXTKEYBLOB;
+ key_blob->header.bVersion = CUR_BLOB_VERSION;
+ key_blob->header.reserved = 0;
+ key_blob->header.aiKeyAlg = CALG_RC2;
+ key_blob->key_size = key_length;
+ memcpy(key_blob->key_data, key, key_length);
+
+ if (!CryptImportKey(provider_, &key_blob_storage[0], key_blob_storage.size(),
+ 0, CRYPT_IPSEC_HMAC_KEY, &hkey_)) {
hkey_ = NULL;
+ }
// Destroy the copy of the key.
- SecureZeroMemory(key_blob.key_data, key_length);
+ SecureZeroMemory(key_blob->key_data, key_length);
}
bool HMAC::SignWithSHA1(const std::string& data,
@@ -95,3 +107,4 @@ bool HMAC::SignWithSHA1(const std::string& data,
return true;
}
+} // namespace base
diff --git a/chrome/browser/safe_browsing/safe_browsing_util.cc b/chrome/browser/safe_browsing/safe_browsing_util.cc
index 1731d75..9ddfbb3 100644
--- a/chrome/browser/safe_browsing/safe_browsing_util.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_util.cc
@@ -147,9 +147,9 @@ bool VerifyMAC(const std::string& key, const std::string& mac,
std::string decoded_mac;
net::Base64Decode(mac_copy, &decoded_mac);
- HMAC hmac(HMAC::SHA1,
- reinterpret_cast<const unsigned char*>(decoded_key.data()),
- static_cast<int>(decoded_key.length()));
+ base::HMAC hmac(base::HMAC::SHA1,
+ reinterpret_cast<const unsigned char*>(decoded_key.data()),
+ static_cast<int>(decoded_key.length()));
const std::string data_str(data, data_length);
unsigned char digest[kSafeBrowsingMacDigestSize];
if (!hmac.Sign(data_str, digest, kSafeBrowsingMacDigestSize))