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