Botan  1.11.15
src/lib/cert/x509/x509path.cpp
Go to the documentation of this file.
00001 /*
00002 * X.509 Certificate Path Validation
00003 * (C) 2010,2011,2012,2014 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/x509path.h>
00009 #include <botan/ocsp.h>
00010 #include <botan/http_util.h>
00011 #include <botan/parsing.h>
00012 #include <botan/pubkey.h>
00013 #include <botan/oids.h>
00014 #include <algorithm>
00015 #include <chrono>
00016 #include <vector>
00017 #include <set>
00018 
00019 #include <iostream>
00020 
00021 namespace Botan {
00022 
00023 namespace {
00024 
00025 const X509_Certificate*
00026 find_issuing_cert(const X509_Certificate& cert,
00027                   Certificate_Store& end_certs,
00028                   const std::vector<Certificate_Store*>& certstores)
00029    {
00030    const X509_DN issuer_dn = cert.issuer_dn();
00031    const std::vector<byte> auth_key_id = cert.authority_key_id();
00032 
00033    if(const X509_Certificate* c = end_certs.find_cert(issuer_dn, auth_key_id))
00034       return c;
00035 
00036    for(size_t i = 0; i != certstores.size(); ++i)
00037       {
00038       if(const X509_Certificate* c = certstores[i]->find_cert(issuer_dn, auth_key_id))
00039          return c;
00040       }
00041 
00042    return nullptr;
00043    }
00044 
00045 const X509_CRL* find_crls_for(const X509_Certificate& cert,
00046                               const std::vector<Certificate_Store*>& certstores)
00047    {
00048    for(size_t i = 0; i != certstores.size(); ++i)
00049       {
00050       if(const X509_CRL* crl = certstores[i]->find_crl_for(cert))
00051          return crl;
00052       }
00053 
00054 #if 0
00055    const std::string crl_url = cert.crl_distribution_point();
00056    if(crl_url != "")
00057       {
00058       std::cout << "Downloading CRL " << crl_url << "\n";
00059       auto http = HTTP::GET_sync(crl_url);
00060 
00061       std::cout << http.status_message() << "\n";
00062 
00063       http.throw_unless_ok();
00064       // check the mime type
00065 
00066       std::unique_ptr<X509_CRL> crl(new X509_CRL(http.body()));
00067 
00068       return crl.release();
00069       }
00070 #endif
00071 
00072    return nullptr;
00073    }
00074 
00075 std::vector<std::set<Certificate_Status_Code>>
00076 check_chain(const std::vector<X509_Certificate>& cert_path,
00077             const Path_Validation_Restrictions& restrictions,
00078             const std::vector<Certificate_Store*>& certstores)
00079    {
00080    const std::set<std::string>& trusted_hashes = restrictions.trusted_hashes();
00081 
00082    const bool self_signed_ee_cert = (cert_path.size() == 1);
00083 
00084    X509_Time current_time(std::chrono::system_clock::now());
00085 
00086    std::vector<std::future<OCSP::Response>> ocsp_responses;
00087 
00088    std::vector<std::set<Certificate_Status_Code>> cert_status(cert_path.size());
00089 
00090    for(size_t i = 0; i != cert_path.size(); ++i)
00091       {
00092       std::set<Certificate_Status_Code>& status = cert_status.at(i);
00093 
00094       const bool at_self_signed_root = (i == cert_path.size() - 1);
00095 
00096       const X509_Certificate& subject = cert_path[i];
00097 
00098       const X509_Certificate& issuer = cert_path[at_self_signed_root ? (i) : (i + 1)];
00099 
00100       if(i == 0 || restrictions.ocsp_all_intermediates())
00101          {
00102          // certstore[0] is treated as trusted for OCSP (FIXME)
00103          if(certstores.size() > 1)
00104             ocsp_responses.push_back(
00105                std::async(std::launch::async,
00106                           OCSP::online_check, issuer, subject, certstores[0]));
00107          }
00108 
00109       // Check all certs for valid time range
00110       if(current_time < X509_Time(subject.start_time()))
00111          status.insert(Certificate_Status_Code::CERT_NOT_YET_VALID);
00112 
00113       if(current_time > X509_Time(subject.end_time()))
00114          status.insert(Certificate_Status_Code::CERT_HAS_EXPIRED);
00115 
00116       // Check issuer constraints
00117 
00118       // Don't require CA bit set on self-signed end entity cert
00119       if(!issuer.is_CA_cert() && !self_signed_ee_cert)
00120          status.insert(Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER);
00121 
00122       if(issuer.path_limit() < i)
00123          status.insert(Certificate_Status_Code::CERT_CHAIN_TOO_LONG);
00124 
00125       std::unique_ptr<Public_Key> issuer_key(issuer.subject_public_key());
00126 
00127       if(!issuer_key)
00128          {
00129          status.insert(Certificate_Status_Code::SIGNATURE_ERROR);
00130          }
00131       else
00132          {
00133          if(subject.check_signature(*issuer_key) == false)
00134             status.insert(Certificate_Status_Code::SIGNATURE_ERROR);
00135 
00136          if(issuer_key->estimated_strength() < restrictions.minimum_key_strength())
00137             status.insert(Certificate_Status_Code::SIGNATURE_METHOD_TOO_WEAK);
00138          }
00139 
00140       // Allow untrusted hashes on self-signed roots
00141       if(!trusted_hashes.empty() && !at_self_signed_root)
00142          {
00143          if(!trusted_hashes.count(subject.hash_used_for_signature()))
00144             status.insert(Certificate_Status_Code::UNTRUSTED_HASH);
00145          }
00146       }
00147 
00148    for(size_t i = 0; i != cert_path.size() - 1; ++i)
00149       {
00150       std::set<Certificate_Status_Code>& status = cert_status.at(i);
00151 
00152       const X509_Certificate& subject = cert_path.at(i);
00153       const X509_Certificate& ca = cert_path.at(i+1);
00154 
00155       if(i < ocsp_responses.size())
00156          {
00157          try
00158             {
00159             OCSP::Response ocsp = ocsp_responses[i].get();
00160 
00161             auto ocsp_status = ocsp.status_for(ca, subject);
00162 
00163             status.insert(ocsp_status);
00164 
00165             //std::cout << "OCSP status: " << Path_Validation_Result::status_string(ocsp_status) << "\n";
00166 
00167             // Either way we have a definitive answer, no need to check CRLs
00168             if(ocsp_status == Certificate_Status_Code::CERT_IS_REVOKED)
00169                return cert_status;
00170             else if(ocsp_status == Certificate_Status_Code::OCSP_RESPONSE_GOOD)
00171                continue;
00172             }
00173          catch(std::exception& e)
00174             {
00175             //std::cout << "OCSP error: " << e.what() << "\n";
00176             }
00177          }
00178 
00179       const X509_CRL* crl_p = find_crls_for(subject, certstores);
00180 
00181       if(!crl_p)
00182          {
00183          if(restrictions.require_revocation_information())
00184             status.insert(Certificate_Status_Code::NO_REVOCATION_DATA);
00185          continue;
00186          }
00187 
00188       const X509_CRL& crl = *crl_p;
00189 
00190       if(!ca.allowed_usage(CRL_SIGN))
00191          status.insert(Certificate_Status_Code::CA_CERT_NOT_FOR_CRL_ISSUER);
00192 
00193       if(current_time < X509_Time(crl.this_update()))
00194          status.insert(Certificate_Status_Code::CRL_NOT_YET_VALID);
00195 
00196       if(current_time > X509_Time(crl.next_update()))
00197          status.insert(Certificate_Status_Code::CRL_HAS_EXPIRED);
00198 
00199       if(crl.check_signature(ca.subject_public_key()) == false)
00200          status.insert(Certificate_Status_Code::CRL_BAD_SIGNATURE);
00201 
00202       if(crl.is_revoked(subject))
00203          status.insert(Certificate_Status_Code::CERT_IS_REVOKED);
00204       }
00205 
00206    if(self_signed_ee_cert)
00207       cert_status.back().insert(Certificate_Status_Code::CANNOT_ESTABLISH_TRUST);
00208 
00209    return cert_status;
00210    }
00211 
00212 }
00213 
00214 Path_Validation_Result x509_path_validate(
00215    const std::vector<X509_Certificate>& end_certs,
00216    const Path_Validation_Restrictions& restrictions,
00217    const std::vector<Certificate_Store*>& certstores)
00218    {
00219    if(end_certs.empty())
00220       throw std::invalid_argument("x509_path_validate called with no subjects");
00221 
00222    std::vector<X509_Certificate> cert_path;
00223    cert_path.push_back(end_certs[0]);
00224 
00225    Certificate_Store_Overlay extra(end_certs);
00226 
00227    // iterate until we reach a root or cannot find the issuer
00228    while(!cert_path.back().is_self_signed())
00229       {
00230       const X509_Certificate* cert = find_issuing_cert(cert_path.back(), extra, certstores);
00231       if(!cert)
00232          return Path_Validation_Result(Certificate_Status_Code::CERT_ISSUER_NOT_FOUND);
00233 
00234       cert_path.push_back(*cert);
00235       }
00236 
00237    return Path_Validation_Result(check_chain(cert_path, restrictions, certstores),
00238                                  std::move(cert_path));
00239    }
00240 
00241 Path_Validation_Result x509_path_validate(
00242    const X509_Certificate& end_cert,
00243    const Path_Validation_Restrictions& restrictions,
00244    const std::vector<Certificate_Store*>& certstores)
00245    {
00246    std::vector<X509_Certificate> certs;
00247    certs.push_back(end_cert);
00248    return x509_path_validate(certs, restrictions, certstores);
00249    }
00250 
00251 Path_Validation_Result x509_path_validate(
00252    const std::vector<X509_Certificate>& end_certs,
00253    const Path_Validation_Restrictions& restrictions,
00254    const Certificate_Store& store)
00255    {
00256    std::vector<Certificate_Store*> certstores;
00257    certstores.push_back(const_cast<Certificate_Store*>(&store));
00258 
00259    return x509_path_validate(end_certs, restrictions, certstores);
00260    }
00261 
00262 Path_Validation_Result x509_path_validate(
00263    const X509_Certificate& end_cert,
00264    const Path_Validation_Restrictions& restrictions,
00265    const Certificate_Store& store)
00266    {
00267    std::vector<X509_Certificate> certs;
00268    certs.push_back(end_cert);
00269 
00270    std::vector<Certificate_Store*> certstores;
00271    certstores.push_back(const_cast<Certificate_Store*>(&store));
00272 
00273    return x509_path_validate(certs, restrictions, certstores);
00274    }
00275 
00276 Path_Validation_Restrictions::Path_Validation_Restrictions(bool require_rev,
00277                                                            size_t key_strength,
00278                                                            bool ocsp_all) :
00279    m_require_revocation_information(require_rev),
00280    m_ocsp_all_intermediates(ocsp_all),
00281    m_minimum_key_strength(key_strength)
00282    {
00283    if(key_strength <= 80)
00284       m_trusted_hashes.insert("SHA-160");
00285 
00286    m_trusted_hashes.insert("SHA-224");
00287    m_trusted_hashes.insert("SHA-256");
00288    m_trusted_hashes.insert("SHA-384");
00289    m_trusted_hashes.insert("SHA-512");
00290    }
00291 
00292 Path_Validation_Result::Path_Validation_Result(std::vector<std::set<Certificate_Status_Code>> status,
00293                                                std::vector<X509_Certificate>&& cert_chain) :
00294    m_overall(Certificate_Status_Code::VERIFIED),
00295    m_all_status(status),
00296    m_cert_path(cert_chain)
00297    {
00298    // take the "worst" error as overall
00299    for(const auto& s : m_all_status)
00300       {
00301       if(!s.empty())
00302          {
00303          auto worst = *s.rbegin();
00304          // Leave OCSP confirmations on cert-level status only
00305          if(worst != Certificate_Status_Code::OCSP_RESPONSE_GOOD)
00306             m_overall = worst;
00307          }
00308       }
00309    }
00310 
00311 const X509_Certificate& Path_Validation_Result::trust_root() const
00312    {
00313    return m_cert_path[m_cert_path.size()-1];
00314    }
00315 
00316 std::set<std::string> Path_Validation_Result::trusted_hashes() const
00317    {
00318    std::set<std::string> hashes;
00319    for(size_t i = 0; i != m_cert_path.size(); ++i)
00320       hashes.insert(m_cert_path[i].hash_used_for_signature());
00321    return hashes;
00322    }
00323 
00324 bool Path_Validation_Result::successful_validation() const
00325    {
00326    if(result() == Certificate_Status_Code::VERIFIED ||
00327       result() == Certificate_Status_Code::OCSP_RESPONSE_GOOD)
00328       return true;
00329    return false;
00330    }
00331 
00332 std::string Path_Validation_Result::result_string() const
00333    {
00334    return status_string(result());
00335    }
00336 
00337 const char* Path_Validation_Result::status_string(Certificate_Status_Code code)
00338    {
00339    switch(code)
00340       {
00341       case Certificate_Status_Code::VERIFIED:
00342          return "Verified";
00343       case Certificate_Status_Code::OCSP_RESPONSE_GOOD:
00344          return "OCSP response good";
00345       case Certificate_Status_Code::NO_REVOCATION_DATA:
00346          return "No revocation data";
00347       case Certificate_Status_Code::SIGNATURE_METHOD_TOO_WEAK:
00348          return "Signature method too weak";
00349       case Certificate_Status_Code::UNTRUSTED_HASH:
00350          return "Untrusted hash";
00351 
00352       case Certificate_Status_Code::CERT_NOT_YET_VALID:
00353          return "Certificate is not yet valid";
00354       case Certificate_Status_Code::CERT_HAS_EXPIRED:
00355          return "Certificate has expired";
00356       case Certificate_Status_Code::OCSP_NOT_YET_VALID:
00357          return "OCSP is not yet valid";
00358       case Certificate_Status_Code::OCSP_HAS_EXPIRED:
00359          return "OCSP has expired";
00360       case Certificate_Status_Code::CRL_NOT_YET_VALID:
00361          return "CRL is not yet valid";
00362       case Certificate_Status_Code::CRL_HAS_EXPIRED:
00363          return "CRL has expired";
00364 
00365       case Certificate_Status_Code::CERT_ISSUER_NOT_FOUND:
00366          return "Certificate issuer not found";
00367       case Certificate_Status_Code::CANNOT_ESTABLISH_TRUST:
00368          return "Cannot establish trust";
00369 
00370       case Certificate_Status_Code::POLICY_ERROR:
00371          return "Policy error";
00372       case Certificate_Status_Code::INVALID_USAGE:
00373          return "Invalid usage";
00374       case Certificate_Status_Code::CERT_CHAIN_TOO_LONG:
00375          return "Certificate chain too long";
00376       case Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER:
00377          return "CA certificate not allowed to issue certs";
00378       case Certificate_Status_Code::CA_CERT_NOT_FOR_CRL_ISSUER:
00379          return "CA certificate not allowed to issue CRLs";
00380       case Certificate_Status_Code::OCSP_CERT_NOT_LISTED:
00381          return "OCSP cert not listed";
00382       case Certificate_Status_Code::OCSP_BAD_STATUS:
00383          return "OCSP bad status";
00384 
00385       case Certificate_Status_Code::CERT_IS_REVOKED:
00386          return "Certificate is revoked";
00387       case Certificate_Status_Code::CRL_BAD_SIGNATURE:
00388          return "CRL bad signature";
00389       case Certificate_Status_Code::SIGNATURE_ERROR:
00390          return "Signature error";
00391       default:
00392          return "Unknown error";
00393       }
00394    }
00395 
00396 }