1 // Copyright 2019 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BSSL_PKI_CRL_H_ 6 #define BSSL_PKI_CRL_H_ 7 8 #include <optional> 9 10 #include <openssl/base.h> 11 12 #include "general_names.h" 13 #include "input.h" 14 #include "parse_values.h" 15 #include "parsed_certificate.h" 16 17 namespace bssl { 18 19 struct ParsedCrlTbsCertList; 20 struct ParsedDistributionPoint; 21 22 // TODO(https://crbug.com/749276): This is the same enum with the same meaning 23 // as OCSPRevocationStatus, maybe they should be merged? 24 enum class CRLRevocationStatus { 25 GOOD = 0, 26 REVOKED = 1, 27 UNKNOWN = 2, 28 MAX_VALUE = UNKNOWN 29 }; 30 31 // Parses a DER-encoded CRL "CertificateList" as specified by RFC 5280 Section 32 // 5.1. Returns true on success and sets the results in the |out_*| parameters. 33 // The contents of the output data is not validated. 34 // 35 // Note that on success the out parameters alias data from the input |crl_tlv|. 36 // Hence the output values are only valid as long as |crl_tlv| remains valid. 37 // 38 // On failure the out parameters have an undefined state. Some of them may have 39 // been updated during parsing, whereas others may not have been changed. 40 // 41 // CertificateList ::= SEQUENCE { 42 // tbsCertList TBSCertList, 43 // signatureAlgorithm AlgorithmIdentifier, 44 // signatureValue BIT STRING } 45 [[nodiscard]] OPENSSL_EXPORT bool ParseCrlCertificateList( 46 der::Input crl_tlv, der::Input *out_tbs_cert_list_tlv, 47 der::Input *out_signature_algorithm_tlv, 48 der::BitString *out_signature_value); 49 50 // Parses a DER-encoded "TBSCertList" as specified by RFC 5280 Section 5.1. 51 // Returns true on success and sets the results in |out|. 52 // 53 // Note that on success |out| aliases data from the input |tbs_tlv|. 54 // Hence the fields of the ParsedCrlTbsCertList are only valid as long as 55 // |tbs_tlv| remains valid. 56 // 57 // On failure |out| has an undefined state. Some of its fields may have been 58 // updated during parsing, whereas others may not have been changed. 59 // 60 // Refer to the per-field documentation of ParsedCrlTbsCertList for details on 61 // what validity checks parsing performs. 62 // 63 // TBSCertList ::= SEQUENCE { 64 // version Version OPTIONAL, 65 // -- if present, MUST be v2 66 // signature AlgorithmIdentifier, 67 // issuer Name, 68 // thisUpdate Time, 69 // nextUpdate Time OPTIONAL, 70 // revokedCertificates SEQUENCE OF SEQUENCE { 71 // userCertificate CertificateSerialNumber, 72 // revocationDate Time, 73 // crlEntryExtensions Extensions OPTIONAL 74 // -- if present, version MUST be v2 75 // } OPTIONAL, 76 // crlExtensions [0] EXPLICIT Extensions OPTIONAL 77 // -- if present, version MUST be v2 78 // } 79 [[nodiscard]] OPENSSL_EXPORT bool ParseCrlTbsCertList( 80 der::Input tbs_tlv, ParsedCrlTbsCertList *out); 81 82 // Represents a CRL "Version" from RFC 5280. TBSCertList reuses the same 83 // Version definition from TBSCertificate, however only v1(not present) and 84 // v2(1) are valid values, so a unique enum is used to avoid confusion. 85 enum class CrlVersion { 86 V1, 87 V2, 88 }; 89 90 // Corresponds with "TBSCertList" from RFC 5280 Section 5.1: 91 struct OPENSSL_EXPORT ParsedCrlTbsCertList { 92 ParsedCrlTbsCertList(); 93 ~ParsedCrlTbsCertList(); 94 95 // version Version OPTIONAL, 96 // -- if present, MUST be v2 97 // 98 // Parsing guarantees that the version is one of v1 or v2. 99 CrlVersion version = CrlVersion::V1; 100 101 // signature AlgorithmIdentifier, 102 // 103 // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No 104 // guarantees are made regarding the value of this SEQUENCE. 105 // 106 // This can be further parsed using SignatureValue::Create(). 107 der::Input signature_algorithm_tlv; 108 109 // issuer Name, 110 // 111 // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No 112 // guarantees are made regarding the value of this SEQUENCE. 113 der::Input issuer_tlv; 114 115 // thisUpdate Time, 116 // nextUpdate Time OPTIONAL, 117 // 118 // Parsing guarantees that thisUpdate and nextUpdate(if present) are valid 119 // DER-encoded dates, however it DOES NOT guarantee anything about their 120 // values. For instance notAfter could be before notBefore, or the dates 121 // could indicate an expired CRL. 122 der::GeneralizedTime this_update; 123 std::optional<der::GeneralizedTime> next_update; 124 125 // revokedCertificates SEQUENCE OF SEQUENCE { 126 // userCertificate CertificateSerialNumber, 127 // revocationDate Time, 128 // crlEntryExtensions Extensions OPTIONAL 129 // -- if present, version MUST be v2 130 // } OPTIONAL, 131 // 132 // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No 133 // guarantees are made regarding the value of this SEQUENCE. 134 std::optional<der::Input> revoked_certificates_tlv; 135 136 // crlExtensions [0] EXPLICIT Extensions OPTIONAL 137 // -- if present, version MUST be v2 138 // 139 // This contains the full (unverified) Tag-Length-Value for a SEQUENCE. No 140 // guarantees are made regarding the value of this SEQUENCE. (Note that the 141 // EXPLICIT outer tag is stripped.) 142 // 143 // Parsing guarantees that if extensions is present the version is v2. 144 std::optional<der::Input> crl_extensions_tlv; 145 }; 146 147 // Represents the IssuingDistributionPoint certificate type constraints: 148 enum class ContainedCertsType { 149 // Neither onlyContainsUserCerts or onlyContainsCACerts was present. 150 ANY_CERTS, 151 // onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, 152 USER_CERTS, 153 // onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, 154 CA_CERTS, 155 }; 156 157 // Parses a DER-encoded IssuingDistributionPoint extension value. 158 // Returns true on success and sets the results in the |out_*| parameters. 159 // 160 // If the IssuingDistributionPoint contains a distributionPoint fullName field, 161 // |out_distribution_point_names| will contain the parsed representation. 162 // If the distributionPoint type is nameRelativeToCRLIssuer, parsing will fail. 163 // 164 // |out_only_contains_cert_type| will contain the logical representation of the 165 // onlyContainsUserCerts and onlyContainsCACerts fields (or their absence). 166 // 167 // indirectCRL and onlyContainsAttributeCerts are not supported and parsing will 168 // fail if they are present. 169 // 170 // Note that on success |out_distribution_point_names| aliases data from the 171 // input |extension_value|. 172 // 173 // On failure the |out_*| parameters have undefined state. 174 // 175 // IssuingDistributionPoint ::= SEQUENCE { 176 // distributionPoint [0] DistributionPointName OPTIONAL, 177 // onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, 178 // onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, 179 // onlySomeReasons [3] ReasonFlags OPTIONAL, 180 // indirectCRL [4] BOOLEAN DEFAULT FALSE, 181 // onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE } 182 [[nodiscard]] OPENSSL_EXPORT bool ParseIssuingDistributionPoint( 183 der::Input extension_value, 184 std::unique_ptr<GeneralNames> *out_distribution_point_names, 185 ContainedCertsType *out_only_contains_cert_type); 186 187 OPENSSL_EXPORT CRLRevocationStatus 188 GetCRLStatusForCert(der::Input cert_serial, CrlVersion crl_version, 189 const std::optional<der::Input> &revoked_certificates_tlv); 190 191 // Checks the revocation status of the certificate |cert| by using the 192 // DER-encoded |raw_crl|. |cert| must already have passed certificate path 193 // validation. 194 // 195 // Returns GOOD if the CRL indicates the certificate is not revoked, 196 // REVOKED if it indicates it is revoked, or UNKNOWN for all other cases. 197 // 198 // * |raw_crl|: A DER encoded CRL CertificateList. 199 // * |valid_chain|: The validated certificate chain containing the target cert. 200 // * |target_cert_index|: The index into |valid_chain| of the certificate being 201 // checked for revocation. 202 // * |cert_dp|: The distribution point from the target certificate's CRL 203 // distribution points extension that |raw_crl| corresponds to. If 204 // |raw_crl| was not specified in a distribution point, the caller must 205 // synthesize a ParsedDistributionPoint object as specified by RFC 5280 206 // 6.3.3. 207 // * |verify_time_epoch_seconds|: The time as the difference in seconds from 208 // the POSIX epoch to use when checking revocation status. 209 // * |max_age_seconds|: If present, the maximum age in seconds for a CRL, 210 // implemented as time since the |thisUpdate| field in the CRL 211 // TBSCertList. Responses older than |max_age_seconds| will be 212 // considered invalid. 213 [[nodiscard]] OPENSSL_EXPORT CRLRevocationStatus CheckCRL( 214 std::string_view raw_crl, const ParsedCertificateList &valid_chain, 215 size_t target_cert_index, const ParsedDistributionPoint &cert_dp, 216 int64_t verify_time_epoch_seconds, std::optional<int64_t> max_age_seconds); 217 218 } // namespace bssl 219 220 #endif // BSSL_PKI_CRL_H_ 221