1 /*
2 * Copyright 2020 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "rtc_base/boringssl_certificate.h"
12
13 #include "absl/strings/string_view.h"
14
15 #if defined(WEBRTC_WIN)
16 // Must be included first before openssl headers.
17 #include "rtc_base/win32.h" // NOLINT
18 #endif // WEBRTC_WIN
19
20 #include <openssl/asn1.h>
21 #include <openssl/bytestring.h>
22 #include <openssl/digest.h>
23 #include <openssl/evp.h>
24 #include <openssl/mem.h>
25 #include <openssl/pool.h>
26 #include <openssl/rand.h>
27 #include <time.h>
28
29 #include <cstring>
30 #include <memory>
31 #include <utility>
32 #include <vector>
33
34 #include "rtc_base/checks.h"
35 #include "rtc_base/helpers.h"
36 #include "rtc_base/logging.h"
37 #include "rtc_base/message_digest.h"
38 #include "rtc_base/openssl_digest.h"
39 #include "rtc_base/openssl_key_pair.h"
40 #include "rtc_base/openssl_utility.h"
41
42 namespace rtc {
43 namespace {
44
45 // List of OIDs of signature algorithms accepted by WebRTC.
46 // Taken from openssl/nid.h.
47 static const uint8_t kMD5WithRSA[] = {0x2b, 0x0e, 0x03, 0x02, 0x03};
48 static const uint8_t kMD5WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
49 0x0d, 0x01, 0x01, 0x04};
50 static const uint8_t kECDSAWithSHA1[] = {0x2a, 0x86, 0x48, 0xce,
51 0x3d, 0x04, 0x01};
52 static const uint8_t kDSAWithSHA1[] = {0x2a, 0x86, 0x48, 0xce,
53 0x38, 0x04, 0x03};
54 static const uint8_t kDSAWithSHA1_2[] = {0x2b, 0x0e, 0x03, 0x02, 0x1b};
55 static const uint8_t kSHA1WithRSA[] = {0x2b, 0x0e, 0x03, 0x02, 0x1d};
56 static const uint8_t kSHA1WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
57 0x0d, 0x01, 0x01, 0x05};
58 static const uint8_t kECDSAWithSHA224[] = {0x2a, 0x86, 0x48, 0xce,
59 0x3d, 0x04, 0x03, 0x01};
60 static const uint8_t kSHA224WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
61 0x0d, 0x01, 0x01, 0x0e};
62 static const uint8_t kDSAWithSHA224[] = {0x60, 0x86, 0x48, 0x01, 0x65,
63 0x03, 0x04, 0x03, 0x01};
64 static const uint8_t kECDSAWithSHA256[] = {0x2a, 0x86, 0x48, 0xce,
65 0x3d, 0x04, 0x03, 0x02};
66 static const uint8_t kSHA256WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
67 0x0d, 0x01, 0x01, 0x0b};
68 static const uint8_t kDSAWithSHA256[] = {0x60, 0x86, 0x48, 0x01, 0x65,
69 0x03, 0x04, 0x03, 0x02};
70 static const uint8_t kECDSAWithSHA384[] = {0x2a, 0x86, 0x48, 0xce,
71 0x3d, 0x04, 0x03, 0x03};
72 static const uint8_t kSHA384WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
73 0x0d, 0x01, 0x01, 0x0c};
74 static const uint8_t kECDSAWithSHA512[] = {0x2a, 0x86, 0x48, 0xce,
75 0x3d, 0x04, 0x03, 0x04};
76 static const uint8_t kSHA512WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
77 0x0d, 0x01, 0x01, 0x0d};
78
79 #if !defined(NDEBUG)
80 // Print a certificate to the log, for debugging.
PrintCert(BoringSSLCertificate * cert)81 static void PrintCert(BoringSSLCertificate* cert) {
82 // Since we're using CRYPTO_BUFFER, we can't use X509_print_ex, so we'll just
83 // print the PEM string.
84 RTC_DLOG(LS_VERBOSE) << "PEM representation of certificate:\n"
85 << cert->ToPEMString();
86 }
87 #endif
88
AddSHA256SignatureAlgorithm(CBB * cbb,KeyType key_type)89 bool AddSHA256SignatureAlgorithm(CBB* cbb, KeyType key_type) {
90 // An AlgorithmIdentifier is described in RFC 5280, 4.1.1.2.
91 CBB sequence, oid, params;
92 if (!CBB_add_asn1(cbb, &sequence, CBS_ASN1_SEQUENCE) ||
93 !CBB_add_asn1(&sequence, &oid, CBS_ASN1_OBJECT)) {
94 return false;
95 }
96
97 switch (key_type) {
98 case KT_RSA:
99 if (!CBB_add_bytes(&oid, kSHA256WithRSAEncryption,
100 sizeof(kSHA256WithRSAEncryption)) ||
101 !CBB_add_asn1(&sequence, ¶ms, CBS_ASN1_NULL)) {
102 return false;
103 }
104 break;
105 case KT_ECDSA:
106 if (!CBB_add_bytes(&oid, kECDSAWithSHA256, sizeof(kECDSAWithSHA256))) {
107 return false;
108 }
109 break;
110 default:
111 RTC_DCHECK_NOTREACHED();
112 return false;
113 }
114 if (!CBB_flush(cbb)) {
115 return false;
116 }
117 return true;
118 }
119
120 // Adds an X.509 Common Name to `cbb`.
AddCommonName(CBB * cbb,absl::string_view common_name)121 bool AddCommonName(CBB* cbb, absl::string_view common_name) {
122 // See RFC 4519.
123 static const uint8_t kCommonName[] = {0x55, 0x04, 0x03};
124
125 if (common_name.empty()) {
126 RTC_LOG(LS_ERROR) << "Common name cannot be empty.";
127 return false;
128 }
129
130 // See RFC 5280, section 4.1.2.4.
131 CBB rdns;
132 if (!CBB_add_asn1(cbb, &rdns, CBS_ASN1_SEQUENCE)) {
133 return false;
134 }
135
136 CBB rdn, attr, type, value;
137 if (!CBB_add_asn1(&rdns, &rdn, CBS_ASN1_SET) ||
138 !CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE) ||
139 !CBB_add_asn1(&attr, &type, CBS_ASN1_OBJECT) ||
140 !CBB_add_bytes(&type, kCommonName, sizeof(kCommonName)) ||
141 !CBB_add_asn1(&attr, &value, CBS_ASN1_UTF8STRING) ||
142 !CBB_add_bytes(&value,
143 reinterpret_cast<const uint8_t*>(common_name.data()),
144 common_name.size()) ||
145 !CBB_flush(cbb)) {
146 return false;
147 }
148
149 return true;
150 }
151
AddTime(CBB * cbb,time_t time)152 bool AddTime(CBB* cbb, time_t time) {
153 bssl::UniquePtr<ASN1_TIME> asn1_time(ASN1_TIME_new());
154 if (!asn1_time) {
155 return false;
156 }
157
158 if (!ASN1_TIME_set(asn1_time.get(), time)) {
159 return false;
160 }
161
162 unsigned tag;
163 switch (asn1_time->type) {
164 case V_ASN1_UTCTIME:
165 tag = CBS_ASN1_UTCTIME;
166 break;
167 case V_ASN1_GENERALIZEDTIME:
168 tag = CBS_ASN1_GENERALIZEDTIME;
169 break;
170 default:
171 return false;
172 }
173
174 CBB child;
175 if (!CBB_add_asn1(cbb, &child, tag) ||
176 !CBB_add_bytes(&child, asn1_time->data, asn1_time->length) ||
177 !CBB_flush(cbb)) {
178 return false;
179 }
180
181 return true;
182 }
183
184 // Generate a self-signed certificate, with the public key from the
185 // given key pair. Caller is responsible for freeing the returned object.
MakeCertificate(EVP_PKEY * pkey,const SSLIdentityParams & params)186 static bssl::UniquePtr<CRYPTO_BUFFER> MakeCertificate(
187 EVP_PKEY* pkey,
188 const SSLIdentityParams& params) {
189 RTC_LOG(LS_INFO) << "Making certificate for " << params.common_name;
190
191 // See RFC 5280, section 4.1. First, construct the TBSCertificate.
192 bssl::ScopedCBB cbb;
193 CBB tbs_cert, version, validity;
194 uint8_t* tbs_cert_bytes;
195 size_t tbs_cert_len;
196 uint64_t serial_number;
197 if (!CBB_init(cbb.get(), 64) ||
198 !CBB_add_asn1(cbb.get(), &tbs_cert, CBS_ASN1_SEQUENCE) ||
199 !CBB_add_asn1(&tbs_cert, &version,
200 CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
201 !CBB_add_asn1_uint64(&version, 2) ||
202 !RAND_bytes(reinterpret_cast<uint8_t*>(&serial_number),
203 sizeof(serial_number)) ||
204 !CBB_add_asn1_uint64(&tbs_cert, serial_number) ||
205 !AddSHA256SignatureAlgorithm(&tbs_cert, params.key_params.type()) ||
206 !AddCommonName(&tbs_cert, params.common_name) || // issuer
207 !CBB_add_asn1(&tbs_cert, &validity, CBS_ASN1_SEQUENCE) ||
208 !AddTime(&validity, params.not_before) ||
209 !AddTime(&validity, params.not_after) ||
210 !AddCommonName(&tbs_cert, params.common_name) || // subject
211 !EVP_marshal_public_key(&tbs_cert, pkey) || // subjectPublicKeyInfo
212 !CBB_finish(cbb.get(), &tbs_cert_bytes, &tbs_cert_len)) {
213 return nullptr;
214 }
215
216 bssl::UniquePtr<uint8_t> delete_tbs_cert_bytes(tbs_cert_bytes);
217
218 // Sign the TBSCertificate and write the entire certificate.
219 CBB cert, signature;
220 bssl::ScopedEVP_MD_CTX ctx;
221 uint8_t* sig_out;
222 size_t sig_len;
223 uint8_t* cert_bytes;
224 size_t cert_len;
225 if (!CBB_init(cbb.get(), tbs_cert_len) ||
226 !CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE) ||
227 !CBB_add_bytes(&cert, tbs_cert_bytes, tbs_cert_len) ||
228 !AddSHA256SignatureAlgorithm(&cert, params.key_params.type()) ||
229 !CBB_add_asn1(&cert, &signature, CBS_ASN1_BITSTRING) ||
230 !CBB_add_u8(&signature, 0 /* no unused bits */) ||
231 !EVP_DigestSignInit(ctx.get(), nullptr, EVP_sha256(), nullptr, pkey) ||
232 // Compute the maximum signature length.
233 !EVP_DigestSign(ctx.get(), nullptr, &sig_len, tbs_cert_bytes,
234 tbs_cert_len) ||
235 !CBB_reserve(&signature, &sig_out, sig_len) ||
236 // Actually sign the TBSCertificate.
237 !EVP_DigestSign(ctx.get(), sig_out, &sig_len, tbs_cert_bytes,
238 tbs_cert_len) ||
239 !CBB_did_write(&signature, sig_len) ||
240 !CBB_finish(cbb.get(), &cert_bytes, &cert_len)) {
241 return nullptr;
242 }
243 bssl::UniquePtr<uint8_t> delete_cert_bytes(cert_bytes);
244
245 RTC_LOG(LS_INFO) << "Returning certificate";
246 return bssl::UniquePtr<CRYPTO_BUFFER>(
247 CRYPTO_BUFFER_new(cert_bytes, cert_len, openssl::GetBufferPool()));
248 }
249
250 } // namespace
251
BoringSSLCertificate(bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer)252 BoringSSLCertificate::BoringSSLCertificate(
253 bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer)
254 : cert_buffer_(std::move(cert_buffer)) {
255 RTC_DCHECK(cert_buffer_ != nullptr);
256 }
257
Generate(OpenSSLKeyPair * key_pair,const SSLIdentityParams & params)258 std::unique_ptr<BoringSSLCertificate> BoringSSLCertificate::Generate(
259 OpenSSLKeyPair* key_pair,
260 const SSLIdentityParams& params) {
261 SSLIdentityParams actual_params(params);
262 if (actual_params.common_name.empty()) {
263 // Use a random string, arbitrarily 8 chars long.
264 actual_params.common_name = CreateRandomString(8);
265 }
266 bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer =
267 MakeCertificate(key_pair->pkey(), actual_params);
268 if (!cert_buffer) {
269 openssl::LogSSLErrors("Generating certificate");
270 return nullptr;
271 }
272 auto ret = std::make_unique<BoringSSLCertificate>(std::move(cert_buffer));
273 #if !defined(NDEBUG)
274 PrintCert(ret.get());
275 #endif
276 return ret;
277 }
278
FromPEMString(absl::string_view pem_string)279 std::unique_ptr<BoringSSLCertificate> BoringSSLCertificate::FromPEMString(
280 absl::string_view pem_string) {
281 std::string der;
282 if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der)) {
283 return nullptr;
284 }
285 bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer(
286 CRYPTO_BUFFER_new(reinterpret_cast<const uint8_t*>(der.c_str()),
287 der.length(), openssl::GetBufferPool()));
288 if (!cert_buffer) {
289 return nullptr;
290 }
291 return std::make_unique<BoringSSLCertificate>(std::move(cert_buffer));
292 }
293
294 #define OID_MATCHES(oid, oid_other) \
295 (CBS_len(&oid) == sizeof(oid_other) && \
296 0 == memcmp(CBS_data(&oid), oid_other, sizeof(oid_other)))
297
GetSignatureDigestAlgorithm(std::string * algorithm) const298 bool BoringSSLCertificate::GetSignatureDigestAlgorithm(
299 std::string* algorithm) const {
300 CBS oid;
301 if (!openssl::ParseCertificate(cert_buffer_.get(), &oid, nullptr)) {
302 RTC_LOG(LS_ERROR) << "Failed to parse certificate.";
303 return false;
304 }
305 if (OID_MATCHES(oid, kMD5WithRSA) ||
306 OID_MATCHES(oid, kMD5WithRSAEncryption)) {
307 *algorithm = DIGEST_MD5;
308 return true;
309 }
310 if (OID_MATCHES(oid, kECDSAWithSHA1) || OID_MATCHES(oid, kDSAWithSHA1) ||
311 OID_MATCHES(oid, kDSAWithSHA1_2) || OID_MATCHES(oid, kSHA1WithRSA) ||
312 OID_MATCHES(oid, kSHA1WithRSAEncryption)) {
313 *algorithm = DIGEST_SHA_1;
314 return true;
315 }
316 if (OID_MATCHES(oid, kECDSAWithSHA224) ||
317 OID_MATCHES(oid, kSHA224WithRSAEncryption) ||
318 OID_MATCHES(oid, kDSAWithSHA224)) {
319 *algorithm = DIGEST_SHA_224;
320 return true;
321 }
322 if (OID_MATCHES(oid, kECDSAWithSHA256) ||
323 OID_MATCHES(oid, kSHA256WithRSAEncryption) ||
324 OID_MATCHES(oid, kDSAWithSHA256)) {
325 *algorithm = DIGEST_SHA_256;
326 return true;
327 }
328 if (OID_MATCHES(oid, kECDSAWithSHA384) ||
329 OID_MATCHES(oid, kSHA384WithRSAEncryption)) {
330 *algorithm = DIGEST_SHA_384;
331 return true;
332 }
333 if (OID_MATCHES(oid, kECDSAWithSHA512) ||
334 OID_MATCHES(oid, kSHA512WithRSAEncryption)) {
335 *algorithm = DIGEST_SHA_512;
336 return true;
337 }
338 // Unknown algorithm. There are several unhandled options that are less
339 // common and more complex.
340 RTC_LOG(LS_ERROR) << "Unknown signature algorithm.";
341 algorithm->clear();
342 return false;
343 }
344
ComputeDigest(absl::string_view algorithm,unsigned char * digest,size_t size,size_t * length) const345 bool BoringSSLCertificate::ComputeDigest(absl::string_view algorithm,
346 unsigned char* digest,
347 size_t size,
348 size_t* length) const {
349 return ComputeDigest(cert_buffer_.get(), algorithm, digest, size, length);
350 }
351
ComputeDigest(const CRYPTO_BUFFER * cert_buffer,absl::string_view algorithm,unsigned char * digest,size_t size,size_t * length)352 bool BoringSSLCertificate::ComputeDigest(const CRYPTO_BUFFER* cert_buffer,
353 absl::string_view algorithm,
354 unsigned char* digest,
355 size_t size,
356 size_t* length) {
357 const EVP_MD* md = nullptr;
358 unsigned int n = 0;
359 if (!OpenSSLDigest::GetDigestEVP(algorithm, &md)) {
360 return false;
361 }
362 if (size < static_cast<size_t>(EVP_MD_size(md))) {
363 return false;
364 }
365 if (!EVP_Digest(CRYPTO_BUFFER_data(cert_buffer),
366 CRYPTO_BUFFER_len(cert_buffer), digest, &n, md, nullptr)) {
367 return false;
368 }
369 *length = n;
370 return true;
371 }
372
~BoringSSLCertificate()373 BoringSSLCertificate::~BoringSSLCertificate() {}
374
Clone() const375 std::unique_ptr<SSLCertificate> BoringSSLCertificate::Clone() const {
376 return std::make_unique<BoringSSLCertificate>(
377 bssl::UpRef(cert_buffer_.get()));
378 }
379
ToPEMString() const380 std::string BoringSSLCertificate::ToPEMString() const {
381 return SSLIdentity::DerToPem(kPemTypeCertificate,
382 CRYPTO_BUFFER_data(cert_buffer_.get()),
383 CRYPTO_BUFFER_len(cert_buffer_.get()));
384 }
385
ToDER(Buffer * der_buffer) const386 void BoringSSLCertificate::ToDER(Buffer* der_buffer) const {
387 der_buffer->SetData(CRYPTO_BUFFER_data(cert_buffer_.get()),
388 CRYPTO_BUFFER_len(cert_buffer_.get()));
389 }
390
operator ==(const BoringSSLCertificate & other) const391 bool BoringSSLCertificate::operator==(const BoringSSLCertificate& other) const {
392 return CRYPTO_BUFFER_len(cert_buffer_.get()) ==
393 CRYPTO_BUFFER_len(other.cert_buffer_.get()) &&
394 0 == memcmp(CRYPTO_BUFFER_data(cert_buffer_.get()),
395 CRYPTO_BUFFER_data(other.cert_buffer_.get()),
396 CRYPTO_BUFFER_len(cert_buffer_.get()));
397 }
398
operator !=(const BoringSSLCertificate & other) const399 bool BoringSSLCertificate::operator!=(const BoringSSLCertificate& other) const {
400 return !(*this == other);
401 }
402
CertificateExpirationTime() const403 int64_t BoringSSLCertificate::CertificateExpirationTime() const {
404 int64_t ret;
405 if (!openssl::ParseCertificate(cert_buffer_.get(), nullptr, &ret)) {
406 RTC_LOG(LS_ERROR) << "Failed to parse certificate.";
407 return -1;
408 }
409 return ret;
410 }
411
412 } // namespace rtc
413