Home | History | Annotate | Download | only in auth
      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