• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Key()25 Key::Key() : key_type_(KEY_TYPE_PASSWORD_PLAIN) {
26 }
27 
Key(const Key & other)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 
Key(const std::string & plain_text_password)35 Key::Key(const std::string& plain_text_password)
36     : key_type_(KEY_TYPE_PASSWORD_PLAIN), secret_(plain_text_password) {
37 }
38 
Key(KeyType key_type,const std::string & salt,const std::string & secret)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 
~Key()43 Key::~Key() {
44 }
45 
operator ==(const Key & other) const46 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 
GetKeyType() const51 Key::KeyType Key::GetKeyType() const {
52   return key_type_;
53 }
54 
GetSecret() const55 const std::string& Key::GetSecret() const {
56   return secret_;
57 }
58 
GetLabel() const59 const std::string& Key::GetLabel() const {
60   return label_;
61 }
62 
SetLabel(const std::string & label)63 void Key::SetLabel(const std::string& label) {
64   label_ = label;
65 }
66 
ClearSecret()67 void Key::ClearSecret() {
68   secret_.clear();
69 }
70 
Transform(KeyType target_key_type,const std::string & salt)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