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