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