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 */
validity_check(const X509_Time & start,const X509_Time & end,u64bit current_time,u32bit slack)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 */
compare_ids(const MemoryVector<byte> & id1,const MemoryVector<byte> & id2)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 */
check_usage(const X509_Certificate & cert,X509_Store::Cert_Usage usage,X509_Store::Cert_Usage check_for,Key_Constraints constraints)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 */
check_usage(const X509_Certificate & cert,X509_Store::Cert_Usage usage,X509_Store::Cert_Usage check_for,const std::string & usage_oid)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 */
usage_check(const X509_Certificate & cert,X509_Store::Cert_Usage usage)83 X509_Code usage_check(const X509_Certificate& cert,
84                       X509_Store::Cert_Usage usage)
85    {
86    if(usage == X509_Store::ANY)
87       return VERIFIED;
88 
89    if(!check_usage(cert, usage, X509_Store::CRL_SIGNING, CRL_SIGN))
90       return CA_CERT_NOT_FOR_CRL_ISSUER;
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 */
operator ==(const CRL_Data & other) const113 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 */
operator !=(const CRL_Data & other) const125 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 */
operator <(const X509_Store::CRL_Data & other) const133 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 */
X509_Store(u32bit slack,u32bit cache_timeout)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 */
X509_Store(const X509_Store & other)182 X509_Store::X509_Store(const X509_Store& other)
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 */
~X509_Store()196 X509_Store::~X509_Store()
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 */
validate_cert(const X509_Certificate & cert,Cert_Usage cert_usage)205 X509_Code X509_Store::validate_cert(const X509_Certificate& cert,
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 */
find_cert(const X509_DN & subject_dn,const MemoryRegion<byte> & subject_key_id) const252 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 */
find_parent_of(const X509_Certificate & cert)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 */
construct_cert_chain(const X509_Certificate & end_cert,std::vector<size_t> & indexes,bool need_full_chain)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())
311          return CA_CERT_NOT_FOR_CERT_ISSUER;
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 */
check_sig(const Cert_Info & cert_info,const Cert_Info & ca_cert_info) const356 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 */
check_sig(const X509_Object & object,Public_Key * key)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 */
recompute_revoked_info() const411 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 */
is_revoked(const X509_Certificate & cert) const432 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>
get_cert_chain(const X509_Certificate & cert)448 X509_Store::get_cert_chain(const X509_Certificate& cert)
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 */
add_new_certstore(Certificate_Store * certstore)465 void X509_Store::add_new_certstore(Certificate_Store* certstore)
466    {
467    stores.push_back(certstore);
468    }
469 
470 /*
471 * Add a certificate to the store
472 */
add_cert(const X509_Certificate & cert,bool trusted)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 */
do_add_certs(DataSource & source,bool trusted)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 */
add_certs(DataSource & source)514 void X509_Store::add_certs(DataSource& source)
515    {
516    do_add_certs(source, false);
517    }
518 
519 /*
520 * Add one or more certificates to the store
521 */
add_trusted_certs(DataSource & source)522 void X509_Store::add_trusted_certs(DataSource& source)
523    {
524    do_add_certs(source, true);
525    }
526 
527 /*
528 * Add one or more certificates to the store
529 */
add_crl(const X509_CRL & crl)530 X509_Code X509_Store::add_crl(const X509_CRL& crl)
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 */
PEM_encode() const596 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 */
Cert_Info(const X509_Certificate & c,bool t)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 */
verify_result() const618 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 */
set_result(X509_Code code) const628 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 */
is_trusted() const638 bool X509_Store::Cert_Info::is_trusted() const
639    {
640    return trusted;
641    }
642 
643 /*
644 * Check if this certificate has been verified
645 */
is_verified(u32bit timeout) const646 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 }
662