1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "crypto/symmetric_key.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
9*6777b538SAndroid Build Coastguard Worker
10*6777b538SAndroid Build Coastguard Worker #include <algorithm>
11*6777b538SAndroid Build Coastguard Worker #include <utility>
12*6777b538SAndroid Build Coastguard Worker
13*6777b538SAndroid Build Coastguard Worker #include "base/check_op.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
15*6777b538SAndroid Build Coastguard Worker #include "crypto/openssl_util.h"
16*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/evp.h"
17*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/rand.h"
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker namespace crypto {
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace {
22*6777b538SAndroid Build Coastguard Worker
CheckDerivationParameters(SymmetricKey::Algorithm algorithm,size_t key_size_in_bits)23*6777b538SAndroid Build Coastguard Worker bool CheckDerivationParameters(SymmetricKey::Algorithm algorithm,
24*6777b538SAndroid Build Coastguard Worker size_t key_size_in_bits) {
25*6777b538SAndroid Build Coastguard Worker switch (algorithm) {
26*6777b538SAndroid Build Coastguard Worker case SymmetricKey::AES:
27*6777b538SAndroid Build Coastguard Worker // Check for supported key sizes. Historically, NSS supported AES-192
28*6777b538SAndroid Build Coastguard Worker // while BoringSSL did not and this check aligned their behavior.
29*6777b538SAndroid Build Coastguard Worker return key_size_in_bits == 128 || key_size_in_bits == 256;
30*6777b538SAndroid Build Coastguard Worker case SymmetricKey::HMAC_SHA1:
31*6777b538SAndroid Build Coastguard Worker return key_size_in_bits % 8 == 0 && key_size_in_bits != 0;
32*6777b538SAndroid Build Coastguard Worker }
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker NOTREACHED();
35*6777b538SAndroid Build Coastguard Worker return false;
36*6777b538SAndroid Build Coastguard Worker }
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker } // namespace
39*6777b538SAndroid Build Coastguard Worker
~SymmetricKey()40*6777b538SAndroid Build Coastguard Worker SymmetricKey::~SymmetricKey() {
41*6777b538SAndroid Build Coastguard Worker std::fill(key_.begin(), key_.end(), '\0'); // Zero out the confidential key.
42*6777b538SAndroid Build Coastguard Worker }
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker // static
GenerateRandomKey(Algorithm algorithm,size_t key_size_in_bits)45*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SymmetricKey> SymmetricKey::GenerateRandomKey(
46*6777b538SAndroid Build Coastguard Worker Algorithm algorithm,
47*6777b538SAndroid Build Coastguard Worker size_t key_size_in_bits) {
48*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(AES, algorithm);
49*6777b538SAndroid Build Coastguard Worker
50*6777b538SAndroid Build Coastguard Worker // Check for supported key sizes. Historically, NSS supported AES-192 while
51*6777b538SAndroid Build Coastguard Worker // BoringSSL did not and this check aligned their behavior.
52*6777b538SAndroid Build Coastguard Worker if (key_size_in_bits != 128 && key_size_in_bits != 256)
53*6777b538SAndroid Build Coastguard Worker return nullptr;
54*6777b538SAndroid Build Coastguard Worker
55*6777b538SAndroid Build Coastguard Worker size_t key_size_in_bytes = key_size_in_bits / 8;
56*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker if (key_size_in_bytes == 0)
59*6777b538SAndroid Build Coastguard Worker return nullptr;
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
62*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SymmetricKey> key(new SymmetricKey);
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker key->key_.resize(key_size_in_bytes);
65*6777b538SAndroid Build Coastguard Worker int rv = RAND_bytes(reinterpret_cast<uint8_t*>(key->key_.data()),
66*6777b538SAndroid Build Coastguard Worker key->key_.size());
67*6777b538SAndroid Build Coastguard Worker return rv == 1 ? std::move(key) : nullptr;
68*6777b538SAndroid Build Coastguard Worker }
69*6777b538SAndroid Build Coastguard Worker
70*6777b538SAndroid Build Coastguard Worker // static
DeriveKeyFromPasswordUsingPbkdf2(Algorithm algorithm,const std::string & password,const std::string & salt,size_t iterations,size_t key_size_in_bits)71*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
72*6777b538SAndroid Build Coastguard Worker Algorithm algorithm,
73*6777b538SAndroid Build Coastguard Worker const std::string& password,
74*6777b538SAndroid Build Coastguard Worker const std::string& salt,
75*6777b538SAndroid Build Coastguard Worker size_t iterations,
76*6777b538SAndroid Build Coastguard Worker size_t key_size_in_bits) {
77*6777b538SAndroid Build Coastguard Worker if (!CheckDerivationParameters(algorithm, key_size_in_bits))
78*6777b538SAndroid Build Coastguard Worker return nullptr;
79*6777b538SAndroid Build Coastguard Worker
80*6777b538SAndroid Build Coastguard Worker size_t key_size_in_bytes = key_size_in_bits / 8;
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
83*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SymmetricKey> key(new SymmetricKey);
84*6777b538SAndroid Build Coastguard Worker key->key_.resize(key_size_in_bytes);
85*6777b538SAndroid Build Coastguard Worker int rv = PKCS5_PBKDF2_HMAC_SHA1(
86*6777b538SAndroid Build Coastguard Worker password.data(), password.length(),
87*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const uint8_t*>(salt.data()), salt.length(),
88*6777b538SAndroid Build Coastguard Worker static_cast<unsigned>(iterations), key->key_.size(),
89*6777b538SAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(key->key_.data()));
90*6777b538SAndroid Build Coastguard Worker return rv == 1 ? std::move(key) : nullptr;
91*6777b538SAndroid Build Coastguard Worker }
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Worker // static
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)94*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPasswordUsingScrypt(
95*6777b538SAndroid Build Coastguard Worker Algorithm algorithm,
96*6777b538SAndroid Build Coastguard Worker const std::string& password,
97*6777b538SAndroid Build Coastguard Worker const std::string& salt,
98*6777b538SAndroid Build Coastguard Worker size_t cost_parameter,
99*6777b538SAndroid Build Coastguard Worker size_t block_size,
100*6777b538SAndroid Build Coastguard Worker size_t parallelization_parameter,
101*6777b538SAndroid Build Coastguard Worker size_t max_memory_bytes,
102*6777b538SAndroid Build Coastguard Worker size_t key_size_in_bits) {
103*6777b538SAndroid Build Coastguard Worker if (!CheckDerivationParameters(algorithm, key_size_in_bits))
104*6777b538SAndroid Build Coastguard Worker return nullptr;
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker size_t key_size_in_bytes = key_size_in_bits / 8;
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
109*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SymmetricKey> key(new SymmetricKey);
110*6777b538SAndroid Build Coastguard Worker key->key_.resize(key_size_in_bytes);
111*6777b538SAndroid Build Coastguard Worker int rv = EVP_PBE_scrypt(
112*6777b538SAndroid Build Coastguard Worker password.data(), password.length(),
113*6777b538SAndroid Build Coastguard Worker reinterpret_cast<const uint8_t*>(salt.data()), salt.length(),
114*6777b538SAndroid Build Coastguard Worker cost_parameter, block_size, parallelization_parameter, max_memory_bytes,
115*6777b538SAndroid Build Coastguard Worker reinterpret_cast<uint8_t*>(key->key_.data()), key->key_.size());
116*6777b538SAndroid Build Coastguard Worker return rv == 1 ? std::move(key) : nullptr;
117*6777b538SAndroid Build Coastguard Worker }
118*6777b538SAndroid Build Coastguard Worker
119*6777b538SAndroid Build Coastguard Worker // static
Import(Algorithm algorithm,const std::string & raw_key)120*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SymmetricKey> SymmetricKey::Import(Algorithm algorithm,
121*6777b538SAndroid Build Coastguard Worker const std::string& raw_key) {
122*6777b538SAndroid Build Coastguard Worker if (algorithm == AES) {
123*6777b538SAndroid Build Coastguard Worker // Check for supported key sizes. Historically, NSS supported AES-192 while
124*6777b538SAndroid Build Coastguard Worker // BoringSSL did not and this check aligned their behavior.
125*6777b538SAndroid Build Coastguard Worker if (raw_key.size() != 128/8 && raw_key.size() != 256/8)
126*6777b538SAndroid Build Coastguard Worker return nullptr;
127*6777b538SAndroid Build Coastguard Worker }
128*6777b538SAndroid Build Coastguard Worker
129*6777b538SAndroid Build Coastguard Worker std::unique_ptr<SymmetricKey> key(new SymmetricKey);
130*6777b538SAndroid Build Coastguard Worker key->key_ = raw_key;
131*6777b538SAndroid Build Coastguard Worker return key;
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker SymmetricKey::SymmetricKey() = default;
135*6777b538SAndroid Build Coastguard Worker
136*6777b538SAndroid Build Coastguard Worker } // namespace crypto
137