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