1 // Copyright 2014 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/auth/key.h" 6 7 #include "base/base64.h" 8 #include "base/logging.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/strings/string_number_conversions.h" 11 #include "base/strings/string_util.h" 12 #include "crypto/sha2.h" 13 #include "crypto/symmetric_key.h" 14 15 namespace chromeos { 16 17 namespace { 18 19 // Parameters for the transformation to KEY_TYPE_SALTED_AES256_1234. 20 const int kNumIterations = 1234; 21 const int kKeySizeInBits = 256; 22 23 } // namespace 24 25 Key::Key() : key_type_(KEY_TYPE_PASSWORD_PLAIN) { 26 } 27 28 Key::Key(const Key& other) : key_type_(other.key_type_), 29 salt_(other.salt_), 30 secret_(other.secret_), 31 label_(other.label_) { 32 } 33 34 Key::Key(const std::string& plain_text_password) 35 : key_type_(KEY_TYPE_PASSWORD_PLAIN), 36 secret_(plain_text_password) { 37 } 38 39 Key::Key(KeyType key_type, const std::string& salt, const std::string& secret) 40 : key_type_(key_type), 41 salt_(salt), 42 secret_(secret) { 43 44 } 45 46 Key::~Key() { 47 } 48 49 bool Key::operator==(const Key& other) const { 50 return other.key_type_ == key_type_ && 51 other.salt_ == salt_ && 52 other.secret_ == secret_ && 53 other.label_ == label_; 54 } 55 56 Key::KeyType Key::GetKeyType() const { 57 return key_type_; 58 } 59 60 const std::string& Key::GetSecret() const { 61 return secret_; 62 } 63 64 const std::string& Key::GetLabel() const { 65 return label_; 66 } 67 68 void Key::SetLabel(const std::string& label) { 69 label_ = label; 70 } 71 72 void Key::ClearSecret() { 73 secret_.clear(); 74 } 75 76 void Key::Transform(KeyType target_key_type, const std::string& salt) { 77 if (key_type_ != KEY_TYPE_PASSWORD_PLAIN) { 78 NOTREACHED(); 79 return; 80 } 81 82 switch (target_key_type) { 83 case KEY_TYPE_SALTED_SHA256_TOP_HALF: { 84 // TODO(stevenjb/nkostylev): Handle empty salt gracefully. 85 CHECK(!salt.empty()); 86 char hash[crypto::kSHA256Length]; 87 crypto::SHA256HashString(salt + secret_, &hash, sizeof(hash)); 88 89 // Keep only the first half of the hash for 'weak' hashing so that the 90 // plain text secret cannot be reconstructed even if the hashing is 91 // reversed. 92 secret_ = StringToLowerASCII(base::HexEncode( 93 reinterpret_cast<const void*>(hash), sizeof(hash) / 2)); 94 break; 95 } case KEY_TYPE_SALTED_PBKDF2_AES256_1234: { 96 scoped_ptr<crypto::SymmetricKey> key( 97 crypto::SymmetricKey::DeriveKeyFromPassword(crypto::SymmetricKey::AES, 98 secret_, 99 salt, 100 kNumIterations, 101 kKeySizeInBits)); 102 std::string raw_secret; 103 key->GetRawKey(&raw_secret); 104 base::Base64Encode(raw_secret, &secret_); 105 break; 106 } default: 107 // The resulting key will be sent to cryptohomed. It should always be 108 // hashed. If hashing fails, crash instead of sending a plain-text key. 109 CHECK(false); 110 return; 111 } 112 113 key_type_ = target_key_type; 114 salt_ = salt; 115 } 116 117 } // namespace chromeos 118