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