8 #include <botan/x509stor.h>
9 #include <botan/parsing.h>
10 #include <botan/pubkey.h>
11 #include <botan/oids.h>
12 #include <botan/time.h>
23 s32bit validity_check(
const X509_Time& start,
const X509_Time& end,
26 const s32bit NOT_YET_VALID = -1, VALID_TIME = 0, EXPIRED = 1;
28 if(start.cmp(current_time + slack) > 0)
30 if(end.cmp(current_time - slack) < 0)
38 bool compare_ids(
const MemoryVector<byte>& id1,
39 const MemoryVector<byte>& id2)
41 if(!id1.size() || !id2.size())
52 if((usage & check_for) == 0)
56 if(cert.constraints() & constraints)
66 const std::string& usage_oid)
68 if((usage & check_for) == 0)
71 const std::vector<std::string> constraints = cert.ex_constraints();
73 if(constraints.empty())
76 return std::binary_search(constraints.begin(), constraints.end(),
83 X509_Code usage_check(
const X509_Certificate& cert,
99 "PKIX.EmailProtection"))
102 "PKIX.TimeStamping"))
115 if(issuer != other.issuer)
117 if(serial != other.serial)
119 return compare_ids(auth_key_id, other.auth_key_id);
127 return !((*this) == other);
138 const MemoryVector<byte>& serial1 = serial;
139 const MemoryVector<byte>& key_id1 = auth_key_id;
140 const MemoryVector<byte>& serial2 = other.serial;
141 const MemoryVector<byte>& key_id2 = other.auth_key_id;
143 if(compare_ids(key_id1, key_id2) ==
false)
145 if(std::lexicographical_compare(key_id1.begin(), key_id1.end(),
146 key_id2.begin(), key_id2.end()))
149 if(std::lexicographical_compare(key_id2.begin(), key_id2.end(),
150 key_id1.begin(), key_id1.end()))
154 if(compare_ids(serial1, serial2) ==
false)
156 if(std::lexicographical_compare(serial1.begin(), serial1.end(),
157 serial2.begin(), serial2.end()))
160 if(std::lexicographical_compare(serial2.begin(), serial2.end(),
161 serial1.begin(), serial1.end()))
165 return (issuer < other.issuer);
173 revoked_info_valid =
true;
175 validation_cache_timeout = cache_timeout;
185 revoked = other.revoked;
186 revoked_info_valid = other.revoked_info_valid;
187 for(
size_t j = 0; j != other.stores.size(); ++j)
188 stores[j] = other.stores[j]->clone();
189 time_slack = other.time_slack;
190 validation_cache_timeout = other.validation_cache_timeout;
198 for(
size_t j = 0; j != stores.size(); ++j)
208 recompute_revoked_info();
210 std::vector<size_t> indexes;
211 X509_Code chaining_result = construct_cert_chain(cert, indexes);
213 return chaining_result;
218 current_time, time_slack);
222 X509_Code sig_check_result = check_sig(cert, certs[indexes[0]]);
224 return sig_check_result;
229 for(
size_t j = 0; j != indexes.size() - 1; ++j)
233 time_check = validity_check(current_cert.
start_time(),
241 sig_check_result = check_sig(certs[indexes[j]], certs[indexes[j+1]]);
243 return sig_check_result;
246 return usage_check(cert, cert_usage);
252 size_t X509_Store::find_cert(
const X509_DN& subject_dn,
255 for(
size_t j = 0; j != certs.size(); ++j)
262 return NO_CERT_FOUND;
268 size_t X509_Store::find_parent_of(
const X509_Certificate& cert)
270 const X509_DN issuer_dn = cert.issuer_dn();
271 const MemoryVector<byte> auth_key_id = cert.authority_key_id();
273 size_t index = find_cert(issuer_dn, auth_key_id);
275 if(index != NO_CERT_FOUND)
278 for(
size_t j = 0; j != stores.size(); ++j)
280 std::vector<X509_Certificate> got =
281 stores[j]->find_cert_by_subject_and_key_id(issuer_dn, auth_key_id);
283 for(
size_t k = 0; k != got.size(); ++k)
287 return find_cert(issuer_dn, auth_key_id);
293 X509_Code X509_Store::construct_cert_chain(
const X509_Certificate& end_cert,
294 std::vector<size_t>& indexes,
295 bool need_full_chain)
297 size_t parent = find_parent_of(end_cert);
301 if(parent == NO_CERT_FOUND)
303 indexes.push_back(parent);
305 if(certs[parent].is_verified(validation_cache_timeout))
306 if(certs[parent].verify_result() !=
VERIFIED)
307 return certs[parent].verify_result();
309 const X509_Certificate& parent_cert = certs[parent].cert;
310 if(!parent_cert.is_CA_cert())
313 if(certs[parent].is_trusted())
315 if(parent_cert.is_self_signed())
318 if(parent_cert.path_limit() < indexes.size() - 1)
321 parent = find_parent_of(parent_cert);
329 if(indexes.size() < 2)
332 const size_t cert = indexes.back();
334 if(certs[cert].is_verified(validation_cache_timeout))
336 if(certs[cert].verify_result() !=
VERIFIED)
337 throw Internal_Error(
"X509_Store::construct_cert_chain");
344 const size_t last_cert = indexes.back();
345 const size_t parent_of_last_cert = find_parent_of(certs[last_cert].cert);
346 if(parent_of_last_cert == NO_CERT_FOUND)
348 indexes.push_back(parent_of_last_cert);
356 X509_Code X509_Store::check_sig(
const Cert_Info& cert_info,
357 const Cert_Info& ca_cert_info)
const
359 if(cert_info.is_verified(validation_cache_timeout))
360 return cert_info.verify_result();
362 const X509_Certificate& cert = cert_info.cert;
363 const X509_Certificate& ca_cert = ca_cert_info.cert;
365 X509_Code verify_code = check_sig(cert, ca_cert.subject_public_key());
367 cert_info.set_result(verify_code);
375 X509_Code X509_Store::check_sig(
const X509_Object&
object, Public_Key* key)
377 std::auto_ptr<Public_Key> pub_key(key);
380 std::vector<std::string> sig_info =
383 if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
386 std::string padding = sig_info[1];
391 PK_Verifier verifier(*pub_key.get(), padding, format);
393 bool valid = verifier.verify_message(
object.tbs_data(),
411 void X509_Store::recompute_revoked_info()
const
413 if(revoked_info_valid)
416 for(
size_t j = 0; j != certs.size(); ++j)
418 if((certs[j].is_verified(validation_cache_timeout)) &&
419 (certs[j].verify_result() !=
VERIFIED))
422 if(is_revoked(certs[j].cert))
426 revoked_info_valid =
true;
432 bool X509_Store::is_revoked(
const X509_Certificate& cert)
const
434 CRL_Data revoked_info;
435 revoked_info.issuer = cert.issuer_dn();
436 revoked_info.serial = cert.serial_number();
437 revoked_info.auth_key_id = cert.authority_key_id();
439 if(std::binary_search(revoked.begin(), revoked.end(), revoked_info))
447 std::vector<X509_Certificate>
450 std::vector<X509_Certificate> result;
451 std::vector<size_t> indexes;
452 X509_Code chaining_result = construct_cert_chain(cert, indexes,
true);
455 throw Invalid_State(
"X509_Store::get_cert_chain: Can't construct chain");
457 for(
size_t j = 0; j != indexes.size(); ++j)
458 result.push_back(certs[indexes[j]].cert);
467 stores.push_back(certstore);
480 revoked_info_valid =
false;
481 Cert_Info info(cert, trusted);
482 certs.push_back(info);
486 for(
size_t j = 0; j != certs.size(); ++j)
489 if(this_cert == cert)
490 certs[j].trusted = trusted;
498 void X509_Store::do_add_certs(
DataSource& source,
bool trusted)
506 catch(Decoding_Error) {}
516 do_add_certs(source,
false);
524 do_add_certs(source,
true);
538 size_t cert_index = NO_CERT_FOUND;
540 for(
size_t j = 0; j != certs.size(); ++j)
550 if(cert_index == NO_CERT_FOUND)
557 return verify_result;
561 return verify_result;
563 std::vector<CRL_Entry> revoked_certs = crl.
get_revoked();
565 for(
size_t j = 0; j != revoked_certs.size(); ++j)
567 CRL_Data revoked_info;
569 revoked_info.serial = revoked_certs[j].serial_number();
572 std::vector<CRL_Data>::iterator p =
573 std::find(revoked.begin(), revoked.end(), revoked_info);
577 if(p == revoked.end())
continue;
582 if(p != revoked.end())
continue;
583 revoked.push_back(revoked_info);
587 std::sort(revoked.begin(), revoked.end());
588 revoked_info_valid =
false;
598 std::string cert_store;
599 for(
size_t j = 0; j != certs.size(); ++j)
600 cert_store += certs[j].cert.PEM_encode();
608 bool t) : cert(c), trusted(t)
618 X509_Code X509_Store::Cert_Info::verify_result()
const
621 throw Invalid_State(
"Cert_Info::verify_result() called; not checked");
628 void X509_Store::Cert_Info::set_result(
X509_Code code)
const
638 bool X509_Store::Cert_Info::is_trusted()
const
646 bool X509_Store::Cert_Info::is_verified(
u32bit timeout)
const
655 if(current_time > last_checked + timeout)
std::string PEM_encode() const
X509_Time this_update() const
bool operator!=(const OctetString &s1, const OctetString &s2)
X509_Code add_crl(const X509_CRL &)
MemoryVector< byte > authority_key_id() const
void add_new_certstore(Certificate_Store *)
X509_DN issuer_dn() const
std::vector< X509_Certificate > get_cert_chain(const X509_Certificate &)
bool operator==(const OctetString &s1, const OctetString &s2)
std::vector< std::string > split_on(const std::string &str, char delim)
std::invalid_argument Invalid_Argument
void add_trusted_certs(DataSource &)
unsigned long long u64bit
X509_Time next_update() const
std::string end_time() const
std::string lookup(const OID &oid)
virtual bool end_of_data() const =0
std::string start_time() const
std::runtime_error Exception
X509_Code validate_cert(const X509_Certificate &, Cert_Usage=ANY)
void add_certs(DataSource &)
MemoryVector< byte > subject_key_id() const
std::vector< CRL_Entry > get_revoked() const
bool BOTAN_DLL operator<(const X509_Time &, const X509_Time &)
bool is_self_signed() const
Public_Key * subject_public_key() const
X509_DN subject_dn() const
void add_cert(const X509_Certificate &, bool=false)
X509_Store(u32bit time_slack=24 *60 *60, u32bit cache_results=30 *60)