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