1*3f982cf4SFabien Sanglard // Copyright 2019 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard
5*3f982cf4SFabien Sanglard #include "util/crypto/rsa_private_key.h"
6*3f982cf4SFabien Sanglard
7*3f982cf4SFabien Sanglard #include <stdint.h>
8*3f982cf4SFabien Sanglard
9*3f982cf4SFabien Sanglard #include <algorithm>
10*3f982cf4SFabien Sanglard #include <memory>
11*3f982cf4SFabien Sanglard #include <utility>
12*3f982cf4SFabien Sanglard
13*3f982cf4SFabien Sanglard #include "openssl/bn.h"
14*3f982cf4SFabien Sanglard #include "openssl/bytestring.h"
15*3f982cf4SFabien Sanglard #include "openssl/evp.h"
16*3f982cf4SFabien Sanglard #include "openssl/mem.h"
17*3f982cf4SFabien Sanglard #include "openssl/rsa.h"
18*3f982cf4SFabien Sanglard #include "util/crypto/openssl_util.h"
19*3f982cf4SFabien Sanglard #include "util/osp_logging.h"
20*3f982cf4SFabien Sanglard
21*3f982cf4SFabien Sanglard namespace openscreen {
22*3f982cf4SFabien Sanglard RSAPrivateKey::~RSAPrivateKey() = default;
23*3f982cf4SFabien Sanglard
24*3f982cf4SFabien Sanglard // static
Create(uint16_t num_bits)25*3f982cf4SFabien Sanglard ErrorOr<RSAPrivateKey> RSAPrivateKey::Create(uint16_t num_bits) {
26*3f982cf4SFabien Sanglard OpenSSLErrStackTracer err_tracer(CURRENT_LOCATION);
27*3f982cf4SFabien Sanglard
28*3f982cf4SFabien Sanglard bssl::UniquePtr<RSA> rsa_key(RSA_new());
29*3f982cf4SFabien Sanglard bssl::UniquePtr<BIGNUM> exponent(BN_new());
30*3f982cf4SFabien Sanglard if (!rsa_key.get() || !exponent.get() ||
31*3f982cf4SFabien Sanglard !BN_set_word(exponent.get(), 65537L) ||
32*3f982cf4SFabien Sanglard !RSA_generate_key_ex(rsa_key.get(), num_bits, exponent.get(), nullptr)) {
33*3f982cf4SFabien Sanglard return Error::Code::kRSAKeyGenerationFailure;
34*3f982cf4SFabien Sanglard }
35*3f982cf4SFabien Sanglard
36*3f982cf4SFabien Sanglard RSAPrivateKey result;
37*3f982cf4SFabien Sanglard result.key_.reset(EVP_PKEY_new());
38*3f982cf4SFabien Sanglard if (!result.key_ || !EVP_PKEY_set1_RSA(result.key_.get(), rsa_key.get())) {
39*3f982cf4SFabien Sanglard return Error::Code::kEVPInitializationError;
40*3f982cf4SFabien Sanglard }
41*3f982cf4SFabien Sanglard
42*3f982cf4SFabien Sanglard return result;
43*3f982cf4SFabien Sanglard }
44*3f982cf4SFabien Sanglard
45*3f982cf4SFabien Sanglard // static
CreateFromPrivateKeyInfo(const std::vector<uint8_t> & input)46*3f982cf4SFabien Sanglard ErrorOr<RSAPrivateKey> RSAPrivateKey::CreateFromPrivateKeyInfo(
47*3f982cf4SFabien Sanglard const std::vector<uint8_t>& input) {
48*3f982cf4SFabien Sanglard OpenSSLErrStackTracer err_tracer(CURRENT_LOCATION);
49*3f982cf4SFabien Sanglard
50*3f982cf4SFabien Sanglard CBS private_key_cbs;
51*3f982cf4SFabien Sanglard CBS_init(&private_key_cbs, input.data(), input.size());
52*3f982cf4SFabien Sanglard bssl::UniquePtr<EVP_PKEY> private_key(
53*3f982cf4SFabien Sanglard EVP_parse_private_key(&private_key_cbs));
54*3f982cf4SFabien Sanglard if (!private_key || CBS_len(&private_key_cbs) != 0 ||
55*3f982cf4SFabien Sanglard EVP_PKEY_id(private_key.get()) != EVP_PKEY_RSA) {
56*3f982cf4SFabien Sanglard return Error::Code::kEVPInitializationError;
57*3f982cf4SFabien Sanglard }
58*3f982cf4SFabien Sanglard
59*3f982cf4SFabien Sanglard RSAPrivateKey result;
60*3f982cf4SFabien Sanglard result.key_ = std::move(private_key);
61*3f982cf4SFabien Sanglard return result;
62*3f982cf4SFabien Sanglard }
63*3f982cf4SFabien Sanglard
64*3f982cf4SFabien Sanglard // static
CreateFromKey(EVP_PKEY * key)65*3f982cf4SFabien Sanglard ErrorOr<RSAPrivateKey> RSAPrivateKey::CreateFromKey(EVP_PKEY* key) {
66*3f982cf4SFabien Sanglard OpenSSLErrStackTracer err_tracer(CURRENT_LOCATION);
67*3f982cf4SFabien Sanglard OSP_DCHECK(key);
68*3f982cf4SFabien Sanglard if (EVP_PKEY_type(key->type) != EVP_PKEY_RSA) {
69*3f982cf4SFabien Sanglard return Error::Code::kEVPInitializationError;
70*3f982cf4SFabien Sanglard }
71*3f982cf4SFabien Sanglard
72*3f982cf4SFabien Sanglard RSAPrivateKey result;
73*3f982cf4SFabien Sanglard result.key_ = bssl::UpRef(key);
74*3f982cf4SFabien Sanglard return result;
75*3f982cf4SFabien Sanglard }
76*3f982cf4SFabien Sanglard
Copy() const77*3f982cf4SFabien Sanglard ErrorOr<RSAPrivateKey> RSAPrivateKey::Copy() const {
78*3f982cf4SFabien Sanglard OpenSSLErrStackTracer err_tracer(CURRENT_LOCATION);
79*3f982cf4SFabien Sanglard RSAPrivateKey result;
80*3f982cf4SFabien Sanglard bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(key_.get()));
81*3f982cf4SFabien Sanglard if (!rsa) {
82*3f982cf4SFabien Sanglard return Error::Code::kEVPInitializationError;
83*3f982cf4SFabien Sanglard }
84*3f982cf4SFabien Sanglard
85*3f982cf4SFabien Sanglard result.key_.reset(EVP_PKEY_new());
86*3f982cf4SFabien Sanglard if (!EVP_PKEY_set1_RSA(result.key_.get(), rsa.get())) {
87*3f982cf4SFabien Sanglard return Error::Code::kEVPInitializationError;
88*3f982cf4SFabien Sanglard }
89*3f982cf4SFabien Sanglard
90*3f982cf4SFabien Sanglard return result;
91*3f982cf4SFabien Sanglard }
92*3f982cf4SFabien Sanglard
ExportPrivateKey() const93*3f982cf4SFabien Sanglard ErrorOr<std::vector<uint8_t>> RSAPrivateKey::ExportPrivateKey() const {
94*3f982cf4SFabien Sanglard OpenSSLErrStackTracer err_tracer(CURRENT_LOCATION);
95*3f982cf4SFabien Sanglard uint8_t* der;
96*3f982cf4SFabien Sanglard size_t der_len;
97*3f982cf4SFabien Sanglard bssl::ScopedCBB cbb;
98*3f982cf4SFabien Sanglard if (!CBB_init(cbb.get(), 0) ||
99*3f982cf4SFabien Sanglard !EVP_marshal_private_key(cbb.get(), key_.get()) ||
100*3f982cf4SFabien Sanglard !CBB_finish(cbb.get(), &der, &der_len)) {
101*3f982cf4SFabien Sanglard return Error::Code::kParseError;
102*3f982cf4SFabien Sanglard }
103*3f982cf4SFabien Sanglard
104*3f982cf4SFabien Sanglard std::vector<uint8_t> output(der, der + der_len);
105*3f982cf4SFabien Sanglard // The temporary buffer has to be freed after we properly copy out data.
106*3f982cf4SFabien Sanglard OPENSSL_free(der);
107*3f982cf4SFabien Sanglard return output;
108*3f982cf4SFabien Sanglard }
109*3f982cf4SFabien Sanglard
ExportPublicKey() const110*3f982cf4SFabien Sanglard ErrorOr<std::vector<uint8_t>> RSAPrivateKey::ExportPublicKey() const {
111*3f982cf4SFabien Sanglard OpenSSLErrStackTracer err_tracer(CURRENT_LOCATION);
112*3f982cf4SFabien Sanglard uint8_t* der;
113*3f982cf4SFabien Sanglard size_t der_len;
114*3f982cf4SFabien Sanglard bssl::ScopedCBB cbb;
115*3f982cf4SFabien Sanglard if (!CBB_init(cbb.get(), 0) ||
116*3f982cf4SFabien Sanglard !EVP_marshal_public_key(cbb.get(), key_.get()) ||
117*3f982cf4SFabien Sanglard !CBB_finish(cbb.get(), &der, &der_len)) {
118*3f982cf4SFabien Sanglard return Error::Code::kParseError;
119*3f982cf4SFabien Sanglard }
120*3f982cf4SFabien Sanglard
121*3f982cf4SFabien Sanglard std::vector<uint8_t> output(der, der + der_len);
122*3f982cf4SFabien Sanglard // The temporary buffer has to be freed after we properly copy out data.
123*3f982cf4SFabien Sanglard OPENSSL_free(der);
124*3f982cf4SFabien Sanglard return output;
125*3f982cf4SFabien Sanglard }
126*3f982cf4SFabien Sanglard
127*3f982cf4SFabien Sanglard RSAPrivateKey::RSAPrivateKey() = default;
128*3f982cf4SFabien Sanglard
129*3f982cf4SFabien Sanglard } // namespace openscreen
130