Botan 3.0.0-alpha0
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 = std::make_shared<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 const 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 const 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() == CRL_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 auto data = std::make_unique<CRL_Data>();
122
123 BER_Decoder tbs_crl(body);
124
125 size_t version;
126 tbs_crl.decode_optional(version, ASN1_Type::Integer, ASN1_Class::Universal);
127
128 if(version != 0 && version != 1)
129 throw Decoding_Error("Unknown X.509 CRL version " + std::to_string(version+1));
130
131 AlgorithmIdentifier sig_algo_inner;
132 tbs_crl.decode(sig_algo_inner);
133
134 if(sig_algo != sig_algo_inner)
135 throw Decoding_Error("Algorithm identifier mismatch in CRL");
136
137 tbs_crl.decode(data->m_issuer)
138 .decode(data->m_this_update)
139 .decode(data->m_next_update);
140
141 BER_Object next = tbs_crl.get_next_object();
142
144 {
145 BER_Decoder cert_list(std::move(next));
146
147 while(cert_list.more_items())
148 {
149 CRL_Entry entry;
150 cert_list.decode(entry);
151 data->m_entries.push_back(entry);
152 }
153 next = tbs_crl.get_next_object();
154 }
155
157 {
158 BER_Decoder crl_options(std::move(next));
159 crl_options.decode(data->m_extensions).verify_end();
160 next = tbs_crl.get_next_object();
161 }
162
163 if(next.is_set())
164 throw Decoding_Error("Unknown tag following extensions in CRL");
165
166 tbs_crl.verify_end();
167
168 // Now cache some fields from the extensions
169 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::CRL_Number>())
170 {
171 data->m_crl_number = ext->get_crl_number();
172 }
173 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::Authority_Key_ID>())
174 {
175 data->m_auth_key_id = ext->get_key_id();
176 }
177 if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::CRL_Issuing_Distribution_Point>())
178 {
179 std::stringstream ss;
180
181 for(const auto& pair : ext->get_point().contents())
182 {
183 ss << pair.first << ": " << pair.second << " ";
184 }
185 data->m_issuing_distribution_point = ss.str();
186 }
187
188 return data;
189 }
190
191}
192
193void X509_CRL::force_decode()
194 {
195 m_data.reset(decode_crl_body(signed_body(), signature_algorithm()).release());
196 }
197
198const CRL_Data& X509_CRL::data() const
199 {
200 if(!m_data)
201 {
202 throw Invalid_State("X509_CRL uninitialized");
203 }
204 return *m_data.get();
205 }
206
208 {
209 return data().m_extensions;
210 }
211
212/*
213* Return the list of revoked certificates
214*/
215const std::vector<CRL_Entry>& X509_CRL::get_revoked() const
216 {
217 return data().m_entries;
218 }
219
220/*
221* Return the distinguished name of the issuer
222*/
224 {
225 return data().m_issuer;
226 }
227
228/*
229* Return the key identifier of the issuer
230*/
231const std::vector<uint8_t>& X509_CRL::authority_key_id() const
232 {
233 return data().m_auth_key_id;
234 }
235
236/*
237* Return the CRL number of this CRL
238*/
239uint32_t X509_CRL::crl_number() const
240 {
241 return static_cast<uint32_t>(data().m_crl_number);
242 }
243
244/*
245* Return the issue data of the CRL
246*/
248 {
249 return data().m_this_update;
250 }
251
252/*
253* Return the date when a new CRL will be issued
254*/
256 {
257 return data().m_next_update;
258 }
259
260/*
261* Return the CRL's distribution point
262*/
264 {
265 return data().m_issuing_distribution_point;
266 }
267}
bool is_a(ASN1_Type type_tag, ASN1_Class class_tag) const
Definition: asn1_obj.cpp:71
bool is_set() const
Definition: asn1_obj.h:141
Definition: x509_crl.h:29
const std::vector< CRL_Entry > & get_revoked() const
Definition: x509_crl.cpp:215
const std::vector< uint8_t > & authority_key_id() const
Definition: x509_crl.cpp:231
const X509_Time & this_update() const
Definition: x509_crl.cpp:247
X509_CRL()=default
const Extensions & extensions() const
Definition: x509_crl.cpp:207
uint32_t crl_number() const
Definition: x509_crl.cpp:239
const X509_Time & next_update() const
Definition: x509_crl.cpp:255
const X509_DN & issuer_dn() const
Definition: x509_crl.cpp:223
bool is_revoked(const X509_Certificate &cert) const
Definition: x509_crl.cpp:76
std::string crl_issuing_distribution_point() const
Definition: x509_crl.cpp:263
const std::vector< uint8_t > & serial_number() const
Definition: x509cert.cpp:449
const std::vector< uint8_t > & authority_key_id() const
Definition: x509cert.cpp:439
const X509_DN & issuer_dn() const
Definition: x509cert.cpp:460
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:43
const AlgorithmIdentifier & signature_algorithm() const
Definition: x509_obj.h:48
void load_data(DataSource &src)
Definition: x509_obj.cpp:52
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:209
Definition: alg_id.cpp:13
ASN1_Time X509_Time
Definition: asn1_obj.h:389