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