Botan 3.5.0
Crypto and TLS for C&
x509_crl.cpp
Go to the documentation of this file.
1/*
2* X.509 CRL
3* (C) 1999-2007 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/x509_crl.h>
9
10#include <botan/ber_dec.h>
11#include <botan/x509_ext.h>
12#include <botan/x509cert.h>
13
14#include <sstream>
15
16namespace Botan {
17
18struct CRL_Data {
19 X509_DN m_issuer;
20 X509_Time m_this_update;
21 X509_Time m_next_update;
22 std::vector<CRL_Entry> m_entries;
23 Extensions m_extensions;
24
25 // cached values from extensions
26 size_t m_crl_number = 0;
27 std::vector<uint8_t> m_auth_key_id;
28 std::vector<std::string> m_idp_urls;
29};
30
31std::string X509_CRL::PEM_label() const {
32 return "X509 CRL";
33}
34
35std::vector<std::string> X509_CRL::alternate_PEM_labels() const {
36 return {"CRL"};
37}
38
42
43X509_CRL::X509_CRL(const std::vector<uint8_t>& vec) {
44 DataSource_Memory src(vec.data(), vec.size());
45 load_data(src);
46}
47
48#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
49X509_CRL::X509_CRL(std::string_view fsname) {
50 DataSource_Stream src(fsname, true);
51 load_data(src);
52}
53#endif
54
56 const X509_Time& this_update,
57 const X509_Time& next_update,
58 const std::vector<CRL_Entry>& revoked) :
59 X509_Object() {
60 m_data = std::make_shared<CRL_Data>();
61 m_data->m_issuer = issuer;
62 m_data->m_this_update = this_update;
63 m_data->m_next_update = next_update;
64 m_data->m_entries = revoked;
65}
66
67/**
68* Check if this particular certificate is listed in the CRL
69*/
70bool X509_CRL::is_revoked(const X509_Certificate& cert) const {
71 /*
72 If the cert wasn't issued by the CRL issuer, it's possible the cert
73 is revoked, but not by this CRL. Maybe throw an exception instead?
74 */
75 if(cert.issuer_dn() != issuer_dn()) {
76 return false;
77 }
78
79 std::vector<uint8_t> crl_akid = authority_key_id();
80 const std::vector<uint8_t>& cert_akid = cert.authority_key_id();
81
82 if(!crl_akid.empty() && !cert_akid.empty()) {
83 if(crl_akid != cert_akid) {
84 return false;
85 }
86 }
87
88 const std::vector<uint8_t>& cert_serial = cert.serial_number();
89
90 bool is_revoked = false;
91
92 // FIXME would be nice to avoid a linear scan here - maybe sort the entries?
93 for(const CRL_Entry& entry : get_revoked()) {
94 if(cert_serial == entry.serial_number()) {
95 if(entry.reason_code() == CRL_Code::RemoveFromCrl) {
96 is_revoked = false;
97 } else {
98 is_revoked = true;
99 }
100 }
101 }
102
103 return is_revoked;
104}
105
106/*
107* Decode the TBSCertList data
108*/
109namespace {
110
111std::unique_ptr<CRL_Data> decode_crl_body(const std::vector<uint8_t>& body, const AlgorithmIdentifier& sig_algo) {
112 auto data = std::make_unique<CRL_Data>();
113
114 BER_Decoder tbs_crl(body);
115
116 size_t version;
117 tbs_crl.decode_optional(version, ASN1_Type::Integer, ASN1_Class::Universal);
118
119 if(version != 0 && version != 1) {
120 throw Decoding_Error("Unknown X.509 CRL version " + std::to_string(version + 1));
121 }
122
123 AlgorithmIdentifier sig_algo_inner;
124 tbs_crl.decode(sig_algo_inner);
125
126 if(sig_algo != sig_algo_inner) {
127 throw Decoding_Error("Algorithm identifier mismatch in CRL");
128 }
129
130 tbs_crl.decode(data->m_issuer).decode(data->m_this_update).decode(data->m_next_update);
131
132 BER_Object next = tbs_crl.get_next_object();
133
135 BER_Decoder cert_list(std::move(next));
136
137 while(cert_list.more_items()) {
138 CRL_Entry entry;
139 cert_list.decode(entry);
140 data->m_entries.push_back(entry);
141 }
142 next = tbs_crl.get_next_object();
143 }
144
146 BER_Decoder crl_options(std::move(next));
147 crl_options.decode(data->m_extensions).verify_end();
148 next = tbs_crl.get_next_object();
149 }
150
151 if(next.is_set()) {
152 throw Decoding_Error("Unknown tag following extensions in CRL");
153 }
154
155 tbs_crl.verify_end();
156
157 // Now cache some fields from the extensions
158 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::CRL_Number>()) {
159 data->m_crl_number = ext->get_crl_number();
160 }
161 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::Authority_Key_ID>()) {
162 data->m_auth_key_id = ext->get_key_id();
163 }
164 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::CRL_Issuing_Distribution_Point>()) {
165 data->m_idp_urls = ext->get_point().get_attribute("URL");
166 }
167
168 return data;
169}
170
171} // namespace
172
173void X509_CRL::force_decode() {
174 m_data.reset(decode_crl_body(signed_body(), signature_algorithm()).release());
175}
176
177const CRL_Data& X509_CRL::data() const {
178 if(!m_data) {
179 throw Invalid_State("X509_CRL uninitialized");
180 }
181 return *m_data;
182}
183
185 return data().m_extensions;
186}
187
188/*
189* Return the list of revoked certificates
190*/
191const std::vector<CRL_Entry>& X509_CRL::get_revoked() const {
192 return data().m_entries;
193}
194
195/*
196* Return the distinguished name of the issuer
197*/
199 return data().m_issuer;
200}
201
202/*
203* Return the key identifier of the issuer
204*/
205const std::vector<uint8_t>& X509_CRL::authority_key_id() const {
206 return data().m_auth_key_id;
207}
208
209/*
210* Return the CRL number of this CRL
211*/
212uint32_t X509_CRL::crl_number() const {
213 return static_cast<uint32_t>(data().m_crl_number);
214}
215
216/*
217* Return the issue data of the CRL
218*/
220 return data().m_this_update;
221}
222
223/*
224* Return the date when a new CRL will be issued
225*/
227 return data().m_next_update;
228}
229
230/*
231* Return the CRL's distribution point
232*/
234 if(!data().m_idp_urls.empty()) {
235 return data().m_idp_urls[0];
236 }
237 return "";
238}
239
240/*
241* Return the CRL's issuing distribution point
242*/
243std::vector<std::string> X509_CRL::issuing_distribution_points() const {
244 return data().m_idp_urls;
245}
246
247} // namespace Botan
Definition x509_crl.h:28
const std::vector< CRL_Entry > & get_revoked() const
Definition x509_crl.cpp:191
const std::vector< uint8_t > & authority_key_id() const
Definition x509_crl.cpp:205
const X509_Time & this_update() const
Definition x509_crl.cpp:219
std::vector< std::string > issuing_distribution_points() const
Definition x509_crl.cpp:243
X509_CRL()=default
const Extensions & extensions() const
Definition x509_crl.cpp:184
uint32_t crl_number() const
Definition x509_crl.cpp:212
const X509_Time & next_update() const
Definition x509_crl.cpp:226
const X509_DN & issuer_dn() const
Definition x509_crl.cpp:198
bool is_revoked(const X509_Certificate &cert) const
Definition x509_crl.cpp:70
std::string crl_issuing_distribution_point() const
Definition x509_crl.cpp:233
const std::vector< uint8_t > & serial_number() const
Definition x509cert.cpp:383
const std::vector< uint8_t > & authority_key_id() const
Definition x509cert.cpp:375
const X509_DN & issuer_dn() const
Definition x509cert.cpp:391
const std::vector< uint8_t > & signed_body() const
Definition x509_obj.h:42
const AlgorithmIdentifier & signature_algorithm() const
Definition x509_obj.h:47
void load_data(DataSource &src)
Definition x509_obj.cpp:24
ASN1_Time X509_Time
Definition asn1_obj.h:409