1*6777b538SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "crypto/rsa_private_key.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
8*6777b538SAndroid Build Coastguard Worker
9*6777b538SAndroid Build Coastguard Worker #include <memory>
10*6777b538SAndroid Build Coastguard Worker #include <utility>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
14*6777b538SAndroid Build Coastguard Worker #include "crypto/openssl_util.h"
15*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/bn.h"
16*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/bytestring.h"
17*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/evp.h"
18*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/mem.h"
19*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/rsa.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker namespace crypto {
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker // static
Create(uint16_t num_bits)24*6777b538SAndroid Build Coastguard Worker std::unique_ptr<RSAPrivateKey> RSAPrivateKey::Create(uint16_t num_bits) {
25*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker bssl::UniquePtr<RSA> rsa_key(RSA_new());
28*6777b538SAndroid Build Coastguard Worker bssl::UniquePtr<BIGNUM> bn(BN_new());
29*6777b538SAndroid Build Coastguard Worker if (!rsa_key.get() || !bn.get() || !BN_set_word(bn.get(), 65537L))
30*6777b538SAndroid Build Coastguard Worker return nullptr;
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker if (!RSA_generate_key_ex(rsa_key.get(), num_bits, bn.get(), nullptr))
33*6777b538SAndroid Build Coastguard Worker return nullptr;
34*6777b538SAndroid Build Coastguard Worker
35*6777b538SAndroid Build Coastguard Worker std::unique_ptr<RSAPrivateKey> result(new RSAPrivateKey);
36*6777b538SAndroid Build Coastguard Worker result->key_.reset(EVP_PKEY_new());
37*6777b538SAndroid Build Coastguard Worker if (!result->key_ || !EVP_PKEY_set1_RSA(result->key_.get(), rsa_key.get()))
38*6777b538SAndroid Build Coastguard Worker return nullptr;
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker return result;
41*6777b538SAndroid Build Coastguard Worker }
42*6777b538SAndroid Build Coastguard Worker
43*6777b538SAndroid Build Coastguard Worker // static
CreateFromPrivateKeyInfo(base::span<const uint8_t> input)44*6777b538SAndroid Build Coastguard Worker std::unique_ptr<RSAPrivateKey> RSAPrivateKey::CreateFromPrivateKeyInfo(
45*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> input) {
46*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
47*6777b538SAndroid Build Coastguard Worker
48*6777b538SAndroid Build Coastguard Worker CBS cbs;
49*6777b538SAndroid Build Coastguard Worker CBS_init(&cbs, input.data(), input.size());
50*6777b538SAndroid Build Coastguard Worker bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_private_key(&cbs));
51*6777b538SAndroid Build Coastguard Worker if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA)
52*6777b538SAndroid Build Coastguard Worker return nullptr;
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker std::unique_ptr<RSAPrivateKey> result(new RSAPrivateKey);
55*6777b538SAndroid Build Coastguard Worker result->key_ = std::move(pkey);
56*6777b538SAndroid Build Coastguard Worker return result;
57*6777b538SAndroid Build Coastguard Worker }
58*6777b538SAndroid Build Coastguard Worker
59*6777b538SAndroid Build Coastguard Worker // static
CreateFromKey(EVP_PKEY * key)60*6777b538SAndroid Build Coastguard Worker std::unique_ptr<RSAPrivateKey> RSAPrivateKey::CreateFromKey(EVP_PKEY* key) {
61*6777b538SAndroid Build Coastguard Worker DCHECK(key);
62*6777b538SAndroid Build Coastguard Worker if (EVP_PKEY_id(key) != EVP_PKEY_RSA)
63*6777b538SAndroid Build Coastguard Worker return nullptr;
64*6777b538SAndroid Build Coastguard Worker std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey);
65*6777b538SAndroid Build Coastguard Worker copy->key_ = bssl::UpRef(key);
66*6777b538SAndroid Build Coastguard Worker return copy;
67*6777b538SAndroid Build Coastguard Worker }
68*6777b538SAndroid Build Coastguard Worker
69*6777b538SAndroid Build Coastguard Worker RSAPrivateKey::RSAPrivateKey() = default;
70*6777b538SAndroid Build Coastguard Worker
71*6777b538SAndroid Build Coastguard Worker RSAPrivateKey::~RSAPrivateKey() = default;
72*6777b538SAndroid Build Coastguard Worker
Copy() const73*6777b538SAndroid Build Coastguard Worker std::unique_ptr<RSAPrivateKey> RSAPrivateKey::Copy() const {
74*6777b538SAndroid Build Coastguard Worker std::unique_ptr<RSAPrivateKey> copy(new RSAPrivateKey);
75*6777b538SAndroid Build Coastguard Worker bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(key_.get()));
76*6777b538SAndroid Build Coastguard Worker if (!rsa)
77*6777b538SAndroid Build Coastguard Worker return nullptr;
78*6777b538SAndroid Build Coastguard Worker copy->key_.reset(EVP_PKEY_new());
79*6777b538SAndroid Build Coastguard Worker if (!EVP_PKEY_set1_RSA(copy->key_.get(), rsa.get()))
80*6777b538SAndroid Build Coastguard Worker return nullptr;
81*6777b538SAndroid Build Coastguard Worker return copy;
82*6777b538SAndroid Build Coastguard Worker }
83*6777b538SAndroid Build Coastguard Worker
ExportPrivateKey(std::vector<uint8_t> * output) const84*6777b538SAndroid Build Coastguard Worker bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
85*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
86*6777b538SAndroid Build Coastguard Worker uint8_t *der;
87*6777b538SAndroid Build Coastguard Worker size_t der_len;
88*6777b538SAndroid Build Coastguard Worker bssl::ScopedCBB cbb;
89*6777b538SAndroid Build Coastguard Worker if (!CBB_init(cbb.get(), 0) ||
90*6777b538SAndroid Build Coastguard Worker !EVP_marshal_private_key(cbb.get(), key_.get()) ||
91*6777b538SAndroid Build Coastguard Worker !CBB_finish(cbb.get(), &der, &der_len)) {
92*6777b538SAndroid Build Coastguard Worker return false;
93*6777b538SAndroid Build Coastguard Worker }
94*6777b538SAndroid Build Coastguard Worker output->assign(der, der + der_len);
95*6777b538SAndroid Build Coastguard Worker OPENSSL_free(der);
96*6777b538SAndroid Build Coastguard Worker return true;
97*6777b538SAndroid Build Coastguard Worker }
98*6777b538SAndroid Build Coastguard Worker
ExportPublicKey(std::vector<uint8_t> * output) const99*6777b538SAndroid Build Coastguard Worker bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
100*6777b538SAndroid Build Coastguard Worker OpenSSLErrStackTracer err_tracer(FROM_HERE);
101*6777b538SAndroid Build Coastguard Worker uint8_t *der;
102*6777b538SAndroid Build Coastguard Worker size_t der_len;
103*6777b538SAndroid Build Coastguard Worker bssl::ScopedCBB cbb;
104*6777b538SAndroid Build Coastguard Worker if (!CBB_init(cbb.get(), 0) ||
105*6777b538SAndroid Build Coastguard Worker !EVP_marshal_public_key(cbb.get(), key_.get()) ||
106*6777b538SAndroid Build Coastguard Worker !CBB_finish(cbb.get(), &der, &der_len)) {
107*6777b538SAndroid Build Coastguard Worker return false;
108*6777b538SAndroid Build Coastguard Worker }
109*6777b538SAndroid Build Coastguard Worker output->assign(der, der + der_len);
110*6777b538SAndroid Build Coastguard Worker OPENSSL_free(der);
111*6777b538SAndroid Build Coastguard Worker return true;
112*6777b538SAndroid Build Coastguard Worker }
113*6777b538SAndroid Build Coastguard Worker
114*6777b538SAndroid Build Coastguard Worker } // namespace crypto
115