| Index: net/base/asn1_util.cc
|
| diff --git a/net/base/asn1_util.cc b/net/base/asn1_util.cc
|
| deleted file mode 100644
|
| index 2f606b626277d91354a7107eebdd690c125b3017..0000000000000000000000000000000000000000
|
| --- a/net/base/asn1_util.cc
|
| +++ /dev/null
|
| @@ -1,331 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "net/base/asn1_util.h"
|
| -
|
| -namespace net {
|
| -
|
| -namespace asn1 {
|
| -
|
| -bool ParseElement(base::StringPiece* in,
|
| - unsigned tag_value,
|
| - base::StringPiece* out,
|
| - 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 & 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) {
|
| - // short form length
|
| - if (out_header_len)
|
| - *out_header_len = 2;
|
| - len = static_cast<size_t>(data[1]) + 2;
|
| - } else {
|
| - // long form length
|
| - const unsigned num_bytes = data[1] & 0x7f;
|
| - if (num_bytes == 0 || num_bytes > 2)
|
| - return false;
|
| - if (in->size() < 2 + num_bytes)
|
| - return false;
|
| - len = data[2];
|
| - if (num_bytes == 2) {
|
| - if (len == 0) {
|
| - // the length encoding must be minimal.
|
| - return false;
|
| - }
|
| - len <<= 8;
|
| - len += data[3];
|
| - }
|
| - if (len < 128) {
|
| - // the length should have been encoded in short form. This distinguishes
|
| - // DER from BER encoding.
|
| - return false;
|
| - }
|
| - if (out_header_len)
|
| - *out_header_len = 2 + num_bytes;
|
| - len += 2 + num_bytes;
|
| - }
|
| -
|
| - if (in->size() < len)
|
| - return false;
|
| - if (out)
|
| - *out = base::StringPiece(in->data(), len);
|
| - in->remove_prefix(len);
|
| - return true;
|
| -}
|
| -
|
| -bool GetElement(base::StringPiece* in,
|
| - unsigned tag_value,
|
| - base::StringPiece* out) {
|
| - unsigned header_len;
|
| - if (!ParseElement(in, tag_value, out, &header_len))
|
| - return false;
|
| - if (out)
|
| - out->remove_prefix(header_len);
|
| - return true;
|
| -}
|
| -
|
| -// 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 {
|
| - // tbsCertificate TBSCertificate,
|
| - // signatureAlgorithm AlgorithmIdentifier,
|
| - // signatureValue BIT STRING }
|
| -
|
| - // TBSCertificate ::= SEQUENCE {
|
| - // version [0] EXPLICIT Version DEFAULT v1,
|
| - // serialNumber CertificateSerialNumber,
|
| - // signature AlgorithmIdentifier,
|
| - // issuer Name,
|
| - // validity Validity,
|
| - // subject Name,
|
| - // subjectPublicKeyInfo SubjectPublicKeyInfo,
|
| -
|
| - base::StringPiece certificate;
|
| - 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;
|
| -
|
| - if (!GetElement(&tbs_certificate,
|
| - kOptional | kConstructed | kContextSpecific | 0,
|
| - NULL)) {
|
| - return false;
|
| - }
|
| -
|
| - // serialNumber
|
| - if (!GetElement(&tbs_certificate, kINTEGER, NULL))
|
| - return false;
|
| - // signature
|
| - if (!GetElement(&tbs_certificate, kSEQUENCE, NULL))
|
| - return false;
|
| - // issuer
|
| - if (!GetElement(&tbs_certificate, kSEQUENCE, NULL))
|
| - return false;
|
| - // validity
|
| - if (!GetElement(&tbs_certificate, kSEQUENCE, NULL))
|
| - return false;
|
| - // subject
|
| - if (!GetElement(&tbs_certificate, kSEQUENCE, NULL))
|
| - return false;
|
| - *cert = tbs_certificate;
|
| - return true;
|
| -}
|
| -
|
| -bool ExtractSPKIFromDERCert(base::StringPiece cert,
|
| - base::StringPiece* spki_out) {
|
| - if (!SeekToSPKI(&cert))
|
| - return false;
|
| - if (!ParseElement(&cert, kSEQUENCE, spki_out, NULL))
|
| - return false;
|
| - return true;
|
| -}
|
| -
|
| -bool ExtractSubjectPublicKeyFromSPKI(base::StringPiece spki,
|
| - base::StringPiece* spk_out) {
|
| - // From RFC 5280, Section 4.1
|
| - // SubjectPublicKeyInfo ::= SEQUENCE {
|
| - // algorithm AlgorithmIdentifier,
|
| - // subjectPublicKey BIT STRING }
|
| - //
|
| - // AlgorithmIdentifier ::= SEQUENCE {
|
| - // algorithm OBJECT IDENTIFIER,
|
| - // parameters ANY DEFINED BY algorithm OPTIONAL }
|
| -
|
| - // Step into SubjectPublicKeyInfo sequence.
|
| - base::StringPiece spki_contents;
|
| - if (!asn1::GetElement(&spki, asn1::kSEQUENCE, &spki_contents))
|
| - return false;
|
| -
|
| - // Step over algorithm field (a SEQUENCE).
|
| - base::StringPiece algorithm;
|
| - if (!asn1::GetElement(&spki_contents, asn1::kSEQUENCE, &algorithm))
|
| - return false;
|
| -
|
| - // Extract the subjectPublicKey field.
|
| - if (!asn1::GetElement(&spki_contents, asn1::kBITSTRING, spk_out))
|
| - return false;
|
| - return true;
|
| -}
|
| -
|
| -
|
| -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;
|
| -
|
| - // From RFC 5280, section 4.1
|
| - // TBSCertificate ::= SEQUENCE {
|
| - // ...
|
| - // subjectPublicKeyInfo SubjectPublicKeyInfo,
|
| - // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
|
| - // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
|
| - // extensions [3] EXPLICIT Extensions OPTIONAL
|
| -
|
| - // subjectPublicKeyInfo
|
| - if (!GetElement(&cert, kSEQUENCE, NULL))
|
| - return false;
|
| - // issuerUniqueID
|
| - if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 1, NULL))
|
| - return false;
|
| - // subjectUniqueID
|
| - if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 2, NULL))
|
| - return false;
|
| -
|
| - base::StringPiece extensions_seq;
|
| - if (!GetElement(&cert, kOptional | kConstructed | kContextSpecific | 3,
|
| - &extensions_seq)) {
|
| - return false;
|
| - }
|
| -
|
| - if (extensions_seq.empty())
|
| - return true;
|
| -
|
| - // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
|
| - // Extension ::= SEQUENCE {
|
| - // extnID OBJECT IDENTIFIER,
|
| - // critical BOOLEAN DEFAULT FALSE,
|
| - // extnValue OCTET STRING
|
| -
|
| - // |extensions_seq| was EXPLICITly tagged, so we still need to remove the
|
| - // ASN.1 SEQUENCE header.
|
| - base::StringPiece extensions;
|
| - if (!GetElement(&extensions_seq, kSEQUENCE, &extensions))
|
| - return false;
|
| -
|
| - while (extensions.size() > 0) {
|
| - base::StringPiece extension;
|
| - if (!GetElement(&extensions, kSEQUENCE, &extension))
|
| - return false;
|
| -
|
| - base::StringPiece oid;
|
| - if (!GetElement(&extension, kOID, &oid))
|
| - return false;
|
| -
|
| - // kCRLDistributionPointsOID is the DER encoding of the OID for the X.509
|
| - // CRL Distribution Points extension.
|
| - static const uint8 kCRLDistributionPointsOID[] = {0x55, 0x1d, 0x1f};
|
| -
|
| - if (oid.size() != sizeof(kCRLDistributionPointsOID) ||
|
| - memcmp(oid.data(), kCRLDistributionPointsOID, oid.size()) != 0) {
|
| - continue;
|
| - }
|
| -
|
| - // critical
|
| - GetElement(&extension, kBOOLEAN, NULL);
|
| -
|
| - // extnValue
|
| - base::StringPiece extension_value;
|
| - if (!GetElement(&extension, kOCTETSTRING, &extension_value))
|
| - return false;
|
| -
|
| - // RFC 5280, section 4.2.1.13.
|
| - //
|
| - // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
|
| - //
|
| - // DistributionPoint ::= SEQUENCE {
|
| - // distributionPoint [0] DistributionPointName OPTIONAL,
|
| - // reasons [1] ReasonFlags OPTIONAL,
|
| - // cRLIssuer [2] GeneralNames OPTIONAL }
|
| -
|
| - base::StringPiece distribution_points;
|
| - if (!GetElement(&extension_value, kSEQUENCE, &distribution_points))
|
| - return false;
|
| -
|
| - while (distribution_points.size() > 0) {
|
| - base::StringPiece distrib_point;
|
| - if (!GetElement(&distribution_points, kSEQUENCE, &distrib_point))
|
| - return false;
|
| -
|
| - base::StringPiece name;
|
| - if (!GetElement(&distrib_point, kContextSpecific | kConstructed | 0,
|
| - &name)) {
|
| - // If it doesn't contain a name then we skip it.
|
| - continue;
|
| - }
|
| -
|
| - if (GetElement(&distrib_point, kContextSpecific | 1, NULL)) {
|
| - // If it contains a subset of reasons then we skip it. We aren't
|
| - // interested in subsets of CRLs and the RFC states that there MUST be
|
| - // a CRL that covers all reasons.
|
| - continue;
|
| - }
|
| -
|
| - if (GetElement(&distrib_point,
|
| - kContextSpecific | kConstructed | 2, NULL)) {
|
| - // If it contains a alternative issuer, then we skip it.
|
| - continue;
|
| - }
|
| -
|
| - // DistributionPointName ::= CHOICE {
|
| - // fullName [0] GeneralNames,
|
| - // nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
|
| - base::StringPiece general_names;
|
| - if (!GetElement(&name,
|
| - kContextSpecific | kConstructed | 0, &general_names)) {
|
| - continue;
|
| - }
|
| -
|
| - // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
|
| - // GeneralName ::= CHOICE {
|
| - // ...
|
| - // uniformResourceIdentifier [6] IA5String,
|
| - // ...
|
| - while (general_names.size() > 0) {
|
| - base::StringPiece url;
|
| - if (GetElement(&general_names, kContextSpecific | 6, &url)) {
|
| - tmp_urls_out.push_back(url);
|
| - } else {
|
| - if (!GetElement(&general_names, kAny, NULL))
|
| - return false;
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - urls_out->swap(tmp_urls_out);
|
| - return true;
|
| -}
|
| -
|
| -} // namespace asn1
|
| -
|
| -} // namespace net
|
|
|