Botan  1.10.9
x509stor.cpp
Go to the documentation of this file.
1 /*
2 * X.509 Certificate Store
3 * (C) 1999-2007 Jack Lloyd
4 *
5 * Distributed under the terms of the Botan license
6 */
7 
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>
13 #include <algorithm>
14 #include <memory>
15 
16 namespace Botan {
17 
18 namespace {
19 
20 /*
21 * Do a validity check
22 */
23 s32bit validity_check(const X509_Time& start, const X509_Time& end,
24  u64bit current_time, u32bit slack)
25  {
26  const s32bit NOT_YET_VALID = -1, VALID_TIME = 0, EXPIRED = 1;
27 
28  if(start.cmp(current_time + slack) > 0)
29  return NOT_YET_VALID;
30  if(end.cmp(current_time - slack) < 0)
31  return EXPIRED;
32  return VALID_TIME;
33  }
34 
35 /*
36 * Compare the value of unique ID fields
37 */
38 bool compare_ids(const MemoryVector<byte>& id1,
39  const MemoryVector<byte>& id2)
40  {
41  if(!id1.size() || !id2.size())
42  return true;
43  return (id1 == id2);
44  }
45 
46 /*
47 * Check a particular usage restriction
48 */
49 bool check_usage(const X509_Certificate& cert, X509_Store::Cert_Usage usage,
50  X509_Store::Cert_Usage check_for, Key_Constraints constraints)
51  {
52  if((usage & check_for) == 0)
53  return true;
54  if(cert.constraints() == NO_CONSTRAINTS)
55  return true;
56  if(cert.constraints() & constraints)
57  return true;
58  return false;
59  }
60 
61 /*
62 * Check a particular usage restriction
63 */
64 bool check_usage(const X509_Certificate& cert, X509_Store::Cert_Usage usage,
65  X509_Store::Cert_Usage check_for,
66  const std::string& usage_oid)
67  {
68  if((usage & check_for) == 0)
69  return true;
70 
71  const std::vector<std::string> constraints = cert.ex_constraints();
72 
73  if(constraints.empty())
74  return true;
75 
76  return std::binary_search(constraints.begin(), constraints.end(),
77  usage_oid);
78  }
79 
80 /*
81 * Check the usage restrictions
82 */
83 X509_Code usage_check(const X509_Certificate& cert,
85  {
86  if(usage == X509_Store::ANY)
87  return VERIFIED;
88 
89  if(!check_usage(cert, usage, X509_Store::CRL_SIGNING, CRL_SIGN))
91 
92  if(!check_usage(cert, usage, X509_Store::TLS_SERVER, "PKIX.ServerAuth"))
93  return INVALID_USAGE;
94  if(!check_usage(cert, usage, X509_Store::TLS_CLIENT, "PKIX.ClientAuth"))
95  return INVALID_USAGE;
96  if(!check_usage(cert, usage, X509_Store::CODE_SIGNING, "PKIX.CodeSigning"))
97  return INVALID_USAGE;
98  if(!check_usage(cert, usage, X509_Store::EMAIL_PROTECTION,
99  "PKIX.EmailProtection"))
100  return INVALID_USAGE;
101  if(!check_usage(cert, usage, X509_Store::TIME_STAMPING,
102  "PKIX.TimeStamping"))
103  return INVALID_USAGE;
104 
105  return VERIFIED;
106  }
107 
108 }
109 
110 /*
111 * Define equality for revocation data
112 */
113 bool X509_Store::CRL_Data::operator==(const CRL_Data& other) const
114  {
115  if(issuer != other.issuer)
116  return false;
117  if(serial != other.serial)
118  return false;
119  return compare_ids(auth_key_id, other.auth_key_id);
120  }
121 
122 /*
123 * Define inequality for revocation data
124 */
125 bool X509_Store::CRL_Data::operator!=(const CRL_Data& other) const
126  {
127  return !((*this) == other);
128  }
129 
130 /*
131 * Define an ordering for revocation data
132 */
133 bool X509_Store::CRL_Data::operator<(const X509_Store::CRL_Data& other) const
134  {
135  if(*this == other)
136  return false;
137 
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;
142 
143  if(compare_ids(key_id1, key_id2) == false)
144  {
145  if(std::lexicographical_compare(key_id1.begin(), key_id1.end(),
146  key_id2.begin(), key_id2.end()))
147  return true;
148 
149  if(std::lexicographical_compare(key_id2.begin(), key_id2.end(),
150  key_id1.begin(), key_id1.end()))
151  return false;
152  }
153 
154  if(compare_ids(serial1, serial2) == false)
155  {
156  if(std::lexicographical_compare(serial1.begin(), serial1.end(),
157  serial2.begin(), serial2.end()))
158  return true;
159 
160  if(std::lexicographical_compare(serial2.begin(), serial2.end(),
161  serial1.begin(), serial1.end()))
162  return false;
163  }
164 
165  return (issuer < other.issuer);
166  }
167 
168 /*
169 * X509_Store Constructor
170 */
171 X509_Store::X509_Store(u32bit slack, u32bit cache_timeout)
172  {
173  revoked_info_valid = true;
174 
175  validation_cache_timeout = cache_timeout;
176  time_slack = slack;
177  }
178 
179 /*
180 * X509_Store Copy Constructor
181 */
183  {
184  certs = other.certs;
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;
191  }
192 
193 /*
194 * X509_Store Destructor
195 */
197  {
198  for(size_t j = 0; j != stores.size(); ++j)
199  delete stores[j];
200  }
201 
202 /*
203 * Verify a certificate's authenticity
204 */
206  Cert_Usage cert_usage)
207  {
208  recompute_revoked_info();
209 
210  std::vector<size_t> indexes;
211  X509_Code chaining_result = construct_cert_chain(cert, indexes);
212  if(chaining_result != VERIFIED)
213  return chaining_result;
214 
215  const u64bit current_time = system_time();
216 
217  s32bit time_check = validity_check(cert.start_time(), cert.end_time(),
218  current_time, time_slack);
219  if(time_check < 0) return CERT_NOT_YET_VALID;
220  else if(time_check > 0) return CERT_HAS_EXPIRED;
221 
222  X509_Code sig_check_result = check_sig(cert, certs[indexes[0]]);
223  if(sig_check_result != VERIFIED)
224  return sig_check_result;
225 
226  if(is_revoked(cert))
227  return CERT_IS_REVOKED;
228 
229  for(size_t j = 0; j != indexes.size() - 1; ++j)
230  {
231  const X509_Certificate& current_cert = certs[indexes[j]].cert;
232 
233  time_check = validity_check(current_cert.start_time(),
234  current_cert.end_time(),
235  current_time,
236  time_slack);
237 
238  if(time_check < 0) return CERT_NOT_YET_VALID;
239  else if(time_check > 0) return CERT_HAS_EXPIRED;
240 
241  sig_check_result = check_sig(certs[indexes[j]], certs[indexes[j+1]]);
242  if(sig_check_result != VERIFIED)
243  return sig_check_result;
244  }
245 
246  return usage_check(cert, cert_usage);
247  }
248 
249 /*
250 * Find this certificate
251 */
252 size_t X509_Store::find_cert(const X509_DN& subject_dn,
253  const MemoryRegion<byte>& subject_key_id) const
254  {
255  for(size_t j = 0; j != certs.size(); ++j)
256  {
257  const X509_Certificate& this_cert = certs[j].cert;
258  if(compare_ids(this_cert.subject_key_id(), subject_key_id) &&
259  this_cert.subject_dn() == subject_dn)
260  return j;
261  }
262  return NO_CERT_FOUND;
263  }
264 
265 /*
266 * Find the parent of this certificate
267 */
268 size_t X509_Store::find_parent_of(const X509_Certificate& cert)
269  {
270  const X509_DN issuer_dn = cert.issuer_dn();
271  const MemoryVector<byte> auth_key_id = cert.authority_key_id();
272 
273  size_t index = find_cert(issuer_dn, auth_key_id);
274 
275  if(index != NO_CERT_FOUND)
276  return index;
277 
278  for(size_t j = 0; j != stores.size(); ++j)
279  {
280  std::vector<X509_Certificate> got =
281  stores[j]->find_cert_by_subject_and_key_id(issuer_dn, auth_key_id);
282 
283  for(size_t k = 0; k != got.size(); ++k)
284  add_cert(got[k]);
285  }
286 
287  return find_cert(issuer_dn, auth_key_id);
288  }
289 
290 /*
291 * Construct a chain of certificate relationships
292 */
293 X509_Code X509_Store::construct_cert_chain(const X509_Certificate& end_cert,
294  std::vector<size_t>& indexes,
295  bool need_full_chain)
296  {
297  size_t parent = find_parent_of(end_cert);
298 
299  while(true)
300  {
301  if(parent == NO_CERT_FOUND)
302  return CERT_ISSUER_NOT_FOUND;
303  indexes.push_back(parent);
304 
305  if(certs[parent].is_verified(validation_cache_timeout))
306  if(certs[parent].verify_result() != VERIFIED)
307  return certs[parent].verify_result();
308 
309  const X509_Certificate& parent_cert = certs[parent].cert;
310  if(!parent_cert.is_CA_cert())
312 
313  if(certs[parent].is_trusted())
314  break;
315  if(parent_cert.is_self_signed())
316  return CANNOT_ESTABLISH_TRUST;
317 
318  if(parent_cert.path_limit() < indexes.size() - 1)
319  return CERT_CHAIN_TOO_LONG;
320 
321  parent = find_parent_of(parent_cert);
322  }
323 
324  if(need_full_chain)
325  return VERIFIED;
326 
327  while(true)
328  {
329  if(indexes.size() < 2)
330  break;
331 
332  const size_t cert = indexes.back();
333 
334  if(certs[cert].is_verified(validation_cache_timeout))
335  {
336  if(certs[cert].verify_result() != VERIFIED)
337  throw Internal_Error("X509_Store::construct_cert_chain");
338  indexes.pop_back();
339  }
340  else
341  break;
342  }
343 
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)
347  return CERT_ISSUER_NOT_FOUND;
348  indexes.push_back(parent_of_last_cert);
349 
350  return VERIFIED;
351  }
352 
353 /*
354 * Check the CAs signature on a certificate
355 */
356 X509_Code X509_Store::check_sig(const Cert_Info& cert_info,
357  const Cert_Info& ca_cert_info) const
358  {
359  if(cert_info.is_verified(validation_cache_timeout))
360  return cert_info.verify_result();
361 
362  const X509_Certificate& cert = cert_info.cert;
363  const X509_Certificate& ca_cert = ca_cert_info.cert;
364 
365  X509_Code verify_code = check_sig(cert, ca_cert.subject_public_key());
366 
367  cert_info.set_result(verify_code);
368 
369  return verify_code;
370  }
371 
372 /*
373 * Check a CA's signature
374 */
375 X509_Code X509_Store::check_sig(const X509_Object& object, Public_Key* key)
376  {
377  std::auto_ptr<Public_Key> pub_key(key);
378 
379  try {
380  std::vector<std::string> sig_info =
381  split_on(OIDS::lookup(object.signature_algorithm().oid), '/');
382 
383  if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
384  return SIGNATURE_ERROR;
385 
386  std::string padding = sig_info[1];
387  Signature_Format format;
388  if(key->message_parts() >= 2) format = DER_SEQUENCE;
389  else format = IEEE_1363;
390 
391  PK_Verifier verifier(*pub_key.get(), padding, format);
392 
393  bool valid = verifier.verify_message(object.tbs_data(),
394  object.signature());
395 
396  if(valid)
397  return VERIFIED;
398  else
399  return SIGNATURE_ERROR;
400  }
401  catch(Lookup_Error) { return CA_CERT_CANNOT_SIGN; }
402  catch(Decoding_Error) { return CERT_FORMAT_ERROR; }
403  catch(Exception) {}
404 
405  return UNKNOWN_X509_ERROR;
406  }
407 
408 /*
409 * Recompute the revocation status of the certs
410 */
411 void X509_Store::recompute_revoked_info() const
412  {
413  if(revoked_info_valid)
414  return;
415 
416  for(size_t j = 0; j != certs.size(); ++j)
417  {
418  if((certs[j].is_verified(validation_cache_timeout)) &&
419  (certs[j].verify_result() != VERIFIED))
420  continue;
421 
422  if(is_revoked(certs[j].cert))
423  certs[j].set_result(CERT_IS_REVOKED);
424  }
425 
426  revoked_info_valid = true;
427  }
428 
429 /*
430 * Check if a certificate is revoked
431 */
432 bool X509_Store::is_revoked(const X509_Certificate& cert) const
433  {
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();
438 
439  if(std::binary_search(revoked.begin(), revoked.end(), revoked_info))
440  return true;
441  return false;
442  }
443 
444 /*
445 * Construct a path back to a root for this cert
446 */
447 std::vector<X509_Certificate>
449  {
450  std::vector<X509_Certificate> result;
451  std::vector<size_t> indexes;
452  X509_Code chaining_result = construct_cert_chain(cert, indexes, true);
453 
454  if(chaining_result != VERIFIED)
455  throw Invalid_State("X509_Store::get_cert_chain: Can't construct chain");
456 
457  for(size_t j = 0; j != indexes.size(); ++j)
458  result.push_back(certs[indexes[j]].cert);
459  return result;
460  }
461 
462 /*
463 * Add a certificate store to the list of stores
464 */
466  {
467  stores.push_back(certstore);
468  }
469 
470 /*
471 * Add a certificate to the store
472 */
473 void X509_Store::add_cert(const X509_Certificate& cert, bool trusted)
474  {
475  if(trusted && !cert.is_self_signed())
476  throw Invalid_Argument("X509_Store: Trusted certs must be self-signed");
477 
478  if(find_cert(cert.subject_dn(), cert.subject_key_id()) == NO_CERT_FOUND)
479  {
480  revoked_info_valid = false;
481  Cert_Info info(cert, trusted);
482  certs.push_back(info);
483  }
484  else if(trusted)
485  {
486  for(size_t j = 0; j != certs.size(); ++j)
487  {
488  const X509_Certificate& this_cert = certs[j].cert;
489  if(this_cert == cert)
490  certs[j].trusted = trusted;
491  }
492  }
493  }
494 
495 /*
496 * Add one or more certificates to the store
497 */
498 void X509_Store::do_add_certs(DataSource& source, bool trusted)
499  {
500  while(!source.end_of_data())
501  {
502  try {
503  X509_Certificate cert(source);
504  add_cert(cert, trusted);
505  }
506  catch(Decoding_Error) {}
507  catch(Invalid_Argument) {}
508  }
509  }
510 
511 /*
512 * Add one or more certificates to the store
513 */
515  {
516  do_add_certs(source, false);
517  }
518 
519 /*
520 * Add one or more certificates to the store
521 */
523  {
524  do_add_certs(source, true);
525  }
526 
527 /*
528 * Add one or more certificates to the store
529 */
531  {
532  s32bit time_check = validity_check(crl.this_update(), crl.next_update(),
533  system_time(), time_slack);
534 
535  if(time_check < 0) return CRL_NOT_YET_VALID;
536  else if(time_check > 0) return CRL_HAS_EXPIRED;
537 
538  size_t cert_index = NO_CERT_FOUND;
539 
540  for(size_t j = 0; j != certs.size(); ++j)
541  {
542  const X509_Certificate& this_cert = certs[j].cert;
543  if(compare_ids(this_cert.subject_key_id(), crl.authority_key_id()))
544  {
545  if(this_cert.subject_dn() == crl.issuer_dn())
546  cert_index = j;
547  }
548  }
549 
550  if(cert_index == NO_CERT_FOUND)
551  return CRL_ISSUER_NOT_FOUND;
552 
553  const X509_Certificate& ca_cert = certs[cert_index].cert;
554 
555  X509_Code verify_result = validate_cert(ca_cert, CRL_SIGNING);
556  if(verify_result != VERIFIED)
557  return verify_result;
558 
559  verify_result = check_sig(crl, ca_cert.subject_public_key());
560  if(verify_result != VERIFIED)
561  return verify_result;
562 
563  std::vector<CRL_Entry> revoked_certs = crl.get_revoked();
564 
565  for(size_t j = 0; j != revoked_certs.size(); ++j)
566  {
567  CRL_Data revoked_info;
568  revoked_info.issuer = crl.issuer_dn();
569  revoked_info.serial = revoked_certs[j].serial_number();
570  revoked_info.auth_key_id = crl.authority_key_id();
571 
572  std::vector<CRL_Data>::iterator p =
573  std::find(revoked.begin(), revoked.end(), revoked_info);
574 
575  if(revoked_certs[j].reason_code() == REMOVE_FROM_CRL)
576  {
577  if(p == revoked.end()) continue;
578  revoked.erase(p);
579  }
580  else
581  {
582  if(p != revoked.end()) continue;
583  revoked.push_back(revoked_info);
584  }
585  }
586 
587  std::sort(revoked.begin(), revoked.end());
588  revoked_info_valid = false;
589 
590  return VERIFIED;
591  }
592 
593 /*
594 * PEM encode the set of certificates
595 */
596 std::string X509_Store::PEM_encode() const
597  {
598  std::string cert_store;
599  for(size_t j = 0; j != certs.size(); ++j)
600  cert_store += certs[j].cert.PEM_encode();
601  return cert_store;
602  }
603 
604 /*
605 * Create a Cert_Info structure
606 */
607 X509_Store::Cert_Info::Cert_Info(const X509_Certificate& c,
608  bool t) : cert(c), trusted(t)
609  {
610  checked = false;
611  result = UNKNOWN_X509_ERROR;
612  last_checked = 0;
613  }
614 
615 /*
616 * Return the verification results
617 */
618 X509_Code X509_Store::Cert_Info::verify_result() const
619  {
620  if(!checked)
621  throw Invalid_State("Cert_Info::verify_result() called; not checked");
622  return result;
623  }
624 
625 /*
626 * Set the verification results
627 */
628 void X509_Store::Cert_Info::set_result(X509_Code code) const
629  {
630  result = code;
631  last_checked = system_time();
632  checked = true;
633  }
634 
635 /*
636 * Check if this certificate can be trusted
637 */
638 bool X509_Store::Cert_Info::is_trusted() const
639  {
640  return trusted;
641  }
642 
643 /*
644 * Check if this certificate has been verified
645 */
646 bool X509_Store::Cert_Info::is_verified(u32bit timeout) const
647  {
648  if(!checked)
649  return false;
650  if(result != VERIFIED && result != CERT_NOT_YET_VALID)
651  return true;
652 
653  const u64bit current_time = system_time();
654 
655  if(current_time > last_checked + timeout)
656  checked = false;
657 
658  return checked;
659  }
660 
661 }
std::string PEM_encode() const
Definition: x509stor.cpp:596
X509_Time this_update() const
Definition: x509_crl.cpp:134
bool operator!=(const OctetString &s1, const OctetString &s2)
Definition: symkey.cpp:106
X509_Code add_crl(const X509_CRL &)
Definition: x509stor.cpp:530
MemoryVector< byte > authority_key_id() const
Definition: x509_crl.cpp:118
void add_new_certstore(Certificate_Store *)
Definition: x509stor.cpp:465
X509_DN issuer_dn() const
Definition: x509_crl.cpp:110
std::vector< X509_Certificate > get_cert_chain(const X509_Certificate &)
Definition: x509stor.cpp:448
bool operator==(const OctetString &s1, const OctetString &s2)
Definition: symkey.cpp:98
Signature_Format
Definition: pubkey.h:24
std::vector< std::string > split_on(const std::string &str, char delim)
Definition: parsing.cpp:152
std::invalid_argument Invalid_Argument
Definition: exceptn.h:20
void add_trusted_certs(DataSource &)
Definition: x509stor.cpp:522
bool valid
Definition: es_capi.cpp:48
signed int s32bit
Definition: types.h:37
unsigned long long u64bit
Definition: types.h:49
X509_Time next_update() const
Definition: x509_crl.cpp:142
std::string end_time() const
Definition: x509cert.cpp:170
std::string lookup(const OID &oid)
Definition: oids.cpp:31
virtual bool end_of_data() const =0
std::string start_time() const
Definition: x509cert.cpp:162
std::runtime_error Exception
Definition: exceptn.h:19
X509_Code validate_cert(const X509_Certificate &, Cert_Usage=ANY)
Definition: x509stor.cpp:205
void add_certs(DataSource &)
Definition: x509stor.cpp:514
MemoryVector< byte > subject_key_id() const
Definition: x509cert.cpp:258
std::vector< CRL_Entry > get_revoked() const
Definition: x509_crl.cpp:102
bool BOTAN_DLL operator<(const X509_Time &, const X509_Time &)
Definition: asn1_tm.cpp:286
bool is_self_signed() const
Definition: x509cert.h:106
X509_Code
Definition: x509stor.h:20
Public_Key * subject_public_key() const
Definition: x509cert.cpp:196
X509_DN subject_dn() const
Definition: x509cert.cpp:282
Key_Constraints
Definition: pubkey_enums.h:18
u64bit system_time()
Definition: time.cpp:73
unsigned int u32bit
Definition: types.h:32
OID oid
Definition: x509_ext.cpp:446
void add_cert(const X509_Certificate &, bool=false)
Definition: x509stor.cpp:473
X509_Store(u32bit time_slack=24 *60 *60, u32bit cache_results=30 *60)
Definition: x509stor.cpp:171