xref: /aosp_15_r20/external/webrtc/rtc_base/boringssl_certificate.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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, &params, 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