| Index: net/base/asn1_util.cc
|
| diff --git a/net/base/asn1_util.cc b/net/base/asn1_util.cc
|
| index ee25d41be8cb22cb58aca4e406c34b3485f24029..a1e8637f8706a95f0aacdc8ad295e6f785322952 100644
|
| --- a/net/base/asn1_util.cc
|
| +++ b/net/base/asn1_util.cc
|
| @@ -14,11 +14,32 @@ bool ParseElement(base::StringPiece* in,
|
| unsigned *out_header_len) {
|
| const uint8* data = reinterpret_cast<const uint8*>(in->data());
|
|
|
| + // We don't support kAny and kOptional at the same time.
|
| + if ((tag_value & kAny) && (tag_value & kOptional))
|
| + return false;
|
| +
|
| + if (in->empty() && (tag_value & kOptional)) {
|
| + if (out_header_len)
|
| + *out_header_len = 0;
|
| + if (out)
|
| + *out = base::StringPiece();
|
| + return true;
|
| + }
|
| +
|
| if (in->size() < 2)
|
| return false;
|
|
|
| - if (tag_value != kAny && static_cast<unsigned char>(data[0]) != tag_value)
|
| + if (tag_value != kAny &&
|
| + static_cast<unsigned char>(data[0]) != (tag_value & 0xff)) {
|
| + if (tag_value & kOptional) {
|
| + if (out_header_len)
|
| + *out_header_len = 0;
|
| + if (out)
|
| + *out = base::StringPiece();
|
| + return true;
|
| + }
|
| return false;
|
| + }
|
|
|
| size_t len = 0;
|
| if ((data[1] & 0x80) == 0) {
|
| @@ -71,9 +92,9 @@ bool GetElement(base::StringPiece* in,
|
| return true;
|
| }
|
|
|
| -// SeekToSPKI changes |cert| so that it points to a suffix of the original
|
| -// value where the suffix begins at the start of the ASN.1 SubjectPublicKeyInfo
|
| -// value.
|
| +// SeekToSPKI changes |cert| so that it points to a suffix of the
|
| +// TBSCertificate where the suffix begins at the start of the ASN.1
|
| +// SubjectPublicKeyInfo value.
|
| static bool SeekToSPKI(base::StringPiece* cert) {
|
| // From RFC 5280, section 4.1
|
| // Certificate ::= SEQUENCE {
|
| @@ -94,14 +115,19 @@ static bool SeekToSPKI(base::StringPiece* cert) {
|
| if (!GetElement(cert, kSEQUENCE, &certificate))
|
| return false;
|
|
|
| + // We don't allow junk after the certificate.
|
| + if (!cert->empty())
|
| + return false;
|
| +
|
| base::StringPiece tbs_certificate;
|
| if (!GetElement(&certificate, kSEQUENCE, &tbs_certificate))
|
| return false;
|
|
|
| - // The version is optional, so a failure to parse it is fine.
|
| - GetElement(&tbs_certificate,
|
| - kCompound | kContextSpecific | 0,
|
| - NULL);
|
| + if (!GetElement(&tbs_certificate,
|
| + kOptional | kConstructed | kContextSpecific | 0,
|
| + NULL)) {
|
| + return false;
|
| + }
|
|
|
| // serialNumber
|
| if (!GetElement(&tbs_certificate, kINTEGER, NULL))
|
| @@ -134,6 +160,7 @@ bool ExtractSPKIFromDERCert(base::StringPiece cert,
|
| bool ExtractCRLURLsFromDERCert(base::StringPiece cert,
|
| std::vector<base::StringPiece>* urls_out) {
|
| urls_out->clear();
|
| + std::vector<base::StringPiece> tmp_urls_out;
|
|
|
| if (!SeekToSPKI(&cert))
|
| return false;
|
| @@ -150,17 +177,21 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert,
|
| if (!GetElement(&cert, kSEQUENCE, NULL))
|
| return false;
|
| // issuerUniqueID
|
| - GetElement(&cert, kCompound | kContextSpecific | 1, NULL);
|
| + if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 1, NULL))
|
| + return false;
|
| // subjectUniqueID
|
| - GetElement(&cert, kCompound | kContextSpecific | 2, NULL);
|
| + if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 2, NULL))
|
| + return false;
|
|
|
| base::StringPiece extensions_seq;
|
| - if (!GetElement(&cert, kCompound | kContextSpecific | 3,
|
| + if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 3,
|
| &extensions_seq)) {
|
| - // If there are no extensions, then there are no CRL URLs.
|
| - return true;
|
| + return false;
|
| }
|
|
|
| + if (extensions_seq.empty())
|
| + return true;
|
| +
|
| // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
|
| // Extension ::= SEQUENCE {
|
| // extnID OBJECT IDENTIFIER,
|
| @@ -218,7 +249,7 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert,
|
| return false;
|
|
|
| base::StringPiece name;
|
| - if (!GetElement(&distrib_point, kContextSpecific | kCompound | 0,
|
| + if (!GetElement(&distrib_point, kContextSpecific | kConstructed | 0,
|
| &name)) {
|
| // If it doesn't contain a name then we skip it.
|
| continue;
|
| @@ -231,7 +262,8 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert,
|
| continue;
|
| }
|
|
|
| - if (GetElement(&distrib_point, kContextSpecific | kCompound | 2, NULL)) {
|
| + if (GetElement(&distrib_point,
|
| + kContextSpecific | kConstructed | 2, NULL)) {
|
| // If it contains a alternative issuer, then we skip it.
|
| continue;
|
| }
|
| @@ -240,8 +272,10 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert,
|
| // fullName [0] GeneralNames,
|
| // nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
|
| base::StringPiece general_names;
|
| - if (!GetElement(&name, kContextSpecific | kCompound | 0, &general_names))
|
| + if (!GetElement(&name,
|
| + kContextSpecific | kConstructed | 0, &general_names)) {
|
| continue;
|
| + }
|
|
|
| // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
|
| // GeneralName ::= CHOICE {
|
| @@ -251,7 +285,7 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert,
|
| while (general_names.size() > 0) {
|
| base::StringPiece url;
|
| if (GetElement(&general_names, kContextSpecific | 6, &url)) {
|
| - urls_out->push_back(url);
|
| + tmp_urls_out.push_back(url);
|
| } else {
|
| if (!GetElement(&general_names, kAny, NULL))
|
| return false;
|
| @@ -260,6 +294,7 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert,
|
| }
|
| }
|
|
|
| + urls_out->swap(tmp_urls_out);
|
| return true;
|
| }
|
|
|
|
|