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 "chrome/browser/chromeos/login/owner_manager.h" 6 7 #include <string> 8 #include <vector> 9 10 #include "base/file_path.h" 11 #include "base/file_util.h" 12 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/chromeos/boot_times_loader.h" 14 #include "chrome/browser/chromeos/login/signed_settings_temp_storage.h" 15 #include "content/browser/browser_thread.h" 16 #include "content/common/notification_service.h" 17 #include "content/common/notification_type.h" 18 19 namespace chromeos { 20 21 OwnerManager::OwnerManager() 22 : private_key_(NULL), 23 public_key_(0), 24 utils_(OwnerKeyUtils::Create()) { 25 } 26 27 OwnerManager::~OwnerManager() {} 28 29 void OwnerManager::UpdateOwnerKey(const BrowserThread::ID thread_id, 30 const std::vector<uint8>& key, 31 KeyUpdateDelegate* d) { 32 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 33 34 public_key_ = key; 35 36 BrowserThread::PostTask( 37 thread_id, FROM_HERE, 38 NewRunnableMethod(this, &OwnerManager::CallKeyUpdateDelegate, d)); 39 } 40 41 void OwnerManager::LoadOwnerKey() { 42 BootTimesLoader::Get()->AddLoginTimeMarker("LoadOwnerKeyStart", false); 43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 44 VLOG(1) << "Loading owner key"; 45 NotificationType result = NotificationType::OWNER_KEY_FETCH_ATTEMPT_SUCCEEDED; 46 47 // If |public_key_| isn't empty, we already have the key, so don't 48 // try to import again. 49 if (public_key_.empty() && 50 !utils_->ImportPublicKey(utils_->GetOwnerKeyFilePath(), &public_key_)) { 51 result = NotificationType::OWNER_KEY_FETCH_ATTEMPT_FAILED; 52 } 53 54 // Whether we loaded the public key or not, send a notification indicating 55 // that we're done with this attempt. 56 BrowserThread::PostTask( 57 BrowserThread::UI, FROM_HERE, 58 NewRunnableMethod(this, 59 &OwnerManager::SendNotification, 60 result, 61 NotificationService::NoDetails())); 62 } 63 64 bool OwnerManager::EnsurePublicKey() { 65 if (public_key_.empty()) 66 LoadOwnerKey(); 67 68 return !public_key_.empty(); 69 } 70 71 bool OwnerManager::EnsurePrivateKey() { 72 if (!EnsurePublicKey()) 73 return false; 74 75 if (!private_key_.get()) 76 private_key_.reset(utils_->FindPrivateKey(public_key_)); 77 78 return private_key_.get() != NULL; 79 } 80 81 void OwnerManager::Sign(const BrowserThread::ID thread_id, 82 const std::string& data, 83 Delegate* d) { 84 BootTimesLoader::Get()->AddLoginTimeMarker("SignStart", false); 85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 86 87 // If it's not the case that we can get both keys... 88 if (!(EnsurePublicKey() && EnsurePrivateKey())) { 89 BrowserThread::PostTask( 90 thread_id, FROM_HERE, 91 NewRunnableMethod(this, 92 &OwnerManager::CallDelegate, 93 d, KEY_UNAVAILABLE, std::vector<uint8>())); 94 BootTimesLoader::Get()->AddLoginTimeMarker("SignEnd", false); 95 return; 96 } 97 98 VLOG(1) << "Starting signing attempt"; 99 KeyOpCode return_code = SUCCESS; 100 std::vector<uint8> signature; 101 if (!utils_->Sign(data, &signature, private_key_.get())) { 102 return_code = OPERATION_FAILED; 103 } 104 105 BrowserThread::PostTask( 106 thread_id, FROM_HERE, 107 NewRunnableMethod(this, 108 &OwnerManager::CallDelegate, 109 d, return_code, signature)); 110 BootTimesLoader::Get()->AddLoginTimeMarker("SignEnd", false); 111 } 112 113 void OwnerManager::Verify(const BrowserThread::ID thread_id, 114 const std::string& data, 115 const std::vector<uint8>& signature, 116 Delegate* d) { 117 BootTimesLoader::Get()->AddLoginTimeMarker("VerifyStart", false); 118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 119 120 if (!EnsurePublicKey()) { 121 BrowserThread::PostTask( 122 thread_id, FROM_HERE, 123 NewRunnableMethod(this, 124 &OwnerManager::CallDelegate, 125 d, KEY_UNAVAILABLE, std::vector<uint8>())); 126 BootTimesLoader::Get()->AddLoginTimeMarker("VerifyEnd", false); 127 return; 128 } 129 130 VLOG(1) << "Starting verify attempt"; 131 KeyOpCode return_code = SUCCESS; 132 if (!utils_->Verify(data, signature, public_key_)) { 133 return_code = OPERATION_FAILED; 134 } 135 BrowserThread::PostTask( 136 thread_id, FROM_HERE, 137 NewRunnableMethod(this, 138 &OwnerManager::CallDelegate, 139 d, return_code, std::vector<uint8>())); 140 BootTimesLoader::Get()->AddLoginTimeMarker("VerifyEnd", false); 141 } 142 143 void OwnerManager::SendNotification(NotificationType type, 144 const NotificationDetails& details) { 145 NotificationService::current()->Notify( 146 type, 147 NotificationService::AllSources(), 148 details); 149 } 150 151 } // namespace chromeos 152