Avi Drissman | 201a9a83 | 2022-09-13 19:39:25 | [diff] [blame] | 1 | // Copyright 2011 The Chromium Authors |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 5 | #include "crypto/rsa_private_key.h" |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 6 | |
avi | dd373b8b | 2015-12-21 21:34:43 | [diff] [blame] | 7 | #include <stdint.h> |
[email protected] | 1f92394 | 2010-11-17 14:39:22 | [diff] [blame] | 8 | |
thakis | d1a1847 | 2016-04-08 22:30:41 | [diff] [blame] | 9 | #include <memory> |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 10 | #include <utility> |
thakis | d1a1847 | 2016-04-08 22:30:41 | [diff] [blame] | 11 | |
Hans Wennborg | 4d0e180 | 2020-04-24 20:19:43 | [diff] [blame] | 12 | #include "base/check.h" |
Maksim Ivanov | bc977822 | 2020-06-29 17:53:16 | [diff] [blame] | 13 | #include "base/containers/span.h" |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 14 | #include "crypto/openssl_util.h" |
tfarina | 29a3a174 | 2016-10-28 18:47:33 | [diff] [blame] | 15 | #include "third_party/boringssl/src/include/openssl/bn.h" |
| 16 | #include "third_party/boringssl/src/include/openssl/bytestring.h" |
| 17 | #include "third_party/boringssl/src/include/openssl/evp.h" |
| 18 | #include "third_party/boringssl/src/include/openssl/mem.h" |
| 19 | #include "third_party/boringssl/src/include/openssl/rsa.h" |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 20 | |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 21 | namespace crypto { |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 22 | |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 23 | // static |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 24 | std::unique_ptr<RSAPrivateKey> RSAPrivateKey::Create(uint16_t num_bits) { |
[email protected] | be796bb | 2010-11-18 15:43:43 | [diff] [blame] | 25 | OpenSSLErrStackTracer err_tracer(FROM_HERE); |
[email protected] | fed406f8 | 2010-12-08 15:40:45 | [diff] [blame] | 26 | |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 27 | bssl::UniquePtr<RSA> rsa_key(RSA_new()); |
| 28 | bssl::UniquePtr<BIGNUM> bn(BN_new()); |
[email protected] | fed406f8 | 2010-12-08 15:40:45 | [diff] [blame] | 29 | if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L)) |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 30 | return nullptr; |
[email protected] | fed406f8 | 2010-12-08 15:40:45 | [diff] [blame] | 31 | |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 32 | if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), nullptr)) |
| 33 | return nullptr; |
[email protected] | 1f92394 | 2010-11-17 14:39:22 | [diff] [blame] | 34 | |
thakis | d1a1847 | 2016-04-08 22:30:41 | [diff] [blame] | 35 | std::unique_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 36 | result->key_.reset(EVP_PKEY_new()); |
| 37 | if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_.get(), rsa_key.get())) |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 38 | return nullptr; |
[email protected] | 1f92394 | 2010-11-17 14:39:22 | [diff] [blame] | 39 | |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 40 | return result; |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 41 | } |
| 42 | |
| 43 | // static |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 44 | std::unique_ptr<RSAPrivateKey> RSAPrivateKey::CreateFromPrivateKeyInfo( |
Maksim Ivanov | bc977822 | 2020-06-29 17:53:16 | [diff] [blame] | 45 | base::span<const uint8_t> input) { |
[email protected] | d641b6e | 2011-07-20 11:07:16 | [diff] [blame] | 46 | OpenSSLErrStackTracer err_tracer(FROM_HERE); |
[email protected] | 1f92394 | 2010-11-17 14:39:22 | [diff] [blame] | 47 | |
davidben | 7dad2a3 | 2016-03-01 23:47:47 | [diff] [blame] | 48 | CBS cbs; |
| 49 | CBS_init(&cbs, input.data(), input.size()); |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 50 | bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs)); |
davidben | 7dad2a3 | 2016-03-01 23:47:47 | [diff] [blame] | 51 | if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA) |
| 52 | return nullptr; |
[email protected] | 1f92394 | 2010-11-17 14:39:22 | [diff] [blame] | 53 | |
thakis | d1a1847 | 2016-04-08 22:30:41 | [diff] [blame] | 54 | std::unique_ptr<RSAPrivateKey> result(new RSAPrivateKey); |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 55 | result->key_ = std::move(pkey); |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 56 | return result; |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 57 | } |
| 58 | |
dougsteed | db7726ae | 2014-09-10 23:21:48 | [diff] [blame] | 59 | // static |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 60 | std::unique_ptr<RSAPrivateKey> RSAPrivateKey::CreateFromKey(EVP_PKEY* key) { |
dougsteed | db7726ae | 2014-09-10 23:21:48 | [diff] [blame] | 61 | DCHECK(key); |
David Benjamin | 4ba5e7f9 | 2022-07-15 15:08:01 | [diff] [blame] | 62 | if (EVP_PKEY_id(key) != EVP_PKEY_RSA) |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 63 | return nullptr; |
| 64 | std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey); |
David Benjamin | 139c557 | 2018-07-06 23:53:42 | [diff] [blame] | 65 | copy->key_ = bssl::UpRef(key); |
dougsteed | db7726ae | 2014-09-10 23:21:48 | [diff] [blame] | 66 | return copy; |
| 67 | } |
| 68 | |
Chris Watkins | a850a30 | 2017-11-30 03:53:49 | [diff] [blame] | 69 | RSAPrivateKey::RSAPrivateKey() = default; |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 70 | |
Chris Watkins | a850a30 | 2017-11-30 03:53:49 | [diff] [blame] | 71 | RSAPrivateKey::~RSAPrivateKey() = default; |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 72 | |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 73 | std::unique_ptr<RSAPrivateKey> RSAPrivateKey::Copy() const { |
| 74 | std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey); |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 75 | bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(key_.get())); |
[email protected] | 5878288 | 2011-12-03 01:12:08 | [diff] [blame] | 76 | if (!rsa) |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 77 | return nullptr; |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 78 | copy->key_.reset(EVP_PKEY_new()); |
| 79 | if (!EVP_PKEY_set1_RSA(copy->key_.get(), rsa.get())) |
rsleevi | d1afa1e | 2016-06-22 04:00:48 | [diff] [blame] | 80 | return nullptr; |
| 81 | return copy; |
[email protected] | 5878288 | 2011-12-03 01:12:08 | [diff] [blame] | 82 | } |
| 83 | |
avi | dd373b8b | 2015-12-21 21:34:43 | [diff] [blame] | 84 | bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const { |
davidben | 212cdf6 | 2016-06-07 17:11:09 | [diff] [blame] | 85 | OpenSSLErrStackTracer err_tracer(FROM_HERE); |
davidben | 7dad2a3 | 2016-03-01 23:47:47 | [diff] [blame] | 86 | uint8_t *der; |
| 87 | size_t der_len; |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 88 | bssl::ScopedCBB cbb; |
davidben | 7dad2a3 | 2016-03-01 23:47:47 | [diff] [blame] | 89 | if (!CBB_init(cbb.get(), 0) || |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 90 | !EVP_marshal_private_key(cbb.get(), key_.get()) || |
davidben | 7dad2a3 | 2016-03-01 23:47:47 | [diff] [blame] | 91 | !CBB_finish(cbb.get(), &der, &der_len)) { |
| 92 | return false; |
| 93 | } |
| 94 | output->assign(der, der + der_len); |
| 95 | OPENSSL_free(der); |
| 96 | return true; |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 97 | } |
| 98 | |
avi | dd373b8b | 2015-12-21 21:34:43 | [diff] [blame] | 99 | bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const { |
davidben | 212cdf6 | 2016-06-07 17:11:09 | [diff] [blame] | 100 | OpenSSLErrStackTracer err_tracer(FROM_HERE); |
davidben | 7dad2a3 | 2016-03-01 23:47:47 | [diff] [blame] | 101 | uint8_t *der; |
| 102 | size_t der_len; |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 103 | bssl::ScopedCBB cbb; |
davidben | 7dad2a3 | 2016-03-01 23:47:47 | [diff] [blame] | 104 | if (!CBB_init(cbb.get(), 0) || |
davidben | 74f6744 | 2016-10-01 01:45:22 | [diff] [blame] | 105 | !EVP_marshal_public_key(cbb.get(), key_.get()) || |
davidben | 7dad2a3 | 2016-03-01 23:47:47 | [diff] [blame] | 106 | !CBB_finish(cbb.get(), &der, &der_len)) { |
| 107 | return false; |
| 108 | } |
| 109 | output->assign(der, der + der_len); |
| 110 | OPENSSL_free(der); |
| 111 | return true; |
[email protected] | 70372d4 | 2010-10-22 13:12:34 | [diff] [blame] | 112 | } |
| 113 | |
[email protected] | 4b559b4d | 2011-04-14 17:37:14 | [diff] [blame] | 114 | } // namespace crypto |