Botan
1.11.15
|
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 }