• 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 "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 
Key()25 Key::Key() : key_type_(KEY_TYPE_PASSWORD_PLAIN) {
26 }
27 
Key(const Key & other)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 
Key(const std::string & plain_text_password)34 Key::Key(const std::string& plain_text_password)
35     : key_type_(KEY_TYPE_PASSWORD_PLAIN),
36       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),
41       salt_(salt),
42       secret_(secret) {
43 
44 }
45 
~Key()46 Key::~Key() {
47 }
48 
operator ==(const Key & other) const49 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 
GetKeyType() const56 Key::KeyType Key::GetKeyType() const {
57   return key_type_;
58 }
59 
GetSecret() const60 const std::string& Key::GetSecret() const {
61   return secret_;
62 }
63 
GetLabel() const64 const std::string& Key::GetLabel() const {
65   return label_;
66 }
67 
SetLabel(const std::string & label)68 void Key::SetLabel(const std::string& label) {
69   label_ = label;
70 }
71 
ClearSecret()72 void Key::ClearSecret() {
73   secret_.clear();
74 }
75 
Transform(KeyType target_key_type,const std::string & salt)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