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