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 |