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