[go: nahoru, domu]

Move crypto_helpers from sync to crypto

crypto_helpers only depends on resources in base and is used by sync and
password_manager.

BUG=
TEST=


Review URL: http://codereview.chromium.org/6873156

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@84223 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/rand_util.cc b/base/rand_util.cc
index b823fa0..4140e9a 100644
--- a/base/rand_util.cc
+++ b/base/rand_util.cc
@@ -10,6 +10,7 @@
 
 #include "base/basictypes.h"
 #include "base/logging.h"
+#include "base/string_util.h"
 
 namespace base {
 
@@ -47,19 +48,19 @@
   return base::RandUint64() % max;
 }
 
-std::string RandBytesAsString(size_t length) {
-  const size_t kBitsPerChar = 8;
-  const int kCharsPerInt64 = sizeof(uint64)/sizeof(char);
-
-  std::string result(length, '\0');
-  uint64 entropy = 0;
-  for (size_t i = 0; i < result.size(); ++i) {
-    if (i % kCharsPerInt64 == 0)
-      entropy = RandUint64();
-    result[i] = static_cast<char>(entropy);
-    entropy >>= kBitsPerChar;
+void RandBytes(void* output, size_t output_length) {
+  uint64 random_int;
+  size_t random_int_size = sizeof(random_int);
+  for (size_t i = 0; i < output_length; i += random_int_size) {
+    random_int = base::RandUint64();
+    size_t copy_count = std::min(output_length - i, random_int_size);
+    memcpy(((uint8*)output) + i, &random_int, copy_count);
   }
+}
 
+std::string RandBytesAsString(size_t length) {
+  std::string result;
+  RandBytes(WriteInto(&result, length + 1), length);
   return result;
 }
 
diff --git a/base/rand_util.h b/base/rand_util.h
index d10cc8b..6bfbcb4 100644
--- a/base/rand_util.h
+++ b/base/rand_util.h
@@ -33,7 +33,14 @@
 // the range [0, 1). Thread-safe.
 BASE_API double BitsToOpenEndedUnitInterval(uint64 bits);
 
-// Returns a random string of the specified length.
+// Fills |output_length| bytes of |output| with cryptographically strong random
+// data.
+BASE_API void RandBytes(void* output, size_t output_length);
+
+// Fills a string of length |length| with with cryptographically strong random
+// data and returns it.
+//
+// Not that this is a variation of |RandBytes| with a different return type.
 BASE_API std::string RandBytesAsString(size_t length);
 
 }  // namespace base
diff --git a/base/rand_util_unittest.cc b/base/rand_util_unittest.cc
index 3bdb815..d7fa37af 100644
--- a/base/rand_util_unittest.cc
+++ b/base/rand_util_unittest.cc
@@ -28,6 +28,19 @@
   EXPECT_LE(0.0, number);
 }
 
+TEST(RandUtilTest, RandBytes) {
+  const size_t buffer_size = 145;
+  char buffer[buffer_size];
+  memset(buffer, 0, buffer_size);
+  base::RandBytes(buffer, buffer_size);
+  char accumulator = 0;
+  for(size_t i = 0; i < buffer_size; ++i)
+    accumulator |= buffer[i];
+  // In theory this test can fail, but it won't before the universe dies of
+  // heat death.
+  EXPECT_NE(0, accumulator);
+}
+
 TEST(RandUtilTest, RandBytesAsString) {
   std::string random_string = base::RandBytesAsString(0);
   EXPECT_EQ(0U, random_string.size());
diff --git a/chrome/browser/password_manager/encryptor_password_mac.mm b/chrome/browser/password_manager/encryptor_password_mac.mm
index a955043..ffdf24ce 100644
--- a/chrome/browser/password_manager/encryptor_password_mac.mm
+++ b/chrome/browser/password_manager/encryptor_password_mac.mm
@@ -7,7 +7,7 @@
 #import <Security/Security.h>
 
 #include "chrome/browser/keychain_mac.h"
-#include "chrome/browser/sync/util/crypto_helpers.h"
+#include "chrome/common/random.h"
 #include "ui/base/l10n/l10n_util.h"
 
 namespace {
@@ -18,7 +18,7 @@
 std::string AddRandomPasswordToKeychain(const MacKeychain& keychain,
                                         const std::string& service_name,
                                         const std::string& account_name) {
-  std::string password = Generate128BitRandomHexString();
+  std::string password = Generate128BitRandomBase64String();
   void* password_data =
       const_cast<void*>(static_cast<const void*>(password.data()));
 
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc
index 3e17d6f3..6cf7408 100644
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -62,7 +62,6 @@
 #include "chrome/browser/sync/syncable/model_type.h"
 #include "chrome/browser/sync/syncable/nigori_util.h"
 #include "chrome/browser/sync/syncable/syncable.h"
-#include "chrome/browser/sync/util/crypto_helpers.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/deprecated/event_sys.h"
 #include "chrome/common/net/gaia/gaia_authenticator.h"
diff --git a/chrome/browser/sync/syncable/directory_backing_store.cc b/chrome/browser/sync/syncable/directory_backing_store.cc
index 7f5721e6..7983c73 100644
--- a/chrome/browser/sync/syncable/directory_backing_store.cc
+++ b/chrome/browser/sync/syncable/directory_backing_store.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
 
@@ -24,7 +24,7 @@
 #include "chrome/browser/sync/protocol/sync.pb.h"
 #include "chrome/browser/sync/syncable/syncable-inl.h"
 #include "chrome/browser/sync/syncable/syncable_columns.h"
-#include "chrome/browser/sync/util/crypto_helpers.h"
+#include "chrome/common/random.h"
 #include "chrome/common/sqlite_utils.h"
 #include "third_party/sqlite/sqlite3.h"
 
@@ -61,7 +61,7 @@
 }
 
 string GenerateCacheGUID() {
-  return Generate128BitRandomHexString();
+  return Generate128BitRandomBase64String();
 }
 
 }  // namespace
diff --git a/chrome/browser/sync/syncable/syncable.cc b/chrome/browser/sync/syncable/syncable.cc
index 0674457ec..9a83458 100644
--- a/chrome/browser/sync/syncable/syncable.cc
+++ b/chrome/browser/sync/syncable/syncable.cc
@@ -49,7 +49,6 @@
 #include "chrome/browser/sync/syncable/syncable_changes_version.h"
 #include "chrome/browser/sync/syncable/syncable_columns.h"
 #include "chrome/browser/sync/syncable/syncable_enum_conversions.h"
-#include "chrome/browser/sync/util/crypto_helpers.h"
 #include "chrome/common/deprecated/event_sys-inl.h"
 #include "net/base/escape.h"
 
diff --git a/chrome/browser/sync/util/crypto_helpers.cc b/chrome/browser/sync/util/crypto_helpers.cc
deleted file mode 100644
index 36c5586..0000000
--- a/chrome/browser/sync/util/crypto_helpers.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2010 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 "chrome/browser/sync/util/crypto_helpers.h"
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/format_macros.h"
-#include "base/logging.h"
-#include "base/base64.h"
-#include "base/rand_util.h"
-#include "base/string_number_conversions.h"
-#include "base/string_util.h"
-
-using std::string;
-using std::vector;
-
-MD5Calculator::MD5Calculator() {
-  MD5Init(&context_);
-}
-
-MD5Calculator::~MD5Calculator() {}
-
-void MD5Calculator::AddData(const unsigned char* data, int length) {
-  CHECK(bin_digest_.empty());
-  MD5Update(&context_, data, length);
-}
-
-void MD5Calculator::CalcDigest() {
-  if (bin_digest_.empty()) {
-    MD5Digest digest;
-    MD5Final(&digest, &context_);
-    bin_digest_.assign(digest.a, digest.a + arraysize(digest.a));
-  }
-}
-
-const vector<uint8>& MD5Calculator::GetDigest() {
-  CalcDigest();
-  return bin_digest_;
-}
-
-std::string MD5Calculator::GetHexDigest() {
-  CalcDigest();
-  string hex = base::HexEncode(reinterpret_cast<char*>(&bin_digest_.front()),
-                               bin_digest_.size());
-  StringToLowerASCII(&hex);
-  return hex;
-}
-
-void GetRandomBytes(char* output, int output_length) {
-  uint64 random_int;
-  const char* random_int_bytes = reinterpret_cast<const char*>(&random_int);
-  int random_int_size = sizeof(random_int);
-  for (int i = 0; i < output_length; i += random_int_size) {
-    random_int = base::RandUint64();
-    int copy_count = std::min(output_length - i, random_int_size);
-    memcpy(output + i, random_int_bytes, copy_count);
-  }
-}
-
-string Generate128BitRandomHexString() {
-  const int kNumberBytes = 128 / 8;
-  std::string random_bytes(kNumberBytes, ' ');
-  GetRandomBytes(&random_bytes[0], kNumberBytes);
-  std::string base64_encoded_bytes;
-  base::Base64Encode(random_bytes, &base64_encoded_bytes);
-  return base64_encoded_bytes;
-}
diff --git a/chrome/browser/sync/util/crypto_helpers.h b/chrome/browser/sync/util/crypto_helpers.h
deleted file mode 100644
index 34b36f4..0000000
--- a/chrome/browser/sync/util/crypto_helpers.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2010 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.
-
-#ifndef CHROME_BROWSER_SYNC_UTIL_CRYPTO_HELPERS_H_
-#define CHROME_BROWSER_SYNC_UTIL_CRYPTO_HELPERS_H_
-#pragma once
-
-#include <string>
-#include <vector>
-
-// An object to handle calculation of MD5 sums.
-#include "base/basictypes.h"
-#include "base/md5.h"
-#include "base/port.h"
-
-class MD5Calculator {
- protected:
-  MD5Context context_;
-  std::vector<uint8> bin_digest_;
-
-  void CalcDigest();
- public:
-  MD5Calculator();
-  ~MD5Calculator();
-  void AddData(const uint8* data, int length);
-  void AddData(const char* data, int length) {
-    AddData(reinterpret_cast<const uint8*>(data), length);
-  }
-  std::string GetHexDigest();
-  const std::vector<uint8>& GetDigest();
- private:
-  DISALLOW_COPY_AND_ASSIGN(MD5Calculator);
-};
-
-void GetRandomBytes(char* output, int output_length);
-std::string Generate128BitRandomHexString();
-
-#endif  // CHROME_BROWSER_SYNC_UTIL_CRYPTO_HELPERS_H_
diff --git a/chrome/browser/sync/util/crypto_helpers_unittest.cc b/chrome/browser/sync/util/crypto_helpers_unittest.cc
deleted file mode 100644
index 7be1270..0000000
--- a/chrome/browser/sync/util/crypto_helpers_unittest.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2009 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 "chrome/browser/sync/util/crypto_helpers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(ChecksumTest, MD5ChecksumTest) {
-  uint8 buffer[256];
-  for (unsigned int i = 0; i < arraysize(buffer); ++i) {
-    buffer[i] = i;
-  }
-  MD5Calculator md5;
-  md5.AddData(buffer, arraysize(buffer));
-  std::string checksum("e2c865db4162bed963bfaa9ef6ac18f0");
-  ASSERT_EQ(checksum, md5.GetHexDigest());
-}
-
-TEST(CryptoHelpers, GetRandomBytes) {
-  for (int i = 1; i < 25; ++i) {
-    std::string random_bytes(i+1, ' ');
-    do {
-      GetRandomBytes(&random_bytes[0], i);
-      ASSERT_EQ(random_bytes[i], ' ');
-    } while (random_bytes[i - 1] == ' ');
-  }
-}
diff --git a/chrome/browser/sync/util/user_settings.cc b/chrome/browser/sync/util/user_settings.cc
index d49a071..b842c43 100644
--- a/chrome/browser/sync/util/user_settings.cc
+++ b/chrome/browser/sync/util/user_settings.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
 //
@@ -18,10 +18,12 @@
 #include <vector>
 
 #include "base/file_util.h"
+#include "base/md5.h"
+#include "base/rand_util.h"
 #include "base/string_util.h"
 #include "chrome/browser/sync/syncable/directory_manager.h"  // For migration.
-#include "chrome/browser/sync/util/crypto_helpers.h"
 #include "chrome/browser/sync/util/data_encryption.h"
+#include "chrome/common/random.h"
 #include "chrome/common/sqlite_utils.h"
 
 using std::numeric_limits;
@@ -166,7 +168,7 @@
     SQLStatement statement;
     statement.prepare(dbhandle,
                       "INSERT INTO client_id values ( ? )");
-    statement.bind_string(0, Generate128BitRandomHexString());
+    statement.bind_string(0, Generate128BitRandomBase64String());
     if (SQLITE_DONE != statement.step()) {
       LOG(FATAL) << "INSERT INTO client_id\n" << sqlite3_errmsg(dbhandle);
     }
@@ -270,13 +272,12 @@
 // We use 10 bits of data from the MD5 digest as the hash.
 const int32 kHashMask = 0x3FF;
 
-int32 GetHashFromDigest(const vector<uint8>& digest) {
+int32 GetHashFromDigest(MD5Digest& digest) {
   int32 hash = 0;
   int32 mask = kHashMask;
-  for (vector<uint8>::const_iterator i = digest.begin(); i != digest.end();
-       ++i) {
+  for (size_t i = 0; i < sizeof(digest.a); ++i) {
     hash = hash << 8;
-    hash = hash | (*i & kHashMask);
+    hash = hash | (digest.a[i] & kHashMask);
     mask = mask >> 8;
     if (0 == mask)
       break;
@@ -351,12 +352,16 @@
                                        const string& password) {
   // Save one-way hashed password:
   char binary_salt[kSaltSize];
-  GetRandomBytes(binary_salt, sizeof(binary_salt));
+  base::RandBytes(binary_salt, sizeof(binary_salt));
 
   const string salt = APEncode(string(binary_salt, sizeof(binary_salt)));
-  MD5Calculator md5;
-  md5.AddData(salt.data(), salt.size());
-  md5.AddData(password.data(), password.size());
+  MD5Context md5_context;
+  MD5Init(&md5_context);
+  MD5Update(&md5_context, salt.data(), salt.size());
+  MD5Update(&md5_context, password.data(), password.size());
+  MD5Digest md5_digest;
+  MD5Final(&md5_digest, &md5_context);
+
   ScopedDBHandle dbhandle(this);
   SQLTransaction transaction(dbhandle.get());
   transaction.BeginExclusive();
@@ -367,7 +372,7 @@
                       " values ( ?, ?, ? )");
     statement.bind_string(0, email);
     statement.bind_string(1, PASSWORD_HASH);
-    statement.bind_int(2, GetHashFromDigest(md5.GetDigest()));
+    statement.bind_int(2, GetHashFromDigest(md5_digest));
     if (SQLITE_DONE != statement.step()) {
       LOG(FATAL) << sqlite3_errmsg(dbhandle.get());
     }
@@ -413,10 +418,13 @@
   CHECK(SQLITE_DONE == query_result);
   if (salt.empty() || hash == kInvalidHash)
     return false;
-  MD5Calculator md5;
-  md5.AddData(salt.data(), salt.size());
-  md5.AddData(password.data(), password.size());
-  return hash == GetHashFromDigest(md5.GetDigest());
+  MD5Context md5_context;
+  MD5Init(&md5_context);
+  MD5Update(&md5_context, salt.data(), salt.size());
+  MD5Update(&md5_context, password.data(), password.size());
+  MD5Digest md5_digest;
+  MD5Final(&md5_digest, &md5_context);
+  return hash == GetHashFromDigest(md5_digest);
 }
 
 void UserSettings::SwitchUser(const string& username) {
diff --git a/chrome/browser/sync/util/user_settings_win.cc b/chrome/browser/sync/util/user_settings_win.cc
index 94090ac..d2b0447 100644
--- a/chrome/browser/sync/util/user_settings_win.cc
+++ b/chrome/browser/sync/util/user_settings_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 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.
 
@@ -7,7 +7,6 @@
 #include <string>
 
 #include "base/logging.h"
-#include "chrome/browser/sync/util/crypto_helpers.h"
 #include "chrome/browser/sync/util/data_encryption.h"
 #include "chrome/common/sqlite_utils.h"
 
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 9bd14c6..2af5f7a 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -626,8 +626,6 @@
         'browser/sync/syncable/syncable_id.h',
         'browser/sync/syncable/syncable_enum_conversions.cc',
         'browser/sync/syncable/syncable_enum_conversions.h',
-        'browser/sync/util/crypto_helpers.cc',
-        'browser/sync/util/crypto_helpers.h',
         'browser/sync/util/cryptographer.cc',
         'browser/sync/util/cryptographer.h',
         'browser/sync/util/dbgq.h',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index d488416..e50fbc9 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -211,6 +211,8 @@
         'common/pref_store.cc',
         'common/pref_store.h',
         'common/print_messages.h',
+        'common/random.cc',
+        'common/random.h',
         'common/remoting/chromoting_host_info.cc',
         'common/remoting/chromoting_host_info.h',
         'common/render_messages.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index ed473fc..3285adb8 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1827,6 +1827,7 @@
         'common/net/gaia/gaia_oauth_client_unittest.cc',
         'common/net/gaia/google_service_auth_error_unittest.cc',
         'common/net/url_fetcher_unittest.cc',
+        'common/random_unittest.cc',
         'common/service_process_util_unittest.cc',
         'common/switch_utils_unittest.cc',
         'common/thumbnail_score_unittest.cc',
@@ -2970,7 +2971,6 @@
         'browser/sync/syncable/syncable_enum_conversions_unittest.cc',
         'browser/sync/syncable/syncable_id_unittest.cc',
         'browser/sync/syncable/syncable_unittest.cc',
-        'browser/sync/util/crypto_helpers_unittest.cc',
         'browser/sync/util/data_encryption_unittest.cc',
         'browser/sync/util/extensions_activity_monitor_unittest.cc',
         'browser/sync/util/protobuf_unittest.cc',
diff --git a/chrome/common/random.cc b/chrome/common/random.cc
new file mode 100644
index 0000000..303d296
--- /dev/null
+++ b/chrome/common/random.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2011 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 "chrome/common/random.h"
+
+#include <string>
+
+#include "base/base64.h"
+#include "base/rand_util.h"
+
+std::string Generate128BitRandomBase64String() {
+  const int kNumberBytes = 128 / 8;
+  std::string base64_encoded_bytes;
+  base::Base64Encode(base::RandBytesAsString(kNumberBytes),
+                     &base64_encoded_bytes);
+  return base64_encoded_bytes;
+}
diff --git a/chrome/common/random.h b/chrome/common/random.h
new file mode 100644
index 0000000..0ad538f
--- /dev/null
+++ b/chrome/common/random.h
@@ -0,0 +1,15 @@
+// Copyright (c) 2011 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.
+
+#ifndef CHROME_COMMON_RANDOM_H_
+#define CHROME_COMMON_RANDOM_H_
+#pragma once
+
+#include <string>
+
+// Generate128BitRandomBase64String returns a string of length 24 containing
+// cryptographically strong random data encoded in base64.
+std::string Generate128BitRandomBase64String();
+
+#endif  // CHROME_COMMON_RANDOM_H_
diff --git a/chrome/common/random_unittest.cc b/chrome/common/random_unittest.cc
new file mode 100644
index 0000000..c1843e0
--- /dev/null
+++ b/chrome/common/random_unittest.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h"
+
+#include "chrome/common/random.h"
+
+TEST(SyncRandomTest, Generate128BitRandomBase64String) {
+  std::string random_string = Generate128BitRandomBase64String();
+  EXPECT_EQ(24U, random_string.size());
+  char accumulator = 0;
+  for (size_t i = 0; i < random_string.size(); ++i)
+    accumulator |= random_string[i];
+  // In theory this test can fail, but it won't before the universe dies of
+  // heat death.
+  EXPECT_NE(0, accumulator);
+}
diff --git a/ppapi/shared_impl/crypto_impl.cc b/ppapi/shared_impl/crypto_impl.cc
index 6295bb2..f8e4aa2 100644
--- a/ppapi/shared_impl/crypto_impl.cc
+++ b/ppapi/shared_impl/crypto_impl.cc
@@ -11,14 +11,7 @@
 
 // static
 void CryptoImpl::GetRandomBytes(char* buffer, uint32_t num_bytes) {
-  // Note: this is a copy of WebKitClientImpl::cryptographicallyRandomValues.
-  uint64 bytes = 0;
-  for (uint32_t i = 0; i < num_bytes; ++i) {
-    uint32_t offset = i % sizeof(bytes);
-    if (!offset)
-      bytes = base::RandUint64();
-    buffer[i] = reinterpret_cast<char*>(&bytes)[offset];
-  }
+  base::RandBytes(buffer, num_bytes);
 }
 
 }  // namespace shared_impl
diff --git a/webkit/glue/webkitclient_impl.cc b/webkit/glue/webkitclient_impl.cc
index b2dd53a8..882cb42 100644
--- a/webkit/glue/webkitclient_impl.cc
+++ b/webkit/glue/webkitclient_impl.cc
@@ -451,13 +451,7 @@
 
 void WebKitClientImpl::cryptographicallyRandomValues(
     unsigned char* buffer, size_t length) {
-  uint64 bytes = 0;
-  for (size_t i = 0; i < length; ++i) {
-    size_t offset = i % sizeof(bytes);
-    if (!offset)
-      bytes = base::RandUint64();
-    buffer[i] = reinterpret_cast<unsigned char*>(&bytes)[offset];
-  }
+  base::RandBytes(buffer, length);
 }
 
 void WebKitClientImpl::setSharedTimerFiredFunction(void (*func)()) {