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