123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- // Copyright (c) 2011 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "crypto/symmetric_key.h"
- #include <stddef.h>
- #include <stdint.h>
- #include <algorithm>
- #include <utility>
- #include "base/check_op.h"
- #include "base/notreached.h"
- #include "base/strings/string_util.h"
- #include "crypto/openssl_util.h"
- #include "third_party/boringssl/src/include/openssl/evp.h"
- #include "third_party/boringssl/src/include/openssl/rand.h"
- namespace crypto {
- namespace {
- bool CheckDerivationParameters(SymmetricKey::Algorithm algorithm,
- size_t key_size_in_bits) {
- switch (algorithm) {
- case SymmetricKey::AES:
- // Check for supported key sizes. Historically, NSS supported AES-192
- // while BoringSSL did not and this check aligned their behavior.
- return key_size_in_bits == 128 || key_size_in_bits == 256;
- case SymmetricKey::HMAC_SHA1:
- return key_size_in_bits % 8 == 0 && key_size_in_bits != 0;
- }
- NOTREACHED();
- return false;
- }
- } // namespace
- SymmetricKey::~SymmetricKey() {
- std::fill(key_.begin(), key_.end(), '\0'); // Zero out the confidential key.
- }
- // static
- std::unique_ptr<SymmetricKey> SymmetricKey::GenerateRandomKey(
- Algorithm algorithm,
- size_t key_size_in_bits) {
- DCHECK_EQ(AES, algorithm);
- // Check for supported key sizes. Historically, NSS supported AES-192 while
- // BoringSSL did not and this check aligned their behavior.
- if (key_size_in_bits != 128 && key_size_in_bits != 256)
- return nullptr;
- size_t key_size_in_bytes = key_size_in_bits / 8;
- DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
- if (key_size_in_bytes == 0)
- return nullptr;
- OpenSSLErrStackTracer err_tracer(FROM_HERE);
- std::unique_ptr<SymmetricKey> key(new SymmetricKey);
- uint8_t* key_data = reinterpret_cast<uint8_t*>(
- base::WriteInto(&key->key_, key_size_in_bytes + 1));
- int rv = RAND_bytes(key_data, static_cast<int>(key_size_in_bytes));
- return rv == 1 ? std::move(key) : nullptr;
- }
- // static
- std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
- Algorithm algorithm,
- const std::string& password,
- const std::string& salt,
- size_t iterations,
- size_t key_size_in_bits) {
- if (!CheckDerivationParameters(algorithm, key_size_in_bits))
- return nullptr;
- size_t key_size_in_bytes = key_size_in_bits / 8;
- OpenSSLErrStackTracer err_tracer(FROM_HERE);
- std::unique_ptr<SymmetricKey> key(new SymmetricKey);
- uint8_t* key_data = reinterpret_cast<uint8_t*>(
- base::WriteInto(&key->key_, key_size_in_bytes + 1));
- int rv = PKCS5_PBKDF2_HMAC_SHA1(
- password.data(), password.length(),
- reinterpret_cast<const uint8_t*>(salt.data()), salt.length(),
- static_cast<unsigned>(iterations),
- key_size_in_bytes, key_data);
- return rv == 1 ? std::move(key) : nullptr;
- }
- // static
- std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPasswordUsingScrypt(
- Algorithm algorithm,
- const std::string& password,
- const std::string& salt,
- size_t cost_parameter,
- size_t block_size,
- size_t parallelization_parameter,
- size_t max_memory_bytes,
- size_t key_size_in_bits) {
- if (!CheckDerivationParameters(algorithm, key_size_in_bits))
- return nullptr;
- size_t key_size_in_bytes = key_size_in_bits / 8;
- OpenSSLErrStackTracer err_tracer(FROM_HERE);
- std::unique_ptr<SymmetricKey> key(new SymmetricKey);
- uint8_t* key_data = reinterpret_cast<uint8_t*>(
- base::WriteInto(&key->key_, key_size_in_bytes + 1));
- int rv = EVP_PBE_scrypt(password.data(), password.length(),
- reinterpret_cast<const uint8_t*>(salt.data()),
- salt.length(), cost_parameter, block_size,
- parallelization_parameter, max_memory_bytes, key_data,
- key_size_in_bytes);
- return rv == 1 ? std::move(key) : nullptr;
- }
- // static
- std::unique_ptr<SymmetricKey> SymmetricKey::Import(Algorithm algorithm,
- const std::string& raw_key) {
- if (algorithm == AES) {
- // Check for supported key sizes. Historically, NSS supported AES-192 while
- // BoringSSL did not and this check aligned their behavior.
- if (raw_key.size() != 128/8 && raw_key.size() != 256/8)
- return nullptr;
- }
- std::unique_ptr<SymmetricKey> key(new SymmetricKey);
- key->key_ = raw_key;
- return key;
- }
- SymmetricKey::SymmetricKey() = default;
- } // namespace crypto
|