Chromium Code Reviews| Index: net/base/asn1_util.cc |
| diff --git a/net/base/asn1_util.cc b/net/base/asn1_util.cc |
| index ee25d41be8cb22cb58aca4e406c34b3485f24029..c7e8f3e5a07d8a2626215067bea02c2f515b86ec 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)) |
| @@ -150,17 +176,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 +248,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 +261,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 +271,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 { |
| @@ -253,8 +286,10 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert, |
| if (GetElement(&general_names, kContextSpecific | 6, &url)) { |
| urls_out->push_back(url); |
| } else { |
| - if (!GetElement(&general_names, kAny, NULL)) |
| + if (!GetElement(&general_names, kAny, NULL)) { |
| + urls_out->clear(); |
| return false; |
|
wtc
2011/06/07 18:17:54
I think some other "return false" statements also
|
| + } |
| } |
| } |
| } |