xref: /aosp_15_r20/external/cronet/net/cert/asn1_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/asn1_util.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <optional>
8*6777b538SAndroid Build Coastguard Worker #include <string_view>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/pki/input.h"
11*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/pki/parse_certificate.h"
12*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/pki/parser.h"
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker namespace net::asn1 {
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace {
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker // Parses input |in| which should point to the beginning of a Certificate, and
19*6777b538SAndroid Build Coastguard Worker // sets |*tbs_certificate| ready to parse the Subject. If parsing
20*6777b538SAndroid Build Coastguard Worker // fails, this function returns false and |*tbs_certificate| is left in an
21*6777b538SAndroid Build Coastguard Worker // undefined state.
SeekToSubject(bssl::der::Input in,bssl::der::Parser * tbs_certificate)22*6777b538SAndroid Build Coastguard Worker bool SeekToSubject(bssl::der::Input in, bssl::der::Parser* tbs_certificate) {
23*6777b538SAndroid Build Coastguard Worker   // From RFC 5280, section 4.1
24*6777b538SAndroid Build Coastguard Worker   //    Certificate  ::=  SEQUENCE  {
25*6777b538SAndroid Build Coastguard Worker   //      tbsCertificate       TBSCertificate,
26*6777b538SAndroid Build Coastguard Worker   //      signatureAlgorithm   AlgorithmIdentifier,
27*6777b538SAndroid Build Coastguard Worker   //      signatureValue       BIT STRING  }
28*6777b538SAndroid Build Coastguard Worker 
29*6777b538SAndroid Build Coastguard Worker   // TBSCertificate  ::=  SEQUENCE  {
30*6777b538SAndroid Build Coastguard Worker   //      version         [0]  EXPLICIT Version DEFAULT v1,
31*6777b538SAndroid Build Coastguard Worker   //      serialNumber         CertificateSerialNumber,
32*6777b538SAndroid Build Coastguard Worker   //      signature            AlgorithmIdentifier,
33*6777b538SAndroid Build Coastguard Worker   //      issuer               Name,
34*6777b538SAndroid Build Coastguard Worker   //      validity             Validity,
35*6777b538SAndroid Build Coastguard Worker   //      subject              Name,
36*6777b538SAndroid Build Coastguard Worker   //      subjectPublicKeyInfo SubjectPublicKeyInfo,
37*6777b538SAndroid Build Coastguard Worker   //      ... }
38*6777b538SAndroid Build Coastguard Worker 
39*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser parser(in);
40*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser certificate;
41*6777b538SAndroid Build Coastguard Worker   if (!parser.ReadSequence(&certificate))
42*6777b538SAndroid Build Coastguard Worker     return false;
43*6777b538SAndroid Build Coastguard Worker 
44*6777b538SAndroid Build Coastguard Worker   // We don't allow junk after the certificate.
45*6777b538SAndroid Build Coastguard Worker   if (parser.HasMore())
46*6777b538SAndroid Build Coastguard Worker     return false;
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker   if (!certificate.ReadSequence(tbs_certificate))
49*6777b538SAndroid Build Coastguard Worker     return false;
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker   bool unused;
52*6777b538SAndroid Build Coastguard Worker   if (!tbs_certificate->SkipOptionalTag(
53*6777b538SAndroid Build Coastguard Worker           CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0, &unused)) {
54*6777b538SAndroid Build Coastguard Worker     return false;
55*6777b538SAndroid Build Coastguard Worker   }
56*6777b538SAndroid Build Coastguard Worker 
57*6777b538SAndroid Build Coastguard Worker   // serialNumber
58*6777b538SAndroid Build Coastguard Worker   if (!tbs_certificate->SkipTag(CBS_ASN1_INTEGER)) {
59*6777b538SAndroid Build Coastguard Worker     return false;
60*6777b538SAndroid Build Coastguard Worker   }
61*6777b538SAndroid Build Coastguard Worker   // signature
62*6777b538SAndroid Build Coastguard Worker   if (!tbs_certificate->SkipTag(CBS_ASN1_SEQUENCE)) {
63*6777b538SAndroid Build Coastguard Worker     return false;
64*6777b538SAndroid Build Coastguard Worker   }
65*6777b538SAndroid Build Coastguard Worker   // issuer
66*6777b538SAndroid Build Coastguard Worker   if (!tbs_certificate->SkipTag(CBS_ASN1_SEQUENCE)) {
67*6777b538SAndroid Build Coastguard Worker     return false;
68*6777b538SAndroid Build Coastguard Worker   }
69*6777b538SAndroid Build Coastguard Worker   // validity
70*6777b538SAndroid Build Coastguard Worker   if (!tbs_certificate->SkipTag(CBS_ASN1_SEQUENCE)) {
71*6777b538SAndroid Build Coastguard Worker     return false;
72*6777b538SAndroid Build Coastguard Worker   }
73*6777b538SAndroid Build Coastguard Worker   return true;
74*6777b538SAndroid Build Coastguard Worker }
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker // Parses input |in| which should point to the beginning of a Certificate, and
77*6777b538SAndroid Build Coastguard Worker // sets |*tbs_certificate| ready to parse the SubjectPublicKeyInfo. If parsing
78*6777b538SAndroid Build Coastguard Worker // fails, this function returns false and |*tbs_certificate| is left in an
79*6777b538SAndroid Build Coastguard Worker // undefined state.
SeekToSPKI(bssl::der::Input in,bssl::der::Parser * tbs_certificate)80*6777b538SAndroid Build Coastguard Worker bool SeekToSPKI(bssl::der::Input in, bssl::der::Parser* tbs_certificate) {
81*6777b538SAndroid Build Coastguard Worker   return SeekToSubject(in, tbs_certificate) &&
82*6777b538SAndroid Build Coastguard Worker          // Skip over Subject.
83*6777b538SAndroid Build Coastguard Worker          tbs_certificate->SkipTag(CBS_ASN1_SEQUENCE);
84*6777b538SAndroid Build Coastguard Worker }
85*6777b538SAndroid Build Coastguard Worker 
86*6777b538SAndroid Build Coastguard Worker // Parses input |in| which should point to the beginning of a
87*6777b538SAndroid Build Coastguard Worker // Certificate. If parsing fails, this function returns false, with
88*6777b538SAndroid Build Coastguard Worker // |*extensions_present| and |*extensions_parser| left in an undefined
89*6777b538SAndroid Build Coastguard Worker // state. If parsing succeeds and extensions are present, this function
90*6777b538SAndroid Build Coastguard Worker // sets |*extensions_present| to true and sets |*extensions_parser|
91*6777b538SAndroid Build Coastguard Worker // ready to parse the Extensions. If extensions are not present, it sets
92*6777b538SAndroid Build Coastguard Worker // |*extensions_present| to false and |*extensions_parser| is left in an
93*6777b538SAndroid Build Coastguard Worker // undefined state.
SeekToExtensions(bssl::der::Input in,bool * extensions_present,bssl::der::Parser * extensions_parser)94*6777b538SAndroid Build Coastguard Worker bool SeekToExtensions(bssl::der::Input in,
95*6777b538SAndroid Build Coastguard Worker                       bool* extensions_present,
96*6777b538SAndroid Build Coastguard Worker                       bssl::der::Parser* extensions_parser) {
97*6777b538SAndroid Build Coastguard Worker   bool present;
98*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser tbs_cert_parser;
99*6777b538SAndroid Build Coastguard Worker   if (!SeekToSPKI(in, &tbs_cert_parser))
100*6777b538SAndroid Build Coastguard Worker     return false;
101*6777b538SAndroid Build Coastguard Worker 
102*6777b538SAndroid Build Coastguard Worker   // From RFC 5280, section 4.1
103*6777b538SAndroid Build Coastguard Worker   // TBSCertificate  ::=  SEQUENCE  {
104*6777b538SAndroid Build Coastguard Worker   //      ...
105*6777b538SAndroid Build Coastguard Worker   //      subjectPublicKeyInfo SubjectPublicKeyInfo,
106*6777b538SAndroid Build Coastguard Worker   //      issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
107*6777b538SAndroid Build Coastguard Worker   //      subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
108*6777b538SAndroid Build Coastguard Worker   //      extensions      [3]  EXPLICIT Extensions OPTIONAL }
109*6777b538SAndroid Build Coastguard Worker 
110*6777b538SAndroid Build Coastguard Worker   // subjectPublicKeyInfo
111*6777b538SAndroid Build Coastguard Worker   if (!tbs_cert_parser.SkipTag(CBS_ASN1_SEQUENCE)) {
112*6777b538SAndroid Build Coastguard Worker     return false;
113*6777b538SAndroid Build Coastguard Worker   }
114*6777b538SAndroid Build Coastguard Worker   // issuerUniqueID
115*6777b538SAndroid Build Coastguard Worker   if (!tbs_cert_parser.SkipOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1,
116*6777b538SAndroid Build Coastguard Worker                                        &present)) {
117*6777b538SAndroid Build Coastguard Worker     return false;
118*6777b538SAndroid Build Coastguard Worker   }
119*6777b538SAndroid Build Coastguard Worker   // subjectUniqueID
120*6777b538SAndroid Build Coastguard Worker   if (!tbs_cert_parser.SkipOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 2,
121*6777b538SAndroid Build Coastguard Worker                                        &present)) {
122*6777b538SAndroid Build Coastguard Worker     return false;
123*6777b538SAndroid Build Coastguard Worker   }
124*6777b538SAndroid Build Coastguard Worker 
125*6777b538SAndroid Build Coastguard Worker   std::optional<bssl::der::Input> extensions;
126*6777b538SAndroid Build Coastguard Worker   if (!tbs_cert_parser.ReadOptionalTag(
127*6777b538SAndroid Build Coastguard Worker           CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3, &extensions)) {
128*6777b538SAndroid Build Coastguard Worker     return false;
129*6777b538SAndroid Build Coastguard Worker   }
130*6777b538SAndroid Build Coastguard Worker 
131*6777b538SAndroid Build Coastguard Worker   if (!extensions) {
132*6777b538SAndroid Build Coastguard Worker     *extensions_present = false;
133*6777b538SAndroid Build Coastguard Worker     return true;
134*6777b538SAndroid Build Coastguard Worker   }
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker   // Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
137*6777b538SAndroid Build Coastguard Worker   // Extension   ::=  SEQUENCE  {
138*6777b538SAndroid Build Coastguard Worker   //      extnID      OBJECT IDENTIFIER,
139*6777b538SAndroid Build Coastguard Worker   //      critical    BOOLEAN DEFAULT FALSE,
140*6777b538SAndroid Build Coastguard Worker   //      extnValue   OCTET STRING }
141*6777b538SAndroid Build Coastguard Worker 
142*6777b538SAndroid Build Coastguard Worker   // |extensions| was EXPLICITly tagged, so we still need to remove the
143*6777b538SAndroid Build Coastguard Worker   // ASN.1 SEQUENCE header.
144*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser explicit_extensions_parser(extensions.value());
145*6777b538SAndroid Build Coastguard Worker   if (!explicit_extensions_parser.ReadSequence(extensions_parser))
146*6777b538SAndroid Build Coastguard Worker     return false;
147*6777b538SAndroid Build Coastguard Worker 
148*6777b538SAndroid Build Coastguard Worker   if (explicit_extensions_parser.HasMore())
149*6777b538SAndroid Build Coastguard Worker     return false;
150*6777b538SAndroid Build Coastguard Worker 
151*6777b538SAndroid Build Coastguard Worker   *extensions_present = true;
152*6777b538SAndroid Build Coastguard Worker   return true;
153*6777b538SAndroid Build Coastguard Worker }
154*6777b538SAndroid Build Coastguard Worker 
155*6777b538SAndroid Build Coastguard Worker // Parse a DER-encoded, X.509 certificate in |cert| and find an extension with
156*6777b538SAndroid Build Coastguard Worker // the given OID. Returns false on parse error or true if the parse was
157*6777b538SAndroid Build Coastguard Worker // successful. |*out_extension_present| will be true iff the extension was
158*6777b538SAndroid Build Coastguard Worker // found. In the case where it was found, |*out_extension| will describe the
159*6777b538SAndroid Build Coastguard Worker // extension, or is undefined on parse error or if the extension is missing.
ExtractExtensionWithOID(std::string_view cert,bssl::der::Input extension_oid,bool * out_extension_present,bssl::ParsedExtension * out_extension)160*6777b538SAndroid Build Coastguard Worker bool ExtractExtensionWithOID(std::string_view cert,
161*6777b538SAndroid Build Coastguard Worker                              bssl::der::Input extension_oid,
162*6777b538SAndroid Build Coastguard Worker                              bool* out_extension_present,
163*6777b538SAndroid Build Coastguard Worker                              bssl::ParsedExtension* out_extension) {
164*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser extensions;
165*6777b538SAndroid Build Coastguard Worker   bool extensions_present;
166*6777b538SAndroid Build Coastguard Worker   if (!SeekToExtensions(bssl::der::Input(cert), &extensions_present,
167*6777b538SAndroid Build Coastguard Worker                         &extensions)) {
168*6777b538SAndroid Build Coastguard Worker     return false;
169*6777b538SAndroid Build Coastguard Worker   }
170*6777b538SAndroid Build Coastguard Worker   if (!extensions_present) {
171*6777b538SAndroid Build Coastguard Worker     *out_extension_present = false;
172*6777b538SAndroid Build Coastguard Worker     return true;
173*6777b538SAndroid Build Coastguard Worker   }
174*6777b538SAndroid Build Coastguard Worker 
175*6777b538SAndroid Build Coastguard Worker   while (extensions.HasMore()) {
176*6777b538SAndroid Build Coastguard Worker     bssl::der::Input extension_tlv;
177*6777b538SAndroid Build Coastguard Worker     if (!extensions.ReadRawTLV(&extension_tlv) ||
178*6777b538SAndroid Build Coastguard Worker         !ParseExtension(extension_tlv, out_extension)) {
179*6777b538SAndroid Build Coastguard Worker       return false;
180*6777b538SAndroid Build Coastguard Worker     }
181*6777b538SAndroid Build Coastguard Worker 
182*6777b538SAndroid Build Coastguard Worker     if (out_extension->oid == extension_oid) {
183*6777b538SAndroid Build Coastguard Worker       *out_extension_present = true;
184*6777b538SAndroid Build Coastguard Worker       return true;
185*6777b538SAndroid Build Coastguard Worker     }
186*6777b538SAndroid Build Coastguard Worker   }
187*6777b538SAndroid Build Coastguard Worker 
188*6777b538SAndroid Build Coastguard Worker   *out_extension_present = false;
189*6777b538SAndroid Build Coastguard Worker   return true;
190*6777b538SAndroid Build Coastguard Worker }
191*6777b538SAndroid Build Coastguard Worker 
192*6777b538SAndroid Build Coastguard Worker }  // namespace
193*6777b538SAndroid Build Coastguard Worker 
ExtractSubjectFromDERCert(std::string_view cert,std::string_view * subject_out)194*6777b538SAndroid Build Coastguard Worker bool ExtractSubjectFromDERCert(std::string_view cert,
195*6777b538SAndroid Build Coastguard Worker                                std::string_view* subject_out) {
196*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser parser;
197*6777b538SAndroid Build Coastguard Worker   if (!SeekToSubject(bssl::der::Input(cert), &parser)) {
198*6777b538SAndroid Build Coastguard Worker     return false;
199*6777b538SAndroid Build Coastguard Worker   }
200*6777b538SAndroid Build Coastguard Worker   bssl::der::Input subject;
201*6777b538SAndroid Build Coastguard Worker   if (!parser.ReadRawTLV(&subject))
202*6777b538SAndroid Build Coastguard Worker     return false;
203*6777b538SAndroid Build Coastguard Worker   *subject_out = subject.AsStringView();
204*6777b538SAndroid Build Coastguard Worker   return true;
205*6777b538SAndroid Build Coastguard Worker }
206*6777b538SAndroid Build Coastguard Worker 
ExtractSPKIFromDERCert(std::string_view cert,std::string_view * spki_out)207*6777b538SAndroid Build Coastguard Worker bool ExtractSPKIFromDERCert(std::string_view cert, std::string_view* spki_out) {
208*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser parser;
209*6777b538SAndroid Build Coastguard Worker   if (!SeekToSPKI(bssl::der::Input(cert), &parser)) {
210*6777b538SAndroid Build Coastguard Worker     return false;
211*6777b538SAndroid Build Coastguard Worker   }
212*6777b538SAndroid Build Coastguard Worker   bssl::der::Input spki;
213*6777b538SAndroid Build Coastguard Worker   if (!parser.ReadRawTLV(&spki))
214*6777b538SAndroid Build Coastguard Worker     return false;
215*6777b538SAndroid Build Coastguard Worker   *spki_out = spki.AsStringView();
216*6777b538SAndroid Build Coastguard Worker   return true;
217*6777b538SAndroid Build Coastguard Worker }
218*6777b538SAndroid Build Coastguard Worker 
ExtractSubjectPublicKeyFromSPKI(std::string_view spki,std::string_view * spk_out)219*6777b538SAndroid Build Coastguard Worker bool ExtractSubjectPublicKeyFromSPKI(std::string_view spki,
220*6777b538SAndroid Build Coastguard Worker                                      std::string_view* spk_out) {
221*6777b538SAndroid Build Coastguard Worker   // From RFC 5280, Section 4.1
222*6777b538SAndroid Build Coastguard Worker   //   SubjectPublicKeyInfo  ::=  SEQUENCE  {
223*6777b538SAndroid Build Coastguard Worker   //     algorithm            AlgorithmIdentifier,
224*6777b538SAndroid Build Coastguard Worker   //     subjectPublicKey     BIT STRING  }
225*6777b538SAndroid Build Coastguard Worker   //
226*6777b538SAndroid Build Coastguard Worker   //   AlgorithmIdentifier  ::=  SEQUENCE  {
227*6777b538SAndroid Build Coastguard Worker   //     algorithm               OBJECT IDENTIFIER,
228*6777b538SAndroid Build Coastguard Worker   //     parameters              ANY DEFINED BY algorithm OPTIONAL  }
229*6777b538SAndroid Build Coastguard Worker 
230*6777b538SAndroid Build Coastguard Worker   // Step into SubjectPublicKeyInfo sequence.
231*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser parser((bssl::der::Input(spki)));
232*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser spki_parser;
233*6777b538SAndroid Build Coastguard Worker   if (!parser.ReadSequence(&spki_parser))
234*6777b538SAndroid Build Coastguard Worker     return false;
235*6777b538SAndroid Build Coastguard Worker 
236*6777b538SAndroid Build Coastguard Worker   // Step over algorithm field (a SEQUENCE).
237*6777b538SAndroid Build Coastguard Worker   if (!spki_parser.SkipTag(CBS_ASN1_SEQUENCE)) {
238*6777b538SAndroid Build Coastguard Worker     return false;
239*6777b538SAndroid Build Coastguard Worker   }
240*6777b538SAndroid Build Coastguard Worker 
241*6777b538SAndroid Build Coastguard Worker   // Extract the subjectPublicKey field.
242*6777b538SAndroid Build Coastguard Worker   bssl::der::Input spk;
243*6777b538SAndroid Build Coastguard Worker   if (!spki_parser.ReadTag(CBS_ASN1_BITSTRING, &spk)) {
244*6777b538SAndroid Build Coastguard Worker     return false;
245*6777b538SAndroid Build Coastguard Worker   }
246*6777b538SAndroid Build Coastguard Worker   *spk_out = spk.AsStringView();
247*6777b538SAndroid Build Coastguard Worker   return true;
248*6777b538SAndroid Build Coastguard Worker }
249*6777b538SAndroid Build Coastguard Worker 
HasCanSignHttpExchangesDraftExtension(std::string_view cert)250*6777b538SAndroid Build Coastguard Worker bool HasCanSignHttpExchangesDraftExtension(std::string_view cert) {
251*6777b538SAndroid Build Coastguard Worker   // kCanSignHttpExchangesDraftOid is the DER encoding of the OID for
252*6777b538SAndroid Build Coastguard Worker   // canSignHttpExchangesDraft defined in:
253*6777b538SAndroid Build Coastguard Worker   // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html
254*6777b538SAndroid Build Coastguard Worker   static const uint8_t kCanSignHttpExchangesDraftOid[] = {
255*6777b538SAndroid Build Coastguard Worker       0x2B, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x16};
256*6777b538SAndroid Build Coastguard Worker 
257*6777b538SAndroid Build Coastguard Worker   bool extension_present;
258*6777b538SAndroid Build Coastguard Worker   bssl::ParsedExtension extension;
259*6777b538SAndroid Build Coastguard Worker   if (!ExtractExtensionWithOID(cert,
260*6777b538SAndroid Build Coastguard Worker                                bssl::der::Input(kCanSignHttpExchangesDraftOid),
261*6777b538SAndroid Build Coastguard Worker                                &extension_present, &extension) ||
262*6777b538SAndroid Build Coastguard Worker       !extension_present) {
263*6777b538SAndroid Build Coastguard Worker     return false;
264*6777b538SAndroid Build Coastguard Worker   }
265*6777b538SAndroid Build Coastguard Worker 
266*6777b538SAndroid Build Coastguard Worker   // The extension should have contents NULL.
267*6777b538SAndroid Build Coastguard Worker   static const uint8_t kNull[] = {0x05, 0x00};
268*6777b538SAndroid Build Coastguard Worker   return extension.value == bssl::der::Input(kNull);
269*6777b538SAndroid Build Coastguard Worker }
270*6777b538SAndroid Build Coastguard Worker 
ExtractSignatureAlgorithmsFromDERCert(std::string_view cert,std::string_view * cert_signature_algorithm_sequence,std::string_view * tbs_signature_algorithm_sequence)271*6777b538SAndroid Build Coastguard Worker bool ExtractSignatureAlgorithmsFromDERCert(
272*6777b538SAndroid Build Coastguard Worker     std::string_view cert,
273*6777b538SAndroid Build Coastguard Worker     std::string_view* cert_signature_algorithm_sequence,
274*6777b538SAndroid Build Coastguard Worker     std::string_view* tbs_signature_algorithm_sequence) {
275*6777b538SAndroid Build Coastguard Worker   // From RFC 5280, section 4.1
276*6777b538SAndroid Build Coastguard Worker   //    Certificate  ::=  SEQUENCE  {
277*6777b538SAndroid Build Coastguard Worker   //      tbsCertificate       TBSCertificate,
278*6777b538SAndroid Build Coastguard Worker   //      signatureAlgorithm   AlgorithmIdentifier,
279*6777b538SAndroid Build Coastguard Worker   //      signatureValue       BIT STRING  }
280*6777b538SAndroid Build Coastguard Worker 
281*6777b538SAndroid Build Coastguard Worker   // TBSCertificate  ::=  SEQUENCE  {
282*6777b538SAndroid Build Coastguard Worker   //      version         [0]  EXPLICIT Version DEFAULT v1,
283*6777b538SAndroid Build Coastguard Worker   //      serialNumber         CertificateSerialNumber,
284*6777b538SAndroid Build Coastguard Worker   //      signature            AlgorithmIdentifier,
285*6777b538SAndroid Build Coastguard Worker   //      issuer               Name,
286*6777b538SAndroid Build Coastguard Worker   //      validity             Validity,
287*6777b538SAndroid Build Coastguard Worker   //      subject              Name,
288*6777b538SAndroid Build Coastguard Worker   //      subjectPublicKeyInfo SubjectPublicKeyInfo,
289*6777b538SAndroid Build Coastguard Worker   //      ... }
290*6777b538SAndroid Build Coastguard Worker 
291*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser parser((bssl::der::Input(cert)));
292*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser certificate;
293*6777b538SAndroid Build Coastguard Worker   if (!parser.ReadSequence(&certificate))
294*6777b538SAndroid Build Coastguard Worker     return false;
295*6777b538SAndroid Build Coastguard Worker 
296*6777b538SAndroid Build Coastguard Worker   bssl::der::Parser tbs_certificate;
297*6777b538SAndroid Build Coastguard Worker   if (!certificate.ReadSequence(&tbs_certificate))
298*6777b538SAndroid Build Coastguard Worker     return false;
299*6777b538SAndroid Build Coastguard Worker 
300*6777b538SAndroid Build Coastguard Worker   bool unused;
301*6777b538SAndroid Build Coastguard Worker   if (!tbs_certificate.SkipOptionalTag(
302*6777b538SAndroid Build Coastguard Worker           CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0, &unused)) {
303*6777b538SAndroid Build Coastguard Worker     return false;
304*6777b538SAndroid Build Coastguard Worker   }
305*6777b538SAndroid Build Coastguard Worker 
306*6777b538SAndroid Build Coastguard Worker   // serialNumber
307*6777b538SAndroid Build Coastguard Worker   if (!tbs_certificate.SkipTag(CBS_ASN1_INTEGER)) {
308*6777b538SAndroid Build Coastguard Worker     return false;
309*6777b538SAndroid Build Coastguard Worker   }
310*6777b538SAndroid Build Coastguard Worker   // signature
311*6777b538SAndroid Build Coastguard Worker   bssl::der::Input tbs_algorithm;
312*6777b538SAndroid Build Coastguard Worker   if (!tbs_certificate.ReadRawTLV(&tbs_algorithm))
313*6777b538SAndroid Build Coastguard Worker     return false;
314*6777b538SAndroid Build Coastguard Worker 
315*6777b538SAndroid Build Coastguard Worker   bssl::der::Input cert_algorithm;
316*6777b538SAndroid Build Coastguard Worker   if (!certificate.ReadRawTLV(&cert_algorithm))
317*6777b538SAndroid Build Coastguard Worker     return false;
318*6777b538SAndroid Build Coastguard Worker 
319*6777b538SAndroid Build Coastguard Worker   *cert_signature_algorithm_sequence = cert_algorithm.AsStringView();
320*6777b538SAndroid Build Coastguard Worker   *tbs_signature_algorithm_sequence = tbs_algorithm.AsStringView();
321*6777b538SAndroid Build Coastguard Worker   return true;
322*6777b538SAndroid Build Coastguard Worker }
323*6777b538SAndroid Build Coastguard Worker 
ExtractExtensionFromDERCert(std::string_view cert,std::string_view extension_oid,bool * out_extension_present,bool * out_extension_critical,std::string_view * out_contents)324*6777b538SAndroid Build Coastguard Worker bool ExtractExtensionFromDERCert(std::string_view cert,
325*6777b538SAndroid Build Coastguard Worker                                  std::string_view extension_oid,
326*6777b538SAndroid Build Coastguard Worker                                  bool* out_extension_present,
327*6777b538SAndroid Build Coastguard Worker                                  bool* out_extension_critical,
328*6777b538SAndroid Build Coastguard Worker                                  std::string_view* out_contents) {
329*6777b538SAndroid Build Coastguard Worker   *out_extension_present = false;
330*6777b538SAndroid Build Coastguard Worker   *out_extension_critical = false;
331*6777b538SAndroid Build Coastguard Worker   *out_contents = std::string_view();
332*6777b538SAndroid Build Coastguard Worker 
333*6777b538SAndroid Build Coastguard Worker   bssl::ParsedExtension extension;
334*6777b538SAndroid Build Coastguard Worker   if (!ExtractExtensionWithOID(cert, bssl::der::Input(extension_oid),
335*6777b538SAndroid Build Coastguard Worker                                out_extension_present, &extension)) {
336*6777b538SAndroid Build Coastguard Worker     return false;
337*6777b538SAndroid Build Coastguard Worker   }
338*6777b538SAndroid Build Coastguard Worker   if (!*out_extension_present)
339*6777b538SAndroid Build Coastguard Worker     return true;
340*6777b538SAndroid Build Coastguard Worker 
341*6777b538SAndroid Build Coastguard Worker   *out_extension_critical = extension.critical;
342*6777b538SAndroid Build Coastguard Worker   *out_contents = extension.value.AsStringView();
343*6777b538SAndroid Build Coastguard Worker   return true;
344*6777b538SAndroid Build Coastguard Worker }
345*6777b538SAndroid Build Coastguard Worker 
346*6777b538SAndroid Build Coastguard Worker }  // namespace net::asn1
347