• 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 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
7 #pragma allow_unsafe_buffers
8 #endif
9 
10 #include "crypto/rsa_private_key.h"
11 
12 #include <stdint.h>
13 
14 #include <memory>
15 #include <utility>
16 
17 #include "base/check.h"
18 #include "base/containers/span.h"
19 #include "crypto/openssl_util.h"
20 #include "third_party/boringssl/src/include/openssl/bn.h"
21 #include "third_party/boringssl/src/include/openssl/bytestring.h"
22 #include "third_party/boringssl/src/include/openssl/evp.h"
23 #include "third_party/boringssl/src/include/openssl/mem.h"
24 #include "third_party/boringssl/src/include/openssl/rsa.h"
25 
26 namespace crypto {
27 
28 // static
Create(uint16_t num_bits)29 std::unique_ptr<RSAPrivateKey> RSAPrivateKey::Create(uint16_t num_bits) {
30   OpenSSLErrStackTracer err_tracer(FROM_HERE);
31 
32   bssl::UniquePtr<RSA> rsa_key(RSA_new());
33   bssl::UniquePtr<BIGNUM> bn(BN_new());
34   if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L))
35     return nullptr;
36 
37   if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), nullptr))
38     return nullptr;
39 
40   std::unique_ptr<RSAPrivateKey> result(new RSAPrivateKey);
41   result->key_.reset(EVP_PKEY_new());
42   if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_.get(), rsa_key.get()))
43     return nullptr;
44 
45   return result;
46 }
47 
48 // static
CreateFromPrivateKeyInfo(base::span<const uint8_t> input)49 std::unique_ptr<RSAPrivateKey> RSAPrivateKey::CreateFromPrivateKeyInfo(
50     base::span<const uint8_t> input) {
51   OpenSSLErrStackTracer err_tracer(FROM_HERE);
52 
53   CBS cbs;
54   CBS_init(&cbs, input.data(), input.size());
55   bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
56   if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA)
57     return nullptr;
58 
59   std::unique_ptr<RSAPrivateKey> result(new RSAPrivateKey);
60   result->key_ = std::move(pkey);
61   return result;
62 }
63 
64 // static
CreateFromKey(EVP_PKEY * key)65 std::unique_ptr<RSAPrivateKey> RSAPrivateKey::CreateFromKey(EVP_PKEY* key) {
66   DCHECK(key);
67   if (EVP_PKEY_id(key) != EVP_PKEY_RSA)
68     return nullptr;
69   std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey);
70   copy->key_ = bssl::UpRef(key);
71   return copy;
72 }
73 
74 RSAPrivateKey::RSAPrivateKey() = default;
75 
76 RSAPrivateKey::~RSAPrivateKey() = default;
77 
Copy() const78 std::unique_ptr<RSAPrivateKey> RSAPrivateKey::Copy() const {
79   std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey);
80   bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(key_.get()));
81   if (!rsa)
82     return nullptr;
83   copy->key_.reset(EVP_PKEY_new());
84   if (!EVP_PKEY_set1_RSA(copy->key_.get(), rsa.get()))
85     return nullptr;
86   return copy;
87 }
88 
ExportPrivateKey(std::vector<uint8_t> * output) const89 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
90   OpenSSLErrStackTracer err_tracer(FROM_HERE);
91   uint8_t *der;
92   size_t der_len;
93   bssl::ScopedCBB cbb;
94   if (!CBB_init(cbb.get(), 0) ||
95       !EVP_marshal_private_key(cbb.get(), key_.get()) ||
96       !CBB_finish(cbb.get(), &der, &der_len)) {
97     return false;
98   }
99   output->assign(der, der + der_len);
100   OPENSSL_free(der);
101   return true;
102 }
103 
ExportPublicKey(std::vector<uint8_t> * output) const104 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
105   OpenSSLErrStackTracer err_tracer(FROM_HERE);
106   uint8_t *der;
107   size_t der_len;
108   bssl::ScopedCBB cbb;
109   if (!CBB_init(cbb.get(), 0) ||
110       !EVP_marshal_public_key(cbb.get(), key_.get()) ||
111       !CBB_finish(cbb.get(), &der, &der_len)) {
112     return false;
113   }
114   output->assign(der, der + der_len);
115   OPENSSL_free(der);
116   return true;
117 }
118 
119 }  // namespace crypto
120