[go: nahoru, domu]

blob: 4c4e0592e9b6839640fd43639320f257ac26e488 [file] [log] [blame]
Avi Drissman201a9a832022-09-13 19:39:251// Copyright 2011 The Chromium Authors
joth@chromium.org70372d42010-10-22 13:12:342// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
rvargas@google.com4b559b4d2011-04-14 17:37:145#include "crypto/symmetric_key.h"
joth@chromium.org70372d42010-10-22 13:12:346
avidd373b82015-12-21 21:34:437#include <stddef.h>
8#include <stdint.h>
joth@chromium.orgac0f8be2010-11-12 12:03:549
10#include <algorithm>
rsleeviffe5a132016-06-28 01:51:5211#include <utility>
joth@chromium.orgac0f8be2010-11-12 12:03:5412
Hans Wennborg4d0e1802020-04-24 20:19:4313#include "base/check_op.h"
14#include "base/notreached.h"
rvargas@google.com4b559b4d2011-04-14 17:37:1415#include "crypto/openssl_util.h"
tfarina29a3a1742016-10-28 18:47:3316#include "third_party/boringssl/src/include/openssl/evp.h"
17#include "third_party/boringssl/src/include/openssl/rand.h"
joth@chromium.org70372d42010-10-22 13:12:3418
rvargas@google.com4b559b4d2011-04-14 17:37:1419namespace crypto {
joth@chromium.org70372d42010-10-22 13:12:3420
David Davidovićf8cd6a02018-08-27 14:02:5121namespace {
22
23bool CheckDerivationParameters(SymmetricKey::Algorithm algorithm,
24 size_t key_size_in_bits) {
25 switch (algorithm) {
26 case SymmetricKey::AES:
David Benjamin9f8324582022-03-01 23:40:5527 // Check for supported key sizes. Historically, NSS supported AES-192
28 // while BoringSSL did not and this check aligned their behavior.
David Davidovićf8cd6a02018-08-27 14:02:5129 return key_size_in_bits == 128 || key_size_in_bits == 256;
30 case SymmetricKey::HMAC_SHA1:
31 return key_size_in_bits % 8 == 0 && key_size_in_bits != 0;
32 }
33
34 NOTREACHED();
35 return false;
36}
37
38} // namespace
39
joth@chromium.org70372d42010-10-22 13:12:3440SymmetricKey::~SymmetricKey() {
joth@chromium.orgac0f8be2010-11-12 12:03:5441 std::fill(key_.begin(), key_.end(), '\0'); // Zero out the confidential key.
joth@chromium.org70372d42010-10-22 13:12:3442}
43
44// static
rsleeviffe5a132016-06-28 01:51:5245std::unique_ptr<SymmetricKey> SymmetricKey::GenerateRandomKey(
46 Algorithm algorithm,
47 size_t key_size_in_bits) {
joth@chromium.orgac0f8be2010-11-12 12:03:5448 DCHECK_EQ(AES, algorithm);
davidben@chromium.orga534bab2014-07-25 21:04:1549
David Benjamin9f8324582022-03-01 23:40:5550 // Check for supported key sizes. Historically, NSS supported AES-192 while
51 // BoringSSL did not and this check aligned their behavior.
davidben@chromium.orga534bab2014-07-25 21:04:1552 if (key_size_in_bits != 128 && key_size_in_bits != 256)
rsleeviffe5a132016-06-28 01:51:5253 return nullptr;
davidben@chromium.orga534bab2014-07-25 21:04:1554
pkasting@chromium.orgfdce4782011-11-29 20:06:1855 size_t key_size_in_bytes = key_size_in_bits / 8;
56 DCHECK_EQ(key_size_in_bits, key_size_in_bytes * 8);
joth@chromium.orgac0f8be2010-11-12 12:03:5457
pkasting@chromium.orgfdce4782011-11-29 20:06:1858 if (key_size_in_bytes == 0)
rsleeviffe5a132016-06-28 01:51:5259 return nullptr;
joth@chromium.orgac0f8be2010-11-12 12:03:5460
joth@chromium.orgbe796bb2010-11-18 15:43:4361 OpenSSLErrStackTracer err_tracer(FROM_HERE);
thakisd1a18472016-04-08 22:30:4162 std::unique_ptr<SymmetricKey> key(new SymmetricKey);
joth@chromium.orgac0f8be2010-11-12 12:03:5463
David Benjamin78bbd022024-02-09 01:02:4964 key->key_.resize(key_size_in_bytes);
65 int rv = RAND_bytes(reinterpret_cast<uint8_t*>(key->key_.data()),
66 key->key_.size());
rsleeviffe5a132016-06-28 01:51:5267 return rv == 1 ? std::move(key) : nullptr;
joth@chromium.org70372d42010-10-22 13:12:3468}
69
70// static
David Davidovićf8cd6a02018-08-27 14:02:5171std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
rsleeviffe5a132016-06-28 01:51:5272 Algorithm algorithm,
73 const std::string& password,
74 const std::string& salt,
75 size_t iterations,
76 size_t key_size_in_bits) {
David Davidovićf8cd6a02018-08-27 14:02:5177 if (!CheckDerivationParameters(algorithm, key_size_in_bits))
78 return nullptr;
davidben@chromium.orga534bab2014-07-25 21:04:1579
pkasting@chromium.orgfdce4782011-11-29 20:06:1880 size_t key_size_in_bytes = key_size_in_bits / 8;
joth@chromium.orgac0f8be2010-11-12 12:03:5481
joth@chromium.orgbe796bb2010-11-18 15:43:4382 OpenSSLErrStackTracer err_tracer(FROM_HERE);
thakisd1a18472016-04-08 22:30:4183 std::unique_ptr<SymmetricKey> key(new SymmetricKey);
David Benjamin78bbd022024-02-09 01:02:4984 key->key_.resize(key_size_in_bytes);
avidd373b82015-12-21 21:34:4385 int rv = PKCS5_PBKDF2_HMAC_SHA1(
86 password.data(), password.length(),
svaldez9c641462016-05-02 20:49:0587 reinterpret_cast<const uint8_t*>(salt.data()), salt.length(),
David Benjamin78bbd022024-02-09 01:02:4988 static_cast<unsigned>(iterations), key->key_.size(),
89 reinterpret_cast<uint8_t*>(key->key_.data()));
rsleeviffe5a132016-06-28 01:51:5290 return rv == 1 ? std::move(key) : nullptr;
joth@chromium.org70372d42010-10-22 13:12:3491}
92
93// static
David Davidovićf8cd6a02018-08-27 14:02:5194std::unique_ptr<SymmetricKey> SymmetricKey::DeriveKeyFromPasswordUsingScrypt(
95 Algorithm algorithm,
96 const std::string& password,
97 const std::string& salt,
98 size_t cost_parameter,
99 size_t block_size,
100 size_t parallelization_parameter,
101 size_t max_memory_bytes,
102 size_t key_size_in_bits) {
103 if (!CheckDerivationParameters(algorithm, key_size_in_bits))
104 return nullptr;
105
106 size_t key_size_in_bytes = key_size_in_bits / 8;
107
108 OpenSSLErrStackTracer err_tracer(FROM_HERE);
109 std::unique_ptr<SymmetricKey> key(new SymmetricKey);
David Benjamin78bbd022024-02-09 01:02:49110 key->key_.resize(key_size_in_bytes);
111 int rv = EVP_PBE_scrypt(
112 password.data(), password.length(),
113 reinterpret_cast<const uint8_t*>(salt.data()), salt.length(),
114 cost_parameter, block_size, parallelization_parameter, max_memory_bytes,
115 reinterpret_cast<uint8_t*>(key->key_.data()), key->key_.size());
David Davidovićf8cd6a02018-08-27 14:02:51116 return rv == 1 ? std::move(key) : nullptr;
117}
118
119// static
rsleeviffe5a132016-06-28 01:51:52120std::unique_ptr<SymmetricKey> SymmetricKey::Import(Algorithm algorithm,
121 const std::string& raw_key) {
davidben@chromium.orga534bab2014-07-25 21:04:15122 if (algorithm == AES) {
David Benjamin9f8324582022-03-01 23:40:55123 // Check for supported key sizes. Historically, NSS supported AES-192 while
124 // BoringSSL did not and this check aligned their behavior.
davidben@chromium.orga534bab2014-07-25 21:04:15125 if (raw_key.size() != 128/8 && raw_key.size() != 256/8)
rsleeviffe5a132016-06-28 01:51:52126 return nullptr;
davidben@chromium.orga534bab2014-07-25 21:04:15127 }
128
thakisd1a18472016-04-08 22:30:41129 std::unique_ptr<SymmetricKey> key(new SymmetricKey);
joth@chromium.orgac0f8be2010-11-12 12:03:54130 key->key_ = raw_key;
rsleeviffe5a132016-06-28 01:51:52131 return key;
joth@chromium.org70372d42010-10-22 13:12:34132}
133
rsleeviffe5a132016-06-28 01:51:52134SymmetricKey::SymmetricKey() = default;
135
rvargas@google.com4b559b4d2011-04-14 17:37:14136} // namespace crypto