Botan  2.4.0
Crypto and TLS for C++11
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 
15 namespace Botan {
16 
17 struct 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 
31 std::string X509_CRL::PEM_label() const
32  {
33  return "X509 CRL";
34  }
35 
36 std::vector<std::string> X509_CRL::alternate_PEM_labels() const
37  {
38  return { "CRL" };
39  }
40 
42  {
43  load_data(src);
44  }
45 
46 X509_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)
53 X509_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) :
64  X509_Object()
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 */
76 bool X509_CRL::is_revoked(const X509_Certificate& cert) const
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 */
116 namespace {
117 
118 std::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.type_tag == SEQUENCE && next.class_tag == CONSTRUCTED)
145  {
146  BER_Decoder cert_list(next.value);
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 
157  if(next.type_tag == 0 &&
159  {
160  BER_Decoder crl_options(next.value);
161  crl_options.decode(data->m_extensions).verify_end();
162  next = tbs_crl.get_next_object();
163  }
164 
165  if(next.type_tag != NO_OBJECT)
166  throw X509_CRL::X509_CRL_Error("Unknown tag in CRL");
167 
168  tbs_crl.verify_end();
169 
170  // Now cache some fields from the extensions
171  if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::CRL_Number>())
172  {
173  data->m_crl_number = ext->get_crl_number();
174  }
175  if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::Authority_Key_ID>())
176  {
177  data->m_auth_key_id = ext->get_key_id();
178  }
179  if(auto ext = data->m_extensions.get_extension_object_as<Cert_Extension::CRL_Issuing_Distribution_Point>())
180  {
181  std::stringstream ss;
182 
183  for(const auto& pair : ext->get_point().contents())
184  {
185  ss << pair.first << ": " << pair.second << " ";
186  }
187  data->m_issuing_distribution_point = ss.str();
188  }
189 
190  return data;
191  }
192 
193 }
194 
195 void X509_CRL::force_decode()
196  {
197  m_data.reset(decode_crl_body(signed_body(), signature_algorithm()).release());
198  }
199 
200 const CRL_Data& X509_CRL::data() const
201  {
202  if(!m_data)
203  {
204  throw Invalid_State("X509_CRL uninitialized");
205  }
206  return *m_data.get();
207  }
208 
210  {
211  return data().m_extensions;
212  }
213 
214 /*
215 * Return the list of revoked certificates
216 */
217 const std::vector<CRL_Entry>& X509_CRL::get_revoked() const
218  {
219  return data().m_entries;
220  }
221 
222 /*
223 * Return the distinguished name of the issuer
224 */
226  {
227  return data().m_issuer;
228  }
229 
230 /*
231 * Return the key identifier of the issuer
232 */
233 const std::vector<uint8_t>& X509_CRL::authority_key_id() const
234  {
235  return data().m_auth_key_id;
236  }
237 
238 /*
239 * Return the CRL number of this CRL
240 */
241 uint32_t X509_CRL::crl_number() const
242  {
243  return data().m_crl_number;
244  }
245 
246 /*
247 * Return the issue data of the CRL
248 */
250  {
251  return data().m_this_update;
252  }
253 
254 /*
255 * Return the date when a new CRL will be issued
256 */
258  {
259  return data().m_next_update;
260  }
261 
262 /*
263 * Return the CRL's distribution point
264 */
266  {
267  return data().m_issuing_distribution_point;
268  }
269 }
X509_CRL()=default
const AlgorithmIdentifier & signature_algorithm() const
Definition: x509_obj.h:47
void push_back(const BER_Object &obj)
Definition: ber_dec.cpp:241
BER_Decoder & decode(bool &v)
Definition: ber_dec.cpp:355
const std::vector< uint8_t > & authority_key_id() const
Definition: x509cert.cpp:389
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:108
ASN1_Tag
Definition: asn1_obj.h:22
BER_Decoder & decode_optional(T &out, ASN1_Tag type_tag, ASN1_Tag class_tag, const T &default_value=T())
Definition: ber_dec.h:230
const X509_Time & next_update() const
Definition: x509_crl.cpp:257
secure_vector< uint8_t > value
Definition: asn1_obj.h:97
const std::vector< uint8_t > & authority_key_id() const
Definition: x509_crl.cpp:233
const std::vector< uint8_t > & signed_body() const
Definition: x509_obj.h:42
const X509_DN & issuer_dn() const
Definition: x509cert.cpp:410
const X509_DN & issuer_dn() const
Definition: x509_crl.cpp:225
Definition: alg_id.cpp:13
Definition: crl_ent.h:42
BER_Object get_next_object()
Definition: ber_dec.cpp:197
const Extensions & extensions() const
Definition: x509_crl.cpp:209
ASN1_Tag class_tag
Definition: asn1_obj.h:94
ASN1_Tag type_tag
Definition: asn1_obj.h:94
std::string crl_issuing_distribution_point() const
Definition: x509_crl.cpp:265
BER_Decoder & verify_end()
Definition: ber_dec.cpp:176
uint32_t crl_number() const
Definition: x509_crl.cpp:241
const std::vector< uint8_t > & serial_number() const
Definition: x509cert.cpp:399
const std::vector< CRL_Entry > & get_revoked() const
Definition: x509_crl.cpp:217
bool more_items() const
Definition: ber_dec.cpp:166
const X509_Time & this_update() const
Definition: x509_crl.cpp:249
bool is_revoked(const X509_Certificate &cert) const
Definition: x509_crl.cpp:76