• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 The Chromium Authors
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/check_op.h"
14 #include "base/notreached.h"
15 #include "crypto/kdf.h"
16 #include "crypto/openssl_util.h"
17 #include "crypto/random.h"
18 
19 namespace crypto {
20 
21 namespace {
22 
IsValidKeySize(size_t key_size_in_bytes)23 bool IsValidKeySize(size_t key_size_in_bytes) {
24   // Nobody should ever be using other symmetric key sizes without consulting
25   // with CRYPTO_OWNERS first, who can modify this check if need be.
26   return key_size_in_bytes == 16 || key_size_in_bytes == 32;
27 }
28 
29 }  // namespace
30 
SymmetricKey(base::span<const uint8_t> key_bytes)31 SymmetricKey::SymmetricKey(base::span<const uint8_t> key_bytes)
32     : key_(base::as_string_view(key_bytes)) {}
33 
34 SymmetricKey::SymmetricKey(const SymmetricKey& other) = default;
35 SymmetricKey& SymmetricKey::operator=(const SymmetricKey& other) = default;
36 
~SymmetricKey()37 SymmetricKey::~SymmetricKey() {
38   std::fill(key_.begin(), key_.end(), '\0');  // Zero out the confidential key.
39 }
40 
41 // static
GenerateRandomKey(Algorithm,size_t key_size_in_bits)42 std::unique_ptr<SymmetricKey> SymmetricKey::GenerateRandomKey(
43     Algorithm,
44     size_t key_size_in_bits) {
45   return std::make_unique<SymmetricKey>(RandomKey(key_size_in_bits));
46 }
47 
48 // static
RandomKey(size_t key_size_in_bits)49 SymmetricKey SymmetricKey::RandomKey(size_t key_size_in_bits) {
50   CHECK(!(key_size_in_bits % 8));
51 
52   const size_t key_size_in_bytes = key_size_in_bits / 8;
53   CHECK(IsValidKeySize(key_size_in_bytes));
54 
55   return SymmetricKey(crypto::RandBytesAsVector(key_size_in_bytes));
56 }
57 
58 // static
DeriveKeyFromPasswordUsingPbkdf2(Algorithm,const std::string & password,const std::string & salt,size_t iterations,size_t key_size_in_bits)59 std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
60     Algorithm,
61     const std::string& password,
62     const std::string& salt,
63     size_t iterations,
64     size_t key_size_in_bits) {
65   if ((key_size_in_bits % 8) || !IsValidKeySize(key_size_in_bits / 8)) {
66     return nullptr;
67   }
68 
69   kdf::Pbkdf2HmacSha1Params params = {
70       .iterations = base::checked_cast<decltype(params.iterations)>(iterations),
71   };
72 
73   std::vector<uint8_t> key(key_size_in_bits / 8);
74   kdf::DeriveKeyPbkdf2HmacSha1(params, base::as_byte_span(password),
75                                base::as_byte_span(salt), key, SubtlePassKey{});
76 
77   return std::make_unique<SymmetricKey>(key);
78 }
79 
80 // static
DeriveKeyFromPasswordUsingScrypt(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)81 std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPasswordUsingScrypt(
82     Algorithm,
83     const std::string& password,
84     const std::string& salt,
85     size_t cost_parameter,
86     size_t block_size,
87     size_t parallelization_parameter,
88     size_t max_memory_bytes,
89     size_t key_size_in_bits) {
90   if ((key_size_in_bits % 8) || !IsValidKeySize(key_size_in_bits / 8)) {
91     return nullptr;
92   }
93 
94   kdf::ScryptParams params = {
95       .cost = cost_parameter,
96       .block_size = block_size,
97       .parallelization = parallelization_parameter,
98       .max_memory_bytes = max_memory_bytes,
99   };
100   std::vector<uint8_t> key(key_size_in_bits / 8);
101   kdf::DeriveKeyScrypt(params, base::as_byte_span(password),
102                        base::as_byte_span(salt), key, SubtlePassKey{});
103   return std::make_unique<SymmetricKey>(key);
104 }
105 
106 // static
Import(Algorithm,const std::string & raw_key)107 std::unique_ptr<SymmetricKey> SymmetricKey::Import(Algorithm,
108                                                    const std::string& raw_key) {
109   if (!IsValidKeySize(raw_key.size())) {
110     return nullptr;
111   }
112   return std::make_unique<SymmetricKey>(base::as_byte_span(raw_key));
113 }
114 
115 }  // namespace crypto
116