|  | // Copyright 2015 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "parse_certificate.h" | 
|  |  | 
|  | #include <optional> | 
|  | #include <utility> | 
|  |  | 
|  | #include <openssl/base.h> | 
|  | #include <openssl/bytestring.h> | 
|  |  | 
|  | #include "cert_error_params.h" | 
|  | #include "cert_errors.h" | 
|  | #include "general_names.h" | 
|  | #include "input.h" | 
|  | #include "parse_values.h" | 
|  | #include "parser.h" | 
|  | #include "string_util.h" | 
|  |  | 
|  | BSSL_NAMESPACE_BEGIN | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | DEFINE_CERT_ERROR_ID(kCertificateNotSequence, | 
|  | "Failed parsing Certificate SEQUENCE"); | 
|  | DEFINE_CERT_ERROR_ID(kUnconsumedDataInsideCertificateSequence, | 
|  | "Unconsumed data inside Certificate SEQUENCE"); | 
|  | DEFINE_CERT_ERROR_ID(kUnconsumedDataAfterCertificateSequence, | 
|  | "Unconsumed data after Certificate SEQUENCE"); | 
|  | DEFINE_CERT_ERROR_ID(kTbsCertificateNotSequence, | 
|  | "Couldn't read tbsCertificate as SEQUENCE"); | 
|  | DEFINE_CERT_ERROR_ID( | 
|  | kSignatureAlgorithmNotSequence, | 
|  | "Couldn't read Certificate.signatureAlgorithm as SEQUENCE"); | 
|  | DEFINE_CERT_ERROR_ID(kSignatureValueNotBitString, | 
|  | "Couldn't read Certificate.signatureValue as BIT STRING"); | 
|  | DEFINE_CERT_ERROR_ID(kUnconsumedDataInsideTbsCertificateSequence, | 
|  | "Unconsumed data inside TBSCertificate"); | 
|  | DEFINE_CERT_ERROR_ID(kTbsNotSequence, "Failed parsing TBSCertificate SEQUENCE"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedReadingVersion, "Failed reading version"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedParsingVersion, "Failed parsing version"); | 
|  | DEFINE_CERT_ERROR_ID(kVersionExplicitlyV1, | 
|  | "Version explicitly V1 (should be omitted)"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedReadingSerialNumber, "Failed reading serialNumber"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedReadingSignatureValue, "Failed reading signature"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedReadingIssuer, "Failed reading issuer"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedReadingValidity, "Failed reading validity"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedParsingValidity, "Failed parsing validity"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedReadingSubject, "Failed reading subject"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedReadingSpki, "Failed reading subjectPublicKeyInfo"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedReadingIssuerUniqueId, | 
|  | "Failed reading issuerUniqueId"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedParsingIssuerUniqueId, | 
|  | "Failed parsing issuerUniqueId"); | 
|  | DEFINE_CERT_ERROR_ID( | 
|  | kIssuerUniqueIdNotExpected, | 
|  | "Unexpected issuerUniqueId (must be V2 or V3 certificate)"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedReadingSubjectUniqueId, | 
|  | "Failed reading subjectUniqueId"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedParsingSubjectUniqueId, | 
|  | "Failed parsing subjectUniqueId"); | 
|  | DEFINE_CERT_ERROR_ID( | 
|  | kSubjectUniqueIdNotExpected, | 
|  | "Unexpected subjectUniqueId (must be V2 or V3 certificate)"); | 
|  | DEFINE_CERT_ERROR_ID(kFailedReadingExtensions, | 
|  | "Failed reading extensions SEQUENCE"); | 
|  | DEFINE_CERT_ERROR_ID(kUnexpectedExtensions, | 
|  | "Unexpected extensions (must be V3 certificate)"); | 
|  | DEFINE_CERT_ERROR_ID(kSerialNumberIsNegative, "Serial number is negative"); | 
|  | DEFINE_CERT_ERROR_ID(kSerialNumberIsZero, "Serial number is zero"); | 
|  | DEFINE_CERT_ERROR_ID(kSerialNumberLengthOver20, | 
|  | "Serial number is longer than 20 octets"); | 
|  | DEFINE_CERT_ERROR_ID(kSerialNumberNotValidInteger, | 
|  | "Serial number is not a valid INTEGER"); | 
|  |  | 
|  | // Returns true if |input| is a SEQUENCE and nothing else. | 
|  | [[nodiscard]] bool IsSequenceTLV(der::Input input) { | 
|  | der::Parser parser(input); | 
|  | der::Parser unused_sequence_parser; | 
|  | if (!parser.ReadSequence(&unused_sequence_parser)) { | 
|  | return false; | 
|  | } | 
|  | // Should by a single SEQUENCE by definition of the function. | 
|  | return !parser.HasMore(); | 
|  | } | 
|  |  | 
|  | // Reads a SEQUENCE from |parser| and writes the full tag-length-value into | 
|  | // |out|. On failure |parser| may or may not have been advanced. | 
|  | [[nodiscard]] bool ReadSequenceTLV(der::Parser *parser, der::Input *out) { | 
|  | return parser->ReadRawTLV(out) && IsSequenceTLV(*out); | 
|  | } | 
|  |  | 
|  | // Parses a Version according to RFC 5280: | 
|  | // | 
|  | //     Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  } | 
|  | // | 
|  | // No value other that v1, v2, or v3 is allowed (and if given will fail). RFC | 
|  | // 5280 minimally requires the handling of v3 (and overwhelmingly these are the | 
|  | // certificate versions in use today): | 
|  | // | 
|  | //     Implementations SHOULD be prepared to accept any version certificate. | 
|  | //     At a minimum, conforming implementations MUST recognize version 3 | 
|  | //     certificates. | 
|  | [[nodiscard]] bool ParseVersion(der::Input in, CertificateVersion *version) { | 
|  | der::Parser parser(in); | 
|  | uint64_t version64; | 
|  | if (!parser.ReadUint64(&version64)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | switch (version64) { | 
|  | case 0: | 
|  | *version = CertificateVersion::V1; | 
|  | break; | 
|  | case 1: | 
|  | *version = CertificateVersion::V2; | 
|  | break; | 
|  | case 2: | 
|  | *version = CertificateVersion::V3; | 
|  | break; | 
|  | default: | 
|  | // Don't allow any other version identifier. | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // By definition the input to this function was a single INTEGER, so there | 
|  | // shouldn't be anything else after it. | 
|  | return !parser.HasMore(); | 
|  | } | 
|  |  | 
|  | // Returns true if every bit in |bits| is zero (including empty). | 
|  | [[nodiscard]] bool BitStringIsAllZeros(const der::BitString &bits) { | 
|  | // Note that it is OK to read from the unused bits, since BitString parsing | 
|  | // guarantees they are all zero. | 
|  | for (uint8_t b : bits.bytes()) { | 
|  | if (b != 0) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // Parses a DistributionPointName. | 
|  | // | 
|  | // From RFC 5280: | 
|  | // | 
|  | //    DistributionPointName ::= CHOICE { | 
|  | //      fullName                [0]     GeneralNames, | 
|  | //      nameRelativeToCRLIssuer [1]     RelativeDistinguishedName } | 
|  | bool ParseDistributionPointName(der::Input dp_name, | 
|  | ParsedDistributionPoint *distribution_point) { | 
|  | der::Parser parser(dp_name); | 
|  | std::optional<der::Input> der_full_name; | 
|  | if (!parser.ReadOptionalTag( | 
|  | CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, | 
|  | &der_full_name)) { | 
|  | return false; | 
|  | } | 
|  | if (der_full_name) { | 
|  | // TODO(mattm): surface the CertErrors. | 
|  | CertErrors errors; | 
|  | distribution_point->distribution_point_fullname = | 
|  | GeneralNames::CreateFromValue(*der_full_name, &errors); | 
|  | if (!distribution_point->distribution_point_fullname) { | 
|  | return false; | 
|  | } | 
|  | return !parser.HasMore(); | 
|  | } | 
|  |  | 
|  | if (!parser.ReadOptionalTag( | 
|  | CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1, | 
|  | &distribution_point | 
|  | ->distribution_point_name_relative_to_crl_issuer)) { | 
|  | return false; | 
|  | } | 
|  | if (distribution_point->distribution_point_name_relative_to_crl_issuer) { | 
|  | return !parser.HasMore(); | 
|  | } | 
|  |  | 
|  | // The CHOICE must contain either fullName or nameRelativeToCRLIssuer. | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // RFC 5280, section 4.2.1.13. | 
|  | // | 
|  | // DistributionPoint ::= SEQUENCE { | 
|  | //  distributionPoint       [0]     DistributionPointName OPTIONAL, | 
|  | //  reasons                 [1]     ReasonFlags OPTIONAL, | 
|  | //  cRLIssuer               [2]     GeneralNames OPTIONAL } | 
|  | bool ParseAndAddDistributionPoint( | 
|  | der::Parser *parser, | 
|  | std::vector<ParsedDistributionPoint> *distribution_points) { | 
|  | ParsedDistributionPoint distribution_point; | 
|  |  | 
|  | // DistributionPoint ::= SEQUENCE { | 
|  | der::Parser distrib_point_parser; | 
|  | if (!parser->ReadSequence(&distrib_point_parser)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //  distributionPoint       [0]     DistributionPointName OPTIONAL, | 
|  | std::optional<der::Input> distribution_point_name; | 
|  | if (!distrib_point_parser.ReadOptionalTag( | 
|  | CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, | 
|  | &distribution_point_name)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (distribution_point_name && | 
|  | !ParseDistributionPointName(*distribution_point_name, | 
|  | &distribution_point)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //  reasons                 [1]     ReasonFlags OPTIONAL, | 
|  | if (!distrib_point_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1, | 
|  | &distribution_point.reasons)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //  cRLIssuer               [2]     GeneralNames OPTIONAL } | 
|  | if (!distrib_point_parser.ReadOptionalTag( | 
|  | CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 2, | 
|  | &distribution_point.crl_issuer)) { | 
|  | return false; | 
|  | } | 
|  | // TODO(eroman): Parse "cRLIssuer"? | 
|  |  | 
|  | // RFC 5280, section 4.2.1.13: | 
|  | // either distributionPoint or cRLIssuer MUST be present. | 
|  | if (!distribution_point_name && !distribution_point.crl_issuer) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (distrib_point_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | distribution_points->push_back(std::move(distribution_point)); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | ParsedTbsCertificate::ParsedTbsCertificate() = default; | 
|  |  | 
|  | ParsedTbsCertificate::ParsedTbsCertificate(ParsedTbsCertificate &&other) = | 
|  | default; | 
|  |  | 
|  | ParsedTbsCertificate::~ParsedTbsCertificate() = default; | 
|  |  | 
|  | bool VerifySerialNumber(der::Input value, bool warnings_only, | 
|  | CertErrors *errors) { | 
|  | // If |warnings_only| was set to true, the exact same errors will be logged, | 
|  | // only they will be logged with a lower severity (warning rather than error). | 
|  | CertError::Severity error_severity = | 
|  | warnings_only ? CertError::SEVERITY_WARNING : CertError::SEVERITY_HIGH; | 
|  |  | 
|  | bool negative; | 
|  | if (!der::IsValidInteger(value, &negative)) { | 
|  | errors->Add(error_severity, kSerialNumberNotValidInteger, nullptr); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // RFC 5280 section 4.1.2.2: | 
|  | // | 
|  | //    Note: Non-conforming CAs may issue certificates with serial numbers | 
|  | //    that are negative or zero.  Certificate users SHOULD be prepared to | 
|  | //    gracefully handle such certificates. | 
|  | if (negative) { | 
|  | errors->AddWarning(kSerialNumberIsNegative); | 
|  | } | 
|  | if (value.size() == 1 && value[0] == 0) { | 
|  | errors->AddWarning(kSerialNumberIsZero); | 
|  | } | 
|  |  | 
|  | // RFC 5280 section 4.1.2.2: | 
|  | // | 
|  | //    Certificate users MUST be able to handle serialNumber values up to 20 | 
|  | //    octets. Conforming CAs MUST NOT use serialNumber values longer than 20 | 
|  | //    octets. | 
|  | if (value.size() > 20) { | 
|  | errors->Add(error_severity, kSerialNumberLengthOver20, | 
|  | CreateCertErrorParams1SizeT("length", value.size())); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool ReadUTCOrGeneralizedTime(der::Parser *parser, der::GeneralizedTime *out) { | 
|  | der::Input value; | 
|  | CBS_ASN1_TAG tag; | 
|  |  | 
|  | if (!parser->ReadTagAndValue(&tag, &value)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (tag == CBS_ASN1_UTCTIME) { | 
|  | return der::ParseUTCTime(value, out); | 
|  | } | 
|  |  | 
|  | if (tag == CBS_ASN1_GENERALIZEDTIME) { | 
|  | return der::ParseGeneralizedTime(value, out); | 
|  | } | 
|  |  | 
|  | // Unrecognized tag. | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool ParseValidity(der::Input validity_tlv, der::GeneralizedTime *not_before, | 
|  | der::GeneralizedTime *not_after) { | 
|  | der::Parser parser(validity_tlv); | 
|  |  | 
|  | //     Validity ::= SEQUENCE { | 
|  | der::Parser validity_parser; | 
|  | if (!parser.ReadSequence(&validity_parser)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //          notBefore      Time, | 
|  | if (!ReadUTCOrGeneralizedTime(&validity_parser, not_before)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //          notAfter       Time } | 
|  | if (!ReadUTCOrGeneralizedTime(&validity_parser, not_after)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // By definition the input was a single Validity sequence, so there shouldn't | 
|  | // be unconsumed data. | 
|  | if (parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // The Validity type does not have an extension point. | 
|  | if (validity_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Note that RFC 5280 doesn't require notBefore to be <= | 
|  | // notAfter, so that will not be considered a "parsing" error here. Instead it | 
|  | // will be considered an expired certificate later when testing against the | 
|  | // current timestamp. | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool ParseCertificate(der::Input certificate_tlv, | 
|  | der::Input *out_tbs_certificate_tlv, | 
|  | der::Input *out_signature_algorithm_tlv, | 
|  | der::BitString *out_signature_value, | 
|  | CertErrors *out_errors) { | 
|  | // |out_errors| is optional. But ensure it is non-null for the remainder of | 
|  | // this function. | 
|  | CertErrors unused_errors; | 
|  | if (!out_errors) { | 
|  | out_errors = &unused_errors; | 
|  | } | 
|  |  | 
|  | der::Parser parser(certificate_tlv); | 
|  |  | 
|  | //   Certificate  ::=  SEQUENCE  { | 
|  | der::Parser certificate_parser; | 
|  | if (!parser.ReadSequence(&certificate_parser)) { | 
|  | out_errors->AddError(kCertificateNotSequence); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //        tbsCertificate       TBSCertificate, | 
|  | if (!ReadSequenceTLV(&certificate_parser, out_tbs_certificate_tlv)) { | 
|  | out_errors->AddError(kTbsCertificateNotSequence); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //        signatureAlgorithm   AlgorithmIdentifier, | 
|  | if (!ReadSequenceTLV(&certificate_parser, out_signature_algorithm_tlv)) { | 
|  | out_errors->AddError(kSignatureAlgorithmNotSequence); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //        signatureValue       BIT STRING  } | 
|  | std::optional<der::BitString> signature_value = | 
|  | certificate_parser.ReadBitString(); | 
|  | if (!signature_value) { | 
|  | out_errors->AddError(kSignatureValueNotBitString); | 
|  | return false; | 
|  | } | 
|  | *out_signature_value = signature_value.value(); | 
|  |  | 
|  | // There isn't an extension point at the end of Certificate. | 
|  | if (certificate_parser.HasMore()) { | 
|  | out_errors->AddError(kUnconsumedDataInsideCertificateSequence); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // By definition the input was a single Certificate, so there shouldn't be | 
|  | // unconsumed data. | 
|  | if (parser.HasMore()) { | 
|  | out_errors->AddError(kUnconsumedDataAfterCertificateSequence); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // From RFC 5280 section 4.1: | 
|  | // | 
|  | //   TBSCertificate  ::=  SEQUENCE  { | 
|  | //        version         [0]  EXPLICIT Version DEFAULT v1, | 
|  | //        serialNumber         CertificateSerialNumber, | 
|  | //        signature            AlgorithmIdentifier, | 
|  | //        issuer               Name, | 
|  | //        validity             Validity, | 
|  | //        subject              Name, | 
|  | //        subjectPublicKeyInfo SubjectPublicKeyInfo, | 
|  | //        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL, | 
|  | //                             -- If present, version MUST be v2 or v3 | 
|  | //        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL, | 
|  | //                             -- If present, version MUST be v2 or v3 | 
|  | //        extensions      [3]  EXPLICIT Extensions OPTIONAL | 
|  | //                             -- If present, version MUST be v3 | 
|  | //        } | 
|  | bool ParseTbsCertificate(der::Input tbs_tlv, | 
|  | const ParseCertificateOptions &options, | 
|  | ParsedTbsCertificate *out, CertErrors *errors) { | 
|  | // The rest of this function assumes that |errors| is non-null. | 
|  | CertErrors unused_errors; | 
|  | if (!errors) { | 
|  | errors = &unused_errors; | 
|  | } | 
|  |  | 
|  | // TODO(crbug.com/634443): Add useful error information to |errors|. | 
|  |  | 
|  | der::Parser parser(tbs_tlv); | 
|  |  | 
|  | //   TBSCertificate  ::=  SEQUENCE  { | 
|  | der::Parser tbs_parser; | 
|  | if (!parser.ReadSequence(&tbs_parser)) { | 
|  | errors->AddError(kTbsNotSequence); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //        version         [0]  EXPLICIT Version DEFAULT v1, | 
|  | std::optional<der::Input> version; | 
|  | if (!tbs_parser.ReadOptionalTag( | 
|  | CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0, &version)) { | 
|  | errors->AddError(kFailedReadingVersion); | 
|  | return false; | 
|  | } | 
|  | if (version) { | 
|  | if (!ParseVersion(version.value(), &out->version)) { | 
|  | errors->AddError(kFailedParsingVersion); | 
|  | return false; | 
|  | } | 
|  | if (out->version == CertificateVersion::V1) { | 
|  | errors->AddError(kVersionExplicitlyV1); | 
|  | // The correct way to specify v1 is to omit the version field since v1 is | 
|  | // the DEFAULT. | 
|  | return false; | 
|  | } | 
|  | } else { | 
|  | out->version = CertificateVersion::V1; | 
|  | } | 
|  |  | 
|  | //        serialNumber         CertificateSerialNumber, | 
|  | if (!tbs_parser.ReadTag(CBS_ASN1_INTEGER, &out->serial_number)) { | 
|  | errors->AddError(kFailedReadingSerialNumber); | 
|  | return false; | 
|  | } | 
|  | if (!VerifySerialNumber(out->serial_number, | 
|  | options.allow_invalid_serial_numbers, errors)) { | 
|  | // Invalid serial numbers are only considered fatal failures if | 
|  | // |!allow_invalid_serial_numbers|. | 
|  | if (!options.allow_invalid_serial_numbers) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | //        signature            AlgorithmIdentifier, | 
|  | if (!ReadSequenceTLV(&tbs_parser, &out->signature_algorithm_tlv)) { | 
|  | errors->AddError(kFailedReadingSignatureValue); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //        issuer               Name, | 
|  | if (!ReadSequenceTLV(&tbs_parser, &out->issuer_tlv)) { | 
|  | errors->AddError(kFailedReadingIssuer); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //        validity             Validity, | 
|  | der::Input validity_tlv; | 
|  | if (!tbs_parser.ReadRawTLV(&validity_tlv)) { | 
|  | errors->AddError(kFailedReadingValidity); | 
|  | return false; | 
|  | } | 
|  | if (!ParseValidity(validity_tlv, &out->validity_not_before, | 
|  | &out->validity_not_after)) { | 
|  | errors->AddError(kFailedParsingValidity); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //        subject              Name, | 
|  | if (!ReadSequenceTLV(&tbs_parser, &out->subject_tlv)) { | 
|  | errors->AddError(kFailedReadingSubject); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //        subjectPublicKeyInfo SubjectPublicKeyInfo, | 
|  | if (!ReadSequenceTLV(&tbs_parser, &out->spki_tlv)) { | 
|  | errors->AddError(kFailedReadingSpki); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //        issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL, | 
|  | //                             -- If present, version MUST be v2 or v3 | 
|  | std::optional<der::Input> issuer_unique_id; | 
|  | if (!tbs_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 1, | 
|  | &issuer_unique_id)) { | 
|  | errors->AddError(kFailedReadingIssuerUniqueId); | 
|  | return false; | 
|  | } | 
|  | if (issuer_unique_id) { | 
|  | out->issuer_unique_id = der::ParseBitString(issuer_unique_id.value()); | 
|  | if (!out->issuer_unique_id) { | 
|  | errors->AddError(kFailedParsingIssuerUniqueId); | 
|  | return false; | 
|  | } | 
|  | if (out->version != CertificateVersion::V2 && | 
|  | out->version != CertificateVersion::V3) { | 
|  | errors->AddError(kIssuerUniqueIdNotExpected); | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | //        subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL, | 
|  | //                             -- If present, version MUST be v2 or v3 | 
|  | std::optional<der::Input> subject_unique_id; | 
|  | if (!tbs_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 2, | 
|  | &subject_unique_id)) { | 
|  | errors->AddError(kFailedReadingSubjectUniqueId); | 
|  | return false; | 
|  | } | 
|  | if (subject_unique_id) { | 
|  | out->subject_unique_id = der::ParseBitString(subject_unique_id.value()); | 
|  | if (!out->subject_unique_id) { | 
|  | errors->AddError(kFailedParsingSubjectUniqueId); | 
|  | return false; | 
|  | } | 
|  | if (out->version != CertificateVersion::V2 && | 
|  | out->version != CertificateVersion::V3) { | 
|  | errors->AddError(kSubjectUniqueIdNotExpected); | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | //        extensions      [3]  EXPLICIT Extensions OPTIONAL | 
|  | //                             -- If present, version MUST be v3 | 
|  | if (!tbs_parser.ReadOptionalTag( | 
|  | CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3, | 
|  | &out->extensions_tlv)) { | 
|  | errors->AddError(kFailedReadingExtensions); | 
|  | return false; | 
|  | } | 
|  | if (out->extensions_tlv) { | 
|  | // extensions_tlv must be a single element. Also check that it is a | 
|  | // SEQUENCE. | 
|  | if (!IsSequenceTLV(out->extensions_tlv.value())) { | 
|  | errors->AddError(kFailedReadingExtensions); | 
|  | return false; | 
|  | } | 
|  | if (out->version != CertificateVersion::V3) { | 
|  | errors->AddError(kUnexpectedExtensions); | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | // Note that there IS an extension point at the end of TBSCertificate | 
|  | // (according to RFC 5912), so from that interpretation, unconsumed data would | 
|  | // be allowed in |tbs_parser|. | 
|  | // | 
|  | // However because only v1, v2, and v3 certificates are supported by the | 
|  | // parsing, there shouldn't be any subsequent data in those versions, so | 
|  | // reject. | 
|  | if (tbs_parser.HasMore()) { | 
|  | errors->AddError(kUnconsumedDataInsideTbsCertificateSequence); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // By definition the input was a single TBSCertificate, so there shouldn't be | 
|  | // unconsumed data. | 
|  | if (parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // From RFC 5280: | 
|  | // | 
|  | //    Extension  ::=  SEQUENCE  { | 
|  | //            extnID      OBJECT IDENTIFIER, | 
|  | //            critical    BOOLEAN DEFAULT FALSE, | 
|  | //            extnValue   OCTET STRING | 
|  | //                        -- contains the DER encoding of an ASN.1 value | 
|  | //                        -- corresponding to the extension type identified | 
|  | //                        -- by extnID | 
|  | //            } | 
|  | bool ParseExtension(der::Input extension_tlv, ParsedExtension *out) { | 
|  | der::Parser parser(extension_tlv); | 
|  |  | 
|  | //    Extension  ::=  SEQUENCE  { | 
|  | der::Parser extension_parser; | 
|  | if (!parser.ReadSequence(&extension_parser)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //            extnID      OBJECT IDENTIFIER, | 
|  | if (!extension_parser.ReadTag(CBS_ASN1_OBJECT, &out->oid)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //            critical    BOOLEAN DEFAULT FALSE, | 
|  | out->critical = false; | 
|  | bool has_critical; | 
|  | der::Input critical; | 
|  | if (!extension_parser.ReadOptionalTag(CBS_ASN1_BOOLEAN, &critical, | 
|  | &has_critical)) { | 
|  | return false; | 
|  | } | 
|  | if (has_critical) { | 
|  | if (!der::ParseBool(critical, &out->critical)) { | 
|  | return false; | 
|  | } | 
|  | if (!out->critical) { | 
|  | return false;  // DER-encoding requires DEFAULT values be omitted. | 
|  | } | 
|  | } | 
|  |  | 
|  | //            extnValue   OCTET STRING | 
|  | if (!extension_parser.ReadTag(CBS_ASN1_OCTETSTRING, &out->value)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // The Extension type does not have an extension point (everything goes in | 
|  | // extnValue). | 
|  | if (extension_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // By definition the input was a single Extension sequence, so there shouldn't | 
|  | // be unconsumed data. | 
|  | if (parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | OPENSSL_EXPORT bool ParseExtensions( | 
|  | der::Input extensions_tlv, | 
|  | std::map<der::Input, ParsedExtension> *extensions) { | 
|  | der::Parser parser(extensions_tlv); | 
|  |  | 
|  | //    Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension | 
|  | der::Parser extensions_parser; | 
|  | if (!parser.ReadSequence(&extensions_parser)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // The Extensions SEQUENCE must contains at least 1 element (otherwise it | 
|  | // should have been omitted). | 
|  | if (!extensions_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | extensions->clear(); | 
|  |  | 
|  | while (extensions_parser.HasMore()) { | 
|  | ParsedExtension extension; | 
|  |  | 
|  | der::Input extension_tlv; | 
|  | if (!extensions_parser.ReadRawTLV(&extension_tlv)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (!ParseExtension(extension_tlv, &extension)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool is_duplicate = | 
|  | !extensions->insert(std::make_pair(extension.oid, extension)).second; | 
|  |  | 
|  | // RFC 5280 says that an extension should not appear more than once. | 
|  | if (is_duplicate) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | // By definition the input was a single Extensions sequence, so there | 
|  | // shouldn't be unconsumed data. | 
|  | if (parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | OPENSSL_EXPORT bool ConsumeExtension( | 
|  | der::Input oid, | 
|  | std::map<der::Input, ParsedExtension> *unconsumed_extensions, | 
|  | ParsedExtension *extension) { | 
|  | auto it = unconsumed_extensions->find(oid); | 
|  | if (it == unconsumed_extensions->end()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | *extension = it->second; | 
|  | unconsumed_extensions->erase(it); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool ParseBasicConstraints(der::Input basic_constraints_tlv, | 
|  | ParsedBasicConstraints *out) { | 
|  | der::Parser parser(basic_constraints_tlv); | 
|  |  | 
|  | //    BasicConstraints ::= SEQUENCE { | 
|  | der::Parser sequence_parser; | 
|  | if (!parser.ReadSequence(&sequence_parser)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //         cA                      BOOLEAN DEFAULT FALSE, | 
|  | out->is_ca = false; | 
|  | bool has_ca; | 
|  | der::Input ca; | 
|  | if (!sequence_parser.ReadOptionalTag(CBS_ASN1_BOOLEAN, &ca, &has_ca)) { | 
|  | return false; | 
|  | } | 
|  | if (has_ca) { | 
|  | if (!der::ParseBool(ca, &out->is_ca)) { | 
|  | return false; | 
|  | } | 
|  | // TODO(eroman): Should reject if CA was set to false, since | 
|  | // DER-encoding requires DEFAULT values be omitted. In | 
|  | // practice however there are a lot of certificates that use | 
|  | // the broken encoding. | 
|  | } | 
|  |  | 
|  | //         pathLenConstraint       INTEGER (0..MAX) OPTIONAL } | 
|  | der::Input encoded_path_len; | 
|  | if (!sequence_parser.ReadOptionalTag(CBS_ASN1_INTEGER, &encoded_path_len, | 
|  | &out->has_path_len)) { | 
|  | return false; | 
|  | } | 
|  | if (out->has_path_len) { | 
|  | // TODO(eroman): Surface reason for failure if length was longer than uint8. | 
|  | if (!der::ParseUint8(encoded_path_len, &out->path_len)) { | 
|  | return false; | 
|  | } | 
|  | } else { | 
|  | // Default initialize to 0 as a precaution. | 
|  | out->path_len = 0; | 
|  | } | 
|  |  | 
|  | // There shouldn't be any unconsumed data in the extension. | 
|  | if (sequence_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // By definition the input was a single BasicConstraints sequence, so there | 
|  | // shouldn't be unconsumed data. | 
|  | if (parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // TODO(crbug.com/1314019): return std::optional<BitString> when converting | 
|  | // has_key_usage_ and key_usage_ into single std::optional field. | 
|  | bool ParseKeyUsage(der::Input key_usage_tlv, der::BitString *key_usage) { | 
|  | der::Parser parser(key_usage_tlv); | 
|  | std::optional<der::BitString> key_usage_internal = parser.ReadBitString(); | 
|  | if (!key_usage_internal) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // By definition the input was a single BIT STRING. | 
|  | if (parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // RFC 5280 section 4.2.1.3: | 
|  | // | 
|  | //     When the keyUsage extension appears in a certificate, at least | 
|  | //     one of the bits MUST be set to 1. | 
|  | if (BitStringIsAllZeros(key_usage_internal.value())) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | *key_usage = key_usage_internal.value(); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool ParseAuthorityInfoAccess( | 
|  | der::Input authority_info_access_tlv, | 
|  | std::vector<AuthorityInfoAccessDescription> *out_access_descriptions) { | 
|  | der::Parser parser(authority_info_access_tlv); | 
|  |  | 
|  | out_access_descriptions->clear(); | 
|  |  | 
|  | //    AuthorityInfoAccessSyntax  ::= | 
|  | //            SEQUENCE SIZE (1..MAX) OF AccessDescription | 
|  | der::Parser sequence_parser; | 
|  | if (!parser.ReadSequence(&sequence_parser)) { | 
|  | return false; | 
|  | } | 
|  | if (!sequence_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | while (sequence_parser.HasMore()) { | 
|  | AuthorityInfoAccessDescription access_description; | 
|  |  | 
|  | //    AccessDescription  ::=  SEQUENCE { | 
|  | der::Parser access_description_sequence_parser; | 
|  | if (!sequence_parser.ReadSequence(&access_description_sequence_parser)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //            accessMethod          OBJECT IDENTIFIER, | 
|  | if (!access_description_sequence_parser.ReadTag( | 
|  | CBS_ASN1_OBJECT, &access_description.access_method_oid)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //            accessLocation        GeneralName  } | 
|  | if (!access_description_sequence_parser.ReadRawTLV( | 
|  | &access_description.access_location)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (access_description_sequence_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | out_access_descriptions->push_back(access_description); | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool ParseAuthorityInfoAccessURIs( | 
|  | der::Input authority_info_access_tlv, | 
|  | std::vector<std::string_view> *out_ca_issuers_uris, | 
|  | std::vector<std::string_view> *out_ocsp_uris) { | 
|  | std::vector<AuthorityInfoAccessDescription> access_descriptions; | 
|  | if (!ParseAuthorityInfoAccess(authority_info_access_tlv, | 
|  | &access_descriptions)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | for (const auto &access_description : access_descriptions) { | 
|  | der::Parser access_location_parser(access_description.access_location); | 
|  | CBS_ASN1_TAG access_location_tag; | 
|  | der::Input access_location_value; | 
|  | if (!access_location_parser.ReadTagAndValue(&access_location_tag, | 
|  | &access_location_value)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // GeneralName ::= CHOICE { | 
|  | if (access_location_tag == (CBS_ASN1_CONTEXT_SPECIFIC | 6)) { | 
|  | // uniformResourceIdentifier       [6]     IA5String, | 
|  | std::string_view uri = BytesAsStringView(access_location_value); | 
|  | if (!bssl::string_util::IsAscii(uri)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (access_description.access_method_oid == der::Input(kAdCaIssuersOid)) { | 
|  | out_ca_issuers_uris->push_back(uri); | 
|  | } else if (access_description.access_method_oid == | 
|  | der::Input(kAdOcspOid)) { | 
|  | out_ocsp_uris->push_back(uri); | 
|  | } | 
|  | } | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | ParsedDistributionPoint::ParsedDistributionPoint() = default; | 
|  | ParsedDistributionPoint::ParsedDistributionPoint( | 
|  | ParsedDistributionPoint &&other) = default; | 
|  | ParsedDistributionPoint::~ParsedDistributionPoint() = default; | 
|  |  | 
|  | bool ParseCrlDistributionPoints( | 
|  | der::Input extension_value, | 
|  | std::vector<ParsedDistributionPoint> *distribution_points) { | 
|  | distribution_points->clear(); | 
|  |  | 
|  | // RFC 5280, section 4.2.1.13. | 
|  | // | 
|  | // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint | 
|  | der::Parser extension_value_parser(extension_value); | 
|  | der::Parser distribution_points_parser; | 
|  | if (!extension_value_parser.ReadSequence(&distribution_points_parser)) { | 
|  | return false; | 
|  | } | 
|  | if (extension_value_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Sequence must have a minimum of 1 item. | 
|  | if (!distribution_points_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | while (distribution_points_parser.HasMore()) { | 
|  | if (!ParseAndAddDistributionPoint(&distribution_points_parser, | 
|  | distribution_points)) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | ParsedAuthorityKeyIdentifier::ParsedAuthorityKeyIdentifier() = default; | 
|  | ParsedAuthorityKeyIdentifier::~ParsedAuthorityKeyIdentifier() = default; | 
|  | ParsedAuthorityKeyIdentifier::ParsedAuthorityKeyIdentifier( | 
|  | ParsedAuthorityKeyIdentifier &&other) = default; | 
|  | ParsedAuthorityKeyIdentifier &ParsedAuthorityKeyIdentifier::operator=( | 
|  | ParsedAuthorityKeyIdentifier &&other) = default; | 
|  |  | 
|  | bool ParseAuthorityKeyIdentifier( | 
|  | der::Input extension_value, | 
|  | ParsedAuthorityKeyIdentifier *authority_key_identifier) { | 
|  | // RFC 5280, section 4.2.1.1. | 
|  | //    AuthorityKeyIdentifier ::= SEQUENCE { | 
|  | //       keyIdentifier             [0] KeyIdentifier           OPTIONAL, | 
|  | //       authorityCertIssuer       [1] GeneralNames            OPTIONAL, | 
|  | //       authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  } | 
|  | // | 
|  | //    KeyIdentifier ::= OCTET STRING | 
|  |  | 
|  | der::Parser extension_value_parser(extension_value); | 
|  | der::Parser aki_parser; | 
|  | if (!extension_value_parser.ReadSequence(&aki_parser)) { | 
|  | return false; | 
|  | } | 
|  | if (extension_value_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // TODO(mattm): Should having an empty AuthorityKeyIdentifier SEQUENCE be an | 
|  | // error? RFC 5280 doesn't explicitly say it. | 
|  |  | 
|  | //       keyIdentifier             [0] KeyIdentifier           OPTIONAL, | 
|  | if (!aki_parser.ReadOptionalTag(CBS_ASN1_CONTEXT_SPECIFIC | 0, | 
|  | &authority_key_identifier->key_identifier)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //       authorityCertIssuer       [1] GeneralNames            OPTIONAL, | 
|  | if (!aki_parser.ReadOptionalTag( | 
|  | CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1, | 
|  | &authority_key_identifier->authority_cert_issuer)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //       authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  } | 
|  | if (!aki_parser.ReadOptionalTag( | 
|  | CBS_ASN1_CONTEXT_SPECIFIC | 2, | 
|  | &authority_key_identifier->authority_cert_serial_number)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | //     -- authorityCertIssuer and authorityCertSerialNumber MUST both | 
|  | //     -- be present or both be absent | 
|  | if (authority_key_identifier->authority_cert_issuer.has_value() != | 
|  | authority_key_identifier->authority_cert_serial_number.has_value()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // There shouldn't be any unconsumed data in the AuthorityKeyIdentifier | 
|  | // SEQUENCE. | 
|  | if (aki_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool ParseSubjectKeyIdentifier(der::Input extension_value, | 
|  | der::Input *subject_key_identifier) { | 
|  | //    SubjectKeyIdentifier ::= KeyIdentifier | 
|  | // | 
|  | //    KeyIdentifier ::= OCTET STRING | 
|  | der::Parser extension_value_parser(extension_value); | 
|  | if (!extension_value_parser.ReadTag(CBS_ASN1_OCTETSTRING, | 
|  | subject_key_identifier)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // There shouldn't be any unconsumed data in the extension SEQUENCE. | 
|  | if (extension_value_parser.HasMore()) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | BSSL_NAMESPACE_END |