xref: /aosp_15_r20/external/cronet/crypto/symmetric_key.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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