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