Botan  1.11.15
src/lib/cert/x509/ocsp.cpp
Go to the documentation of this file.
00001 /*
00002 * OCSP
00003 * (C) 2012,2013 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/ocsp.h>
00009 #include <botan/certstor.h>
00010 #include <botan/der_enc.h>
00011 #include <botan/ber_dec.h>
00012 #include <botan/x509_ext.h>
00013 #include <botan/oids.h>
00014 #include <botan/base64.h>
00015 #include <botan/pubkey.h>
00016 #include <botan/x509path.h>
00017 #include <botan/http_util.h>
00018 
00019 namespace Botan {
00020 
00021 namespace OCSP {
00022 
00023 namespace {
00024 
00025 void decode_optional_list(BER_Decoder& ber,
00026                           ASN1_Tag tag,
00027                           std::vector<X509_Certificate>& output)
00028    {
00029    BER_Object obj = ber.get_next_object();
00030 
00031    if(obj.type_tag != tag || obj.class_tag != (CONTEXT_SPECIFIC | CONSTRUCTED))
00032       {
00033       ber.push_back(obj);
00034       return;
00035       }
00036 
00037    BER_Decoder list(obj.value);
00038 
00039    while(list.more_items())
00040       {
00041       BER_Object certbits = list.get_next_object();
00042       X509_Certificate cert(unlock(certbits.value));
00043       output.push_back(std::move(cert));
00044       }
00045    }
00046 
00047 void check_signature(const std::vector<byte>& tbs_response,
00048                      const AlgorithmIdentifier& sig_algo,
00049                      const std::vector<byte>& signature,
00050                      const X509_Certificate& cert)
00051    {
00052    std::unique_ptr<Public_Key> pub_key(cert.subject_public_key());
00053 
00054    const std::vector<std::string> sig_info =
00055       split_on(OIDS::lookup(sig_algo.oid), '/');
00056 
00057    if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name())
00058       throw std::runtime_error("Information in OCSP response does not match cert");
00059 
00060    std::string padding = sig_info[1];
00061    Signature_Format format =
00062       (pub_key->message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363;
00063 
00064    PK_Verifier verifier(*pub_key, padding, format);
00065 
00066    if(!verifier.verify_message(ASN1::put_in_sequence(tbs_response), signature))
00067       throw std::runtime_error("Signature on OCSP response does not verify");
00068    }
00069 
00070 void check_signature(const std::vector<byte>& tbs_response,
00071                      const AlgorithmIdentifier& sig_algo,
00072                      const std::vector<byte>& signature,
00073                      const Certificate_Store& trusted_roots,
00074                      const std::vector<X509_Certificate>& certs)
00075    {
00076    if(certs.size() < 1)
00077       throw std::invalid_argument("Short cert chain for check_signature");
00078 
00079    if(trusted_roots.certificate_known(certs[0]))
00080       return check_signature(tbs_response, sig_algo, signature, certs[0]);
00081 
00082    // Otherwise attempt to chain the signing cert to a trust root
00083 
00084    if(!certs[0].allowed_usage("PKIX.OCSPSigning"))
00085       throw std::runtime_error("OCSP response cert does not allow OCSP signing");
00086 
00087    auto result = x509_path_validate(certs, Path_Validation_Restrictions(), trusted_roots);
00088 
00089    if(!result.successful_validation())
00090       throw std::runtime_error("Certificate validation failure: " + result.result_string());
00091 
00092    if(!trusted_roots.certificate_known(result.trust_root())) // not needed anymore?
00093       throw std::runtime_error("Certificate chain roots in unknown/untrusted CA");
00094 
00095    const std::vector<X509_Certificate>& cert_path = result.cert_path();
00096 
00097    check_signature(tbs_response, sig_algo, signature, cert_path[0]);
00098    }
00099 
00100 }
00101 
00102 std::vector<byte> Request::BER_encode() const
00103    {
00104    CertID certid(m_issuer, m_subject);
00105 
00106    return DER_Encoder().start_cons(SEQUENCE)
00107         .start_cons(SEQUENCE)
00108           .start_explicit(0)
00109             .encode(static_cast<size_t>(0)) // version #
00110           .end_explicit()
00111             .start_cons(SEQUENCE)
00112               .start_cons(SEQUENCE)
00113                 .encode(certid)
00114               .end_cons()
00115             .end_cons()
00116           .end_cons()
00117       .end_cons().get_contents_unlocked();
00118    }
00119 
00120 std::string Request::base64_encode() const
00121    {
00122    return Botan::base64_encode(BER_encode());
00123    }
00124 
00125 Response::Response(const Certificate_Store& trusted_roots,
00126                    const std::vector<byte>& response_bits)
00127    {
00128    BER_Decoder response_outer = BER_Decoder(response_bits).start_cons(SEQUENCE);
00129 
00130    size_t resp_status = 0;
00131 
00132    response_outer.decode(resp_status, ENUMERATED, UNIVERSAL);
00133 
00134    if(resp_status != 0)
00135       throw std::runtime_error("OCSP response status " + std::to_string(resp_status));
00136 
00137    if(response_outer.more_items())
00138       {
00139       BER_Decoder response_bytes =
00140          response_outer.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).start_cons(SEQUENCE);
00141 
00142       response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"),
00143                                       "Unknown response type in OCSP response");
00144 
00145       BER_Decoder basicresponse =
00146          BER_Decoder(response_bytes.get_next_octet_string()).start_cons(SEQUENCE);
00147 
00148       std::vector<byte> tbs_bits;
00149       AlgorithmIdentifier sig_algo;
00150       std::vector<byte> signature;
00151       std::vector<X509_Certificate> certs;
00152 
00153       basicresponse.start_cons(SEQUENCE)
00154            .raw_bytes(tbs_bits)
00155          .end_cons()
00156          .decode(sig_algo)
00157          .decode(signature, BIT_STRING);
00158       decode_optional_list(basicresponse, ASN1_Tag(0), certs);
00159 
00160       size_t responsedata_version = 0;
00161       X509_DN name;
00162       std::vector<byte> key_hash;
00163       X509_Time produced_at;
00164       Extensions extensions;
00165 
00166       BER_Decoder(tbs_bits)
00167          .decode_optional(responsedata_version, ASN1_Tag(0),
00168                           ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
00169 
00170          .decode_optional(name, ASN1_Tag(1),
00171                           ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
00172 
00173          .decode_optional_string(key_hash, OCTET_STRING, 2,
00174                                  ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
00175 
00176          .decode(produced_at)
00177 
00178          .decode_list(m_responses)
00179 
00180          .decode_optional(extensions, ASN1_Tag(1),
00181                           ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC));
00182 
00183       if(certs.empty())
00184          {
00185          if(auto cert = trusted_roots.find_cert(name, std::vector<byte>()))
00186             certs.push_back(*cert);
00187          else
00188             throw std::runtime_error("Could not find certificate that signed OCSP response");
00189          }
00190 
00191       check_signature(tbs_bits, sig_algo, signature, trusted_roots, certs);
00192       }
00193 
00194    response_outer.end_cons();
00195    }
00196 
00197 Certificate_Status_Code Response::status_for(const X509_Certificate& issuer,
00198                                                    const X509_Certificate& subject) const
00199    {
00200    for(const auto& response : m_responses)
00201       {
00202       if(response.certid().is_id_for(issuer, subject))
00203          {
00204          X509_Time current_time(std::chrono::system_clock::now());
00205 
00206          if(response.cert_status() == 1)
00207             return Certificate_Status_Code::CERT_IS_REVOKED;
00208 
00209          if(response.this_update() > current_time)
00210             return Certificate_Status_Code::OCSP_NOT_YET_VALID;
00211 
00212          if(response.next_update().time_is_set() && current_time > response.next_update())
00213             return Certificate_Status_Code::OCSP_HAS_EXPIRED;
00214 
00215          if(response.cert_status() == 0)
00216             return Certificate_Status_Code::OCSP_RESPONSE_GOOD;
00217          else
00218             return Certificate_Status_Code::OCSP_BAD_STATUS;
00219          }
00220       }
00221 
00222    return Certificate_Status_Code::OCSP_CERT_NOT_LISTED;
00223    }
00224 
00225 Response online_check(const X509_Certificate& issuer,
00226                       const X509_Certificate& subject,
00227                       const Certificate_Store* trusted_roots)
00228    {
00229    const std::string responder_url = subject.ocsp_responder();
00230 
00231    if(responder_url == "")
00232       throw std::runtime_error("No OCSP responder specified");
00233 
00234    OCSP::Request req(issuer, subject);
00235 
00236    auto http = HTTP::POST_sync(responder_url,
00237                                "application/ocsp-request",
00238                                req.BER_encode());
00239 
00240    http.throw_unless_ok();
00241 
00242    // Check the MIME type?
00243 
00244    OCSP::Response response(*trusted_roots, http.body());
00245 
00246    return response;
00247    }
00248 
00249 }
00250 
00251 }