Home | History | Annotate | Download | only in crypto
      1 // Copyright (c) 2011 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 "crypto/symmetric_key.h"
      6 
      7 #include <openssl/evp.h>
      8 #include <openssl/rand.h>
      9 
     10 #include <algorithm>
     11 
     12 #include "base/logging.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/strings/string_util.h"
     15 #include "crypto/openssl_util.h"
     16 
     17 namespace crypto {
     18 
     19 SymmetricKey::~SymmetricKey() {
     20   std::fill(key_.begin(), key_.end(), '\0');  // Zero out the confidential key.
     21 }
     22 
     23 // static
     24 SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm,
     25                                               size_t key_size_in_bits) {
     26   DCHECK_EQ(AES, algorithm);
     27   size_t key_size_in_bytes = key_size_in_bits / 8;
     28   DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
     29 
     30   if (key_size_in_bytes == 0)
     31     return NULL;
     32 
     33   OpenSSLErrStackTracer err_tracer(FROM_HERE);
     34   scoped_ptr<SymmetricKey> key(new SymmetricKey);
     35   uint8* key_data =
     36       reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
     37 
     38   int rv = RAND_bytes(key_data, static_cast<int>(key_size_in_bytes));
     39   return rv == 1 ? key.release() : NULL;
     40 }
     41 
     42 // static
     43 SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm,
     44                                                   const std::string& password,
     45                                                   const std::string& salt,
     46                                                   size_t iterations,
     47                                                   size_t key_size_in_bits) {
     48   DCHECK(algorithm == AES || algorithm == HMAC_SHA1);
     49   size_t key_size_in_bytes = key_size_in_bits / 8;
     50   DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
     51 
     52   if (key_size_in_bytes == 0)
     53     return NULL;
     54 
     55   OpenSSLErrStackTracer err_tracer(FROM_HERE);
     56   scoped_ptr<SymmetricKey> key(new SymmetricKey);
     57   uint8* key_data =
     58       reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
     59   int rv = PKCS5_PBKDF2_HMAC_SHA1(password.data(), password.length(),
     60                                   reinterpret_cast<const uint8*>(salt.data()),
     61                                   salt.length(), iterations,
     62                                   static_cast<int>(key_size_in_bytes),
     63                                   key_data);
     64   return rv == 1 ? key.release() : NULL;
     65 }
     66 
     67 // static
     68 SymmetricKey* SymmetricKey::Import(Algorithm algorithm,
     69                                    const std::string& raw_key) {
     70   scoped_ptr<SymmetricKey> key(new SymmetricKey);
     71   key->key_ = raw_key;
     72   return key.release();
     73 }
     74 
     75 bool SymmetricKey::GetRawKey(std::string* raw_key) {
     76   *raw_key = key_;
     77   return true;
     78 }
     79 
     80 }  // namespace crypto
     81