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/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   int key_size_in_bytes = key_size_in_bits / 8;
     28   DCHECK_EQ(static_cast<int>(key_size_in_bits), key_size_in_bytes * 8);
     29 
     30   if (key_size_in_bits == 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, 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   int key_size_in_bytes = key_size_in_bits / 8;
     50   DCHECK_EQ(static_cast<int>(key_size_in_bits), key_size_in_bytes * 8);
     51 
     52   OpenSSLErrStackTracer err_tracer(FROM_HERE);
     53   scoped_ptr<SymmetricKey> key(new SymmetricKey);
     54   uint8* key_data =
     55       reinterpret_cast<uint8*>(WriteInto(&key->key_, key_size_in_bytes + 1));
     56   int rv = PKCS5_PBKDF2_HMAC_SHA1(password.data(), password.length(),
     57                                   reinterpret_cast<const uint8*>(salt.data()),
     58                                   salt.length(), iterations,
     59                                   key_size_in_bytes, key_data);
     60   return rv == 1 ? key.release() : NULL;
     61 }
     62 
     63 // static
     64 SymmetricKey* SymmetricKey::Import(Algorithm algorithm,
     65                                    const std::string& raw_key) {
     66   scoped_ptr<SymmetricKey> key(new SymmetricKey);
     67   key->key_ = raw_key;
     68   return key.release();
     69 }
     70 
     71 bool SymmetricKey::GetRawKey(std::string* raw_key) {
     72   *raw_key = key_;
     73   return true;
     74 }
     75 
     76 }  // namespace crypto
     77