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