Botan 2.19.1
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#include <botan/x509_ext.h>
10#include <botan/x509cert.h>
11#include <botan/ber_dec.h>
12
13#include <sstream>
14
15namespace Botan {
16
17struct CRL_Data
18 {
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::string m_issuing_distribution_point;
29 };
30
31std::string X509_CRL::PEM_label() const
32 {
33 return "X509 CRL";
34 }
35
36std::vector<std::string> X509_CRL::alternate_PEM_labels() const
37 {
38 return { "CRL" };
39 }
40
42 {
43 load_data(src);
44 }
45
46X509_CRL::X509_CRL(const std::vector<uint8_t>& vec)
47 {
48 DataSource_Memory src(vec.data(), vec.size());
49 load_data(src);
50 }
51
52#if defined(BOTAN_TARGET_OS_HAS_FILESYSTEM)
53X509_CRL::X509_CRL(const std::string& fsname)
54 {
55 DataSource_Stream src(fsname, true);
56 load_data(src);
57 }
58#endif
59
61 const X509_Time& this_update,
62 const X509_Time& next_update,
63 const std::vector<CRL_Entry>& revoked) :
65 {
66 m_data.reset(new CRL_Data);
67 m_data->m_issuer = issuer;
68 m_data->m_this_update = this_update;
69 m_data->m_next_update = next_update;
70 m_data->m_entries = revoked;
71 }
72
73/**
74* Check if this particular certificate is listed in the CRL
75*/
77 {
78 /*
79 If the cert wasn't issued by the CRL issuer, it's possible the cert
80 is revoked, but not by this CRL. Maybe throw an exception instead?
81 */
82 if(cert.issuer_dn() != issuer_dn())
83 return false;
84
85 std::vector<uint8_t> crl_akid = authority_key_id();
86 std::vector<uint8_t> cert_akid = cert.authority_key_id();
87
88 if(!crl_akid.empty() && !cert_akid.empty())
89 {
90 if(crl_akid != cert_akid)
91 return false;
92 }
93
94 std::vector<uint8_t> cert_serial = cert.serial_number();
95
96 bool is_revoked = false;
97
98 // FIXME would be nice to avoid a linear scan here - maybe sort the entries?
99 for(const CRL_Entry& entry : get_revoked())
100 {
101 if(cert_serial == entry.serial_number())
102 {
103 if(entry.reason_code() == REMOVE_FROM_CRL)
104 is_revoked = false;
105 else
106 is_revoked = true;
107 }
108 }
109
110 return is_revoked;
111 }
112
113/*
114* Decode the TBSCertList data
115*/
116namespace {
117
118std::unique_ptr<CRL_Data> decode_crl_body(const std::vector<uint8_t>& body,
119 const AlgorithmIdentifier& sig_algo)
120 {
121 std::unique_ptr<CRL_Data> data(new CRL_Data);
122
123 BER_Decoder tbs_crl(body);
124
125 size_t version;
126 tbs_crl.decode_optional(version, INTEGER, UNIVERSAL);
127
128 if(version != 0 && version != 1)
129 throw X509_CRL::X509_CRL_Error("Unknown X.509 CRL version " +
130 std::to_string(version+1));
131
132 AlgorithmIdentifier sig_algo_inner;
133 tbs_crl.decode(sig_algo_inner);
134
135 if(sig_algo != sig_algo_inner)
136 throw X509_CRL::X509_CRL_Error("Algorithm identifier mismatch");
137
138 tbs_crl.decode(data->m_issuer)
139 .decode(data->m_this_update)
140 .decode(data->m_next_update);
141
142 BER_Object next = tbs_crl.get_next_object();
143
144 if(next.is_a(SEQUENCE, CONSTRUCTED))
145 {
146 BER_Decoder cert_list(std::move(next));
147
148 while(cert_list.more_items())
149 {
150 CRL_Entry entry;
151 cert_list.decode(entry);
152 data->m_entries.push_back(entry);
153 }
154 next = tbs_crl.get_next_object();
155 }
156
158 {
159 BER_Decoder crl_options(std::move(next));
160 crl_options.decode(data->m_extensions).verify_end();
161 next = tbs_crl.get_next_object();
162 }
163
164 if(next.is_set())
165 throw X509_CRL::X509_CRL_Error("Unknown tag in CRL");
166
167 tbs_crl.verify_end();
168
169 // Now cache some fields from the extensions
170 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::CRL_Number>())
171 {
172 data->m_crl_number = ext->get_crl_number();
173 }
174 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::Authority_Key_ID>())
175 {
176 data->m_auth_key_id = ext->get_key_id();
177 }
178 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::CRL_Issuing_Distribution_Point>())
179 {
180 std::stringstream ss;
181
182 for(const auto& pair : ext->get_point().contents())
183 {
184 ss << pair.first << ": " << pair.second << " ";
185 }
186 data->m_issuing_distribution_point = ss.str();
187 }
188
189 return data;
190 }
191
192}
193
194void X509_CRL::force_decode()
195 {
196 m_data.reset(decode_crl_body(signed_body(), signature_algorithm()).release());
197 }
198
199const CRL_Data& X509_CRL::data() const
200 {
201 if(!m_data)
202 {
203 throw Invalid_State("X509_CRL uninitialized");
204 }
205 return *m_data.get();
206 }
207
209 {
210 return data().m_extensions;
211 }
212
213/*
214* Return the list of revoked certificates
215*/
216const std::vector<CRL_Entry>& X509_CRL::get_revoked() const
217 {
218 return data().m_entries;
219 }
220
221/*
222* Return the distinguished name of the issuer
223*/
225 {
226 return data().m_issuer;
227 }
228
229/*
230* Return the key identifier of the issuer
231*/
232const std::vector<uint8_t>& X509_CRL::authority_key_id() const
233 {
234 return data().m_auth_key_id;
235 }
236
237/*
238* Return the CRL number of this CRL
239*/
240uint32_t X509_CRL::crl_number() const
241 {
242 return static_cast<uint32_t>(data().m_crl_number);
243 }
244
245/*
246* Return the issue data of the CRL
247*/
249 {
250 return data().m_this_update;
251 }
252
253/*
254* Return the date when a new CRL will be issued
255*/
257 {
258 return data().m_next_update;
259 }
260
261/*
262* Return the CRL's distribution point
263*/
265 {
266 return data().m_issuing_distribution_point;
267 }
268}
bool is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) const
Definition: asn1_obj.cpp:71
bool is_set() const
Definition: asn1_obj.h:112
Definition: x509_crl.h:29
const std::vector< CRL_Entry > & get_revoked() const
Definition: x509_crl.cpp:216
const std::vector< uint8_t > & authority_key_id() const
Definition: x509_crl.cpp:232
const X509_Time & this_update() const
Definition: x509_crl.cpp:248
X509_CRL()=default
const Extensions & extensions() const
Definition: x509_crl.cpp:208
uint32_t crl_number() const
Definition: x509_crl.cpp:240
const X509_Time & next_update() const
Definition: x509_crl.cpp:256
const X509_DN & issuer_dn() const
Definition: x509_crl.cpp:224
bool is_revoked(const X509_Certificate &cert) const
Definition: x509_crl.cpp:76
std::string crl_issuing_distribution_point() const
Definition: x509_crl.cpp:264
const std::vector< uint8_t > & serial_number() const
Definition: x509cert.cpp:460
const std::vector< uint8_t > & authority_key_id() const
Definition: x509cert.cpp:450
const X509_DN & issuer_dn() const
Definition: x509cert.cpp:471
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:52
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Definition: alg_id.cpp:13
ASN1_Time X509_Time
Definition: asn1_obj.h:386
@ REMOVE_FROM_CRL
Definition: pkix_enums.h:131
ASN1_Tag
Definition: asn1_obj.h:25
@ CONSTRUCTED
Definition: asn1_obj.h:30
@ SEQUENCE
Definition: asn1_obj.h:42
@ CONTEXT_SPECIFIC
Definition: asn1_obj.h:28
@ UNIVERSAL
Definition: asn1_obj.h:26
@ INTEGER
Definition: asn1_obj.h:36