Home | History | Annotate | Download | only in cros
      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