Refactoring key generation and export util code to make mocking possible.

BUG=chromium-os:4485
TEST=unit tests

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@53292 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/chromeos/login/owner_manager.cc b/chrome/browser/chromeos/login/owner_key_utils.cc
similarity index 70%
rename from chrome/browser/chromeos/login/owner_manager.cc
rename to chrome/browser/chromeos/login/owner_key_utils.cc
index 69adbc1..916d9c7 100644
--- a/chrome/browser/chromeos/login/owner_manager.cc
+++ b/chrome/browser/chromeos/login/owner_key_utils.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/login/owner_manager.h"
+#include "chrome/browser/chromeos/login/owner_key_utils.h"
 
 #include <keyhi.h>     // SECKEY_CreateSubjectPublicKeyInfo()
 #include <pk11pub.h>
@@ -21,19 +21,73 @@
 #include "base/string_util.h"
 
 // static
-const char OwnerManager::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key";
+OwnerKeyUtils::Factory* OwnerKeyUtils::factory_ = NULL;
+
+class OwnerKeyUtilsImpl : public OwnerKeyUtils {
+ public:
+  OwnerKeyUtilsImpl();
+  virtual ~OwnerKeyUtilsImpl();
+
+  bool GenerateKeyPair(SECKEYPrivateKey** private_key_out,
+                               SECKEYPublicKey** public_key_out);
+
+  bool ExportPublicKey(SECKEYPublicKey* key, const FilePath& key_file);
+
+  SECKEYPublicKey* ImportPublicKey(const FilePath& key_file);
+
+ private:
+  // Fills in fields of |key_der| with DER encoded data from a file at
+  // |key_file|.  The caller must pass in a pointer to an actual SECItem
+  // struct for |key_der|.  |key_der->data| should be initialized to NULL
+  // and |key_der->len| should be set to 0.
+  //
+  // Upon success, data is stored in key_der->data, and the caller takes
+  // ownership.  Returns false on error.
+  //
+  // To free the data, call
+  //    SECITEM_FreeItem(key_der, PR_FALSE);
+  static bool ReadDERFromFile(const FilePath& key_file, SECItem* key_der);
+
+  // The place outside the owner's encrypted home directory where her
+  // key will live.
+  static const char kOwnerKeyFile[];
+
+  // Key generation parameters.
+  static const uint32 kKeyGenMechanism;  // used by PK11_GenerateKeyPair()
+  static const unsigned long kExponent;
+  static const int kKeySizeInBits;
+
+  DISALLOW_COPY_AND_ASSIGN(OwnerKeyUtilsImpl);
+};
+
+OwnerKeyUtils::OwnerKeyUtils() {}
+
+OwnerKeyUtils::~OwnerKeyUtils() {}
+
+OwnerKeyUtils* OwnerKeyUtils::Create() {
+  if (!factory_)
+    return new OwnerKeyUtilsImpl();
+  else
+    return factory_->CreateOwnerKeyUtils();
+}
+
+// static
+const char OwnerKeyUtilsImpl::kOwnerKeyFile[] = "/var/lib/whitelist/owner.key";
 
 // We're generating and using 2048-bit RSA keys.
 // static
-const uint32 OwnerManager::kKeyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
+const uint32 OwnerKeyUtilsImpl::kKeyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
 // static
-const unsigned long OwnerManager::kExponent = 65537UL;
+const unsigned long OwnerKeyUtilsImpl::kExponent = 65537UL;
 // static
-const int OwnerManager::kKeySizeInBits = 2048;
+const int OwnerKeyUtilsImpl::kKeySizeInBits = 2048;
 
-// static
-bool OwnerManager::GenerateKeyPair(SECKEYPrivateKey** private_key_out,
-                                   SECKEYPublicKey** public_key_out) {
+OwnerKeyUtilsImpl::OwnerKeyUtilsImpl(){}
+
+OwnerKeyUtilsImpl::~OwnerKeyUtilsImpl() {}
+
+bool OwnerKeyUtilsImpl::GenerateKeyPair(SECKEYPrivateKey** private_key_out,
+                                        SECKEYPublicKey** public_key_out) {
   DCHECK(private_key_out);
   DCHECK(public_key_out);
 
@@ -115,9 +169,8 @@
   return is_success;
 }
 
-// static
-bool OwnerManager::ExportPublicKey(SECKEYPublicKey* key,
-                                   const FilePath& key_file) {
+bool OwnerKeyUtilsImpl::ExportPublicKey(SECKEYPublicKey* key,
+                                        const FilePath& key_file) {
   DCHECK(key);
   SECItem* der;
   bool ok = false;
@@ -147,8 +200,7 @@
   return ok;
 }
 
-// static
-SECKEYPublicKey* OwnerManager::ImportPublicKey(const FilePath& key_file) {
+SECKEYPublicKey* OwnerKeyUtilsImpl::ImportPublicKey(const FilePath& key_file) {
   SECItem key_der;
 
   if (!ReadDERFromFile(key_file, &key_der)) {
@@ -173,8 +225,8 @@
 }
 
 // static
-bool OwnerManager::ReadDERFromFile(const FilePath& key_file,
-                                   SECItem* key_der) {
+bool OwnerKeyUtilsImpl::ReadDERFromFile(const FilePath& key_file,
+                                        SECItem* key_der) {
   // I'd use NSS' SECU_ReadDERFromFile() here, but the SECU_* functions are
   // considered internal to the NSS command line utils.
   // This code is lifted, in spirit, from the implementation of that function.
diff --git a/chrome/browser/chromeos/login/owner_key_utils.h b/chrome/browser/chromeos/login/owner_key_utils.h
new file mode 100644
index 0000000..8900ed4
--- /dev/null
+++ b/chrome/browser/chromeos/login/owner_key_utils.h
@@ -0,0 +1,70 @@
+// 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_CHROMEOS_LOGIN_OWNER_KEY_UTILS_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_OWNER_KEY_UTILS_H_
+
+#include "base/basictypes.h"
+
+// Forward declarations of NSS data structures.
+struct SECKEYPrivateKeyStr;
+struct SECKEYPublicKeyStr;
+struct SECItemStr;
+
+typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey;
+typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
+typedef struct SECItemStr SECItem;
+
+class FilePath;
+
+class OwnerKeyUtils {
+ public:
+  class Factory {
+   public:
+    virtual OwnerKeyUtils* CreateOwnerKeyUtils() = 0;
+  };
+
+  OwnerKeyUtils();
+  virtual ~OwnerKeyUtils();
+
+  // Sets the factory used by the static method Create to create an
+  // OwnerKeyUtils.  OwnerKeyUtils does not take ownership of
+  // |factory|. A value of NULL results in an OwnerKeyUtils being
+  // created directly.
+#if defined(UNIT_TEST)
+  static void set_factory(Factory* factory) { factory_ = factory; }
+#endif
+
+  // Creates an OwnerKeyUtils, ownership returns to the caller. If there is no
+  // Factory (the default) this creates and returns a new OwnerKeyUtils.
+  static OwnerKeyUtils* Create();
+
+  // Generate a public/private RSA keypair and store them in the NSS database.
+  // The keys will be kKeySizeInBits in length (Recommend >= 2048 bits).
+  //
+  //  Returns false on error.
+  //
+  // The caller takes ownership of both objects, which are allocated by libnss.
+  // To free them, call
+  //    SECKEY_DestroyPrivateKey(*private_key_out);
+  //    SECKEY_DestroyPublicKey(*public_key_out);
+  virtual bool GenerateKeyPair(SECKEYPrivateKey** private_key_out,
+                               SECKEYPublicKey** public_key_out) = 0;
+
+  // DER encodes |key| and writes it out to |key_file|.
+  // The blob on disk is a DER-encoded X509 SubjectPublicKeyInfo object.
+  // Returns false on error.
+  virtual bool ExportPublicKey(SECKEYPublicKey* key,
+                               const FilePath& key_file) = 0;
+
+  // Assumes that the file at |key_file| exists.
+  // Caller takes ownership of returned object; returns NULL on error.
+  // To free, call SECKEY_DestroyPublicKey.
+  virtual SECKEYPublicKey* ImportPublicKey(const FilePath& key_file) = 0;
+
+ private:
+  static Factory* factory_;
+};
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_OWNER_KEY_UTILS_H_
diff --git a/chrome/browser/chromeos/login/owner_manager_unittest.cc b/chrome/browser/chromeos/login/owner_key_utils_unittest.cc
similarity index 79%
rename from chrome/browser/chromeos/login/owner_manager_unittest.cc
rename to chrome/browser/chromeos/login/owner_key_utils_unittest.cc
index 1f429004..7a7e9e7 100644
--- a/chrome/browser/chromeos/login/owner_manager_unittest.cc
+++ b/chrome/browser/chromeos/login/owner_key_utils_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/chromeos/login/owner_manager.h"
+#include "chrome/browser/chromeos/login/owner_key_utils.h"
 
 #include <cert.h>
 #include <keyhi.h>
@@ -17,20 +17,22 @@
 #include "base/logging.h"
 #include "base/nss_util_internal.h"
 #include "base/nss_util.h"
+#include "base/scoped_ptr.h"
 #include "base/scoped_temp_dir.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace chromeos {
 
-class OwnerManagerTest : public ::testing::Test {
+class OwnerKeyUtilsTest : public ::testing::Test {
  public:
-  OwnerManagerTest()
+  OwnerKeyUtilsTest()
       : private_key_(NULL),
-        public_key_(NULL) {
+        public_key_(NULL),
+        utils_(OwnerKeyUtils::Create()) {
 
   }
-  virtual ~OwnerManagerTest() {}
+  virtual ~OwnerKeyUtilsTest() {}
 
   virtual void SetUp() {
     base::OpenPersistentNSSDB();
@@ -49,24 +51,25 @@
 
   SECKEYPrivateKey* private_key_;
   SECKEYPublicKey* public_key_;
+  scoped_ptr<OwnerKeyUtils> utils_;
 };
 
-TEST_F(OwnerManagerTest, KeyGenerate) {
-  EXPECT_TRUE(OwnerManager::GenerateKeyPair(&private_key_, &public_key_));
+TEST_F(OwnerKeyUtilsTest, KeyGenerate) {
+  EXPECT_TRUE(utils_->GenerateKeyPair(&private_key_, &public_key_));
   EXPECT_TRUE(private_key_ != NULL);
   ASSERT_TRUE(public_key_ != NULL);
   EXPECT_EQ(public_key_->keyType, rsaKey);
 }
 
-TEST_F(OwnerManagerTest, ExportImportPublicKey) {
-  EXPECT_TRUE(OwnerManager::GenerateKeyPair(&private_key_, &public_key_));
+TEST_F(OwnerKeyUtilsTest, ExportImportPublicKey) {
+  EXPECT_TRUE(utils_->GenerateKeyPair(&private_key_, &public_key_));
 
   ScopedTempDir tmpdir;
   FilePath tmpfile;
   ASSERT_TRUE(tmpdir.CreateUniqueTempDir());
   ASSERT_TRUE(file_util::CreateTemporaryFileInDir(tmpdir.path(), &tmpfile));
 
-  EXPECT_TRUE(OwnerManager::ExportPublicKey(public_key_, tmpfile));
+  EXPECT_TRUE(utils_->ExportPublicKey(public_key_, tmpfile));
 
   // Now, verify that we can look up the private key, given the public key
   // we exported.  We'll create
@@ -83,7 +86,7 @@
   if (NULL == slot)
     goto cleanup;
 
-  from_disk = OwnerManager::ImportPublicKey(tmpfile);
+  from_disk = utils_->ImportPublicKey(tmpfile);
   ASSERT_TRUE(from_disk != NULL);
 
   ck_id = PK11_MakeIDFromPubKey(&(from_disk->u.rsa.modulus));
diff --git a/chrome/browser/chromeos/login/owner_manager.h b/chrome/browser/chromeos/login/owner_manager.h
deleted file mode 100644
index ed7a3d6..0000000
--- a/chrome/browser/chromeos/login/owner_manager.h
+++ /dev/null
@@ -1,83 +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_CHROMEOS_LOGIN_OWNER_MANAGER_H_
-#define CHROME_BROWSER_CHROMEOS_LOGIN_OWNER_MANAGER_H_
-
-#include "base/basictypes.h"
-
-// Forward declarations of NSS data structures.
-struct CERTCertificateStr;
-struct CERTCertificateRequestStr;
-struct SECKEYPrivateKeyStr;
-struct SECKEYPublicKeyStr;
-struct SECItemStr;
-
-typedef struct CERTCertificateStr CERTCertificate;
-typedef struct CERTCertificateRequestStr CERTCertificateRequest;
-typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey;
-typedef struct SECKEYPublicKeyStr SECKEYPublicKey;
-typedef struct SECItemStr SECItem;
-
-class FilePath;
-
-// This class allows the registration of an Owner of a Chromium OS device.
-// It handles generating the appropriate keys and storing them in the
-// appropriate locations.
-class OwnerManager {
- public:
-  OwnerManager() {}
-  virtual ~OwnerManager() {}
-
-  bool OwnershipAlreadyTaken();
-
-  bool TakeOwnership();
-
-  // Generate a public/private RSA keypair and store them in the NSS database.
-  // The keys will be kKeySizeInBits in length (Recommend >= 2048 bits).
-  //
-  //  Returns false on error.
-  //
-  // The caller takes ownership of both objects, which are allocated by libnss.
-  // To free them, call
-  //    SECKEY_DestroyPrivateKey(*private_key_out);
-  //    SECKEY_DestroyPublicKey(*public_key_out);
-  static bool GenerateKeyPair(SECKEYPrivateKey** private_key_out,
-                              SECKEYPublicKey** public_key_out);
-
-  // DER encodes |key| and writes it out to |key_file|.
-  // The blob on disk is a DER-encoded X509 SubjectPublicKeyInfo object.
-  // Returns false on error.
-  static bool ExportPublicKey(SECKEYPublicKey* key,
-                              const FilePath& key_file);
-
-  // Assumes that the file at |key_file| exists.
-  // Caller takes ownership of returned object; returns NULL on error.
-  // To free, call SECKEY_DestroyPublicKey.
-  static SECKEYPublicKey* ImportPublicKey(const FilePath& key_file);
-
- private:
-  // Fills in fields of |key_der| with DER encoded data from a file at
-  // |key_file|.  The caller must pass in a pointer to an actual SECItem
-  // struct for |key_der|.  |key_der->data| should be initialized to NULL
-  // and |key_der->len| should be set to 0.
-  //
-  // Upon success, data is stored in key_der->data, and the caller takes
-  // ownership.  Returns false on error.
-  //
-  // To free the data, call
-  //    SECITEM_FreeItem(key_der, PR_FALSE);
-  static bool ReadDERFromFile(const FilePath& key_file, SECItem* key_der);
-
-  // The place outside the owner's encrypted home directory where her
-  // key will live.
-  static const char kOwnerKeyFile[];
-
-  // Key generation parameters.
-  static const uint32 kKeyGenMechanism;  // used by PK11_GenerateKeyPair()
-  static const unsigned long kExponent;
-  static const int kKeySizeInBits;
-};
-
-#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_OWNER_MANAGER_H_
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index c25182b..f6198d06 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -476,8 +476,8 @@
         'browser/chromeos/login/network_screen_delegate.h',
         'browser/chromeos/login/new_user_view.cc',
         'browser/chromeos/login/new_user_view.h',
-        'browser/chromeos/login/owner_manager.cc',
-        'browser/chromeos/login/owner_manager.h',
+        'browser/chromeos/login/owner_key_utils.cc',
+        'browser/chromeos/login/owner_key_utils.h',
         'browser/chromeos/login/password_changed_view.cc',
         'browser/chromeos/login/password_changed_view.h',
         'browser/chromeos/login/registration_screen.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 7101011f..253b779 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -737,7 +737,7 @@
         'browser/chromeos/login/cookie_fetcher_unittest.cc',
         'browser/chromeos/login/google_authenticator_unittest.cc',
         'browser/chromeos/login/mock_auth_response_handler.cc',
-        'browser/chromeos/login/owner_manager_unittest.cc',
+        'browser/chromeos/login/owner_key_utils_unittest.cc',
         'browser/chromeos/notifications/desktop_notifications_unittest.cc',
         'browser/chromeos/offline/offline_load_page_unittest.cc',
         'browser/chromeos/options/language_config_model_unittest.cc',