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/certificate_utils.h"
6
7 #include <openssl/asn1.h>
8 #include <openssl/bio.h>
9 #include <openssl/bn.h>
10 #include <openssl/crypto.h>
11 #include <openssl/evp.h>
12 #include <openssl/rsa.h>
13 #include <openssl/ssl.h>
14 #include <openssl/x509v3.h>
15 #include <time.h>
16
17 #include <string>
18
19 #include "util/crypto/openssl_util.h"
20 #include "util/crypto/sha2.h"
21 #include "util/osp_logging.h"
22
23 namespace openscreen {
24
25 namespace {
26
27 // These values are bit positions from RFC 5280 4.2.1.3 and will be passed to
28 // ASN1_BIT_STRING_set_bit.
29 enum KeyUsageBits {
30 kDigitalSignature = 0,
31 kKeyCertSign = 5,
32 };
33
34 // Returns whether or not the certificate field successfully was added.
AddCertificateField(X509_NAME * certificate_name,absl::string_view field,absl::string_view value)35 bool AddCertificateField(X509_NAME* certificate_name,
36 absl::string_view field,
37 absl::string_view value) {
38 return X509_NAME_add_entry_by_txt(
39 certificate_name, std::string(field).c_str(), MBSTRING_ASC,
40 reinterpret_cast<const unsigned char*>(value.data()),
41 value.length(), -1, 0) == 1;
42 }
43
ToAsn1Time(std::chrono::seconds time_since_epoch)44 bssl::UniquePtr<ASN1_TIME> ToAsn1Time(std::chrono::seconds time_since_epoch) {
45 return bssl::UniquePtr<ASN1_TIME>(
46 ASN1_TIME_set(nullptr, time_since_epoch.count()));
47 }
48
CreateCertificateInternal(absl::string_view name,std::chrono::seconds certificate_duration,EVP_PKEY key_pair,std::chrono::seconds time_since_unix_epoch,bool make_ca,X509 * issuer,EVP_PKEY * issuer_key)49 bssl::UniquePtr<X509> CreateCertificateInternal(
50 absl::string_view name,
51 std::chrono::seconds certificate_duration,
52 EVP_PKEY key_pair,
53 std::chrono::seconds time_since_unix_epoch,
54 bool make_ca,
55 X509* issuer,
56 EVP_PKEY* issuer_key) {
57 OSP_DCHECK((!!issuer) == (!!issuer_key));
58 bssl::UniquePtr<X509> certificate(X509_new());
59 if (!issuer) {
60 issuer = certificate.get();
61 }
62 if (!issuer_key) {
63 issuer_key = &key_pair;
64 }
65
66 // Certificate versions are zero indexed, so V1 = 0.
67 const int kCertificateVersion3 = 2;
68 if (X509_set_version(certificate.get(), kCertificateVersion3) != 1) {
69 OSP_DVLOG << "Failed to set certificate version";
70 return nullptr;
71 }
72
73 // Serial numbers must be unique for this session. As a pretend CA, we should
74 // not issue certificates with the same serial number in the same session.
75 static int serial_number(1);
76 if (ASN1_INTEGER_set(X509_get_serialNumber(certificate.get()),
77 serial_number++) != 1) {
78 OSP_DVLOG << "Failed to set serial number.";
79 return nullptr;
80 }
81
82 const bssl::UniquePtr<ASN1_TIME> now(ToAsn1Time(time_since_unix_epoch));
83 const bssl::UniquePtr<ASN1_TIME> expiration_time(
84 ToAsn1Time(time_since_unix_epoch + certificate_duration));
85
86 if ((X509_set_notBefore(certificate.get(), now.get()) != 1) ||
87 (X509_set_notAfter(certificate.get(), expiration_time.get()) != 1)) {
88 OSP_DVLOG << "Failed to set before and after ranges.";
89 return nullptr;
90 }
91
92 X509_NAME* certificate_name = X509_get_subject_name(certificate.get());
93 if (!AddCertificateField(certificate_name, "CN", name)) {
94 OSP_DVLOG << "Failed to set subject name";
95 return nullptr;
96 }
97
98 bssl::UniquePtr<ASN1_BIT_STRING> x(ASN1_BIT_STRING_new());
99 ASN1_BIT_STRING_set_bit(x.get(), KeyUsageBits::kDigitalSignature, 1);
100 if (make_ca) {
101 ASN1_BIT_STRING_set_bit(x.get(), KeyUsageBits::kKeyCertSign, 1);
102 }
103 if (X509_add1_ext_i2d(certificate.get(), NID_key_usage, x.get(), 0, 0) != 1) {
104 OSP_DVLOG << "Failed to set key usage extension";
105 return nullptr;
106 }
107 if (make_ca) {
108 X509V3_CTX ctx;
109 X509V3_set_ctx_nodb(&ctx);
110 X509V3_set_ctx(&ctx, issuer, certificate.get(), nullptr, nullptr, 0);
111 bssl::UniquePtr<X509_EXTENSION> ex(
112 X509V3_EXT_nconf_nid(nullptr, &ctx, NID_basic_constraints,
113 const_cast<char*>("critical,CA:TRUE")));
114 if (!ex) {
115 OSP_DVLOG << "Failed to set constraints extension";
116 return nullptr;
117 }
118 void* thing = X509V3_EXT_d2i(ex.get());
119 X509_add1_ext_i2d(certificate.get(), NID_basic_constraints, thing, 1, 0);
120 X509V3_EXT_free(NID_basic_constraints, thing);
121 }
122
123 X509_NAME* issuer_name = X509_get_subject_name(issuer);
124 if ((X509_set_issuer_name(certificate.get(), issuer_name) != 1) ||
125 (X509_set_pubkey(certificate.get(), &key_pair) != 1) ||
126 // Unlike all of the other BoringSSL methods here, X509_sign returns
127 // the size of the signature in bytes.
128 (X509_sign(certificate.get(), issuer_key, EVP_sha256()) <= 0) ||
129 (X509_verify(certificate.get(), issuer_key) != 1)) {
130 OSP_DVLOG << "Failed to set pubkey, set issuer, sign, or verify";
131 return nullptr;
132 }
133
134 return certificate;
135 }
136
137 } // namespace
138
GenerateRsaKeyPair(int key_bits)139 bssl::UniquePtr<EVP_PKEY> GenerateRsaKeyPair(int key_bits) {
140 bssl::UniquePtr<BIGNUM> prime(BN_new());
141 if (BN_set_word(prime.get(), RSA_F4) == 0) {
142 return nullptr;
143 }
144
145 bssl::UniquePtr<RSA> rsa(RSA_new());
146 if (RSA_generate_key_ex(rsa.get(), key_bits, prime.get(), nullptr) == 0) {
147 return nullptr;
148 }
149
150 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
151 if (EVP_PKEY_set1_RSA(pkey.get(), rsa.get()) == 0) {
152 return nullptr;
153 }
154
155 return pkey;
156 }
157
CreateSelfSignedX509Certificate(absl::string_view name,std::chrono::seconds duration,const EVP_PKEY & key_pair,std::chrono::seconds time_since_unix_epoch,bool make_ca,X509 * issuer,EVP_PKEY * issuer_key)158 ErrorOr<bssl::UniquePtr<X509>> CreateSelfSignedX509Certificate(
159 absl::string_view name,
160 std::chrono::seconds duration,
161 const EVP_PKEY& key_pair,
162 std::chrono::seconds time_since_unix_epoch,
163 bool make_ca,
164 X509* issuer,
165 EVP_PKEY* issuer_key) {
166 bssl::UniquePtr<X509> certificate =
167 CreateCertificateInternal(name, duration, key_pair, time_since_unix_epoch,
168 make_ca, issuer, issuer_key);
169 if (!certificate) {
170 return Error::Code::kCertificateCreationError;
171 }
172 return certificate;
173 }
174
ExportX509CertificateToDer(const X509 & certificate)175 ErrorOr<std::vector<uint8_t>> ExportX509CertificateToDer(
176 const X509& certificate) {
177 unsigned char* buffer = nullptr;
178 // Casting-away the const because the legacy i2d_X509() function is not
179 // const-correct.
180 X509* const certificate_ptr = const_cast<X509*>(&certificate);
181 const int len = i2d_X509(certificate_ptr, &buffer);
182 if (len <= 0) {
183 return Error::Code::kCertificateValidationError;
184 }
185 std::vector<uint8_t> raw_der_certificate(buffer, buffer + len);
186 // BoringSSL doesn't free the temporary buffer.
187 OPENSSL_free(buffer);
188 return raw_der_certificate;
189 }
190
ImportCertificate(const uint8_t * der_x509_cert,int der_x509_cert_length)191 ErrorOr<bssl::UniquePtr<X509>> ImportCertificate(const uint8_t* der_x509_cert,
192 int der_x509_cert_length) {
193 if (!der_x509_cert) {
194 return Error::Code::kErrCertsMissing;
195 }
196 bssl::UniquePtr<X509> certificate(
197 d2i_X509(nullptr, &der_x509_cert, der_x509_cert_length));
198 if (!certificate) {
199 return Error::Code::kCertificateValidationError;
200 }
201 return certificate;
202 }
203
ImportRSAPrivateKey(const uint8_t * der_rsa_private_key,int key_length)204 ErrorOr<bssl::UniquePtr<EVP_PKEY>> ImportRSAPrivateKey(
205 const uint8_t* der_rsa_private_key,
206 int key_length) {
207 if (!der_rsa_private_key || key_length == 0) {
208 return Error::Code::kParameterInvalid;
209 }
210
211 RSA* rsa = RSA_private_key_from_bytes(der_rsa_private_key, key_length);
212 if (!rsa) {
213 return Error::Code::kRSAKeyParseError;
214 }
215 bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
216 EVP_PKEY_assign_RSA(pkey.get(), rsa);
217 return pkey;
218 }
219
GetSpkiTlv(X509 * cert)220 std::string GetSpkiTlv(X509* cert) {
221 X509_PUBKEY* key = X509_get_X509_PUBKEY(cert);
222 int len = i2d_X509_PUBKEY(key, nullptr);
223 if (len <= 0) {
224 return {};
225 }
226 std::string x(len, 0);
227 uint8_t* data = reinterpret_cast<uint8_t*>(&x[0]);
228 if (!i2d_X509_PUBKEY(key, &data)) {
229 return {};
230 }
231 return x;
232 }
233
ParseDerUint64(const ASN1_INTEGER * asn1int)234 ErrorOr<uint64_t> ParseDerUint64(const ASN1_INTEGER* asn1int) {
235 const uint8_t* data = ASN1_STRING_get0_data(asn1int);
236 int length = ASN1_STRING_length(asn1int);
237 if (length > 8 || length <= 0) {
238 return Error::Code::kParameterInvalid;
239 }
240 uint64_t result = 0;
241 for (int i = 0; i < length; ++i) {
242 result = (result << 8) | data[i];
243 }
244 return result;
245 }
246
247 } // namespace openscreen
248