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