// 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/browser/chromeos/login/owner_manager.h" #include "chrome/browser/chromeos/login/owner_manager_unittest.h" #include <string> #include "base/file_path.h" #include "base/file_util.h" #include "base/logging.h" #include "base/memory/scoped_temp_dir.h" #include "crypto/nss_util.h" #include "crypto/rsa_private_key.h" #include "chrome/browser/chromeos/login/mock_owner_key_utils.h" #include "content/browser/browser_thread.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" using ::crypto::RSAPrivateKey; using ::testing::DoAll; using ::testing::Eq; using ::testing::Invoke; using ::testing::Return; using ::testing::SetArgumentPointee; using ::testing::_; namespace chromeos { class OwnerManagerTest : public ::testing::Test { public: OwnerManagerTest() : message_loop_(MessageLoop::TYPE_UI), ui_thread_(BrowserThread::UI, &message_loop_), file_thread_(BrowserThread::FILE), mock_(new MockKeyUtils), injector_(mock_) /* injector_ takes ownership of mock_ */ { } virtual ~OwnerManagerTest() {} virtual void SetUp() { crypto::OpenPersistentNSSDB(); // TODO(cmasone): use test DB instead fake_private_key_.reset(RSAPrivateKey::Create(256)); ASSERT_TRUE(fake_private_key_->ExportPublicKey(&fake_public_key_)); // Mimic ownership. ASSERT_TRUE(tmpdir_.CreateUniqueTempDir()); ASSERT_TRUE(file_util::CreateTemporaryFileInDir(tmpdir_.path(), &tmpfile_)); file_thread_.Start(); OwnerKeyUtils::set_factory(&injector_); } virtual void TearDown() { OwnerKeyUtils::set_factory(NULL); } void StartUnowned() { file_util::Delete(tmpfile_, false); } void InjectKeys(OwnerManager* manager) { manager->public_key_ = fake_public_key_; manager->private_key_.reset(fake_private_key_.release()); } ScopedTempDir tmpdir_; FilePath tmpfile_; MessageLoop message_loop_; BrowserThread ui_thread_; BrowserThread file_thread_; std::vector<uint8> fake_public_key_; scoped_ptr<RSAPrivateKey> fake_private_key_; MockKeyUtils* mock_; MockInjector injector_; }; TEST_F(OwnerManagerTest, UpdateOwnerKey) { scoped_refptr<OwnerManager> manager(new OwnerManager); MockKeyUpdateUser delegate; BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, NewRunnableMethod(manager.get(), &OwnerManager::UpdateOwnerKey, BrowserThread::UI, std::vector<uint8>(), &delegate)); message_loop_.Run(); } TEST_F(OwnerManagerTest, LoadOwnerKeyFail) { StartUnowned(); MockKeyLoadObserver loader; scoped_refptr<OwnerManager> manager(new OwnerManager); EXPECT_CALL(*mock_, GetOwnerKeyFilePath()) .WillRepeatedly(Return(tmpfile_)); EXPECT_CALL(*mock_, ImportPublicKey(tmpfile_, _)) .WillOnce(Return(false)) .RetiresOnSaturation(); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, NewRunnableMethod(manager.get(), &OwnerManager::LoadOwnerKey)); message_loop_.Run(); } TEST_F(OwnerManagerTest, AlreadyLoadedOwnerKey) { MockKeyLoadObserver loader; loader.ExpectKeyFetchSuccess(true); scoped_refptr<OwnerManager> manager(new OwnerManager); EXPECT_CALL(*mock_, GetOwnerKeyFilePath()) .WillRepeatedly(Return(tmpfile_)); InjectKeys(manager.get()); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, NewRunnableMethod(manager.get(), &OwnerManager::LoadOwnerKey)); message_loop_.Run(); } TEST_F(OwnerManagerTest, LoadOwnerKey) { MockKeyLoadObserver loader; loader.ExpectKeyFetchSuccess(true); scoped_refptr<OwnerManager> manager(new OwnerManager); EXPECT_CALL(*mock_, GetOwnerKeyFilePath()) .WillRepeatedly(Return(tmpfile_)); EXPECT_CALL(*mock_, ImportPublicKey(tmpfile_, _)) .WillOnce(DoAll(SetArgumentPointee<1>(fake_public_key_), Return(true))) .RetiresOnSaturation(); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, NewRunnableMethod(manager.get(), &OwnerManager::LoadOwnerKey)); message_loop_.Run(); } TEST_F(OwnerManagerTest, GetKeyFailDuringVerify) { StartUnowned(); MockKeyLoadObserver loader; loader.ExpectKeyFetchSuccess(false); scoped_refptr<OwnerManager> manager(new OwnerManager); EXPECT_CALL(*mock_, GetOwnerKeyFilePath()) .WillRepeatedly(Return(tmpfile_)); EXPECT_CALL(*mock_, ImportPublicKey(tmpfile_, _)) .WillOnce(Return(false)) .RetiresOnSaturation(); MockKeyUser delegate(OwnerManager::KEY_UNAVAILABLE); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, NewRunnableMethod(manager.get(), &OwnerManager::Verify, BrowserThread::UI, std::string(), std::vector<uint8>(), &delegate)); message_loop_.Run(); } TEST_F(OwnerManagerTest, AlreadyHaveKeysVerify) { scoped_refptr<OwnerManager> manager(new OwnerManager); std::string data; std::vector<uint8> sig(0, 2); EXPECT_CALL(*mock_, GetOwnerKeyFilePath()) .WillRepeatedly(Return(tmpfile_)); EXPECT_CALL(*mock_, Verify(Eq(data), Eq(sig), Eq(fake_public_key_))) .WillOnce(Return(true)) .RetiresOnSaturation(); InjectKeys(manager.get()); MockKeyUser delegate(OwnerManager::SUCCESS); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, NewRunnableMethod(manager.get(), &OwnerManager::Verify, BrowserThread::UI, data, sig, &delegate)); message_loop_.Run(); } TEST_F(OwnerManagerTest, GetKeyAndVerify) { MockKeyLoadObserver loader; loader.ExpectKeyFetchSuccess(true); loader.SetQuitOnKeyFetch(false); scoped_refptr<OwnerManager> manager(new OwnerManager); std::string data; std::vector<uint8> sig(0, 2); EXPECT_CALL(*mock_, GetOwnerKeyFilePath()) .WillRepeatedly(Return(tmpfile_)); EXPECT_CALL(*mock_, ImportPublicKey(tmpfile_, _)) .WillOnce(DoAll(SetArgumentPointee<1>(fake_public_key_), Return(true))) .RetiresOnSaturation(); EXPECT_CALL(*mock_, Verify(Eq(data), Eq(sig), Eq(fake_public_key_))) .WillOnce(Return(true)) .RetiresOnSaturation(); MockKeyUser delegate(OwnerManager::SUCCESS); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, NewRunnableMethod(manager.get(), &OwnerManager::Verify, BrowserThread::UI, data, sig, &delegate)); message_loop_.Run(); } TEST_F(OwnerManagerTest, AlreadyHaveKeysSign) { scoped_refptr<OwnerManager> manager(new OwnerManager); std::string data; std::vector<uint8> sig(0, 2); EXPECT_CALL(*mock_, GetOwnerKeyFilePath()) .WillRepeatedly(Return(tmpfile_)); EXPECT_CALL(*mock_, Sign(Eq(data), _, Eq(fake_private_key_.get()))) .WillOnce(DoAll(SetArgumentPointee<1>(sig), Return(true))) .RetiresOnSaturation(); InjectKeys(manager.get()); MockSigner delegate(OwnerManager::SUCCESS, sig); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, NewRunnableMethod(manager.get(), &OwnerManager::Sign, BrowserThread::UI, data, &delegate)); message_loop_.Run(); } } // namespace chromeos