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/cros/cryptohome_library.h" 6 7 #include "base/command_line.h" 8 #include "base/hash_tables.h" 9 #include "base/message_loop.h" 10 #include "chrome/browser/chromeos/cros/cros_library.h" 11 #include "chrome/common/chrome_switches.h" 12 #include "content/browser/browser_thread.h" 13 14 namespace chromeos { 15 16 // This class handles the interaction with the ChromeOS cryptohome library APIs. 17 class CryptohomeLibraryImpl : public CryptohomeLibrary { 18 public: 19 CryptohomeLibraryImpl() { 20 if (CrosLibrary::Get()->EnsureLoaded()) 21 Init(); 22 } 23 virtual ~CryptohomeLibraryImpl() {} 24 25 bool CheckKey(const std::string& user_email, const std::string& passhash) { 26 return chromeos::CryptohomeCheckKey(user_email.c_str(), passhash.c_str()); 27 } 28 29 bool AsyncCheckKey(const std::string& user_email, 30 const std::string& passhash, 31 Delegate* d) { 32 return CacheCallback( 33 chromeos::CryptohomeAsyncCheckKey(user_email.c_str(), passhash.c_str()), 34 d, 35 "Couldn't initiate async check of user's key."); 36 } 37 38 bool MigrateKey(const std::string& user_email, 39 const std::string& old_hash, 40 const std::string& new_hash) { 41 return chromeos::CryptohomeMigrateKey(user_email.c_str(), 42 old_hash.c_str(), 43 new_hash.c_str()); 44 } 45 46 bool AsyncMigrateKey(const std::string& user_email, 47 const std::string& old_hash, 48 const std::string& new_hash, 49 Delegate* d) { 50 return CacheCallback( 51 chromeos::CryptohomeAsyncMigrateKey(user_email.c_str(), 52 old_hash.c_str(), 53 new_hash.c_str()), 54 d, 55 "Couldn't initiate aync migration of user's key"); 56 } 57 58 bool Mount(const std::string& user_email, 59 const std::string& passhash, 60 int* error_code) { 61 return chromeos::CryptohomeMountAllowFail(user_email.c_str(), 62 passhash.c_str(), 63 error_code); 64 } 65 66 bool AsyncMount(const std::string& user_email, 67 const std::string& passhash, 68 const bool create_if_missing, 69 Delegate* d) { 70 return CacheCallback( 71 chromeos::CryptohomeAsyncMountSafe(user_email.c_str(), 72 passhash.c_str(), 73 create_if_missing, 74 false, 75 NULL), 76 d, 77 "Couldn't initiate async mount of cryptohome."); 78 } 79 80 bool MountForBwsi(int* error_code) { 81 return chromeos::CryptohomeMountGuest(error_code); 82 } 83 84 bool AsyncMountForBwsi(Delegate* d) { 85 return CacheCallback(chromeos::CryptohomeAsyncMountGuest(), 86 d, 87 "Couldn't initiate async mount of cryptohome."); 88 } 89 90 bool Unmount() { 91 return chromeos::CryptohomeUnmount(); 92 } 93 94 bool Remove(const std::string& user_email) { 95 return chromeos::CryptohomeRemove(user_email.c_str()); 96 } 97 98 bool AsyncRemove(const std::string& user_email, Delegate* d) { 99 return CacheCallback( 100 chromeos::CryptohomeAsyncRemove(user_email.c_str()), 101 d, 102 "Couldn't initiate async removal of cryptohome."); 103 } 104 105 bool IsMounted() { 106 return chromeos::CryptohomeIsMounted(); 107 } 108 109 CryptohomeBlob GetSystemSalt() { 110 CryptohomeBlob system_salt; 111 char* salt_buf; 112 int salt_len; 113 bool result = chromeos::CryptohomeGetSystemSaltSafe(&salt_buf, &salt_len); 114 if (result) { 115 system_salt.resize(salt_len); 116 if ((int)system_salt.size() == salt_len) { 117 memcpy(&system_salt[0], static_cast<const void*>(salt_buf), 118 salt_len); 119 } else { 120 system_salt.clear(); 121 } 122 } 123 return system_salt; 124 } 125 126 bool AsyncDoAutomaticFreeDiskSpaceControl(Delegate* d) { 127 return CacheCallback( 128 chromeos::CryptohomeAsyncDoAutomaticFreeDiskSpaceControl(), 129 d, 130 "Couldn't do automatic free disk space control."); 131 } 132 133 bool TpmIsReady() { 134 return chromeos::CryptohomeTpmIsReady(); 135 } 136 137 bool TpmIsEnabled() { 138 return chromeos::CryptohomeTpmIsEnabled(); 139 } 140 141 bool TpmIsOwned() { 142 return chromeos::CryptohomeTpmIsOwned(); 143 } 144 145 bool TpmIsBeingOwned() { 146 return chromeos::CryptohomeTpmIsBeingOwned(); 147 } 148 149 bool TpmGetPassword(std::string* password) { 150 char *password_buf; 151 bool result = chromeos::CryptohomeTpmGetPasswordSafe(&password_buf); 152 *password = password_buf; 153 chromeos::CryptohomeFreeString(password_buf); 154 return result; 155 } 156 157 void TpmCanAttemptOwnership() { 158 chromeos::CryptohomeTpmCanAttemptOwnership(); 159 } 160 161 void TpmClearStoredPassword() { 162 chromeos::CryptohomeTpmClearStoredPassword(); 163 } 164 165 bool InstallAttributesGet(const std::string& name, std::string* value) { 166 char* local_value; 167 bool done = 168 chromeos::CryptohomeInstallAttributesGet(name.c_str(), &local_value); 169 if (done) { 170 *value = local_value; 171 chromeos::CryptohomeFreeString(local_value); 172 } 173 return done; 174 } 175 176 bool InstallAttributesSet(const std::string& name, const std::string& value) { 177 return chromeos::CryptohomeInstallAttributesSet(name.c_str(), 178 value.c_str()); 179 } 180 181 int InstallAttributesCount() { 182 return chromeos::CryptohomeInstallAttributesCount(); 183 } 184 185 bool InstallAttributesFinalize() { 186 return chromeos::CryptohomeInstallAttributesFinalize(); 187 } 188 189 bool InstallAttributesIsReady() { 190 return chromeos::CryptohomeInstallAttributesIsReady(); 191 } 192 193 bool InstallAttributesIsSecure() { 194 return chromeos::CryptohomeInstallAttributesIsSecure(); 195 } 196 197 bool InstallAttributesIsInvalid() { 198 return chromeos::CryptohomeInstallAttributesIsInvalid(); 199 } 200 201 bool InstallAttributesIsFirstInstall() { 202 return chromeos::CryptohomeInstallAttributesIsFirstInstall(); 203 } 204 205 void Pkcs11GetTpmTokenInfo(std::string* label, std::string* user_pin) { 206 chromeos::CryptohomePkcs11GetTpmTokenInfo(label, user_pin); 207 } 208 209 bool Pkcs11IsTpmTokenReady() { 210 return chromeos::CryptohomePkcs11IsTpmTokenReady(); 211 } 212 213 private: 214 static void Handler(const chromeos::CryptohomeAsyncCallStatus& event, 215 void* cryptohome_library) { 216 CryptohomeLibraryImpl* library = 217 reinterpret_cast<CryptohomeLibraryImpl*>(cryptohome_library); 218 library->Dispatch(event); 219 } 220 221 void Init() { 222 cryptohome_connection_ = chromeos::CryptohomeMonitorSession(&Handler, this); 223 } 224 225 void Dispatch(const chromeos::CryptohomeAsyncCallStatus& event) { 226 const CallbackMap::iterator callback = callback_map_.find(event.async_id); 227 if (callback == callback_map_.end()) { 228 LOG(ERROR) << "Received signal for unknown async_id " << event.async_id; 229 return; 230 } 231 if (callback->second) 232 callback->second->OnComplete(event.return_status, event.return_code); 233 callback_map_.erase(callback); 234 } 235 236 bool CacheCallback(int async_id, Delegate* d, const char* error) { 237 if (async_id == 0) { 238 LOG(ERROR) << error; 239 return false; 240 } 241 VLOG(1) << "Adding handler for " << async_id; 242 callback_map_[async_id] = d; 243 return true; 244 } 245 246 typedef base::hash_map<int, Delegate*> CallbackMap; 247 mutable CallbackMap callback_map_; 248 249 void* cryptohome_connection_; 250 251 DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryImpl); 252 }; 253 254 class CryptohomeLibraryStubImpl : public CryptohomeLibrary { 255 public: 256 CryptohomeLibraryStubImpl() 257 : locked_(false) {} 258 virtual ~CryptohomeLibraryStubImpl() {} 259 260 bool CheckKey(const std::string& user_email, const std::string& passhash) { 261 return true; 262 } 263 264 bool AsyncCheckKey(const std::string& user_email, 265 const std::string& passhash, 266 Delegate* callback) { 267 BrowserThread::PostTask( 268 BrowserThread::UI, FROM_HERE, 269 NewRunnableFunction(&DoStubCallback, callback)); 270 return true; 271 } 272 273 bool MigrateKey(const std::string& user_email, 274 const std::string& old_hash, 275 const std::string& new_hash) { 276 return true; 277 } 278 279 bool AsyncMigrateKey(const std::string& user_email, 280 const std::string& old_hash, 281 const std::string& new_hash, 282 Delegate* callback) { 283 BrowserThread::PostTask( 284 BrowserThread::UI, FROM_HERE, 285 NewRunnableFunction(&DoStubCallback, callback)); 286 return true; 287 } 288 289 bool Mount(const std::string& user_email, 290 const std::string& passhash, 291 int* error_code) { 292 // For testing password change. 293 if (user_email == 294 CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 295 switches::kLoginUserWithNewPassword)) { 296 *error_code = kCryptohomeMountErrorKeyFailure; 297 return false; 298 } 299 300 return true; 301 } 302 303 bool AsyncMount(const std::string& user_email, 304 const std::string& passhash, 305 const bool create_if_missing, 306 Delegate* callback) { 307 BrowserThread::PostTask( 308 BrowserThread::UI, FROM_HERE, 309 NewRunnableFunction(&DoStubCallback, callback)); 310 return true; 311 } 312 313 bool MountForBwsi(int* error_code) { 314 return true; 315 } 316 317 bool AsyncMountForBwsi(Delegate* callback) { 318 BrowserThread::PostTask( 319 BrowserThread::UI, FROM_HERE, 320 NewRunnableFunction(&DoStubCallback, callback)); 321 return true; 322 } 323 324 bool Unmount() { 325 return true; 326 } 327 328 bool Remove(const std::string& user_email) { 329 return true; 330 } 331 332 bool AsyncRemove(const std::string& user_email, Delegate* callback) { 333 BrowserThread::PostTask( 334 BrowserThread::UI, FROM_HERE, 335 NewRunnableFunction(&DoStubCallback, callback)); 336 return true; 337 } 338 339 bool IsMounted() { 340 return true; 341 } 342 343 CryptohomeBlob GetSystemSalt() { 344 CryptohomeBlob salt = CryptohomeBlob(); 345 salt.push_back(0); 346 salt.push_back(0); 347 return salt; 348 } 349 350 bool AsyncDoAutomaticFreeDiskSpaceControl(Delegate* callback) { 351 BrowserThread::PostTask( 352 BrowserThread::UI, FROM_HERE, 353 NewRunnableFunction(&DoStubCallback, callback)); 354 return true; 355 } 356 357 // Tpm begin ready after 20-th call. 358 bool TpmIsReady() { 359 static int counter = 0; 360 return ++counter > 20; 361 } 362 363 bool TpmIsEnabled() { 364 return true; 365 } 366 367 bool TpmIsOwned() { 368 return true; 369 } 370 371 bool TpmIsBeingOwned() { 372 return true; 373 } 374 375 bool TpmGetPassword(std::string* password) { 376 *password = "Stub-TPM-password"; 377 return true; 378 } 379 380 void TpmCanAttemptOwnership() {} 381 382 void TpmClearStoredPassword() {} 383 384 bool InstallAttributesGet(const std::string& name, std::string* value) { 385 if (install_attrs_.find(name) != install_attrs_.end()) { 386 *value = install_attrs_[name]; 387 return true; 388 } 389 return false; 390 } 391 392 bool InstallAttributesSet(const std::string& name, const std::string& value) { 393 install_attrs_[name] = value; 394 return true; 395 } 396 397 int InstallAttributesCount() { 398 return install_attrs_.size(); 399 } 400 401 bool InstallAttributesFinalize() { 402 locked_ = true; 403 return true; 404 } 405 406 bool InstallAttributesIsReady() { 407 return true; 408 } 409 410 bool InstallAttributesIsSecure() { 411 return false; 412 } 413 414 bool InstallAttributesIsInvalid() { 415 return false; 416 } 417 418 bool InstallAttributesIsFirstInstall() { 419 return !locked_; 420 } 421 422 void Pkcs11GetTpmTokenInfo(std::string* label, 423 std::string* user_pin) { 424 *label = "Stub TPM Token"; 425 *user_pin = "012345"; 426 } 427 428 bool Pkcs11IsTpmTokenReady() { return true; } 429 430 private: 431 static void DoStubCallback(Delegate* callback) { 432 if (callback) 433 callback->OnComplete(true, kCryptohomeMountErrorNone); 434 } 435 436 std::map<std::string, std::string> install_attrs_; 437 bool locked_; 438 DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryStubImpl); 439 }; 440 441 CryptohomeLibrary::CryptohomeLibrary() {} 442 CryptohomeLibrary::~CryptohomeLibrary() {} 443 444 // static 445 CryptohomeLibrary* CryptohomeLibrary::GetImpl(bool stub) { 446 if (stub) 447 return new CryptohomeLibraryStubImpl(); 448 else 449 return new CryptohomeLibraryImpl(); 450 } 451 452 } // namespace chromeos 453