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 #include <stddef.h>
     10 #include <stdint.h>
     11 
     12 #include <algorithm>
     13 
     14 #include "base/logging.h"
     15 #include "base/memory/scoped_ptr.h"
     16 #include "base/strings/string_util.h"
     17 #include "crypto/openssl_util.h"
     18 
     19 namespace crypto {
     20 
     21 SymmetricKey::~SymmetricKey() {
     22   std::fill(key_.begin(), key_.end(), '\0');  // Zero out the confidential key.
     23 }
     24 
     25 // static
     26 SymmetricKey* SymmetricKey::GenerateRandomKey(Algorithm algorithm,
     27                                               size_t key_size_in_bits) {
     28   DCHECK_EQ(AES, algorithm);
     29 
     30   // Whitelist supported key sizes to avoid accidentaly relying on
     31   // algorithms available in NSS but not BoringSSL and vice
     32   // versa. Note that BoringSSL does not support AES-192.
     33   if (key_size_in_bits != 128 && key_size_in_bits != 256)
     34     return NULL;
     35 
     36   size_t key_size_in_bytes = key_size_in_bits / 8;
     37   DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
     38 
     39   if (key_size_in_bytes == 0)
     40     return NULL;
     41 
     42   OpenSSLErrStackTracer err_tracer(FROM_HERE);
     43   scoped_ptr<SymmetricKey> key(new SymmetricKey);
     44   uint8_t* key_data = reinterpret_cast<uint8_t*>(
     45       base::WriteInto(&key->key_, key_size_in_bytes + 1));
     46 
     47   int rv = RAND_bytes(key_data, static_cast<int>(key_size_in_bytes));
     48   return rv == 1 ? key.release() : NULL;
     49 }
     50 
     51 // static
     52 SymmetricKey* SymmetricKey::DeriveKeyFromPassword(Algorithm algorithm,
     53                                                   const std::string& password,
     54                                                   const std::string& salt,
     55                                                   size_t iterations,
     56                                                   size_t key_size_in_bits) {
     57   DCHECK(algorithm == AES || algorithm == HMAC_SHA1);
     58 
     59   if (algorithm == AES) {
     60     // Whitelist supported key sizes to avoid accidentaly relying on
     61     // algorithms available in NSS but not BoringSSL and vice
     62     // versa. Note that BoringSSL does not support AES-192.
     63     if (key_size_in_bits != 128 && key_size_in_bits != 256)
     64       return NULL;
     65   }
     66 
     67   size_t key_size_in_bytes = key_size_in_bits / 8;
     68   DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
     69 
     70   if (key_size_in_bytes == 0)
     71     return NULL;
     72 
     73   OpenSSLErrStackTracer err_tracer(FROM_HERE);
     74   scoped_ptr<SymmetricKey> key(new SymmetricKey);
     75   uint8_t* key_data = reinterpret_cast<uint8_t*>(
     76       base::WriteInto(&key->key_, key_size_in_bytes + 1));
     77   int rv = PKCS5_PBKDF2_HMAC_SHA1(
     78       password.data(), password.length(),
     79       reinterpret_cast<const uint8_t*>(salt.data()), salt.length(), iterations,
     80       static_cast<int>(key_size_in_bytes), key_data);
     81   return rv == 1 ? key.release() : NULL;
     82 }
     83 
     84 // static
     85 SymmetricKey* SymmetricKey::Import(Algorithm algorithm,
     86                                    const std::string& raw_key) {
     87   if (algorithm == AES) {
     88     // Whitelist supported key sizes to avoid accidentaly relying on
     89     // algorithms available in NSS but not BoringSSL and vice
     90     // versa. Note that BoringSSL does not support AES-192.
     91     if (raw_key.size() != 128/8 && raw_key.size() != 256/8)
     92       return NULL;
     93   }
     94 
     95   scoped_ptr<SymmetricKey> key(new SymmetricKey);
     96   key->key_ = raw_key;
     97   return key.release();
     98 }
     99 
    100 bool SymmetricKey::GetRawKey(std::string* raw_key) {
    101   *raw_key = key_;
    102   return true;
    103 }
    104 
    105 }  // namespace crypto
    106