xref: /aosp_15_r20/external/cronet/net/cert/x509_util.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "net/cert/x509_util.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <string.h>
8*6777b538SAndroid Build Coastguard Worker 
9*6777b538SAndroid Build Coastguard Worker #include <map>
10*6777b538SAndroid Build Coastguard Worker #include <memory>
11*6777b538SAndroid Build Coastguard Worker #include <string_view>
12*6777b538SAndroid Build Coastguard Worker 
13*6777b538SAndroid Build Coastguard Worker #include "base/lazy_instance.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/notreached.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_split.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/time/time.h"
20*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
21*6777b538SAndroid Build Coastguard Worker #include "crypto/openssl_util.h"
22*6777b538SAndroid Build Coastguard Worker #include "crypto/rsa_private_key.h"
23*6777b538SAndroid Build Coastguard Worker #include "crypto/sha2.h"
24*6777b538SAndroid Build Coastguard Worker #include "net/base/hash_value.h"
25*6777b538SAndroid Build Coastguard Worker #include "net/cert/asn1_util.h"
26*6777b538SAndroid Build Coastguard Worker #include "net/cert/time_conversions.h"
27*6777b538SAndroid Build Coastguard Worker #include "net/cert/x509_certificate.h"
28*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/bytestring.h"
29*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/digest.h"
30*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/ec.h"
31*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/ec_key.h"
32*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/evp.h"
33*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/mem.h"
34*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/pkcs7.h"
35*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/pool.h"
36*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/stack.h"
37*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/pki/cert_errors.h"
38*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/pki/input.h"
39*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/pki/name_constraints.h"
40*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/pki/parse_certificate.h"
41*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/pki/parse_name.h"
42*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/pki/parse_values.h"
43*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/pki/signature_algorithm.h"
44*6777b538SAndroid Build Coastguard Worker 
45*6777b538SAndroid Build Coastguard Worker namespace net::x509_util {
46*6777b538SAndroid Build Coastguard Worker 
47*6777b538SAndroid Build Coastguard Worker namespace {
48*6777b538SAndroid Build Coastguard Worker 
AddSignatureAlgorithm(CBB * cbb,base::span<const uint8_t> oid_bytes,bool null_param)49*6777b538SAndroid Build Coastguard Worker bool AddSignatureAlgorithm(CBB* cbb,
50*6777b538SAndroid Build Coastguard Worker                            base::span<const uint8_t> oid_bytes,
51*6777b538SAndroid Build Coastguard Worker                            bool null_param) {
52*6777b538SAndroid Build Coastguard Worker   // An AlgorithmIdentifier is described in RFC 5280, 4.1.1.2.
53*6777b538SAndroid Build Coastguard Worker   CBB sequence, oid, params;
54*6777b538SAndroid Build Coastguard Worker   if (!CBB_add_asn1(cbb, &sequence, CBS_ASN1_SEQUENCE) ||
55*6777b538SAndroid Build Coastguard Worker       !CBB_add_asn1(&sequence, &oid, CBS_ASN1_OBJECT) ||
56*6777b538SAndroid Build Coastguard Worker       !CBB_add_bytes(&oid, oid_bytes.data(), oid_bytes.size()) ||
57*6777b538SAndroid Build Coastguard Worker       (null_param && !CBB_add_asn1(&sequence, &params, CBS_ASN1_NULL)) ||
58*6777b538SAndroid Build Coastguard Worker       !CBB_flush(cbb)) {
59*6777b538SAndroid Build Coastguard Worker     return false;
60*6777b538SAndroid Build Coastguard Worker   }
61*6777b538SAndroid Build Coastguard Worker   return true;
62*6777b538SAndroid Build Coastguard Worker }
63*6777b538SAndroid Build Coastguard Worker 
AddSignatureAlgorithm(CBB * cbb,const EVP_PKEY * pkey,DigestAlgorithm digest_alg)64*6777b538SAndroid Build Coastguard Worker bool AddSignatureAlgorithm(CBB* cbb,
65*6777b538SAndroid Build Coastguard Worker                            const EVP_PKEY* pkey,
66*6777b538SAndroid Build Coastguard Worker                            DigestAlgorithm digest_alg) {
67*6777b538SAndroid Build Coastguard Worker   if (digest_alg != DIGEST_SHA256) {
68*6777b538SAndroid Build Coastguard Worker     return false;
69*6777b538SAndroid Build Coastguard Worker   }
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker   if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
72*6777b538SAndroid Build Coastguard Worker     // See RFC 4055.
73*6777b538SAndroid Build Coastguard Worker     static const uint8_t kSHA256WithRSAEncryption[] = {
74*6777b538SAndroid Build Coastguard Worker         0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b};
75*6777b538SAndroid Build Coastguard Worker     // RSA always has null parameters.
76*6777b538SAndroid Build Coastguard Worker     return AddSignatureAlgorithm(cbb, kSHA256WithRSAEncryption,
77*6777b538SAndroid Build Coastguard Worker                                  /*null_param=*/true);
78*6777b538SAndroid Build Coastguard Worker   } else if (EVP_PKEY_id(pkey) == EVP_PKEY_EC) {
79*6777b538SAndroid Build Coastguard Worker     // 1.2.840.10045.4.3.2
80*6777b538SAndroid Build Coastguard Worker     static const uint8_t kECDSAWithSHA256[] = {0x2a, 0x86, 0x48, 0xce,
81*6777b538SAndroid Build Coastguard Worker                                                0x3d, 0x04, 0x03, 0x02};
82*6777b538SAndroid Build Coastguard Worker     return AddSignatureAlgorithm(cbb, kECDSAWithSHA256,
83*6777b538SAndroid Build Coastguard Worker                                  /*null_param=*/false);
84*6777b538SAndroid Build Coastguard Worker   }
85*6777b538SAndroid Build Coastguard Worker   return false;
86*6777b538SAndroid Build Coastguard Worker }
87*6777b538SAndroid Build Coastguard Worker 
ToEVP(DigestAlgorithm alg)88*6777b538SAndroid Build Coastguard Worker const EVP_MD* ToEVP(DigestAlgorithm alg) {
89*6777b538SAndroid Build Coastguard Worker   switch (alg) {
90*6777b538SAndroid Build Coastguard Worker     case DIGEST_SHA256:
91*6777b538SAndroid Build Coastguard Worker       return EVP_sha256();
92*6777b538SAndroid Build Coastguard Worker   }
93*6777b538SAndroid Build Coastguard Worker   return nullptr;
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker 
96*6777b538SAndroid Build Coastguard Worker class BufferPoolSingleton {
97*6777b538SAndroid Build Coastguard Worker  public:
BufferPoolSingleton()98*6777b538SAndroid Build Coastguard Worker   BufferPoolSingleton() {
99*6777b538SAndroid Build Coastguard Worker     crypto::EnsureOpenSSLInit();
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker     pool_ = CRYPTO_BUFFER_POOL_new();
102*6777b538SAndroid Build Coastguard Worker   }
103*6777b538SAndroid Build Coastguard Worker 
pool()104*6777b538SAndroid Build Coastguard Worker   CRYPTO_BUFFER_POOL* pool() { return pool_; }
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker  private:
107*6777b538SAndroid Build Coastguard Worker   // The singleton is leaky, so there is no need to use a smart pointer.
108*6777b538SAndroid Build Coastguard Worker   raw_ptr<CRYPTO_BUFFER_POOL> pool_;
109*6777b538SAndroid Build Coastguard Worker };
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker base::LazyInstance<BufferPoolSingleton>::Leaky g_buffer_pool_singleton =
112*6777b538SAndroid Build Coastguard Worker     LAZY_INSTANCE_INITIALIZER;
113*6777b538SAndroid Build Coastguard Worker 
114*6777b538SAndroid Build Coastguard Worker }  // namespace
115*6777b538SAndroid Build Coastguard Worker 
116*6777b538SAndroid Build Coastguard Worker // Adds an X.509 Name with the specified distinguished name to |cbb|.
AddName(CBB * cbb,std::string_view name)117*6777b538SAndroid Build Coastguard Worker bool AddName(CBB* cbb, std::string_view name) {
118*6777b538SAndroid Build Coastguard Worker   // See RFC 4519.
119*6777b538SAndroid Build Coastguard Worker   static const uint8_t kCommonName[] = {0x55, 0x04, 0x03};
120*6777b538SAndroid Build Coastguard Worker   static const uint8_t kCountryName[] = {0x55, 0x04, 0x06};
121*6777b538SAndroid Build Coastguard Worker   static const uint8_t kOrganizationName[] = {0x55, 0x04, 0x0a};
122*6777b538SAndroid Build Coastguard Worker   static const uint8_t kOrganizationalUnitName[] = {0x55, 0x04, 0x0b};
123*6777b538SAndroid Build Coastguard Worker 
124*6777b538SAndroid Build Coastguard Worker   std::vector<std::string> attributes = SplitString(
125*6777b538SAndroid Build Coastguard Worker       name, /*separators=*/",", base::WhitespaceHandling::TRIM_WHITESPACE,
126*6777b538SAndroid Build Coastguard Worker       base::SplitResult::SPLIT_WANT_NONEMPTY);
127*6777b538SAndroid Build Coastguard Worker 
128*6777b538SAndroid Build Coastguard Worker   if (attributes.size() == 0) {
129*6777b538SAndroid Build Coastguard Worker     LOG(ERROR) << "Missing DN or wrong format";
130*6777b538SAndroid Build Coastguard Worker     return false;
131*6777b538SAndroid Build Coastguard Worker   }
132*6777b538SAndroid Build Coastguard Worker 
133*6777b538SAndroid Build Coastguard Worker   // See RFC 5280, section 4.1.2.4.
134*6777b538SAndroid Build Coastguard Worker   CBB rdns;
135*6777b538SAndroid Build Coastguard Worker   if (!CBB_add_asn1(cbb, &rdns, CBS_ASN1_SEQUENCE)) {
136*6777b538SAndroid Build Coastguard Worker     return false;
137*6777b538SAndroid Build Coastguard Worker   }
138*6777b538SAndroid Build Coastguard Worker 
139*6777b538SAndroid Build Coastguard Worker   for (const std::string& attribute : attributes) {
140*6777b538SAndroid Build Coastguard Worker     std::vector<std::string> parts =
141*6777b538SAndroid Build Coastguard Worker         SplitString(attribute, /*separators=*/"=",
142*6777b538SAndroid Build Coastguard Worker                     base::WhitespaceHandling::KEEP_WHITESPACE,
143*6777b538SAndroid Build Coastguard Worker                     base::SplitResult::SPLIT_WANT_ALL);
144*6777b538SAndroid Build Coastguard Worker     if (parts.size() != 2) {
145*6777b538SAndroid Build Coastguard Worker       LOG(ERROR) << "Wrong DN format at " + attribute;
146*6777b538SAndroid Build Coastguard Worker       return false;
147*6777b538SAndroid Build Coastguard Worker     }
148*6777b538SAndroid Build Coastguard Worker 
149*6777b538SAndroid Build Coastguard Worker     const std::string& type_string = parts[0];
150*6777b538SAndroid Build Coastguard Worker     const std::string& value_string = parts[1];
151*6777b538SAndroid Build Coastguard Worker     base::span<const uint8_t> type_bytes;
152*6777b538SAndroid Build Coastguard Worker     if (type_string == "CN") {
153*6777b538SAndroid Build Coastguard Worker       type_bytes = kCommonName;
154*6777b538SAndroid Build Coastguard Worker     } else if (type_string == "C") {
155*6777b538SAndroid Build Coastguard Worker       type_bytes = kCountryName;
156*6777b538SAndroid Build Coastguard Worker     } else if (type_string == "O") {
157*6777b538SAndroid Build Coastguard Worker       type_bytes = kOrganizationName;
158*6777b538SAndroid Build Coastguard Worker     } else if (type_string == "OU") {
159*6777b538SAndroid Build Coastguard Worker       type_bytes = kOrganizationalUnitName;
160*6777b538SAndroid Build Coastguard Worker     } else {
161*6777b538SAndroid Build Coastguard Worker       LOG(ERROR) << "Unrecognized type " + type_string;
162*6777b538SAndroid Build Coastguard Worker       return false;
163*6777b538SAndroid Build Coastguard Worker     }
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker     CBB rdn, attr, type, value;
166*6777b538SAndroid Build Coastguard Worker     if (!CBB_add_asn1(&rdns, &rdn, CBS_ASN1_SET) ||
167*6777b538SAndroid Build Coastguard Worker         !CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE) ||
168*6777b538SAndroid Build Coastguard Worker         !CBB_add_asn1(&attr, &type, CBS_ASN1_OBJECT) ||
169*6777b538SAndroid Build Coastguard Worker         !CBB_add_bytes(&type, type_bytes.data(), type_bytes.size()) ||
170*6777b538SAndroid Build Coastguard Worker         !CBB_add_asn1(&attr, &value, type_string == "C" ?
171*6777b538SAndroid Build Coastguard Worker                           CBS_ASN1_PRINTABLESTRING : CBS_ASN1_UTF8STRING) ||
172*6777b538SAndroid Build Coastguard Worker         !CBB_add_bytes(&value,
173*6777b538SAndroid Build Coastguard Worker                        reinterpret_cast<const uint8_t*>(value_string.data()),
174*6777b538SAndroid Build Coastguard Worker                        value_string.size()) ||
175*6777b538SAndroid Build Coastguard Worker         !CBB_flush(&rdns)) {
176*6777b538SAndroid Build Coastguard Worker       return false;
177*6777b538SAndroid Build Coastguard Worker     }
178*6777b538SAndroid Build Coastguard Worker   }
179*6777b538SAndroid Build Coastguard Worker   if (!CBB_flush(cbb)) {
180*6777b538SAndroid Build Coastguard Worker     return false;
181*6777b538SAndroid Build Coastguard Worker   }
182*6777b538SAndroid Build Coastguard Worker   return true;
183*6777b538SAndroid Build Coastguard Worker }
184*6777b538SAndroid Build Coastguard Worker 
ConvertToX509CertificatesIgnoreErrors(const std::vector<std::vector<uint8_t>> & certs_bytes)185*6777b538SAndroid Build Coastguard Worker NET_EXPORT net::CertificateList ConvertToX509CertificatesIgnoreErrors(
186*6777b538SAndroid Build Coastguard Worker     const std::vector<std::vector<uint8_t>>& certs_bytes) {
187*6777b538SAndroid Build Coastguard Worker   net::CertificateList x509_certs;
188*6777b538SAndroid Build Coastguard Worker   for (const auto& cert_uint8 : certs_bytes) {
189*6777b538SAndroid Build Coastguard Worker     scoped_refptr<net::X509Certificate> x509_cert =
190*6777b538SAndroid Build Coastguard Worker         net::X509Certificate::CreateFromBytes(base::as_byte_span(cert_uint8));
191*6777b538SAndroid Build Coastguard Worker     if (x509_cert) {
192*6777b538SAndroid Build Coastguard Worker       x509_certs.push_back(std::move(x509_cert));
193*6777b538SAndroid Build Coastguard Worker     }
194*6777b538SAndroid Build Coastguard Worker   }
195*6777b538SAndroid Build Coastguard Worker   return x509_certs;
196*6777b538SAndroid Build Coastguard Worker }
197*6777b538SAndroid Build Coastguard Worker 
ParseAllValidCerts(const CertificateList & x509_certs)198*6777b538SAndroid Build Coastguard Worker bssl::ParsedCertificateList ParseAllValidCerts(
199*6777b538SAndroid Build Coastguard Worker     const CertificateList& x509_certs) {
200*6777b538SAndroid Build Coastguard Worker   bssl::ParsedCertificateList parsed_certs;
201*6777b538SAndroid Build Coastguard Worker   for (const auto& x509_cert : x509_certs) {
202*6777b538SAndroid Build Coastguard Worker     std::shared_ptr<const bssl::ParsedCertificate> cert =
203*6777b538SAndroid Build Coastguard Worker         bssl::ParsedCertificate::Create(
204*6777b538SAndroid Build Coastguard Worker             bssl::UpRef(x509_cert->cert_buffer()),
205*6777b538SAndroid Build Coastguard Worker             net::x509_util::DefaultParseCertificateOptions(), NULL);
206*6777b538SAndroid Build Coastguard Worker     if (cert) {
207*6777b538SAndroid Build Coastguard Worker       parsed_certs.push_back(std::move(cert));
208*6777b538SAndroid Build Coastguard Worker     }
209*6777b538SAndroid Build Coastguard Worker   }
210*6777b538SAndroid Build Coastguard Worker 
211*6777b538SAndroid Build Coastguard Worker   return parsed_certs;
212*6777b538SAndroid Build Coastguard Worker }
213*6777b538SAndroid Build Coastguard Worker 
CBBAddTime(CBB * cbb,base::Time time)214*6777b538SAndroid Build Coastguard Worker bool CBBAddTime(CBB* cbb, base::Time time) {
215*6777b538SAndroid Build Coastguard Worker   bssl::der::GeneralizedTime generalized_time;
216*6777b538SAndroid Build Coastguard Worker   if (!EncodeTimeAsGeneralizedTime(time, &generalized_time)) {
217*6777b538SAndroid Build Coastguard Worker     return false;
218*6777b538SAndroid Build Coastguard Worker   }
219*6777b538SAndroid Build Coastguard Worker 
220*6777b538SAndroid Build Coastguard Worker   // Per RFC 5280, 4.1.2.5, times which fit in UTCTime must be encoded as
221*6777b538SAndroid Build Coastguard Worker   // UTCTime rather than GeneralizedTime.
222*6777b538SAndroid Build Coastguard Worker   CBB child;
223*6777b538SAndroid Build Coastguard Worker   uint8_t* out;
224*6777b538SAndroid Build Coastguard Worker   if (generalized_time.InUTCTimeRange()) {
225*6777b538SAndroid Build Coastguard Worker     return CBB_add_asn1(cbb, &child, CBS_ASN1_UTCTIME) &&
226*6777b538SAndroid Build Coastguard Worker            CBB_add_space(&child, &out, bssl::der::kUTCTimeLength) &&
227*6777b538SAndroid Build Coastguard Worker            bssl::der::EncodeUTCTime(generalized_time, out) && CBB_flush(cbb);
228*6777b538SAndroid Build Coastguard Worker   }
229*6777b538SAndroid Build Coastguard Worker 
230*6777b538SAndroid Build Coastguard Worker   return CBB_add_asn1(cbb, &child, CBS_ASN1_GENERALIZEDTIME) &&
231*6777b538SAndroid Build Coastguard Worker          CBB_add_space(&child, &out, bssl::der::kGeneralizedTimeLength) &&
232*6777b538SAndroid Build Coastguard Worker          bssl::der::EncodeGeneralizedTime(generalized_time, out) &&
233*6777b538SAndroid Build Coastguard Worker          CBB_flush(cbb);
234*6777b538SAndroid Build Coastguard Worker }
235*6777b538SAndroid Build Coastguard Worker 
GetTLSServerEndPointChannelBinding(const X509Certificate & certificate,std::string * token)236*6777b538SAndroid Build Coastguard Worker bool GetTLSServerEndPointChannelBinding(const X509Certificate& certificate,
237*6777b538SAndroid Build Coastguard Worker                                         std::string* token) {
238*6777b538SAndroid Build Coastguard Worker   static const char kChannelBindingPrefix[] = "tls-server-end-point:";
239*6777b538SAndroid Build Coastguard Worker 
240*6777b538SAndroid Build Coastguard Worker   std::string_view der_encoded_certificate =
241*6777b538SAndroid Build Coastguard Worker       x509_util::CryptoBufferAsStringPiece(certificate.cert_buffer());
242*6777b538SAndroid Build Coastguard Worker 
243*6777b538SAndroid Build Coastguard Worker   bssl::der::Input tbs_certificate_tlv;
244*6777b538SAndroid Build Coastguard Worker   bssl::der::Input signature_algorithm_tlv;
245*6777b538SAndroid Build Coastguard Worker   bssl::der::BitString signature_value;
246*6777b538SAndroid Build Coastguard Worker   if (!bssl::ParseCertificate(bssl::der::Input(der_encoded_certificate),
247*6777b538SAndroid Build Coastguard Worker                               &tbs_certificate_tlv, &signature_algorithm_tlv,
248*6777b538SAndroid Build Coastguard Worker                               &signature_value, nullptr)) {
249*6777b538SAndroid Build Coastguard Worker     return false;
250*6777b538SAndroid Build Coastguard Worker   }
251*6777b538SAndroid Build Coastguard Worker   std::optional<bssl::SignatureAlgorithm> signature_algorithm =
252*6777b538SAndroid Build Coastguard Worker       bssl::ParseSignatureAlgorithm(signature_algorithm_tlv);
253*6777b538SAndroid Build Coastguard Worker   if (!signature_algorithm) {
254*6777b538SAndroid Build Coastguard Worker     return false;
255*6777b538SAndroid Build Coastguard Worker   }
256*6777b538SAndroid Build Coastguard Worker 
257*6777b538SAndroid Build Coastguard Worker   std::optional<bssl::DigestAlgorithm> binding_digest =
258*6777b538SAndroid Build Coastguard Worker       bssl::GetTlsServerEndpointDigestAlgorithm(*signature_algorithm);
259*6777b538SAndroid Build Coastguard Worker   if (!binding_digest) {
260*6777b538SAndroid Build Coastguard Worker     return false;
261*6777b538SAndroid Build Coastguard Worker   }
262*6777b538SAndroid Build Coastguard Worker   const EVP_MD* digest_evp_md = nullptr;
263*6777b538SAndroid Build Coastguard Worker   switch (binding_digest.value()) {
264*6777b538SAndroid Build Coastguard Worker     case bssl::DigestAlgorithm::Md2:
265*6777b538SAndroid Build Coastguard Worker     case bssl::DigestAlgorithm::Md4:
266*6777b538SAndroid Build Coastguard Worker     case bssl::DigestAlgorithm::Md5:
267*6777b538SAndroid Build Coastguard Worker     case bssl::DigestAlgorithm::Sha1:
268*6777b538SAndroid Build Coastguard Worker       // Legacy digests are not supported, and
269*6777b538SAndroid Build Coastguard Worker       // `GetTlsServerEndpointDigestAlgorithm` internally maps MD5 and SHA-1 to
270*6777b538SAndroid Build Coastguard Worker       // SHA-256.
271*6777b538SAndroid Build Coastguard Worker       NOTREACHED();
272*6777b538SAndroid Build Coastguard Worker       break;
273*6777b538SAndroid Build Coastguard Worker 
274*6777b538SAndroid Build Coastguard Worker     case bssl::DigestAlgorithm::Sha256:
275*6777b538SAndroid Build Coastguard Worker       digest_evp_md = EVP_sha256();
276*6777b538SAndroid Build Coastguard Worker       break;
277*6777b538SAndroid Build Coastguard Worker 
278*6777b538SAndroid Build Coastguard Worker     case bssl::DigestAlgorithm::Sha384:
279*6777b538SAndroid Build Coastguard Worker       digest_evp_md = EVP_sha384();
280*6777b538SAndroid Build Coastguard Worker       break;
281*6777b538SAndroid Build Coastguard Worker 
282*6777b538SAndroid Build Coastguard Worker     case bssl::DigestAlgorithm::Sha512:
283*6777b538SAndroid Build Coastguard Worker       digest_evp_md = EVP_sha512();
284*6777b538SAndroid Build Coastguard Worker       break;
285*6777b538SAndroid Build Coastguard Worker   }
286*6777b538SAndroid Build Coastguard Worker   if (!digest_evp_md)
287*6777b538SAndroid Build Coastguard Worker     return false;
288*6777b538SAndroid Build Coastguard Worker 
289*6777b538SAndroid Build Coastguard Worker   uint8_t digest[EVP_MAX_MD_SIZE];
290*6777b538SAndroid Build Coastguard Worker   unsigned int out_size;
291*6777b538SAndroid Build Coastguard Worker   if (!EVP_Digest(der_encoded_certificate.data(),
292*6777b538SAndroid Build Coastguard Worker                   der_encoded_certificate.size(), digest, &out_size,
293*6777b538SAndroid Build Coastguard Worker                   digest_evp_md, nullptr))
294*6777b538SAndroid Build Coastguard Worker     return false;
295*6777b538SAndroid Build Coastguard Worker 
296*6777b538SAndroid Build Coastguard Worker   token->assign(kChannelBindingPrefix);
297*6777b538SAndroid Build Coastguard Worker   token->append(digest, digest + out_size);
298*6777b538SAndroid Build Coastguard Worker   return true;
299*6777b538SAndroid Build Coastguard Worker }
300*6777b538SAndroid Build Coastguard Worker 
301*6777b538SAndroid Build Coastguard Worker // RSA keys created by CreateKeyAndSelfSignedCert will be of this length.
302*6777b538SAndroid Build Coastguard Worker static const uint16_t kRSAKeyLength = 1024;
303*6777b538SAndroid Build Coastguard Worker 
304*6777b538SAndroid Build Coastguard Worker // Certificates made by CreateKeyAndSelfSignedCert will be signed using this
305*6777b538SAndroid Build Coastguard Worker // digest algorithm.
306*6777b538SAndroid Build Coastguard Worker static const DigestAlgorithm kSignatureDigestAlgorithm = DIGEST_SHA256;
307*6777b538SAndroid Build Coastguard Worker 
CreateKeyAndSelfSignedCert(std::string_view subject,uint32_t serial_number,base::Time not_valid_before,base::Time not_valid_after,std::unique_ptr<crypto::RSAPrivateKey> * key,std::string * der_cert)308*6777b538SAndroid Build Coastguard Worker bool CreateKeyAndSelfSignedCert(std::string_view subject,
309*6777b538SAndroid Build Coastguard Worker                                 uint32_t serial_number,
310*6777b538SAndroid Build Coastguard Worker                                 base::Time not_valid_before,
311*6777b538SAndroid Build Coastguard Worker                                 base::Time not_valid_after,
312*6777b538SAndroid Build Coastguard Worker                                 std::unique_ptr<crypto::RSAPrivateKey>* key,
313*6777b538SAndroid Build Coastguard Worker                                 std::string* der_cert) {
314*6777b538SAndroid Build Coastguard Worker   std::unique_ptr<crypto::RSAPrivateKey> new_key(
315*6777b538SAndroid Build Coastguard Worker       crypto::RSAPrivateKey::Create(kRSAKeyLength));
316*6777b538SAndroid Build Coastguard Worker   if (!new_key)
317*6777b538SAndroid Build Coastguard Worker     return false;
318*6777b538SAndroid Build Coastguard Worker 
319*6777b538SAndroid Build Coastguard Worker   bool success = CreateSelfSignedCert(new_key->key(), kSignatureDigestAlgorithm,
320*6777b538SAndroid Build Coastguard Worker                                       subject, serial_number, not_valid_before,
321*6777b538SAndroid Build Coastguard Worker                                       not_valid_after, {}, der_cert);
322*6777b538SAndroid Build Coastguard Worker   if (success)
323*6777b538SAndroid Build Coastguard Worker     *key = std::move(new_key);
324*6777b538SAndroid Build Coastguard Worker 
325*6777b538SAndroid Build Coastguard Worker   return success;
326*6777b538SAndroid Build Coastguard Worker }
327*6777b538SAndroid Build Coastguard Worker 
Extension(base::span<const uint8_t> in_oid,bool in_critical,base::span<const uint8_t> in_contents)328*6777b538SAndroid Build Coastguard Worker Extension::Extension(base::span<const uint8_t> in_oid,
329*6777b538SAndroid Build Coastguard Worker                      bool in_critical,
330*6777b538SAndroid Build Coastguard Worker                      base::span<const uint8_t> in_contents)
331*6777b538SAndroid Build Coastguard Worker     : oid(in_oid), critical(in_critical), contents(in_contents) {}
332*6777b538SAndroid Build Coastguard Worker Extension::~Extension() = default;
333*6777b538SAndroid Build Coastguard Worker Extension::Extension(const Extension&) = default;
334*6777b538SAndroid Build Coastguard Worker 
CreateCert(EVP_PKEY * subject_key,DigestAlgorithm digest_alg,std::string_view subject,uint32_t serial_number,base::Time not_valid_before,base::Time not_valid_after,const std::vector<Extension> & extension_specs,std::string_view issuer,EVP_PKEY * issuer_key,std::string * der_encoded)335*6777b538SAndroid Build Coastguard Worker bool CreateCert(EVP_PKEY* subject_key,
336*6777b538SAndroid Build Coastguard Worker                 DigestAlgorithm digest_alg,
337*6777b538SAndroid Build Coastguard Worker                 std::string_view subject,
338*6777b538SAndroid Build Coastguard Worker                 uint32_t serial_number,
339*6777b538SAndroid Build Coastguard Worker                 base::Time not_valid_before,
340*6777b538SAndroid Build Coastguard Worker                 base::Time not_valid_after,
341*6777b538SAndroid Build Coastguard Worker                 const std::vector<Extension>& extension_specs,
342*6777b538SAndroid Build Coastguard Worker                 std::string_view issuer,
343*6777b538SAndroid Build Coastguard Worker                 EVP_PKEY* issuer_key,
344*6777b538SAndroid Build Coastguard Worker                 std::string* der_encoded) {
345*6777b538SAndroid Build Coastguard Worker   crypto::EnsureOpenSSLInit();
346*6777b538SAndroid Build Coastguard Worker   crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
347*6777b538SAndroid Build Coastguard Worker 
348*6777b538SAndroid Build Coastguard Worker   // See RFC 5280, section 4.1. First, construct the TBSCertificate.
349*6777b538SAndroid Build Coastguard Worker   bssl::ScopedCBB cbb;
350*6777b538SAndroid Build Coastguard Worker   CBB tbs_cert, version, validity;
351*6777b538SAndroid Build Coastguard Worker   uint8_t* tbs_cert_bytes;
352*6777b538SAndroid Build Coastguard Worker   size_t tbs_cert_len;
353*6777b538SAndroid Build Coastguard Worker   if (!CBB_init(cbb.get(), 64) ||
354*6777b538SAndroid Build Coastguard Worker       !CBB_add_asn1(cbb.get(), &tbs_cert, CBS_ASN1_SEQUENCE) ||
355*6777b538SAndroid Build Coastguard Worker       !CBB_add_asn1(&tbs_cert, &version,
356*6777b538SAndroid Build Coastguard Worker                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
357*6777b538SAndroid Build Coastguard Worker       !CBB_add_asn1_uint64(&version, 2) ||
358*6777b538SAndroid Build Coastguard Worker       !CBB_add_asn1_uint64(&tbs_cert, serial_number) ||
359*6777b538SAndroid Build Coastguard Worker       !AddSignatureAlgorithm(&tbs_cert, issuer_key, digest_alg) ||  // signature
360*6777b538SAndroid Build Coastguard Worker       !AddName(&tbs_cert, issuer) ||
361*6777b538SAndroid Build Coastguard Worker       !CBB_add_asn1(&tbs_cert, &validity, CBS_ASN1_SEQUENCE) ||
362*6777b538SAndroid Build Coastguard Worker       !CBBAddTime(&validity, not_valid_before) ||
363*6777b538SAndroid Build Coastguard Worker       !CBBAddTime(&validity, not_valid_after) ||
364*6777b538SAndroid Build Coastguard Worker       !AddName(&tbs_cert, subject) ||  // subject
365*6777b538SAndroid Build Coastguard Worker       !EVP_marshal_public_key(&tbs_cert,
366*6777b538SAndroid Build Coastguard Worker                               subject_key)) {  // subjectPublicKeyInfo
367*6777b538SAndroid Build Coastguard Worker     return false;
368*6777b538SAndroid Build Coastguard Worker   }
369*6777b538SAndroid Build Coastguard Worker 
370*6777b538SAndroid Build Coastguard Worker   if (!extension_specs.empty()) {
371*6777b538SAndroid Build Coastguard Worker     CBB outer_extensions, extensions;
372*6777b538SAndroid Build Coastguard Worker     if (!CBB_add_asn1(&tbs_cert, &outer_extensions,
373*6777b538SAndroid Build Coastguard Worker                       3 | CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED) ||
374*6777b538SAndroid Build Coastguard Worker         !CBB_add_asn1(&outer_extensions, &extensions, CBS_ASN1_SEQUENCE)) {
375*6777b538SAndroid Build Coastguard Worker       return false;
376*6777b538SAndroid Build Coastguard Worker     }
377*6777b538SAndroid Build Coastguard Worker 
378*6777b538SAndroid Build Coastguard Worker     for (const auto& extension_spec : extension_specs) {
379*6777b538SAndroid Build Coastguard Worker       CBB extension, oid, value;
380*6777b538SAndroid Build Coastguard Worker       if (!CBB_add_asn1(&extensions, &extension, CBS_ASN1_SEQUENCE) ||
381*6777b538SAndroid Build Coastguard Worker           !CBB_add_asn1(&extension, &oid, CBS_ASN1_OBJECT) ||
382*6777b538SAndroid Build Coastguard Worker           !CBB_add_bytes(&oid, extension_spec.oid.data(),
383*6777b538SAndroid Build Coastguard Worker                          extension_spec.oid.size()) ||
384*6777b538SAndroid Build Coastguard Worker           (extension_spec.critical && !CBB_add_asn1_bool(&extension, 1)) ||
385*6777b538SAndroid Build Coastguard Worker           !CBB_add_asn1(&extension, &value, CBS_ASN1_OCTETSTRING) ||
386*6777b538SAndroid Build Coastguard Worker           !CBB_add_bytes(&value, extension_spec.contents.data(),
387*6777b538SAndroid Build Coastguard Worker                          extension_spec.contents.size()) ||
388*6777b538SAndroid Build Coastguard Worker           !CBB_flush(&extensions)) {
389*6777b538SAndroid Build Coastguard Worker         return false;
390*6777b538SAndroid Build Coastguard Worker       }
391*6777b538SAndroid Build Coastguard Worker     }
392*6777b538SAndroid Build Coastguard Worker 
393*6777b538SAndroid Build Coastguard Worker     if (!CBB_flush(&tbs_cert)) {
394*6777b538SAndroid Build Coastguard Worker       return false;
395*6777b538SAndroid Build Coastguard Worker     }
396*6777b538SAndroid Build Coastguard Worker   }
397*6777b538SAndroid Build Coastguard Worker 
398*6777b538SAndroid Build Coastguard Worker   if (!CBB_finish(cbb.get(), &tbs_cert_bytes, &tbs_cert_len))
399*6777b538SAndroid Build Coastguard Worker     return false;
400*6777b538SAndroid Build Coastguard Worker   bssl::UniquePtr<uint8_t> delete_tbs_cert_bytes(tbs_cert_bytes);
401*6777b538SAndroid Build Coastguard Worker 
402*6777b538SAndroid Build Coastguard Worker   // Sign the TBSCertificate and write the entire certificate.
403*6777b538SAndroid Build Coastguard Worker   CBB cert, signature;
404*6777b538SAndroid Build Coastguard Worker   bssl::ScopedEVP_MD_CTX ctx;
405*6777b538SAndroid Build Coastguard Worker   uint8_t* sig_out;
406*6777b538SAndroid Build Coastguard Worker   size_t sig_len;
407*6777b538SAndroid Build Coastguard Worker   uint8_t* cert_bytes;
408*6777b538SAndroid Build Coastguard Worker   size_t cert_len;
409*6777b538SAndroid Build Coastguard Worker   if (!CBB_init(cbb.get(), tbs_cert_len) ||
410*6777b538SAndroid Build Coastguard Worker       !CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE) ||
411*6777b538SAndroid Build Coastguard Worker       !CBB_add_bytes(&cert, tbs_cert_bytes, tbs_cert_len) ||
412*6777b538SAndroid Build Coastguard Worker       !AddSignatureAlgorithm(&cert, issuer_key, digest_alg) ||
413*6777b538SAndroid Build Coastguard Worker       !CBB_add_asn1(&cert, &signature, CBS_ASN1_BITSTRING) ||
414*6777b538SAndroid Build Coastguard Worker       !CBB_add_u8(&signature, 0 /* no unused bits */) ||
415*6777b538SAndroid Build Coastguard Worker       !EVP_DigestSignInit(ctx.get(), nullptr, ToEVP(digest_alg), nullptr,
416*6777b538SAndroid Build Coastguard Worker                           issuer_key) ||
417*6777b538SAndroid Build Coastguard Worker       // Compute the maximum signature length.
418*6777b538SAndroid Build Coastguard Worker       !EVP_DigestSign(ctx.get(), nullptr, &sig_len, tbs_cert_bytes,
419*6777b538SAndroid Build Coastguard Worker                       tbs_cert_len) ||
420*6777b538SAndroid Build Coastguard Worker       !CBB_reserve(&signature, &sig_out, sig_len) ||
421*6777b538SAndroid Build Coastguard Worker       // Actually sign the TBSCertificate.
422*6777b538SAndroid Build Coastguard Worker       !EVP_DigestSign(ctx.get(), sig_out, &sig_len, tbs_cert_bytes,
423*6777b538SAndroid Build Coastguard Worker                       tbs_cert_len) ||
424*6777b538SAndroid Build Coastguard Worker       !CBB_did_write(&signature, sig_len) ||
425*6777b538SAndroid Build Coastguard Worker       !CBB_finish(cbb.get(), &cert_bytes, &cert_len)) {
426*6777b538SAndroid Build Coastguard Worker     return false;
427*6777b538SAndroid Build Coastguard Worker   }
428*6777b538SAndroid Build Coastguard Worker   bssl::UniquePtr<uint8_t> delete_cert_bytes(cert_bytes);
429*6777b538SAndroid Build Coastguard Worker   der_encoded->assign(reinterpret_cast<char*>(cert_bytes), cert_len);
430*6777b538SAndroid Build Coastguard Worker   return true;
431*6777b538SAndroid Build Coastguard Worker }
432*6777b538SAndroid Build Coastguard Worker 
CreateSelfSignedCert(EVP_PKEY * key,DigestAlgorithm digest_alg,std::string_view subject,uint32_t serial_number,base::Time not_valid_before,base::Time not_valid_after,const std::vector<Extension> & extension_specs,std::string * der_encoded)433*6777b538SAndroid Build Coastguard Worker bool CreateSelfSignedCert(EVP_PKEY* key,
434*6777b538SAndroid Build Coastguard Worker                           DigestAlgorithm digest_alg,
435*6777b538SAndroid Build Coastguard Worker                           std::string_view subject,
436*6777b538SAndroid Build Coastguard Worker                           uint32_t serial_number,
437*6777b538SAndroid Build Coastguard Worker                           base::Time not_valid_before,
438*6777b538SAndroid Build Coastguard Worker                           base::Time not_valid_after,
439*6777b538SAndroid Build Coastguard Worker                           const std::vector<Extension>& extension_specs,
440*6777b538SAndroid Build Coastguard Worker                           std::string* der_encoded) {
441*6777b538SAndroid Build Coastguard Worker   return CreateCert(/*subject_key=*/key, digest_alg, subject, serial_number,
442*6777b538SAndroid Build Coastguard Worker                     not_valid_before, not_valid_after, extension_specs,
443*6777b538SAndroid Build Coastguard Worker                     /*issuer=*/subject, /*issuer_key=*/key, der_encoded);
444*6777b538SAndroid Build Coastguard Worker }
445*6777b538SAndroid Build Coastguard Worker 
GetBufferPool()446*6777b538SAndroid Build Coastguard Worker CRYPTO_BUFFER_POOL* GetBufferPool() {
447*6777b538SAndroid Build Coastguard Worker   return g_buffer_pool_singleton.Get().pool();
448*6777b538SAndroid Build Coastguard Worker }
449*6777b538SAndroid Build Coastguard Worker 
CreateCryptoBuffer(base::span<const uint8_t> data)450*6777b538SAndroid Build Coastguard Worker bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(
451*6777b538SAndroid Build Coastguard Worker     base::span<const uint8_t> data) {
452*6777b538SAndroid Build Coastguard Worker   return bssl::UniquePtr<CRYPTO_BUFFER>(
453*6777b538SAndroid Build Coastguard Worker       CRYPTO_BUFFER_new(data.data(), data.size(), GetBufferPool()));
454*6777b538SAndroid Build Coastguard Worker }
455*6777b538SAndroid Build Coastguard Worker 
CreateCryptoBuffer(std::string_view data)456*6777b538SAndroid Build Coastguard Worker bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(std::string_view data) {
457*6777b538SAndroid Build Coastguard Worker   return bssl::UniquePtr<CRYPTO_BUFFER>(
458*6777b538SAndroid Build Coastguard Worker       CRYPTO_BUFFER_new(reinterpret_cast<const uint8_t*>(data.data()),
459*6777b538SAndroid Build Coastguard Worker                         data.size(), GetBufferPool()));
460*6777b538SAndroid Build Coastguard Worker }
461*6777b538SAndroid Build Coastguard Worker 
CreateCryptoBufferFromStaticDataUnsafe(base::span<const uint8_t> data)462*6777b538SAndroid Build Coastguard Worker bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBufferFromStaticDataUnsafe(
463*6777b538SAndroid Build Coastguard Worker     base::span<const uint8_t> data) {
464*6777b538SAndroid Build Coastguard Worker   return bssl::UniquePtr<CRYPTO_BUFFER>(
465*6777b538SAndroid Build Coastguard Worker       CRYPTO_BUFFER_new_from_static_data_unsafe(data.data(), data.size(),
466*6777b538SAndroid Build Coastguard Worker                                                 GetBufferPool()));
467*6777b538SAndroid Build Coastguard Worker }
468*6777b538SAndroid Build Coastguard Worker 
CryptoBufferEqual(const CRYPTO_BUFFER * a,const CRYPTO_BUFFER * b)469*6777b538SAndroid Build Coastguard Worker bool CryptoBufferEqual(const CRYPTO_BUFFER* a, const CRYPTO_BUFFER* b) {
470*6777b538SAndroid Build Coastguard Worker   DCHECK(a && b);
471*6777b538SAndroid Build Coastguard Worker   if (a == b)
472*6777b538SAndroid Build Coastguard Worker     return true;
473*6777b538SAndroid Build Coastguard Worker   return CRYPTO_BUFFER_len(a) == CRYPTO_BUFFER_len(b) &&
474*6777b538SAndroid Build Coastguard Worker          memcmp(CRYPTO_BUFFER_data(a), CRYPTO_BUFFER_data(b),
475*6777b538SAndroid Build Coastguard Worker                 CRYPTO_BUFFER_len(a)) == 0;
476*6777b538SAndroid Build Coastguard Worker }
477*6777b538SAndroid Build Coastguard Worker 
CryptoBufferAsStringPiece(const CRYPTO_BUFFER * buffer)478*6777b538SAndroid Build Coastguard Worker std::string_view CryptoBufferAsStringPiece(const CRYPTO_BUFFER* buffer) {
479*6777b538SAndroid Build Coastguard Worker   return std::string_view(
480*6777b538SAndroid Build Coastguard Worker       reinterpret_cast<const char*>(CRYPTO_BUFFER_data(buffer)),
481*6777b538SAndroid Build Coastguard Worker       CRYPTO_BUFFER_len(buffer));
482*6777b538SAndroid Build Coastguard Worker }
483*6777b538SAndroid Build Coastguard Worker 
CryptoBufferAsSpan(const CRYPTO_BUFFER * buffer)484*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> CryptoBufferAsSpan(const CRYPTO_BUFFER* buffer) {
485*6777b538SAndroid Build Coastguard Worker   return base::make_span(CRYPTO_BUFFER_data(buffer), CRYPTO_BUFFER_len(buffer));
486*6777b538SAndroid Build Coastguard Worker }
487*6777b538SAndroid Build Coastguard Worker 
CreateX509CertificateFromBuffers(const STACK_OF (CRYPTO_BUFFER)* buffers)488*6777b538SAndroid Build Coastguard Worker scoped_refptr<X509Certificate> CreateX509CertificateFromBuffers(
489*6777b538SAndroid Build Coastguard Worker     const STACK_OF(CRYPTO_BUFFER) * buffers) {
490*6777b538SAndroid Build Coastguard Worker   if (sk_CRYPTO_BUFFER_num(buffers) == 0) {
491*6777b538SAndroid Build Coastguard Worker     NOTREACHED();
492*6777b538SAndroid Build Coastguard Worker     return nullptr;
493*6777b538SAndroid Build Coastguard Worker   }
494*6777b538SAndroid Build Coastguard Worker 
495*6777b538SAndroid Build Coastguard Worker   std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediate_chain;
496*6777b538SAndroid Build Coastguard Worker   for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(buffers); ++i) {
497*6777b538SAndroid Build Coastguard Worker     intermediate_chain.push_back(
498*6777b538SAndroid Build Coastguard Worker         bssl::UpRef(sk_CRYPTO_BUFFER_value(buffers, i)));
499*6777b538SAndroid Build Coastguard Worker   }
500*6777b538SAndroid Build Coastguard Worker   return X509Certificate::CreateFromBuffer(
501*6777b538SAndroid Build Coastguard Worker       bssl::UpRef(sk_CRYPTO_BUFFER_value(buffers, 0)),
502*6777b538SAndroid Build Coastguard Worker       std::move(intermediate_chain));
503*6777b538SAndroid Build Coastguard Worker }
504*6777b538SAndroid Build Coastguard Worker 
CreateCertBuffersFromPKCS7Bytes(base::span<const uint8_t> data,std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> * handles)505*6777b538SAndroid Build Coastguard Worker bool CreateCertBuffersFromPKCS7Bytes(
506*6777b538SAndroid Build Coastguard Worker     base::span<const uint8_t> data,
507*6777b538SAndroid Build Coastguard Worker     std::vector<bssl::UniquePtr<CRYPTO_BUFFER>>* handles) {
508*6777b538SAndroid Build Coastguard Worker   crypto::EnsureOpenSSLInit();
509*6777b538SAndroid Build Coastguard Worker   crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE);
510*6777b538SAndroid Build Coastguard Worker 
511*6777b538SAndroid Build Coastguard Worker   CBS der_data;
512*6777b538SAndroid Build Coastguard Worker   CBS_init(&der_data, data.data(), data.size());
513*6777b538SAndroid Build Coastguard Worker   STACK_OF(CRYPTO_BUFFER)* certs = sk_CRYPTO_BUFFER_new_null();
514*6777b538SAndroid Build Coastguard Worker   bool success =
515*6777b538SAndroid Build Coastguard Worker       PKCS7_get_raw_certificates(certs, &der_data, x509_util::GetBufferPool());
516*6777b538SAndroid Build Coastguard Worker   if (success) {
517*6777b538SAndroid Build Coastguard Worker     for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(certs); ++i) {
518*6777b538SAndroid Build Coastguard Worker       handles->push_back(
519*6777b538SAndroid Build Coastguard Worker           bssl::UniquePtr<CRYPTO_BUFFER>(sk_CRYPTO_BUFFER_value(certs, i)));
520*6777b538SAndroid Build Coastguard Worker     }
521*6777b538SAndroid Build Coastguard Worker   }
522*6777b538SAndroid Build Coastguard Worker   // |handles| took ownership of the individual buffers, so only free the list
523*6777b538SAndroid Build Coastguard Worker   // itself.
524*6777b538SAndroid Build Coastguard Worker   sk_CRYPTO_BUFFER_free(certs);
525*6777b538SAndroid Build Coastguard Worker 
526*6777b538SAndroid Build Coastguard Worker   return success;
527*6777b538SAndroid Build Coastguard Worker }
528*6777b538SAndroid Build Coastguard Worker 
DefaultParseCertificateOptions()529*6777b538SAndroid Build Coastguard Worker bssl::ParseCertificateOptions DefaultParseCertificateOptions() {
530*6777b538SAndroid Build Coastguard Worker   bssl::ParseCertificateOptions options;
531*6777b538SAndroid Build Coastguard Worker   options.allow_invalid_serial_numbers = true;
532*6777b538SAndroid Build Coastguard Worker   return options;
533*6777b538SAndroid Build Coastguard Worker }
534*6777b538SAndroid Build Coastguard Worker 
CalculateSha256SpkiHash(const CRYPTO_BUFFER * buffer,HashValue * hash)535*6777b538SAndroid Build Coastguard Worker bool CalculateSha256SpkiHash(const CRYPTO_BUFFER* buffer, HashValue* hash) {
536*6777b538SAndroid Build Coastguard Worker   std::string_view spki;
537*6777b538SAndroid Build Coastguard Worker   if (!asn1::ExtractSPKIFromDERCert(CryptoBufferAsStringPiece(buffer), &spki)) {
538*6777b538SAndroid Build Coastguard Worker     return false;
539*6777b538SAndroid Build Coastguard Worker   }
540*6777b538SAndroid Build Coastguard Worker   *hash = HashValue(HASH_VALUE_SHA256);
541*6777b538SAndroid Build Coastguard Worker   crypto::SHA256HashString(spki, hash->data(), hash->size());
542*6777b538SAndroid Build Coastguard Worker   return true;
543*6777b538SAndroid Build Coastguard Worker }
544*6777b538SAndroid Build Coastguard Worker 
SignatureVerifierInitWithCertificate(crypto::SignatureVerifier * verifier,crypto::SignatureVerifier::SignatureAlgorithm signature_algorithm,base::span<const uint8_t> signature,const CRYPTO_BUFFER * certificate)545*6777b538SAndroid Build Coastguard Worker bool SignatureVerifierInitWithCertificate(
546*6777b538SAndroid Build Coastguard Worker     crypto::SignatureVerifier* verifier,
547*6777b538SAndroid Build Coastguard Worker     crypto::SignatureVerifier::SignatureAlgorithm signature_algorithm,
548*6777b538SAndroid Build Coastguard Worker     base::span<const uint8_t> signature,
549*6777b538SAndroid Build Coastguard Worker     const CRYPTO_BUFFER* certificate) {
550*6777b538SAndroid Build Coastguard Worker   std::string_view cert_der = x509_util::CryptoBufferAsStringPiece(certificate);
551*6777b538SAndroid Build Coastguard Worker 
552*6777b538SAndroid Build Coastguard Worker   bssl::der::Input tbs_certificate_tlv;
553*6777b538SAndroid Build Coastguard Worker   bssl::der::Input signature_algorithm_tlv;
554*6777b538SAndroid Build Coastguard Worker   bssl::der::BitString signature_value;
555*6777b538SAndroid Build Coastguard Worker   bssl::ParsedTbsCertificate tbs;
556*6777b538SAndroid Build Coastguard Worker   if (!bssl::ParseCertificate(bssl::der::Input(cert_der), &tbs_certificate_tlv,
557*6777b538SAndroid Build Coastguard Worker                               &signature_algorithm_tlv, &signature_value,
558*6777b538SAndroid Build Coastguard Worker                               nullptr) ||
559*6777b538SAndroid Build Coastguard Worker       !ParseTbsCertificate(tbs_certificate_tlv,
560*6777b538SAndroid Build Coastguard Worker                            DefaultParseCertificateOptions(), &tbs, nullptr)) {
561*6777b538SAndroid Build Coastguard Worker     return false;
562*6777b538SAndroid Build Coastguard Worker   }
563*6777b538SAndroid Build Coastguard Worker 
564*6777b538SAndroid Build Coastguard Worker   // The key usage extension, if present, must assert the digitalSignature bit.
565*6777b538SAndroid Build Coastguard Worker   if (tbs.extensions_tlv) {
566*6777b538SAndroid Build Coastguard Worker     std::map<bssl::der::Input, bssl::ParsedExtension> extensions;
567*6777b538SAndroid Build Coastguard Worker     if (!ParseExtensions(tbs.extensions_tlv.value(), &extensions)) {
568*6777b538SAndroid Build Coastguard Worker       return false;
569*6777b538SAndroid Build Coastguard Worker     }
570*6777b538SAndroid Build Coastguard Worker     bssl::ParsedExtension key_usage_ext;
571*6777b538SAndroid Build Coastguard Worker     if (ConsumeExtension(bssl::der::Input(bssl::kKeyUsageOid), &extensions,
572*6777b538SAndroid Build Coastguard Worker                          &key_usage_ext)) {
573*6777b538SAndroid Build Coastguard Worker       bssl::der::BitString key_usage;
574*6777b538SAndroid Build Coastguard Worker       if (!bssl::ParseKeyUsage(key_usage_ext.value, &key_usage) ||
575*6777b538SAndroid Build Coastguard Worker           !key_usage.AssertsBit(bssl::KEY_USAGE_BIT_DIGITAL_SIGNATURE)) {
576*6777b538SAndroid Build Coastguard Worker         return false;
577*6777b538SAndroid Build Coastguard Worker       }
578*6777b538SAndroid Build Coastguard Worker     }
579*6777b538SAndroid Build Coastguard Worker   }
580*6777b538SAndroid Build Coastguard Worker 
581*6777b538SAndroid Build Coastguard Worker   return verifier->VerifyInit(signature_algorithm, signature, tbs.spki_tlv);
582*6777b538SAndroid Build Coastguard Worker }
583*6777b538SAndroid Build Coastguard Worker 
HasRsaPkcs1Sha1Signature(const CRYPTO_BUFFER * cert_buffer)584*6777b538SAndroid Build Coastguard Worker bool HasRsaPkcs1Sha1Signature(const CRYPTO_BUFFER* cert_buffer) {
585*6777b538SAndroid Build Coastguard Worker   bssl::der::Input tbs_certificate_tlv;
586*6777b538SAndroid Build Coastguard Worker   bssl::der::Input signature_algorithm_tlv;
587*6777b538SAndroid Build Coastguard Worker   bssl::der::BitString signature_value;
588*6777b538SAndroid Build Coastguard Worker   if (!bssl::ParseCertificate(bssl::der::Input(CRYPTO_BUFFER_data(cert_buffer),
589*6777b538SAndroid Build Coastguard Worker                                                CRYPTO_BUFFER_len(cert_buffer)),
590*6777b538SAndroid Build Coastguard Worker                               &tbs_certificate_tlv, &signature_algorithm_tlv,
591*6777b538SAndroid Build Coastguard Worker                               &signature_value, /*out_errors=*/nullptr)) {
592*6777b538SAndroid Build Coastguard Worker     return false;
593*6777b538SAndroid Build Coastguard Worker   }
594*6777b538SAndroid Build Coastguard Worker 
595*6777b538SAndroid Build Coastguard Worker   std::optional<bssl::SignatureAlgorithm> signature_algorithm =
596*6777b538SAndroid Build Coastguard Worker       bssl::ParseSignatureAlgorithm(signature_algorithm_tlv);
597*6777b538SAndroid Build Coastguard Worker 
598*6777b538SAndroid Build Coastguard Worker   return signature_algorithm &&
599*6777b538SAndroid Build Coastguard Worker          *signature_algorithm == bssl::SignatureAlgorithm::kRsaPkcs1Sha1;
600*6777b538SAndroid Build Coastguard Worker }
601*6777b538SAndroid Build Coastguard Worker 
602*6777b538SAndroid Build Coastguard Worker }  // namespace net::x509_util
603