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