15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/asn1_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace asn1 {
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseElement(base::StringPiece* in,
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  unsigned tag_value,
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  base::StringPiece* out,
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  unsigned *out_header_len) {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8* data = reinterpret_cast<const uint8*>(in->data());
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't support kAny and kOptional at the same time.
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((tag_value & kAny) && (tag_value & kOptional))
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (in->empty() && (tag_value & kOptional)) {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (out_header_len)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *out_header_len = 0;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (out)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *out = base::StringPiece();
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (in->size() < 2)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tag_value != kAny &&
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<unsigned char>(data[0]) != (tag_value & 0xff)) {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (tag_value & kOptional) {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (out_header_len)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *out_header_len = 0;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (out)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *out = base::StringPiece();
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t len = 0;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((data[1] & 0x80) == 0) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // short form length
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (out_header_len)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *out_header_len = 2;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = static_cast<size_t>(data[1]) + 2;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // long form length
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const unsigned num_bytes = data[1] & 0x7f;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (num_bytes == 0 || num_bytes > 2)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (in->size() < 2 + num_bytes)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len = data[2];
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (num_bytes == 2) {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (len == 0) {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the length encoding must be minimal.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      len <<= 8;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      len += data[3];
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (len < 128) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the length should have been encoded in short form. This distinguishes
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // DER from BER encoding.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (out_header_len)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *out_header_len = 2 + num_bytes;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    len += 2 + num_bytes;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (in->size() < len)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (out)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out = base::StringPiece(in->data(), len);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  in->remove_prefix(len);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetElement(base::StringPiece* in,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                unsigned tag_value,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                base::StringPiece* out) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned header_len;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseElement(in, tag_value, out, &header_len))
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (out)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    out->remove_prefix(header_len);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SeekToSPKI changes |cert| so that it points to a suffix of the
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TBSCertificate where the suffix begins at the start of the ASN.1
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SubjectPublicKeyInfo value.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool SeekToSPKI(base::StringPiece* cert) {
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From RFC 5280, section 4.1
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    Certificate  ::=  SEQUENCE  {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      tbsCertificate       TBSCertificate,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      signatureAlgorithm   AlgorithmIdentifier,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      signatureValue       BIT STRING  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TBSCertificate  ::=  SEQUENCE  {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      version         [0]  EXPLICIT Version DEFAULT v1,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      serialNumber         CertificateSerialNumber,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      signature            AlgorithmIdentifier,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      issuer               Name,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      validity             Validity,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      subject              Name,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      subjectPublicKeyInfo SubjectPublicKeyInfo,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece certificate;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(cert, kSEQUENCE, &certificate))
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't allow junk after the certificate.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!cert->empty())
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece tbs_certificate;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&certificate, kSEQUENCE, &tbs_certificate))
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&tbs_certificate,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  kOptional | kConstructed | kContextSpecific | 0,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  NULL)) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // serialNumber
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&tbs_certificate, kINTEGER, NULL))
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // signature
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&tbs_certificate, kSEQUENCE, NULL))
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // issuer
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&tbs_certificate, kSEQUENCE, NULL))
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // validity
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&tbs_certificate, kSEQUENCE, NULL))
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // subject
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&tbs_certificate, kSEQUENCE, NULL))
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *cert = tbs_certificate;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtractSPKIFromDERCert(base::StringPiece cert,
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            base::StringPiece* spki_out) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SeekToSPKI(&cert))
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseElement(&cert, kSEQUENCE, spki_out, NULL))
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtractSubjectPublicKeyFromSPKI(base::StringPiece spki,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     base::StringPiece* spk_out) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From RFC 5280, Section 4.1
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   SubjectPublicKeyInfo  ::=  SEQUENCE  {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     algorithm            AlgorithmIdentifier,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     subjectPublicKey     BIT STRING  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   AlgorithmIdentifier  ::=  SEQUENCE  {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     algorithm               OBJECT IDENTIFIER,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //     parameters              ANY DEFINED BY algorithm OPTIONAL  }
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Step into SubjectPublicKeyInfo sequence.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece spki_contents;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!asn1::GetElement(&spki, asn1::kSEQUENCE, &spki_contents))
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Step over algorithm field (a SEQUENCE).
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece algorithm;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!asn1::GetElement(&spki_contents, asn1::kSEQUENCE, &algorithm))
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extract the subjectPublicKey field.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!asn1::GetElement(&spki_contents, asn1::kBITSTRING, spk_out))
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtractCRLURLsFromDERCert(base::StringPiece cert,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               std::vector<base::StringPiece>* urls_out) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  urls_out->clear();
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<base::StringPiece> tmp_urls_out;
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SeekToSPKI(&cert))
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From RFC 5280, section 4.1
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TBSCertificate  ::=  SEQUENCE  {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      ...
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      subjectPublicKeyInfo SubjectPublicKeyInfo,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      extensions      [3]  EXPLICIT Extensions OPTIONAL
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // subjectPublicKeyInfo
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&cert, kSEQUENCE, NULL))
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // issuerUniqueID
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 1, NULL))
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // subjectUniqueID
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 2, NULL))
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece extensions_seq;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 3,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  &extensions_seq)) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (extensions_seq.empty())
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extension   ::=  SEQUENCE  {
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      extnID      OBJECT IDENTIFIER,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      critical    BOOLEAN DEFAULT FALSE,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //      extnValue   OCTET STRING
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |extensions_seq| was EXPLICITly tagged, so we still need to remove the
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ASN.1 SEQUENCE header.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringPiece extensions;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetElement(&extensions_seq, kSEQUENCE, &extensions))
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (extensions.size() > 0) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringPiece extension;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetElement(&extensions, kSEQUENCE, &extension))
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringPiece oid;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetElement(&extension, kOID, &oid))
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // kCRLDistributionPointsOID is the DER encoding of the OID for the X.509
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // CRL Distribution Points extension.
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static const uint8 kCRLDistributionPointsOID[] = {0x55, 0x1d, 0x1f};
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (oid.size() != sizeof(kCRLDistributionPointsOID) ||
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcmp(oid.data(), kCRLDistributionPointsOID, oid.size()) != 0) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // critical
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetElement(&extension, kBOOLEAN, NULL);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // extnValue
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringPiece extension_value;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetElement(&extension, kOCTETSTRING, &extension_value))
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // RFC 5280, section 4.2.1.13.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // DistributionPoint ::= SEQUENCE {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //  distributionPoint       [0]     DistributionPointName OPTIONAL,
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //  reasons                 [1]     ReasonFlags OPTIONAL,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //  cRLIssuer               [2]     GeneralNames OPTIONAL }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringPiece distribution_points;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetElement(&extension_value, kSEQUENCE, &distribution_points))
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (distribution_points.size() > 0) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPiece distrib_point;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!GetElement(&distribution_points, kSEQUENCE, &distrib_point))
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPiece name;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!GetElement(&distrib_point, kContextSpecific | kConstructed | 0,
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      &name)) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If it doesn't contain a name then we skip it.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (GetElement(&distrib_point, kContextSpecific | 1, NULL)) {
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If it contains a subset of reasons then we skip it. We aren't
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // interested in subsets of CRLs and the RFC states that there MUST be
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // a CRL that covers all reasons.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (GetElement(&distrib_point,
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     kContextSpecific | kConstructed | 2, NULL)) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If it contains a alternative issuer, then we skip it.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // DistributionPointName ::= CHOICE {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //   fullName                [0]     GeneralNames,
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //   nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::StringPiece general_names;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!GetElement(&name,
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      kContextSpecific | kConstructed | 0, &general_names)) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // GeneralName ::= CHOICE {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //   ...
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //   uniformResourceIdentifier [6]  IA5String,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //   ...
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (general_names.size() > 0) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringPiece url;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (GetElement(&general_names, kContextSpecific | 6, &url)) {
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          tmp_urls_out.push_back(url);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        } else {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (!GetElement(&general_names, kAny, NULL))
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  urls_out->swap(tmp_urls_out);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace asn1
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net
332