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