Home | History | Annotate | Download | only in settings
      1 // Copyright 2013 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/settings/token_encryptor.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/logging.h"
     10 #include "base/strings/string_number_conversions.h"
     11 #include "base/strings/string_util.h"
     12 #include "base/sys_info.h"
     13 #include "chromeos/cryptohome/system_salt_getter.h"
     14 #include "crypto/encryptor.h"
     15 #include "crypto/nss_util.h"
     16 #include "crypto/sha2.h"
     17 #include "crypto/symmetric_key.h"
     18 
     19 namespace chromeos {
     20 
     21 namespace {
     22 const size_t kNonceSize = 16;
     23 }  // namespace
     24 
     25 CryptohomeTokenEncryptor::CryptohomeTokenEncryptor(
     26     const std::string& system_salt)
     27     : system_salt_(system_salt) {
     28   DCHECK(!system_salt.empty());
     29   // TODO(davidroche): should this use the system salt for both the password
     30   // and the salt value, or should this use a separate salt value?
     31   system_salt_key_.reset(PassphraseToKey(system_salt_, system_salt_));
     32 }
     33 
     34 CryptohomeTokenEncryptor::~CryptohomeTokenEncryptor() {
     35 }
     36 
     37 std::string CryptohomeTokenEncryptor::EncryptWithSystemSalt(
     38     const std::string& token) {
     39   // Don't care about token encryption while debugging.
     40   if (!base::SysInfo::IsRunningOnChromeOS())
     41     return token;
     42 
     43   if (!system_salt_key_) {
     44     LOG(WARNING) << "System salt key is not available for encrypt.";
     45     return std::string();
     46   }
     47   return EncryptTokenWithKey(system_salt_key_.get(),
     48                              system_salt_,
     49                              token);
     50 }
     51 
     52 std::string CryptohomeTokenEncryptor::DecryptWithSystemSalt(
     53     const std::string& encrypted_token_hex) {
     54   // Don't care about token encryption while debugging.
     55   if (!base::SysInfo::IsRunningOnChromeOS())
     56     return encrypted_token_hex;
     57 
     58   if (!system_salt_key_) {
     59     LOG(WARNING) << "System salt key is not available for decrypt.";
     60     return std::string();
     61   }
     62   return DecryptTokenWithKey(system_salt_key_.get(),
     63                              system_salt_,
     64                              encrypted_token_hex);
     65 }
     66 
     67 crypto::SymmetricKey* CryptohomeTokenEncryptor::PassphraseToKey(
     68     const std::string& passphrase,
     69     const std::string& salt) {
     70   return crypto::SymmetricKey::DeriveKeyFromPassword(
     71       crypto::SymmetricKey::AES, passphrase, salt, 1000, 256);
     72 }
     73 
     74 std::string CryptohomeTokenEncryptor::EncryptTokenWithKey(
     75     crypto::SymmetricKey* key,
     76     const std::string& salt,
     77     const std::string& token) {
     78   crypto::Encryptor encryptor;
     79   if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) {
     80     LOG(WARNING) << "Failed to initialize Encryptor.";
     81     return std::string();
     82   }
     83   std::string nonce = salt.substr(0, kNonceSize);
     84   std::string encoded_token;
     85   CHECK(encryptor.SetCounter(nonce));
     86   if (!encryptor.Encrypt(token, &encoded_token)) {
     87     LOG(WARNING) << "Failed to encrypt token.";
     88     return std::string();
     89   }
     90 
     91   return base::StringToLowerASCII(base::HexEncode(
     92       reinterpret_cast<const void*>(encoded_token.data()),
     93       encoded_token.size()));
     94 }
     95 
     96 std::string CryptohomeTokenEncryptor::DecryptTokenWithKey(
     97     crypto::SymmetricKey* key,
     98     const std::string& salt,
     99     const std::string& encrypted_token_hex) {
    100   std::vector<uint8> encrypted_token_bytes;
    101   if (!base::HexStringToBytes(encrypted_token_hex, &encrypted_token_bytes)) {
    102     LOG(WARNING) << "Corrupt encrypted token found.";
    103     return std::string();
    104   }
    105 
    106   std::string encrypted_token(
    107       reinterpret_cast<char*>(encrypted_token_bytes.data()),
    108       encrypted_token_bytes.size());
    109   crypto::Encryptor encryptor;
    110   if (!encryptor.Init(key, crypto::Encryptor::CTR, std::string())) {
    111     LOG(WARNING) << "Failed to initialize Encryptor.";
    112     return std::string();
    113   }
    114 
    115   std::string nonce = salt.substr(0, kNonceSize);
    116   std::string token;
    117   CHECK(encryptor.SetCounter(nonce));
    118   if (!encryptor.Decrypt(encrypted_token, &token)) {
    119     LOG(WARNING) << "Failed to decrypt token.";
    120     return std::string();
    121   }
    122   return token;
    123 }
    124 
    125 }  // namespace chromeos
    126