diff options
author | lloyd <[email protected]> | 2012-03-28 21:09:47 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-03-28 21:09:47 +0000 |
commit | d4050e6b838acfd9552b4ab137fbf0717ff1e0ca (patch) | |
tree | a811718e0ada95191fd64c353bb2357953be86d3 /src/cert | |
parent | 199bc49219175d29076692a3131ac5425d750461 (diff) | |
parent | f1a2b5a7b5f35322927446d1b9a381f05cc677df (diff) |
propagate from branch 'net.randombit.botan' (head 0d0f3fba72f3300bc995c79124a75a4fc0b83879)
to branch 'net.randombit.botan.x509-path-validation' (head 48d03e596f032c0c69d691dbf49a2a1415b348c3)
Diffstat (limited to 'src/cert')
-rw-r--r-- | src/cert/certstore/info.txt | 6 | ||||
-rw-r--r-- | src/cert/pkcs10/info.txt | 6 | ||||
-rw-r--r-- | src/cert/x509/certstor.cpp (renamed from src/cert/certstore/certstor.cpp) | 22 | ||||
-rw-r--r-- | src/cert/x509/certstor.h (renamed from src/cert/certstore/certstor.h) | 16 | ||||
-rw-r--r-- | src/cert/x509/crl_ent.cpp (renamed from src/cert/x509crl/crl_ent.cpp) | 0 | ||||
-rw-r--r-- | src/cert/x509/crl_ent.h (renamed from src/cert/x509crl/crl_ent.h) | 20 | ||||
-rw-r--r-- | src/cert/x509/info.txt (renamed from src/cert/x509cert/info.txt) | 1 | ||||
-rw-r--r-- | src/cert/x509/pkcs10.cpp (renamed from src/cert/pkcs10/pkcs10.cpp) | 0 | ||||
-rw-r--r-- | src/cert/x509/pkcs10.h (renamed from src/cert/pkcs10/pkcs10.h) | 0 | ||||
-rw-r--r-- | src/cert/x509/x509_ca.cpp (renamed from src/cert/x509ca/x509_ca.cpp) | 0 | ||||
-rw-r--r-- | src/cert/x509/x509_ca.h (renamed from src/cert/x509ca/x509_ca.h) | 0 | ||||
-rw-r--r-- | src/cert/x509/x509_crl.cpp (renamed from src/cert/x509crl/x509_crl.cpp) | 38 | ||||
-rw-r--r-- | src/cert/x509/x509_crl.h (renamed from src/cert/x509crl/x509_crl.h) | 7 | ||||
-rw-r--r-- | src/cert/x509/x509_ext.cpp (renamed from src/cert/x509cert/x509_ext.cpp) | 0 | ||||
-rw-r--r-- | src/cert/x509/x509_ext.h (renamed from src/cert/x509cert/x509_ext.h) | 2 | ||||
-rw-r--r-- | src/cert/x509/x509_obj.cpp (renamed from src/cert/x509cert/x509_obj.cpp) | 5 | ||||
-rw-r--r-- | src/cert/x509/x509_obj.h (renamed from src/cert/x509cert/x509_obj.h) | 0 | ||||
-rw-r--r-- | src/cert/x509/x509cert.cpp (renamed from src/cert/x509cert/x509cert.cpp) | 10 | ||||
-rw-r--r-- | src/cert/x509/x509cert.h (renamed from src/cert/x509cert/x509cert.h) | 10 | ||||
-rw-r--r-- | src/cert/x509/x509opt.cpp (renamed from src/cert/x509self/x509opt.cpp) | 0 | ||||
-rw-r--r-- | src/cert/x509/x509path.cpp | 211 | ||||
-rw-r--r-- | src/cert/x509/x509path.h | 110 | ||||
-rw-r--r-- | src/cert/x509/x509self.cpp (renamed from src/cert/x509self/x509self.cpp) | 0 | ||||
-rw-r--r-- | src/cert/x509/x509self.h (renamed from src/cert/x509self/x509self.h) | 0 | ||||
-rw-r--r-- | src/cert/x509ca/info.txt | 6 | ||||
-rw-r--r-- | src/cert/x509crl/info.txt | 6 | ||||
-rw-r--r-- | src/cert/x509self/info.txt | 6 | ||||
-rw-r--r-- | src/cert/x509store/info.txt | 5 | ||||
-rw-r--r-- | src/cert/x509store/x509stor.cpp | 660 | ||||
-rw-r--r-- | src/cert/x509store/x509stor.h | 131 |
30 files changed, 424 insertions, 854 deletions
diff --git a/src/cert/certstore/info.txt b/src/cert/certstore/info.txt deleted file mode 100644 index a5de1baff..000000000 --- a/src/cert/certstore/info.txt +++ /dev/null @@ -1,6 +0,0 @@ -define CERTIFICATE_STORE - -<requires> -x509cert -x509crl -</requires> diff --git a/src/cert/pkcs10/info.txt b/src/cert/pkcs10/info.txt deleted file mode 100644 index bf53a562a..000000000 --- a/src/cert/pkcs10/info.txt +++ /dev/null @@ -1,6 +0,0 @@ -define PKCS10_REQUESTS - -<requires> -asn1 -x509cert -</requires> diff --git a/src/cert/certstore/certstor.cpp b/src/cert/x509/certstor.cpp index 3cba2f39e..de27361ed 100644 --- a/src/cert/certstore/certstor.cpp +++ b/src/cert/x509/certstor.cpp @@ -9,12 +9,16 @@ namespace Botan { -Certificate_Store* Certificate_Store_Memory::clone() const +bool Certificate_Store::certificate_known(const X509_Certificate& cert) const { - return new Certificate_Store_Memory(*this); + std::vector<X509_Certificate> found = + find_cert_by_subject_and_key_id(cert.subject_dn(), + cert.subject_key_id()); + + return (found.size() > 0); } -void Certificate_Store_Memory::add_certificate(const X509_Certificate& cert) +void Certificate_Store_In_Memory::add_certificate(const X509_Certificate& cert) { for(size_t i = 0; i != certs.size(); ++i) { @@ -26,7 +30,7 @@ void Certificate_Store_Memory::add_certificate(const X509_Certificate& cert) } std::vector<X509_Certificate> -Certificate_Store_Memory::find_cert_by_subject_and_key_id( +Certificate_Store_In_Memory::find_cert_by_subject_and_key_id( const X509_DN& subject_dn, const MemoryRegion<byte>& key_id) const { @@ -50,7 +54,7 @@ Certificate_Store_Memory::find_cert_by_subject_and_key_id( return result; } -void Certificate_Store_Memory::add_crl(const X509_CRL& crl) +void Certificate_Store_In_Memory::add_crl(const X509_CRL& crl) { X509_DN crl_issuer = crl.issuer_dn(); @@ -59,11 +63,9 @@ void Certificate_Store_Memory::add_crl(const X509_CRL& crl) // Found an update of a previously existing one; replace it if(crls[i].issuer_dn() == crl_issuer) { - if(crls[i].this_update() < crl.this_update()) - { + if(crls[i].this_update() <= crl.this_update()) crls[i] = crl; - return; - } + return; } } @@ -72,7 +74,7 @@ void Certificate_Store_Memory::add_crl(const X509_CRL& crl) } std::vector<X509_CRL> -Certificate_Store_Memory::find_crl_by_subject_and_key_id( +Certificate_Store_In_Memory::find_crl_by_issuer_and_key_id( const X509_DN& issuer_dn, const MemoryRegion<byte>& key_id) const { diff --git a/src/cert/certstore/certstor.h b/src/cert/x509/certstor.h index 374013984..e2727c569 100644 --- a/src/cert/certstore/certstor.h +++ b/src/cert/x509/certstor.h @@ -21,8 +21,6 @@ class BOTAN_DLL Certificate_Store public: virtual ~Certificate_Store() {} - virtual Certificate_Store* clone() const = 0; - /** * Add a certificate; this may fail if the store is write-only */ @@ -33,6 +31,8 @@ class BOTAN_DLL Certificate_Store */ virtual void add_crl(const X509_CRL& crl) = 0; + bool certificate_known(const X509_Certificate& cert) const; + /** * Subject DN and (optionally) key identifier */ @@ -45,7 +45,7 @@ class BOTAN_DLL Certificate_Store * Find CRLs by the DN and key id of the issuer */ virtual std::vector<X509_CRL> - find_crl_by_subject_and_key_id( + find_crl_by_issuer_and_key_id( const X509_DN& issuer_dn, const MemoryRegion<byte>& key_id) const = 0; }; @@ -53,11 +53,9 @@ class BOTAN_DLL Certificate_Store /** * In Memory Certificate Store */ -class BOTAN_DLL Certificate_Store_Memory : public Certificate_Store +class BOTAN_DLL Certificate_Store_In_Memory : public Certificate_Store { public: - Certificate_Store* clone() const; - void add_certificate(const X509_Certificate& cert); void add_crl(const X509_CRL& crl); @@ -66,13 +64,13 @@ class BOTAN_DLL Certificate_Store_Memory : public Certificate_Store const X509_DN& subject_dn, const MemoryRegion<byte>& key_id) const; - std::vector<X509_CRL> find_crl_by_subject_and_key_id( + std::vector<X509_CRL> find_crl_by_issuer_and_key_id( const X509_DN& issuer_dn, const MemoryRegion<byte>& key_id) const; - Certificate_Store_Memory() {} + Certificate_Store_In_Memory() {} private: - // TODO: Add indexing on the DN and key id to avoid linear search? + // TODO: Add indexing on the DN and key id to avoid linear search std::vector<X509_Certificate> certs; std::vector<X509_CRL> crls; }; diff --git a/src/cert/x509crl/crl_ent.cpp b/src/cert/x509/crl_ent.cpp index d566637f6..d566637f6 100644 --- a/src/cert/x509crl/crl_ent.cpp +++ b/src/cert/x509/crl_ent.cpp diff --git a/src/cert/x509crl/crl_ent.h b/src/cert/x509/crl_ent.h index b3e696a86..ae9535484 100644 --- a/src/cert/x509crl/crl_ent.h +++ b/src/cert/x509/crl_ent.h @@ -13,6 +13,26 @@ namespace Botan { /** +* X.509v2 CRL Reason Code. +*/ +enum CRL_Code { + UNSPECIFIED = 0, + KEY_COMPROMISE = 1, + CA_COMPROMISE = 2, + AFFILIATION_CHANGED = 3, + SUPERSEDED = 4, + CESSATION_OF_OPERATION = 5, + CERTIFICATE_HOLD = 6, + REMOVE_FROM_CRL = 8, + PRIVLEDGE_WITHDRAWN = 9, + AA_COMPROMISE = 10, + + DELETE_CRL_ENTRY = 0xFF00, + OCSP_GOOD = 0xFF01, + OCSP_UNKNOWN = 0xFF02 +}; + +/** * This class represents CRL entries */ class BOTAN_DLL CRL_Entry : public ASN1_Object diff --git a/src/cert/x509cert/info.txt b/src/cert/x509/info.txt index 5e3715e7a..c994dab8f 100644 --- a/src/cert/x509cert/info.txt +++ b/src/cert/x509/info.txt @@ -1,6 +1,5 @@ define X509_CERTIFICATES <requires> -certstore datastor </requires> diff --git a/src/cert/pkcs10/pkcs10.cpp b/src/cert/x509/pkcs10.cpp index 784318d3d..784318d3d 100644 --- a/src/cert/pkcs10/pkcs10.cpp +++ b/src/cert/x509/pkcs10.cpp diff --git a/src/cert/pkcs10/pkcs10.h b/src/cert/x509/pkcs10.h index bd01fb6b5..bd01fb6b5 100644 --- a/src/cert/pkcs10/pkcs10.h +++ b/src/cert/x509/pkcs10.h diff --git a/src/cert/x509ca/x509_ca.cpp b/src/cert/x509/x509_ca.cpp index 40f2e3b3a..40f2e3b3a 100644 --- a/src/cert/x509ca/x509_ca.cpp +++ b/src/cert/x509/x509_ca.cpp diff --git a/src/cert/x509ca/x509_ca.h b/src/cert/x509/x509_ca.h index 97be6a415..97be6a415 100644 --- a/src/cert/x509ca/x509_ca.h +++ b/src/cert/x509/x509_ca.h diff --git a/src/cert/x509crl/x509_crl.cpp b/src/cert/x509/x509_crl.cpp index 01fce4c52..9c6b891c7 100644 --- a/src/cert/x509crl/x509_crl.cpp +++ b/src/cert/x509/x509_crl.cpp @@ -7,6 +7,7 @@ #include <botan/x509_crl.h> #include <botan/x509_ext.h> +#include <botan/x509cert.h> #include <botan/ber_dec.h> #include <botan/parsing.h> #include <botan/bigint.h> @@ -32,6 +33,43 @@ X509_CRL::X509_CRL(const std::string& in, bool touc) : do_decode(); } +/** +* Check if this particular certificate is listed in the CRL +*/ +bool X509_CRL::is_revoked(const X509_Certificate& cert) const + { + /* + If the cert wasn't issued by the CRL issuer, it's possible the cert + is revoked, but not by this CRL. Maybe throw an exception instead? + */ + if(cert.issuer_dn() != issuer_dn()) + return false; + + MemoryVector<byte> crl_akid = authority_key_id(); + MemoryVector<byte> cert_akid = cert.authority_key_id(); + + if(!crl_akid.empty() && !cert_akid.empty()) + if(crl_akid != cert_akid) + return false; + + MemoryVector<byte> cert_serial = cert.serial_number(); + + bool is_revoked = false; + + for(size_t i = 0; i != revoked.size(); ++i) + { + if(cert_serial == revoked[i].serial_number()) + { + if(revoked[i].reason_code() == REMOVE_FROM_CRL) + is_revoked = false; + else + is_revoked = true; + } + } + + return is_revoked; + } + /* * Decode the TBSCertList data */ diff --git a/src/cert/x509crl/x509_crl.h b/src/cert/x509/x509_crl.h index c2b3c4f5c..55eb8424b 100644 --- a/src/cert/x509crl/x509_crl.h +++ b/src/cert/x509/x509_crl.h @@ -14,6 +14,8 @@ namespace Botan { +class X509_Certificate; + /** * This class represents X.509 Certificate Revocation Lists (CRLs). */ @@ -30,6 +32,11 @@ class BOTAN_DLL X509_CRL : public X509_Object }; /** + * Check if this particular certificate is listed in the CRL + */ + bool is_revoked(const X509_Certificate& cert) const; + + /** * Get the entries of this CRL in the form of a vector. * @return vector containing the entries of this CRL. */ diff --git a/src/cert/x509cert/x509_ext.cpp b/src/cert/x509/x509_ext.cpp index 6e0befaf3..6e0befaf3 100644 --- a/src/cert/x509cert/x509_ext.cpp +++ b/src/cert/x509/x509_ext.cpp diff --git a/src/cert/x509cert/x509_ext.h b/src/cert/x509/x509_ext.h index 8799c5921..714e29562 100644 --- a/src/cert/x509cert/x509_ext.h +++ b/src/cert/x509/x509_ext.h @@ -12,7 +12,7 @@ #include <botan/asn1_oid.h> #include <botan/asn1_obj.h> #include <botan/datastor.h> -#include <botan/pubkey_enums.h> +#include <botan/crl_ent.h> namespace Botan { diff --git a/src/cert/x509cert/x509_obj.cpp b/src/cert/x509/x509_obj.cpp index 13193f09c..c58081225 100644 --- a/src/cert/x509cert/x509_obj.cpp +++ b/src/cert/x509/x509_obj.cpp @@ -16,6 +16,8 @@ #include <algorithm> #include <memory> +#include <stdio.h> + namespace Botan { /* @@ -192,8 +194,9 @@ bool X509_Object::check_signature(Public_Key& pub_key) const return verifier.verify_message(tbs_data(), signature()); } - catch(...) + catch(std::exception& e) { + printf("Failure during validation %s\n", e.what()); return false; } } diff --git a/src/cert/x509cert/x509_obj.h b/src/cert/x509/x509_obj.h index 570b00f51..570b00f51 100644 --- a/src/cert/x509cert/x509_obj.h +++ b/src/cert/x509/x509_obj.h diff --git a/src/cert/x509cert/x509cert.cpp b/src/cert/x509/x509cert.cpp index 7d9370f2a..52115a1a8 100644 --- a/src/cert/x509cert/x509cert.cpp +++ b/src/cert/x509/x509cert.cpp @@ -206,9 +206,15 @@ bool X509_Certificate::is_CA_cert() const { if(!subject.get1_u32bit("X509v3.BasicConstraints.is_ca")) return false; - if((constraints() & KEY_CERT_SIGN) || (constraints() == NO_CONSTRAINTS)) + + return allowed_usage(KEY_CERT_SIGN); + } + +bool X509_Certificate::allowed_usage(Key_Constraints restriction) const + { + if(constraints() == NO_CONSTRAINTS) return true; - return false; + return (constraints() & restriction); } /* diff --git a/src/cert/x509cert/x509cert.h b/src/cert/x509/x509cert.h index 8798ef1c2..d25b97694 100644 --- a/src/cert/x509cert/x509cert.h +++ b/src/cert/x509/x509cert.h @@ -23,10 +23,10 @@ namespace Botan { class BOTAN_DLL X509_Certificate : public X509_Object { public: - /** - * Get the public key associated with this certificate. - * @return subject public key of this certificate - */ + /** + * Get the public key associated with this certificate. + * @return subject public key of this certificate + */ Public_Key* subject_public_key() const; /** @@ -111,6 +111,8 @@ class BOTAN_DLL X509_Certificate : public X509_Object */ bool is_CA_cert() const; + bool allowed_usage(Key_Constraints restriction) const; + /** * Get the path limit as defined in the BasicConstraints extension of * this certificate. diff --git a/src/cert/x509self/x509opt.cpp b/src/cert/x509/x509opt.cpp index 345df1fe0..345df1fe0 100644 --- a/src/cert/x509self/x509opt.cpp +++ b/src/cert/x509/x509opt.cpp diff --git a/src/cert/x509/x509path.cpp b/src/cert/x509/x509path.cpp new file mode 100644 index 000000000..a9b8150ae --- /dev/null +++ b/src/cert/x509/x509path.cpp @@ -0,0 +1,211 @@ +/* +* X.509 Certificate Path Validation +* (C) 2010-2011 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/x509path.h> +#include <botan/parsing.h> +#include <botan/pubkey.h> +#include <botan/oids.h> +#include <botan/time.h> +#include <algorithm> +#include <memory> + +namespace Botan { + +namespace { + +class PKIX_Validation_Failure : public std::exception + { + public: + PKIX_Validation_Failure(X509_Path_Validation_Code code) : m_code(code) {} + + X509_Path_Validation_Code code() const { return m_code; } + + const char* what() { return "PKIX validation failed"; } + private: + X509_Path_Validation_Code m_code; + }; + +X509_Certificate find_issuing_cert(const X509_Certificate& cert, + const std::vector<Certificate_Store*>& certstores) + { + const X509_DN issuer_dn = cert.issuer_dn(); + const MemoryVector<byte> auth_key_id = cert.authority_key_id(); + + for(size_t i = 0; i != certstores.size(); ++i) + { + std::vector<X509_Certificate> certs = + certstores[i]->find_cert_by_subject_and_key_id(issuer_dn, auth_key_id); + + if(certs.size() == 0) + throw PKIX_Validation_Failure(CERT_ISSUER_NOT_FOUND); + else if(certs.size() > 1) + throw PKIX_Validation_Failure(CERT_MULTIPLE_ISSUERS_FOUND); + + return certs[0]; + } + + throw PKIX_Validation_Failure(CERT_ISSUER_NOT_FOUND); + } + +std::vector<X509_CRL> find_crls_from(const X509_Certificate& cert, + const std::vector<Certificate_Store*>& certstores) + { + const X509_DN issuer_dn = cert.subject_dn(); + const MemoryVector<byte> auth_key_id = cert.subject_key_id(); + + for(size_t i = 0; i != certstores.size(); ++i) + { + std::vector<X509_CRL> crl = + certstores[i]->find_crl_by_issuer_and_key_id(issuer_dn, auth_key_id); + + if(!crl.empty()) + return crl; + } + + return std::vector<X509_CRL>(); + } + +} + +const X509_Certificate& Path_Validation_Result::trust_root() const + { + return m_cert_path[m_cert_path.size()-1]; + } + +std::set<std::string> Path_Validation_Result::trusted_hashes() const + { + std::set<std::string> hashes; + for(size_t i = 0; i != m_cert_path.size(); ++i) + hashes.insert(m_cert_path[i].hash_used_for_signature()); + return hashes; + } + +Path_Validation_Result x509_path_validate( + const X509_Certificate& end_cert, + const std::vector<Certificate_Store*>& certstores) + { + std::vector<X509_Certificate> certs; + certs.push_back(end_cert); + return x509_path_validate(certs, certstores); + } + +Path_Validation_Result x509_path_validate( + const std::vector<X509_Certificate>& end_certs, + Certificate_Store& store) + { + std::vector<Certificate_Store*> certstores; + certstores.push_back(&store); + + return x509_path_validate(end_certs, certstores); + } + +Path_Validation_Result x509_path_validate( + const X509_Certificate& end_cert, + Certificate_Store& store) + { + std::vector<X509_Certificate> certs; + certs.push_back(end_cert); + + std::vector<Certificate_Store*> certstores; + certstores.push_back(&store); + + return x509_path_validate(certs, certstores); + } + +Path_Validation_Result +x509_path_validate(const std::vector<X509_Certificate>& end_certs, + const std::vector<Certificate_Store*>& certstores) + { + Path_Validation_Result r; + + r.m_cert_path = end_certs; + + std::vector<X509_Certificate>& cert_path = r.m_cert_path; + + try + { + // iterate until we reach a root or cannot find the issuer + while(!cert_path.back().is_self_signed()) + { + cert_path.push_back( + find_issuing_cert(cert_path.back(), certstores) + ); + } + + const bool self_signed_ee_cert = (cert_path.size() == 1); + + X509_Time current_time(system_time()); + + for(size_t i = 0; i != cert_path.size(); ++i) + { + const X509_Certificate& subject = cert_path[i]; + + // Check all certs for valid time range + if(current_time < X509_Time(subject.start_time())) + throw PKIX_Validation_Failure(CERT_NOT_YET_VALID); + + if(current_time > X509_Time(subject.end_time())) + throw PKIX_Validation_Failure(CERT_HAS_EXPIRED); + + const bool at_self_signed_root = (i == cert_path.size() - 1); + + const X509_Certificate& issuer = + cert_path[at_self_signed_root ? (i) : (i + 1)]; + + // Check issuer constraints + + // Don't require CA bit set on self-signed end entity cert + if(!issuer.is_CA_cert() && !self_signed_ee_cert) + throw PKIX_Validation_Failure(CA_CERT_NOT_FOR_CERT_ISSUER); + + if(issuer.path_limit() < i) + throw PKIX_Validation_Failure(CERT_CHAIN_TOO_LONG); + + if(subject.check_signature(issuer.subject_public_key()) == false) + throw PKIX_Validation_Failure(SIGNATURE_ERROR); + } + + for(size_t i = 1; i != cert_path.size(); ++i) + { + const X509_Certificate& subject = cert_path[i-1]; + const X509_Certificate& ca = cert_path[i]; + + std::vector<X509_CRL> crls = find_crls_from(ca, certstores); + + if(crls.empty()) + //throw PKIX_Validation_Failure(CRL_NOT_FOUND); + continue; + + const X509_CRL& crl = crls[0]; + + if(!ca.allowed_usage(CRL_SIGN)) + throw PKIX_Validation_Failure(CA_CERT_NOT_FOR_CRL_ISSUER); + + if(current_time < X509_Time(crl.this_update())) + throw PKIX_Validation_Failure(CRL_NOT_YET_VALID); + + if(current_time > X509_Time(crl.next_update())) + throw PKIX_Validation_Failure(CRL_HAS_EXPIRED); + + if(crl.check_signature(ca.subject_public_key()) == false) + throw PKIX_Validation_Failure(SIGNATURE_ERROR); + + if(crl.is_revoked(subject)) + throw PKIX_Validation_Failure(CERT_IS_REVOKED); + } + + r.set_result(self_signed_ee_cert ? CANNOT_ESTABLISH_TRUST : VERIFIED); + } + catch(PKIX_Validation_Failure& e) + { + r.set_result(e.code()); + } + + return r; + } + +} diff --git a/src/cert/x509/x509path.h b/src/cert/x509/x509path.h new file mode 100644 index 000000000..c389431d8 --- /dev/null +++ b/src/cert/x509/x509path.h @@ -0,0 +1,110 @@ +/* +* X.509 Cert Path Validation +* (C) 2010-2011 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#ifndef BOTAN_X509_CERT_PATH_VALIDATION_H__ +#define BOTAN_X509_CERT_PATH_VALIDATION_H__ + +#include <botan/x509cert.h> +#include <botan/certstor.h> +#include <set> + +namespace Botan { + +/** +* X.509 Certificate Validation Result +*/ +enum X509_Path_Validation_Code { + VERIFIED, + UNKNOWN_X509_ERROR, + CANNOT_ESTABLISH_TRUST, + CERT_CHAIN_TOO_LONG, + SIGNATURE_ERROR, + POLICY_ERROR, + INVALID_USAGE, + + CERT_MULTIPLE_ISSUERS_FOUND, + + CERT_FORMAT_ERROR, + CERT_ISSUER_NOT_FOUND, + CERT_NOT_YET_VALID, + CERT_HAS_EXPIRED, + CERT_IS_REVOKED, + + CRL_NOT_FOUND, + CRL_FORMAT_ERROR, + CRL_ISSUER_NOT_FOUND, + CRL_NOT_YET_VALID, + CRL_HAS_EXPIRED, + + CA_CERT_CANNOT_SIGN, + CA_CERT_NOT_FOR_CERT_ISSUER, + CA_CERT_NOT_FOR_CRL_ISSUER +}; + +enum Usage_Restrictions { + NO_RESTRICTIONS = 0x00, + TLS_SERVER = 0x01, + TLS_CLIENT = 0x02, + CODE_SIGNING = 0x04, + EMAIL_PROTECTION = 0x08, + TIME_STAMPING = 0x10, + CRL_SIGNING = 0x20 +}; + +class BOTAN_DLL Path_Validation_Result + { + public: + Path_Validation_Result() : + m_result(UNKNOWN_X509_ERROR), + m_usages(NO_RESTRICTIONS) + {} + + /** + * Returns the set of hash functions you are implicitly + * trusting by trusting this result. + */ + std::set<std::string> trusted_hashes() const; + + const X509_Certificate& trust_root() const; + + const std::vector<X509_Certificate>& cert_path() const { return m_cert_path; } + + bool successful_validation() const { return result() == VERIFIED; } + + X509_Path_Validation_Code result() const { return m_result; } + private: + friend Path_Validation_Result x509_path_validate( + const std::vector<X509_Certificate>& end_certs, + const std::vector<Certificate_Store*>& certstores); + + void set_result(X509_Path_Validation_Code result) { m_result = result; } + + X509_Path_Validation_Code m_result; + Usage_Restrictions m_usages; + + std::vector<X509_Certificate> m_cert_path; + }; + +Path_Validation_Result BOTAN_DLL x509_path_validate( + const std::vector<X509_Certificate>& end_certs, + const std::vector<Certificate_Store*>& certstores); + +Path_Validation_Result BOTAN_DLL x509_path_validate( + const X509_Certificate& end_cert, + const std::vector<Certificate_Store*>& certstores); + +Path_Validation_Result BOTAN_DLL x509_path_validate( + const X509_Certificate& end_cert, + Certificate_Store& store); + +Path_Validation_Result BOTAN_DLL x509_path_validate( + const std::vector<X509_Certificate>& end_certs, + Certificate_Store& store); + +} + +#endif diff --git a/src/cert/x509self/x509self.cpp b/src/cert/x509/x509self.cpp index a2f89159f..a2f89159f 100644 --- a/src/cert/x509self/x509self.cpp +++ b/src/cert/x509/x509self.cpp diff --git a/src/cert/x509self/x509self.h b/src/cert/x509/x509self.h index 2850096c8..2850096c8 100644 --- a/src/cert/x509self/x509self.h +++ b/src/cert/x509/x509self.h diff --git a/src/cert/x509ca/info.txt b/src/cert/x509ca/info.txt deleted file mode 100644 index d412c3070..000000000 --- a/src/cert/x509ca/info.txt +++ /dev/null @@ -1,6 +0,0 @@ -define X509_CA - -<requires> -pkcs10 -x509cert -</requires> diff --git a/src/cert/x509crl/info.txt b/src/cert/x509crl/info.txt deleted file mode 100644 index 77de46074..000000000 --- a/src/cert/x509crl/info.txt +++ /dev/null @@ -1,6 +0,0 @@ -define X509_CRL - -<requires> -x509cert -</requires> - diff --git a/src/cert/x509self/info.txt b/src/cert/x509self/info.txt deleted file mode 100644 index bb02c4f74..000000000 --- a/src/cert/x509self/info.txt +++ /dev/null @@ -1,6 +0,0 @@ -define X509_SELF_SIGNED - -<requires> -x509cert -</requires> - diff --git a/src/cert/x509store/info.txt b/src/cert/x509store/info.txt deleted file mode 100644 index b24b03a02..000000000 --- a/src/cert/x509store/info.txt +++ /dev/null @@ -1,5 +0,0 @@ -define X509_STORE - -<requires> -x509cert -</requires> diff --git a/src/cert/x509store/x509stor.cpp b/src/cert/x509store/x509stor.cpp deleted file mode 100644 index 3fe1adf62..000000000 --- a/src/cert/x509store/x509stor.cpp +++ /dev/null @@ -1,660 +0,0 @@ -/* -* X.509 Certificate Store -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/x509stor.h> -#include <botan/parsing.h> -#include <botan/pubkey.h> -#include <botan/oids.h> -#include <botan/time.h> -#include <algorithm> -#include <memory> - -namespace Botan { - -namespace { - -/* -* Do a validity check -*/ -s32bit validity_check(const X509_Time& start, const X509_Time& end, - u64bit current_time, u32bit slack) - { - const s32bit NOT_YET_VALID = -1, VALID_TIME = 0, EXPIRED = 1; - - if(start.cmp(current_time + slack) > 0) - return NOT_YET_VALID; - if(end.cmp(current_time - slack) < 0) - return EXPIRED; - return VALID_TIME; - } - -/* -* Compare the value of unique ID fields -*/ -bool compare_ids(const MemoryVector<byte>& id1, - const MemoryVector<byte>& id2) - { - if(!id1.size() || !id2.size()) - return true; - return (id1 == id2); - } - -/* -* Check a particular usage restriction -*/ -bool check_usage(const X509_Certificate& cert, X509_Store::Cert_Usage usage, - X509_Store::Cert_Usage check_for, Key_Constraints constraints) - { - if((usage & check_for) == 0) - return true; - if(cert.constraints() == NO_CONSTRAINTS) - return true; - if(cert.constraints() & constraints) - return true; - return false; - } - -/* -* Check a particular usage restriction -*/ -bool check_usage(const X509_Certificate& cert, X509_Store::Cert_Usage usage, - X509_Store::Cert_Usage check_for, - const std::string& usage_oid) - { - if((usage & check_for) == 0) - return true; - - const std::vector<std::string> constraints = cert.ex_constraints(); - - if(constraints.empty()) - return true; - - return std::binary_search(constraints.begin(), constraints.end(), - usage_oid); - } - -/* -* Check the usage restrictions -*/ -X509_Code usage_check(const X509_Certificate& cert, - X509_Store::Cert_Usage usage) - { - if(usage == X509_Store::ANY) - return VERIFIED; - - if(!check_usage(cert, usage, X509_Store::CRL_SIGNING, CRL_SIGN)) - return CA_CERT_NOT_FOR_CRL_ISSUER; - - if(!check_usage(cert, usage, X509_Store::TLS_SERVER, "PKIX.ServerAuth")) - return INVALID_USAGE; - if(!check_usage(cert, usage, X509_Store::TLS_CLIENT, "PKIX.ClientAuth")) - return INVALID_USAGE; - if(!check_usage(cert, usage, X509_Store::CODE_SIGNING, "PKIX.CodeSigning")) - return INVALID_USAGE; - if(!check_usage(cert, usage, X509_Store::EMAIL_PROTECTION, - "PKIX.EmailProtection")) - return INVALID_USAGE; - if(!check_usage(cert, usage, X509_Store::TIME_STAMPING, - "PKIX.TimeStamping")) - return INVALID_USAGE; - - return VERIFIED; - } - -} - -/* -* Define equality for revocation data -*/ -bool X509_Store::CRL_Data::operator==(const CRL_Data& other) const - { - if(issuer != other.issuer) - return false; - if(serial != other.serial) - return false; - return compare_ids(auth_key_id, other.auth_key_id); - } - -/* -* Define inequality for revocation data -*/ -bool X509_Store::CRL_Data::operator!=(const CRL_Data& other) const - { - return !((*this) == other); - } - -/* -* Define an ordering for revocation data -*/ -bool X509_Store::CRL_Data::operator<(const X509_Store::CRL_Data& other) const - { - if(*this == other) - return false; - - const MemoryVector<byte>& serial1 = serial; - const MemoryVector<byte>& key_id1 = auth_key_id; - const MemoryVector<byte>& serial2 = other.serial; - const MemoryVector<byte>& key_id2 = other.auth_key_id; - - if(compare_ids(key_id1, key_id2) == false) - { - if(std::lexicographical_compare(key_id1.begin(), key_id1.end(), - key_id2.begin(), key_id2.end())) - return true; - - if(std::lexicographical_compare(key_id2.begin(), key_id2.end(), - key_id1.begin(), key_id1.end())) - return false; - } - - if(compare_ids(serial1, serial2) == false) - { - if(std::lexicographical_compare(serial1.begin(), serial1.end(), - serial2.begin(), serial2.end())) - return true; - - if(std::lexicographical_compare(serial2.begin(), serial2.end(), - serial1.begin(), serial1.end())) - return false; - } - - return (issuer < other.issuer); - } - -/* -* X509_Store Constructor -*/ -X509_Store::X509_Store(u32bit slack, u32bit cache_timeout) - { - revoked_info_valid = true; - - validation_cache_timeout = cache_timeout; - time_slack = slack; - } - -/* -* X509_Store Copy Constructor -*/ -X509_Store::X509_Store(const X509_Store& other) - { - certs = other.certs; - revoked = other.revoked; - revoked_info_valid = other.revoked_info_valid; - for(size_t j = 0; j != other.stores.size(); ++j) - stores[j] = other.stores[j]->clone(); - time_slack = other.time_slack; - } - -/* -* X509_Store Destructor -*/ -X509_Store::~X509_Store() - { - for(size_t j = 0; j != stores.size(); ++j) - delete stores[j]; - } - -/* -* Verify a certificate's authenticity -*/ -X509_Code X509_Store::validate_cert(const X509_Certificate& cert, - Cert_Usage cert_usage) - { - recompute_revoked_info(); - - std::vector<size_t> indexes; - X509_Code chaining_result = construct_cert_chain(cert, indexes); - if(chaining_result != VERIFIED) - return chaining_result; - - const u64bit current_time = system_time(); - - s32bit time_check = validity_check(cert.start_time(), cert.end_time(), - current_time, time_slack); - if(time_check < 0) return CERT_NOT_YET_VALID; - else if(time_check > 0) return CERT_HAS_EXPIRED; - - X509_Code sig_check_result = check_sig(cert, certs[indexes[0]]); - if(sig_check_result != VERIFIED) - return sig_check_result; - - if(is_revoked(cert)) - return CERT_IS_REVOKED; - - for(size_t j = 0; j != indexes.size() - 1; ++j) - { - const X509_Certificate& current_cert = certs[indexes[j]].cert; - - time_check = validity_check(current_cert.start_time(), - current_cert.end_time(), - current_time, - time_slack); - - if(time_check < 0) return CERT_NOT_YET_VALID; - else if(time_check > 0) return CERT_HAS_EXPIRED; - - sig_check_result = check_sig(certs[indexes[j]], certs[indexes[j+1]]); - if(sig_check_result != VERIFIED) - return sig_check_result; - } - - return usage_check(cert, cert_usage); - } - -/* -* Find this certificate -*/ -size_t X509_Store::find_cert(const X509_DN& subject_dn, - const MemoryRegion<byte>& subject_key_id) const - { - for(size_t j = 0; j != certs.size(); ++j) - { - const X509_Certificate& this_cert = certs[j].cert; - if(compare_ids(this_cert.subject_key_id(), subject_key_id) && - this_cert.subject_dn() == subject_dn) - return j; - } - return NO_CERT_FOUND; - } - -/* -* Find the parent of this certificate -*/ -size_t X509_Store::find_parent_of(const X509_Certificate& cert) - { - const X509_DN issuer_dn = cert.issuer_dn(); - const MemoryVector<byte> auth_key_id = cert.authority_key_id(); - - size_t index = find_cert(issuer_dn, auth_key_id); - - if(index != NO_CERT_FOUND) - return index; - - for(size_t j = 0; j != stores.size(); ++j) - { - std::vector<X509_Certificate> got = - stores[j]->find_cert_by_subject_and_key_id(issuer_dn, auth_key_id); - - for(size_t k = 0; k != got.size(); ++k) - add_cert(got[k]); - } - - return find_cert(issuer_dn, auth_key_id); - } - -/* -* Construct a chain of certificate relationships -*/ -X509_Code X509_Store::construct_cert_chain(const X509_Certificate& end_cert, - std::vector<size_t>& indexes, - bool need_full_chain) - { - size_t parent = find_parent_of(end_cert); - - while(true) - { - if(parent == NO_CERT_FOUND) - return CERT_ISSUER_NOT_FOUND; - indexes.push_back(parent); - - if(certs[parent].is_verified(validation_cache_timeout)) - if(certs[parent].verify_result() != VERIFIED) - return certs[parent].verify_result(); - - const X509_Certificate& parent_cert = certs[parent].cert; - if(!parent_cert.is_CA_cert()) - return CA_CERT_NOT_FOR_CERT_ISSUER; - - if(certs[parent].is_trusted()) - break; - if(parent_cert.is_self_signed()) - return CANNOT_ESTABLISH_TRUST; - - if(parent_cert.path_limit() < indexes.size() - 1) - return CERT_CHAIN_TOO_LONG; - - parent = find_parent_of(parent_cert); - } - - if(need_full_chain) - return VERIFIED; - - while(true) - { - if(indexes.size() < 2) - break; - - const size_t cert = indexes.back(); - - if(certs[cert].is_verified(validation_cache_timeout)) - { - if(certs[cert].verify_result() != VERIFIED) - throw Internal_Error("X509_Store::construct_cert_chain"); - indexes.pop_back(); - } - else - break; - } - - const size_t last_cert = indexes.back(); - const size_t parent_of_last_cert = find_parent_of(certs[last_cert].cert); - if(parent_of_last_cert == NO_CERT_FOUND) - return CERT_ISSUER_NOT_FOUND; - indexes.push_back(parent_of_last_cert); - - return VERIFIED; - } - -/* -* Check the CAs signature on a certificate -*/ -X509_Code X509_Store::check_sig(const Cert_Info& cert_info, - const Cert_Info& ca_cert_info) const - { - if(cert_info.is_verified(validation_cache_timeout)) - return cert_info.verify_result(); - - const X509_Certificate& cert = cert_info.cert; - const X509_Certificate& ca_cert = ca_cert_info.cert; - - X509_Code verify_code = check_sig(cert, ca_cert.subject_public_key()); - - cert_info.set_result(verify_code); - - return verify_code; - } - -/* -* Check a CA's signature -*/ -X509_Code X509_Store::check_sig(const X509_Object& object, Public_Key* key) - { - std::auto_ptr<Public_Key> pub_key(key); - - try { - std::vector<std::string> sig_info = - split_on(OIDS::lookup(object.signature_algorithm().oid), '/'); - - if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name()) - return SIGNATURE_ERROR; - - std::string padding = sig_info[1]; - Signature_Format format; - if(key->message_parts() >= 2) format = DER_SEQUENCE; - else format = IEEE_1363; - - PK_Verifier verifier(*pub_key.get(), padding, format); - - bool valid = verifier.verify_message(object.tbs_data(), - object.signature()); - - if(valid) - return VERIFIED; - else - return SIGNATURE_ERROR; - } - catch(Lookup_Error) { return CA_CERT_CANNOT_SIGN; } - catch(Decoding_Error) { return CERT_FORMAT_ERROR; } - catch(Exception) {} - - return UNKNOWN_X509_ERROR; - } - -/* -* Recompute the revocation status of the certs -*/ -void X509_Store::recompute_revoked_info() const - { - if(revoked_info_valid) - return; - - for(size_t j = 0; j != certs.size(); ++j) - { - if((certs[j].is_verified(validation_cache_timeout)) && - (certs[j].verify_result() != VERIFIED)) - continue; - - if(is_revoked(certs[j].cert)) - certs[j].set_result(CERT_IS_REVOKED); - } - - revoked_info_valid = true; - } - -/* -* Check if a certificate is revoked -*/ -bool X509_Store::is_revoked(const X509_Certificate& cert) const - { - CRL_Data revoked_info; - revoked_info.issuer = cert.issuer_dn(); - revoked_info.serial = cert.serial_number(); - revoked_info.auth_key_id = cert.authority_key_id(); - - if(std::binary_search(revoked.begin(), revoked.end(), revoked_info)) - return true; - return false; - } - -/* -* Construct a path back to a root for this cert -*/ -std::vector<X509_Certificate> -X509_Store::get_cert_chain(const X509_Certificate& cert) - { - std::vector<X509_Certificate> result; - std::vector<size_t> indexes; - X509_Code chaining_result = construct_cert_chain(cert, indexes, true); - - if(chaining_result != VERIFIED) - throw Invalid_State("X509_Store::get_cert_chain: Can't construct chain"); - - for(size_t j = 0; j != indexes.size(); ++j) - result.push_back(certs[indexes[j]].cert); - return result; - } - -/* -* Add a certificate store to the list of stores -*/ -void X509_Store::add_new_certstore(Certificate_Store* certstore) - { - stores.push_back(certstore); - } - -/* -* Add a certificate to the store -*/ -void X509_Store::add_cert(const X509_Certificate& cert, bool trusted) - { - if(trusted && !cert.is_self_signed()) - throw Invalid_Argument("X509_Store: Trusted certs must be self-signed"); - - if(find_cert(cert.subject_dn(), cert.subject_key_id()) == NO_CERT_FOUND) - { - revoked_info_valid = false; - Cert_Info info(cert, trusted); - certs.push_back(info); - } - else if(trusted) - { - for(size_t j = 0; j != certs.size(); ++j) - { - const X509_Certificate& this_cert = certs[j].cert; - if(this_cert == cert) - certs[j].trusted = trusted; - } - } - } - -/* -* Add one or more certificates to the store -*/ -void X509_Store::do_add_certs(DataSource& source, bool trusted) - { - while(!source.end_of_data()) - { - try { - X509_Certificate cert(source); - add_cert(cert, trusted); - } - catch(Decoding_Error) {} - catch(Invalid_Argument) {} - } - } - -/* -* Add one or more certificates to the store -*/ -void X509_Store::add_certs(DataSource& source) - { - do_add_certs(source, false); - } - -/* -* Add one or more certificates to the store -*/ -void X509_Store::add_trusted_certs(DataSource& source) - { - do_add_certs(source, true); - } - -/* -* Add one or more certificates to the store -*/ -X509_Code X509_Store::add_crl(const X509_CRL& crl) - { - s32bit time_check = validity_check(crl.this_update(), crl.next_update(), - system_time(), time_slack); - - if(time_check < 0) return CRL_NOT_YET_VALID; - else if(time_check > 0) return CRL_HAS_EXPIRED; - - size_t cert_index = NO_CERT_FOUND; - - for(size_t j = 0; j != certs.size(); ++j) - { - const X509_Certificate& this_cert = certs[j].cert; - if(compare_ids(this_cert.subject_key_id(), crl.authority_key_id())) - { - if(this_cert.subject_dn() == crl.issuer_dn()) - cert_index = j; - } - } - - if(cert_index == NO_CERT_FOUND) - return CRL_ISSUER_NOT_FOUND; - - const X509_Certificate& ca_cert = certs[cert_index].cert; - - X509_Code verify_result = validate_cert(ca_cert, CRL_SIGNING); - if(verify_result != VERIFIED) - return verify_result; - - verify_result = check_sig(crl, ca_cert.subject_public_key()); - if(verify_result != VERIFIED) - return verify_result; - - std::vector<CRL_Entry> revoked_certs = crl.get_revoked(); - - for(size_t j = 0; j != revoked_certs.size(); ++j) - { - CRL_Data revoked_info; - revoked_info.issuer = crl.issuer_dn(); - revoked_info.serial = revoked_certs[j].serial_number(); - revoked_info.auth_key_id = crl.authority_key_id(); - - std::vector<CRL_Data>::iterator p = - std::find(revoked.begin(), revoked.end(), revoked_info); - - if(revoked_certs[j].reason_code() == REMOVE_FROM_CRL) - { - if(p == revoked.end()) continue; - revoked.erase(p); - } - else - { - if(p != revoked.end()) continue; - revoked.push_back(revoked_info); - } - } - - std::sort(revoked.begin(), revoked.end()); - revoked_info_valid = false; - - return VERIFIED; - } - -/* -* PEM encode the set of certificates -*/ -std::string X509_Store::PEM_encode() const - { - std::string cert_store; - for(size_t j = 0; j != certs.size(); ++j) - cert_store += certs[j].cert.PEM_encode(); - return cert_store; - } - -/* -* Create a Cert_Info structure -*/ -X509_Store::Cert_Info::Cert_Info(const X509_Certificate& c, - bool t) : cert(c), trusted(t) - { - checked = false; - result = UNKNOWN_X509_ERROR; - last_checked = 0; - } - -/* -* Return the verification results -*/ -X509_Code X509_Store::Cert_Info::verify_result() const - { - if(!checked) - throw Invalid_State("Cert_Info::verify_result() called; not checked"); - return result; - } - -/* -* Set the verification results -*/ -void X509_Store::Cert_Info::set_result(X509_Code code) const - { - result = code; - last_checked = system_time(); - checked = true; - } - -/* -* Check if this certificate can be trusted -*/ -bool X509_Store::Cert_Info::is_trusted() const - { - return trusted; - } - -/* -* Check if this certificate has been verified -*/ -bool X509_Store::Cert_Info::is_verified(u32bit timeout) const - { - if(!checked) - return false; - if(result != VERIFIED && result != CERT_NOT_YET_VALID) - return true; - - const u64bit current_time = system_time(); - - if(current_time > last_checked + timeout) - checked = false; - - return checked; - } - -} diff --git a/src/cert/x509store/x509stor.h b/src/cert/x509store/x509stor.h deleted file mode 100644 index b4b50022c..000000000 --- a/src/cert/x509store/x509stor.h +++ /dev/null @@ -1,131 +0,0 @@ -/* -* X.509 Certificate Store -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_X509_CERT_STORE_H__ -#define BOTAN_X509_CERT_STORE_H__ - -#include <botan/x509cert.h> -#include <botan/x509_crl.h> -#include <botan/certstor.h> - -namespace Botan { - -/** -* X.509 Certificate Validation Result -*/ -enum X509_Code { - VERIFIED, - UNKNOWN_X509_ERROR, - CANNOT_ESTABLISH_TRUST, - CERT_CHAIN_TOO_LONG, - SIGNATURE_ERROR, - POLICY_ERROR, - INVALID_USAGE, - - CERT_FORMAT_ERROR, - CERT_ISSUER_NOT_FOUND, - CERT_NOT_YET_VALID, - CERT_HAS_EXPIRED, - CERT_IS_REVOKED, - - CRL_FORMAT_ERROR, - CRL_ISSUER_NOT_FOUND, - CRL_NOT_YET_VALID, - CRL_HAS_EXPIRED, - - CA_CERT_CANNOT_SIGN, - CA_CERT_NOT_FOR_CERT_ISSUER, - CA_CERT_NOT_FOR_CRL_ISSUER -}; - -/** -* X.509 Certificate Store -*/ -class BOTAN_DLL X509_Store - { - public: - enum Cert_Usage { - ANY = 0x00, - TLS_SERVER = 0x01, - TLS_CLIENT = 0x02, - CODE_SIGNING = 0x04, - EMAIL_PROTECTION = 0x08, - TIME_STAMPING = 0x10, - CRL_SIGNING = 0x20 - }; - - X509_Code validate_cert(const X509_Certificate&, Cert_Usage = ANY); - - std::vector<X509_Certificate> get_cert_chain(const X509_Certificate&); - std::string PEM_encode() const; - - X509_Code add_crl(const X509_CRL&); - void add_cert(const X509_Certificate&, bool = false); - void add_certs(DataSource&); - void add_trusted_certs(DataSource&); - - void add_new_certstore(Certificate_Store*); - - X509_Store(u32bit time_slack = 24*60*60, - u32bit cache_results = 30*60); - - X509_Store(const X509_Store&); - ~X509_Store(); - private: - X509_Store& operator=(const X509_Store&) { return (*this); } - - class BOTAN_DLL CRL_Data - { - public: - X509_DN issuer; - MemoryVector<byte> serial, auth_key_id; - bool operator==(const CRL_Data&) const; - bool operator!=(const CRL_Data&) const; - bool operator<(const CRL_Data&) const; - }; - - class BOTAN_DLL Cert_Info - { - public: - bool is_verified(u32bit timeout) const; - bool is_trusted() const; - X509_Code verify_result() const; - void set_result(X509_Code) const; - Cert_Info(const X509_Certificate&, bool = false); - - X509_Certificate cert; - bool trusted; - private: - mutable bool checked; - mutable X509_Code result; - mutable u64bit last_checked; - }; - - static X509_Code check_sig(const X509_Object&, Public_Key*); - - size_t find_cert(const X509_DN&, const MemoryRegion<byte>&) const; - X509_Code check_sig(const Cert_Info&, const Cert_Info&) const; - void recompute_revoked_info() const; - - void do_add_certs(DataSource&, bool); - X509_Code construct_cert_chain(const X509_Certificate&, - std::vector<size_t>&, bool = false); - - size_t find_parent_of(const X509_Certificate&); - bool is_revoked(const X509_Certificate&) const; - - static const size_t NO_CERT_FOUND = 0xFFFFFFFF; - std::vector<Cert_Info> certs; - std::vector<CRL_Data> revoked; - std::vector<Certificate_Store*> stores; - u32bit time_slack, validation_cache_timeout; - mutable bool revoked_info_valid; - }; - -} - -#endif |