diff options
author | lloyd <[email protected]> | 2014-01-01 21:20:55 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2014-01-01 21:20:55 +0000 |
commit | 197dc467dec28a04c3b2f30da7cef122dfbb13e9 (patch) | |
tree | cdbd3ddaec051c72f0a757db461973d90c37b97a /src/cert/x509 | |
parent | 62faac373c07cfe10bc8c309e89ebdd30d8e5eaa (diff) |
Shuffle things around. Add NIST X.509 test to build.
Diffstat (limited to 'src/cert/x509')
29 files changed, 0 insertions, 5364 deletions
diff --git a/src/cert/x509/cert_status.h b/src/cert/x509/cert_status.h deleted file mode 100644 index b688cbcd7..000000000 --- a/src/cert/x509/cert_status.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -* Result enums -* (C) 2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_X509_PATH_RESULT_H__ -#define BOTAN_X509_PATH_RESULT_H__ - -#include <string> - -namespace Botan { - -enum Certificate_Status_Code { - VERIFIED, - UNKNOWN_X509_ERROR, - CANNOT_ESTABLISH_TRUST, - CERT_CHAIN_TOO_LONG, - SIGNATURE_ERROR, - POLICY_ERROR, - INVALID_USAGE, - - SIGNATURE_METHOD_TOO_WEAK, - UNTRUSTED_HASH, - - CERT_MULTIPLE_ISSUERS_FOUND, - - CERT_FORMAT_ERROR, - CERT_ISSUER_NOT_FOUND, - CERT_NOT_YET_VALID, - CERT_HAS_EXPIRED, - CERT_IS_REVOKED, - - NO_REVOCATION_DATA, - - CRL_FORMAT_ERROR, - CRL_NOT_YET_VALID, - CRL_HAS_EXPIRED, - - OCSP_CERT_NOT_LISTED, - OCSP_NOT_YET_VALID, - OCSP_EXPIRED, - OCSP_BAD_STATUS, - OCSP_RESPONSE_GOOD, - - CA_CERT_CANNOT_SIGN, - CA_CERT_NOT_FOR_CERT_ISSUER, - CA_CERT_NOT_FOR_CRL_ISSUER -}; - - -} - -#endif diff --git a/src/cert/x509/certstor.cpp b/src/cert/x509/certstor.cpp deleted file mode 100644 index e8b3a0718..000000000 --- a/src/cert/x509/certstor.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* -* Certificate Store -* (C) 1999-2010,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/certstor.h> -#include <boost/filesystem.hpp> - -namespace Botan { - -const X509_CRL* Certificate_Store::find_crl(const X509_Certificate&) const - { - return nullptr; - } - -void Certificate_Store_In_Memory::add_certificate(const X509_Certificate& cert) - { - for(size_t i = 0; i != m_certs.size(); ++i) - { - if(m_certs[i] == cert) - return; - } - - m_certs.push_back(cert); - } - -std::vector<X509_DN> Certificate_Store_In_Memory::all_subjects() const - { - std::vector<X509_DN> subjects; - for(size_t i = 0; i != m_certs.size(); ++i) - subjects.push_back(m_certs[i].subject_dn()); - return subjects; - } - -namespace { - -const X509_Certificate* -cert_search(const X509_DN& subject_dn, const std::vector<byte>& key_id, - const std::vector<X509_Certificate>& certs) - { - for(size_t i = 0; i != certs.size(); ++i) - { - // Only compare key ids if set in both call and in the cert - if(key_id.size()) - { - std::vector<byte> skid = certs[i].subject_key_id(); - - if(skid.size() && skid != key_id) // no match - continue; - } - - if(certs[i].subject_dn() == subject_dn) - return &certs[i]; - } - - return nullptr; - } - -} - -const X509_Certificate* -Certificate_Store_In_Memory::find_cert(const X509_DN& subject_dn, - const std::vector<byte>& key_id) const - { - return cert_search(subject_dn, key_id, m_certs); - } - -void Certificate_Store_In_Memory::add_crl(const X509_CRL& crl) - { - X509_DN crl_issuer = crl.issuer_dn(); - - for(size_t i = 0; i != m_crls.size(); ++i) - { - // Found an update of a previously existing one; replace it - if(m_crls[i].issuer_dn() == crl_issuer) - { - if(m_crls[i].this_update() <= crl.this_update()) - m_crls[i] = crl; - return; - } - } - - // Totally new CRL, add to the list - m_crls.push_back(crl); - } - -const X509_CRL* Certificate_Store_In_Memory::find_crl(const X509_Certificate& subject) const - { - const std::vector<byte>& key_id = subject.authority_key_id(); - - for(size_t i = 0; i != m_crls.size(); ++i) - { - // Only compare key ids if set in both call and in the CRL - if(key_id.size()) - { - std::vector<byte> akid = m_crls[i].authority_key_id(); - - if(akid.size() && akid != key_id) // no match - continue; - } - - if(m_crls[i].issuer_dn() == subject.issuer_dn()) - return &m_crls[i]; - } - - return nullptr; - } - -Certificate_Store_In_Memory::Certificate_Store_In_Memory(const std::string& dir) - { - if(dir == "") - return; - - boost::filesystem::recursive_directory_iterator i(dir); - boost::filesystem::recursive_directory_iterator end; - - while(i != end) - { - auto path = i->path(); - ++i; - - try - { - if(boost::filesystem::is_regular_file(path)) - m_certs.push_back(X509_Certificate(path.native())); - } - catch(...) {} - } - } - -const X509_Certificate* -Certificate_Store_Overlay::find_cert(const X509_DN& subject_dn, - const std::vector<byte>& key_id) const - { - return cert_search(subject_dn, key_id, m_certs); - } - -std::vector<X509_DN> Certificate_Store_Overlay::all_subjects() const - { - std::vector<X509_DN> subjects; - for(size_t i = 0; i != m_certs.size(); ++i) - subjects.push_back(m_certs[i].subject_dn()); - return subjects; - } - -} diff --git a/src/cert/x509/certstor.h b/src/cert/x509/certstor.h deleted file mode 100644 index fc37d8327..000000000 --- a/src/cert/x509/certstor.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -* Certificate Store -* (C) 1999-2010,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_CERT_STORE_H__ -#define BOTAN_CERT_STORE_H__ - -#include <botan/x509cert.h> -#include <botan/x509_crl.h> - -namespace Botan { - -/** -* Certificate Store Interface -*/ -class BOTAN_DLL Certificate_Store - { - public: - virtual ~Certificate_Store() {} - - /** - * Subject DN and (optionally) key identifier - */ - virtual const X509_Certificate* - find_cert(const X509_DN& subject_dn, const std::vector<byte>& key_id) const = 0; - - virtual const X509_CRL* find_crl(const X509_Certificate& subject) const; - - bool certificate_known(const X509_Certificate& cert) const - { - return find_cert(cert.subject_dn(), cert.subject_key_id()); - } - - // remove this (used by TLS::Server) - virtual std::vector<X509_DN> all_subjects() const = 0; - }; - -/** -* In Memory Certificate Store -*/ -class BOTAN_DLL Certificate_Store_In_Memory : public Certificate_Store - { - public: - /** - * Attempt to parse all files in dir (including subdirectories) - * as certificates. Ignores errors. - */ - Certificate_Store_In_Memory(const std::string& dir); - - Certificate_Store_In_Memory() {} - - void add_certificate(const X509_Certificate& cert); - - void add_crl(const X509_CRL& crl); - - std::vector<X509_DN> all_subjects() const override; - - const X509_Certificate* find_cert( - const X509_DN& subject_dn, - const std::vector<byte>& key_id) const override; - - const X509_CRL* find_crl(const X509_Certificate& subject) const override; - private: - // TODO: Add indexing on the DN and key id to avoid linear search - std::vector<X509_Certificate> m_certs; - std::vector<X509_CRL> m_crls; - }; - -class BOTAN_DLL Certificate_Store_Overlay : public Certificate_Store - { - public: - Certificate_Store_Overlay(const std::vector<X509_Certificate>& certs) : - m_certs(certs) {} - - std::vector<X509_DN> all_subjects() const override; - - const X509_Certificate* find_cert( - const X509_DN& subject_dn, - const std::vector<byte>& key_id) const override; - private: - const std::vector<X509_Certificate>& m_certs; - }; - -} - -#endif diff --git a/src/cert/x509/crl_ent.cpp b/src/cert/x509/crl_ent.cpp deleted file mode 100644 index a5663e6bb..000000000 --- a/src/cert/x509/crl_ent.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* -* CRL Entry -* (C) 1999-2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/crl_ent.h> -#include <botan/x509_ext.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/bigint.h> -#include <botan/oids.h> - -namespace Botan { - -/* -* Create a CRL_Entry -*/ -CRL_Entry::CRL_Entry(bool t_on_unknown_crit) : - throw_on_unknown_critical(t_on_unknown_crit) - { - reason = UNSPECIFIED; - } - -/* -* Create a CRL_Entry -*/ -CRL_Entry::CRL_Entry(const X509_Certificate& cert, CRL_Code why) : - throw_on_unknown_critical(false) - { - serial = cert.serial_number(); - time = X509_Time(std::chrono::system_clock::now()); - reason = why; - } - -/* -* Compare two CRL_Entrys for equality -*/ -bool operator==(const CRL_Entry& a1, const CRL_Entry& a2) - { - if(a1.serial_number() != a2.serial_number()) - return false; - if(a1.expire_time() != a2.expire_time()) - return false; - if(a1.reason_code() != a2.reason_code()) - return false; - return true; - } - -/* -* Compare two CRL_Entrys for inequality -*/ -bool operator!=(const CRL_Entry& a1, const CRL_Entry& a2) - { - return !(a1 == a2); - } - -/* -* DER encode a CRL_Entry -*/ -void CRL_Entry::encode_into(DER_Encoder& der) const - { - Extensions extensions; - - extensions.add(new Cert_Extension::CRL_ReasonCode(reason)); - - der.start_cons(SEQUENCE) - .encode(BigInt::decode(serial)) - .encode(time) - .start_cons(SEQUENCE) - .encode(extensions) - .end_cons() - .end_cons(); - } - -/* -* Decode a BER encoded CRL_Entry -*/ -void CRL_Entry::decode_from(BER_Decoder& source) - { - BigInt serial_number_bn; - reason = UNSPECIFIED; - - BER_Decoder entry = source.start_cons(SEQUENCE); - - entry.decode(serial_number_bn).decode(time); - - if(entry.more_items()) - { - Extensions extensions(throw_on_unknown_critical); - entry.decode(extensions); - Data_Store info; - extensions.contents_to(info, info); - reason = CRL_Code(info.get1_u32bit("X509v3.CRLReasonCode")); - } - - entry.end_cons(); - - serial = BigInt::encode(serial_number_bn); - } - -} diff --git a/src/cert/x509/crl_ent.h b/src/cert/x509/crl_ent.h deleted file mode 100644 index e68008b70..000000000 --- a/src/cert/x509/crl_ent.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -* CRL Entry -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_CRL_ENTRY_H__ -#define BOTAN_CRL_ENTRY_H__ - -#include <botan/x509cert.h> -#include <botan/asn1_time.h> - -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 - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - /** - * Get the serial number of the certificate associated with this entry. - * @return certificate's serial number - */ - std::vector<byte> serial_number() const { return serial; } - - /** - * Get the revocation date of the certificate associated with this entry - * @return certificate's revocation date - */ - X509_Time expire_time() const { return time; } - - /** - * Get the entries reason code - * @return reason code - */ - CRL_Code reason_code() const { return reason; } - - /** - * Construct an empty CRL entry. - */ - CRL_Entry(bool throw_on_unknown_critical_extension = false); - - /** - * Construct an CRL entry. - * @param cert the certificate to revoke - * @param reason the reason code to set in the entry - */ - CRL_Entry(const X509_Certificate& cert, - CRL_Code reason = UNSPECIFIED); - - private: - bool throw_on_unknown_critical; - std::vector<byte> serial; - X509_Time time; - CRL_Code reason; - }; - -/** -* Test two CRL entries for equality in all fields. -*/ -BOTAN_DLL bool operator==(const CRL_Entry&, const CRL_Entry&); - -/** -* Test two CRL entries for inequality in at least one field. -*/ -BOTAN_DLL bool operator!=(const CRL_Entry&, const CRL_Entry&); - -} - -#endif diff --git a/src/cert/x509/info.txt b/src/cert/x509/info.txt deleted file mode 100644 index 83512857f..000000000 --- a/src/cert/x509/info.txt +++ /dev/null @@ -1,10 +0,0 @@ -define X509_CERTIFICATES 20131128 -define OCSP 20131128 - -<requires> -datastor -</requires> - -<libs> -all -> boost_filesystem -</libs> diff --git a/src/cert/x509/key_constraint.cpp b/src/cert/x509/key_constraint.cpp deleted file mode 100644 index 8a4b3deb3..000000000 --- a/src/cert/x509/key_constraint.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* -* KeyUsage -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/key_constraint.h> -#include <botan/x509_key.h> -#include <botan/ber_dec.h> - -namespace Botan { - -namespace BER { - -/* -* Decode a BER encoded KeyUsage -*/ -void decode(BER_Decoder& source, Key_Constraints& key_usage) - { - BER_Object obj = source.get_next_object(); - - if(obj.type_tag != BIT_STRING || obj.class_tag != UNIVERSAL) - throw BER_Bad_Tag("Bad tag for usage constraint", - obj.type_tag, obj.class_tag); - if(obj.value.size() != 2 && obj.value.size() != 3) - throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint"); - if(obj.value[0] >= 8) - throw BER_Decoding_Error("Invalid unused bits in usage constraint"); - - const byte mask = (0xFF << obj.value[0]); - obj.value[obj.value.size()-1] &= mask; - - u16bit usage = 0; - for(size_t j = 1; j != obj.value.size(); ++j) - usage = (obj.value[j] << 8) | usage; - - key_usage = Key_Constraints(usage); - } - -} - -/* -* Find the allowable key constraints -*/ -Key_Constraints find_constraints(const Public_Key& pub_key, - Key_Constraints limits) - { - const std::string name = pub_key.algo_name(); - - size_t constraints = 0; - - if(name == "DH" || name == "ECDH") - constraints |= KEY_AGREEMENT; - - if(name == "RSA" || name == "ElGamal") - constraints |= KEY_ENCIPHERMENT | DATA_ENCIPHERMENT; - - if(name == "RSA" || name == "RW" || name == "NR" || - name == "DSA" || name == "ECDSA") - constraints |= DIGITAL_SIGNATURE | NON_REPUDIATION; - - if(limits) - constraints &= limits; - - return Key_Constraints(constraints); - } - -} diff --git a/src/cert/x509/key_constraint.h b/src/cert/x509/key_constraint.h deleted file mode 100644 index 2c9b3778b..000000000 --- a/src/cert/x509/key_constraint.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -* Enumerations -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_ENUMS_H__ -#define BOTAN_ENUMS_H__ - -#include <botan/ber_dec.h> - -namespace Botan { - -/** -* X.509v3 Key Constraints. -*/ -enum Key_Constraints { - NO_CONSTRAINTS = 0, - DIGITAL_SIGNATURE = 32768, - NON_REPUDIATION = 16384, - KEY_ENCIPHERMENT = 8192, - DATA_ENCIPHERMENT = 4096, - KEY_AGREEMENT = 2048, - KEY_CERT_SIGN = 1024, - CRL_SIGN = 512, - ENCIPHER_ONLY = 256, - DECIPHER_ONLY = 128 -}; - -class Public_Key; - -/** -* Create the key constraints for a specific public key. -* @param pub_key the public key from which the basic set of -* constraints to be placed in the return value is derived -* @param limits additional limits that will be incorporated into the -* return value -* @return combination of key type specific constraints and -* additional limits -*/ - -BOTAN_DLL Key_Constraints find_constraints(const Public_Key& pub_key, - Key_Constraints limits); - -/** -* BER Decoding Function for key constraints -*/ -namespace BER { - -void BOTAN_DLL decode(BER_Decoder&, Key_Constraints&); - -} - -} - -#endif diff --git a/src/cert/x509/ocsp.cpp b/src/cert/x509/ocsp.cpp deleted file mode 100644 index a118a9c4e..000000000 --- a/src/cert/x509/ocsp.cpp +++ /dev/null @@ -1,251 +0,0 @@ -/* -* OCSP -* (C) 2012,2013 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/ocsp.h> -#include <botan/certstor.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/x509_ext.h> -#include <botan/oids.h> -#include <botan/base64.h> -#include <botan/pubkey.h> -#include <botan/x509path.h> -#include <botan/http_util.h> -#include <memory> - -namespace Botan { - -namespace OCSP { - -namespace { - -void decode_optional_list(BER_Decoder& ber, - ASN1_Tag tag, - std::vector<X509_Certificate>& output) - { - BER_Object obj = ber.get_next_object(); - - if(obj.type_tag != tag || obj.class_tag != (CONTEXT_SPECIFIC | CONSTRUCTED)) - { - ber.push_back(obj); - return; - } - - BER_Decoder list(obj.value); - - while(list.more_items()) - { - BER_Object certbits = list.get_next_object(); - X509_Certificate cert(unlock(certbits.value)); - output.push_back(std::move(cert)); - } - } - -void check_signature(const std::vector<byte>& tbs_response, - const AlgorithmIdentifier& sig_algo, - const std::vector<byte>& signature, - const X509_Certificate& cert) - { - std::unique_ptr<Public_Key> pub_key(cert.subject_public_key()); - - const std::vector<std::string> sig_info = - split_on(OIDS::lookup(sig_algo.oid), '/'); - - if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name()) - throw std::runtime_error("Information in OCSP response does not match cert"); - - std::string padding = sig_info[1]; - Signature_Format format = - (pub_key->message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; - - PK_Verifier verifier(*pub_key, padding, format); - - if(!verifier.verify_message(ASN1::put_in_sequence(tbs_response), signature)) - throw std::runtime_error("Signature on OCSP response does not verify"); - } - -void check_signature(const std::vector<byte>& tbs_response, - const AlgorithmIdentifier& sig_algo, - const std::vector<byte>& signature, - const Certificate_Store& trusted_roots, - const std::vector<X509_Certificate>& certs) - { - if(certs.size() < 1) - throw std::invalid_argument("Short cert chain for check_signature"); - - if(trusted_roots.certificate_known(certs[0])) - return check_signature(tbs_response, sig_algo, signature, certs[0]); - - // Otherwise attempt to chain the signing cert to a trust root - - if(!certs[0].allowed_usage("PKIX.OCSPSigning")) - throw std::runtime_error("OCSP response cert does not allow OCSP signing"); - - auto result = x509_path_validate(certs, Path_Validation_Restrictions(), trusted_roots); - - if(!result.successful_validation()) - throw std::runtime_error("Certificate validation failure: " + result.result_string()); - - if(!trusted_roots.certificate_known(result.trust_root())) // not needed anymore? - throw std::runtime_error("Certificate chain roots in unknown/untrusted CA"); - - const std::vector<X509_Certificate>& cert_path = result.cert_path(); - - check_signature(tbs_response, sig_algo, signature, cert_path[0]); - } - -} - -std::vector<byte> Request::BER_encode() const - { - CertID certid(m_issuer, m_subject); - - return DER_Encoder().start_cons(SEQUENCE) - .start_cons(SEQUENCE) - .start_explicit(0) - .encode(static_cast<size_t>(0)) // version # - .end_explicit() - .start_cons(SEQUENCE) - .start_cons(SEQUENCE) - .encode(certid) - .end_cons() - .end_cons() - .end_cons() - .end_cons().get_contents_unlocked(); - } - -std::string Request::base64_encode() const - { - return Botan::base64_encode(BER_encode()); - } - -Response::Response(const Certificate_Store& trusted_roots, - const std::vector<byte>& response_bits) - { - BER_Decoder response_outer = BER_Decoder(response_bits).start_cons(SEQUENCE); - - size_t resp_status = 0; - - response_outer.decode(resp_status, ENUMERATED, UNIVERSAL); - - if(resp_status != 0) - throw std::runtime_error("OCSP response status " + std::to_string(resp_status)); - - if(response_outer.more_items()) - { - BER_Decoder response_bytes = - response_outer.start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC).start_cons(SEQUENCE); - - response_bytes.decode_and_check(OID("1.3.6.1.5.5.7.48.1.1"), - "Unknown response type in OCSP response"); - - BER_Decoder basicresponse = - BER_Decoder(response_bytes.get_next_octet_string()).start_cons(SEQUENCE); - - std::vector<byte> tbs_bits; - AlgorithmIdentifier sig_algo; - std::vector<byte> signature; - std::vector<X509_Certificate> certs; - - basicresponse.start_cons(SEQUENCE) - .raw_bytes(tbs_bits) - .end_cons() - .decode(sig_algo) - .decode(signature, BIT_STRING); - decode_optional_list(basicresponse, ASN1_Tag(0), certs); - - size_t responsedata_version = 0; - X509_DN name; - std::vector<byte> key_hash; - X509_Time produced_at; - Extensions extensions; - - BER_Decoder(tbs_bits) - .decode_optional(responsedata_version, ASN1_Tag(0), - ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) - - .decode_optional(name, ASN1_Tag(1), - ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) - - .decode_optional_string(key_hash, ASN1_Tag(2), - ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) - - .decode(produced_at) - - .decode_list(m_responses) - - .decode_optional(extensions, ASN1_Tag(1), - ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)); - - if(certs.empty()) - { - if(auto cert = trusted_roots.find_cert(name, std::vector<byte>())) - certs.push_back(*cert); - else - throw std::runtime_error("Could not find certificate that signed OCSP response"); - } - - check_signature(tbs_bits, sig_algo, signature, trusted_roots, certs); - } - - response_outer.end_cons(); - } - -Certificate_Status_Code Response::status_for(const X509_Certificate& issuer, - const X509_Certificate& subject) const - { - for(const auto& response : m_responses) - { - if(response.certid().is_id_for(issuer, subject)) - { - X509_Time current_time(std::chrono::system_clock::now()); - - if(response.this_update() > current_time) - return Certificate_Status_Code::OCSP_NOT_YET_VALID; - - if(response.next_update().time_is_set() && current_time > response.next_update()) - return Certificate_Status_Code::OCSP_EXPIRED; - - if(response.cert_status() == 1) - return Certificate_Status_Code::CERT_IS_REVOKED; - else if(response.cert_status() == 0) - return Certificate_Status_Code::OCSP_RESPONSE_GOOD; - else - return Certificate_Status_Code::OCSP_BAD_STATUS; - } - } - - return Certificate_Status_Code::OCSP_CERT_NOT_LISTED; - } - -Response online_check(const X509_Certificate& issuer, - const X509_Certificate& subject, - const Certificate_Store* trusted_roots) - { - const std::string responder_url = subject.ocsp_responder(); - - if(responder_url == "") - throw std::runtime_error("No OCSP responder specified"); - - OCSP::Request req(issuer, subject); - - auto http = HTTP::POST_sync(responder_url, - "application/ocsp-request", - req.BER_encode()); - - http.throw_unless_ok(); - - // Check the MIME type? - - OCSP::Response response(*trusted_roots, http.body()); - - return response; - } - -} - -} diff --git a/src/cert/x509/ocsp.h b/src/cert/x509/ocsp.h deleted file mode 100644 index b2a06b9a4..000000000 --- a/src/cert/x509/ocsp.h +++ /dev/null @@ -1,61 +0,0 @@ -/* -* OCSP -* (C) 2012 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_OCSP_H__ -#define BOTAN_OCSP_H__ - -#include <botan/cert_status.h> -#include <botan/ocsp_types.h> - -namespace Botan { - -class Certificate_Store; - -namespace OCSP { - -class BOTAN_DLL Request - { - public: - Request(const X509_Certificate& issuer_cert, - const X509_Certificate& subject_cert) : - m_issuer(issuer_cert), - m_subject(subject_cert) - {} - - std::vector<byte> BER_encode() const; - - std::string base64_encode() const; - - const X509_Certificate& issuer() const { return m_issuer; } - - const X509_Certificate& subject() const { return m_subject; } - private: - X509_Certificate m_issuer, m_subject; - }; - -class BOTAN_DLL Response - { - public: - Response(const Certificate_Store& trusted_roots, - const std::vector<byte>& response); - - Certificate_Status_Code status_for(const X509_Certificate& issuer, - const X509_Certificate& subject) const; - - private: - std::vector<SingleResponse> m_responses; - }; - -BOTAN_DLL Response online_check(const X509_Certificate& issuer, - const X509_Certificate& subject, - const Certificate_Store* trusted_roots); - -} - -} - -#endif diff --git a/src/cert/x509/ocsp_types.cpp b/src/cert/x509/ocsp_types.cpp deleted file mode 100644 index be41499ee..000000000 --- a/src/cert/x509/ocsp_types.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/* -* OCSP subtypes -* (C) 2012 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/ocsp_types.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/x509_ext.h> -#include <botan/lookup.h> -#include <botan/hash.h> -#include <botan/oids.h> -#include <memory> - -namespace Botan { - -namespace OCSP { - -CertID::CertID(const X509_Certificate& issuer, - const X509_Certificate& subject) - { - /* - In practice it seems some responders, including, notably, - ocsp.verisign.com, will reject anything but SHA-1 here - */ - std::unique_ptr<HashFunction> hash(get_hash("SHA-160")); - - m_hash_id = AlgorithmIdentifier(hash->name(), AlgorithmIdentifier::USE_NULL_PARAM); - m_issuer_key_hash = unlock(hash->process(extract_key_bitstr(issuer))); - m_issuer_dn_hash = unlock(hash->process(subject.raw_issuer_dn())); - m_subject_serial = BigInt::decode(subject.serial_number()); - } - -std::vector<byte> CertID::extract_key_bitstr(const X509_Certificate& cert) const - { - const auto key_bits = cert.subject_public_key_bits(); - - AlgorithmIdentifier public_key_algid; - std::vector<byte> public_key_bitstr; - - BER_Decoder(key_bits) - .decode(public_key_algid) - .decode(public_key_bitstr, BIT_STRING); - - return public_key_bitstr; - } - -bool CertID::is_id_for(const X509_Certificate& issuer, - const X509_Certificate& subject) const - { - try - { - if(BigInt::decode(subject.serial_number()) != m_subject_serial) - return false; - - std::unique_ptr<HashFunction> hash(get_hash(OIDS::lookup(m_hash_id.oid))); - - if(m_issuer_dn_hash != unlock(hash->process(subject.raw_issuer_dn()))) - return false; - - if(m_issuer_key_hash != unlock(hash->process(extract_key_bitstr(issuer)))) - return false; - } - catch(...) - { - return false; - } - - return true; - } - -void CertID::encode_into(class DER_Encoder& to) const - { - to.start_cons(SEQUENCE) - .encode(m_hash_id) - .encode(m_issuer_dn_hash, OCTET_STRING) - .encode(m_issuer_key_hash, OCTET_STRING) - .encode(m_subject_serial) - .end_cons(); - } - -void CertID::decode_from(class BER_Decoder& from) - { - from.start_cons(SEQUENCE) - .decode(m_hash_id) - .decode(m_issuer_dn_hash, OCTET_STRING) - .decode(m_issuer_key_hash, OCTET_STRING) - .decode(m_subject_serial) - .end_cons(); - - } - -void SingleResponse::encode_into(class DER_Encoder&) const - { - throw std::runtime_error("Not implemented (SingleResponse::encode_into)"); - } - -void SingleResponse::decode_from(class BER_Decoder& from) - { - BER_Object cert_status; - Extensions extensions; - - from.start_cons(SEQUENCE) - .decode(m_certid) - .get_next(cert_status) - .decode(m_thisupdate) - .decode_optional(m_nextupdate, ASN1_Tag(0), - ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED)) - .decode_optional(extensions, - ASN1_Tag(1), - ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED)) - .end_cons(); - - m_cert_status = cert_status.type_tag; - } - -} - -} diff --git a/src/cert/x509/ocsp_types.h b/src/cert/x509/ocsp_types.h deleted file mode 100644 index a2983f10b..000000000 --- a/src/cert/x509/ocsp_types.h +++ /dev/null @@ -1,67 +0,0 @@ -/* -* OCSP subtypes -* (C) 2012 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_OCSP_TYPES_H__ -#define BOTAN_OCSP_TYPES_H__ - -#include <botan/x509cert.h> -#include <botan/asn1_time.h> -#include <botan/bigint.h> - -namespace Botan { - -namespace OCSP { - -class BOTAN_DLL CertID : public ASN1_Object - { - public: - CertID() {} - - CertID(const X509_Certificate& issuer, - const X509_Certificate& subject); - - bool is_id_for(const X509_Certificate& issuer, - const X509_Certificate& subject) const; - - void encode_into(class DER_Encoder& to) const override; - - void decode_from(class BER_Decoder& from) override; - private: - std::vector<byte> extract_key_bitstr(const X509_Certificate& cert) const; - - AlgorithmIdentifier m_hash_id; - std::vector<byte> m_issuer_dn_hash; - std::vector<byte> m_issuer_key_hash; - BigInt m_subject_serial; - }; - -class BOTAN_DLL SingleResponse : public ASN1_Object - { - public: - const CertID& certid() const { return m_certid; } - - size_t cert_status() const { return m_cert_status; } - - X509_Time this_update() const { return m_thisupdate; } - - X509_Time next_update() const { return m_nextupdate; } - - void encode_into(class DER_Encoder& to) const override; - - void decode_from(class BER_Decoder& from) override; - private: - CertID m_certid; - size_t m_cert_status = 2; // unknown - X509_Time m_thisupdate; - X509_Time m_nextupdate; - }; - -} - -} - -#endif diff --git a/src/cert/x509/pkcs10.cpp b/src/cert/x509/pkcs10.cpp deleted file mode 100644 index c67f74142..000000000 --- a/src/cert/x509/pkcs10.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/* -* PKCS #10 -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/pkcs10.h> -#include <botan/x509_ext.h> -#include <botan/x509cert.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/parsing.h> -#include <botan/oids.h> -#include <botan/pem.h> - -namespace Botan { - -/* -* PKCS10_Request Constructor -*/ -PKCS10_Request::PKCS10_Request(DataSource& in) : - X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") - { - do_decode(); - } - -/* -* PKCS10_Request Constructor -*/ -PKCS10_Request::PKCS10_Request(const std::string& in) : - X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") - { - do_decode(); - } - -/* -* PKCS10_Request Constructor -*/ -PKCS10_Request::PKCS10_Request(const std::vector<byte>& in) : - X509_Object(in, "CERTIFICATE REQUEST/NEW CERTIFICATE REQUEST") - { - do_decode(); - } - -/* -* Deocde the CertificateRequestInfo -*/ -void PKCS10_Request::force_decode() - { - BER_Decoder cert_req_info(tbs_bits); - - size_t version; - cert_req_info.decode(version); - if(version != 0) - throw Decoding_Error("Unknown version code in PKCS #10 request: " + - std::to_string(version)); - - X509_DN dn_subject; - cert_req_info.decode(dn_subject); - - info.add(dn_subject.contents()); - - BER_Object public_key = cert_req_info.get_next_object(); - if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED) - throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for public key", - public_key.type_tag, public_key.class_tag); - - info.add("X509.Certificate.public_key", - PEM_Code::encode( - ASN1::put_in_sequence(unlock(public_key.value)), - "PUBLIC KEY" - ) - ); - - BER_Object attr_bits = cert_req_info.get_next_object(); - - if(attr_bits.type_tag == 0 && - attr_bits.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) - { - BER_Decoder attributes(attr_bits.value); - while(attributes.more_items()) - { - Attribute attr; - attributes.decode(attr); - handle_attribute(attr); - } - attributes.verify_end(); - } - else if(attr_bits.type_tag != NO_OBJECT) - throw BER_Bad_Tag("PKCS10_Request: Unexpected tag for attributes", - attr_bits.type_tag, attr_bits.class_tag); - - cert_req_info.verify_end(); - - if(!this->check_signature(subject_public_key())) - throw Decoding_Error("PKCS #10 request: Bad signature detected"); - } - -/* -* Handle attributes in a PKCS #10 request -*/ -void PKCS10_Request::handle_attribute(const Attribute& attr) - { - BER_Decoder value(attr.parameters); - - if(attr.oid == OIDS::lookup("PKCS9.EmailAddress")) - { - ASN1_String email; - value.decode(email); - info.add("RFC822", email.value()); - } - else if(attr.oid == OIDS::lookup("PKCS9.ChallengePassword")) - { - ASN1_String challenge_password; - value.decode(challenge_password); - info.add("PKCS9.ChallengePassword", challenge_password.value()); - } - else if(attr.oid == OIDS::lookup("PKCS9.ExtensionRequest")) - { - Extensions extensions; - value.decode(extensions).verify_end(); - - Data_Store issuer_info; - extensions.contents_to(info, issuer_info); - } - } - -/* -* Return the challenge password (if any) -*/ -std::string PKCS10_Request::challenge_password() const - { - return info.get1("PKCS9.ChallengePassword"); - } - -/* -* Return the name of the requestor -*/ -X509_DN PKCS10_Request::subject_dn() const - { - return create_dn(info); - } - -/* -* Return the public key of the requestor -*/ -std::vector<byte> PKCS10_Request::raw_public_key() const - { - DataSource_Memory source(info.get1("X509.Certificate.public_key")); - return unlock(PEM_Code::decode_check_label(source, "PUBLIC KEY")); - } - -/* -* Return the public key of the requestor -*/ -Public_Key* PKCS10_Request::subject_public_key() const - { - DataSource_Memory source(info.get1("X509.Certificate.public_key")); - return X509::load_key(source); - } - -/* -* Return the alternative names of the requestor -*/ -AlternativeName PKCS10_Request::subject_alt_name() const - { - return create_alt_name(info); - } - -/* -* Return the key constraints (if any) -*/ -Key_Constraints PKCS10_Request::constraints() const - { - return Key_Constraints(info.get1_u32bit("X509v3.KeyUsage", NO_CONSTRAINTS)); - } - -/* -* Return the extendend key constraints (if any) -*/ -std::vector<OID> PKCS10_Request::ex_constraints() const - { - std::vector<std::string> oids = info.get("X509v3.ExtendedKeyUsage"); - - std::vector<OID> result; - for(size_t i = 0; i != oids.size(); ++i) - result.push_back(OID(oids[i])); - return result; - } - -/* -* Return is a CA certificate is requested -*/ -bool PKCS10_Request::is_CA() const - { - return (info.get1_u32bit("X509v3.BasicConstraints.is_ca") > 0); - } - -/* -* Return the desired path limit (if any) -*/ -u32bit PKCS10_Request::path_limit() const - { - return info.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0); - } - -} diff --git a/src/cert/x509/pkcs10.h b/src/cert/x509/pkcs10.h deleted file mode 100644 index b54425133..000000000 --- a/src/cert/x509/pkcs10.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -* PKCS #10 -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_PKCS10_H__ -#define BOTAN_PKCS10_H__ - -#include <botan/x509_obj.h> -#include <botan/x509_dn.h> -#include <botan/pkcs8.h> -#include <botan/datastor.h> -#include <botan/key_constraint.h> -#include <botan/asn1_attribute.h> -#include <botan/asn1_alt_name.h> -#include <vector> - -namespace Botan { - -/** -* PKCS #10 Certificate Request. -*/ -class BOTAN_DLL PKCS10_Request : public X509_Object - { - public: - /** - * Get the subject public key. - * @return subject public key - */ - Public_Key* subject_public_key() const; - - /** - * Get the raw DER encoded public key. - * @return raw DER encoded public key - */ - std::vector<byte> raw_public_key() const; - - /** - * Get the subject DN. - * @return subject DN - */ - X509_DN subject_dn() const; - - /** - * Get the subject alternative name. - * @return subject alternative name. - */ - AlternativeName subject_alt_name() const; - - /** - * Get the key constraints for the key associated with this - * PKCS#10 object. - * @return key constraints - */ - Key_Constraints constraints() const; - - /** - * Get the extendend key constraints (if any). - * @return extended key constraints - */ - std::vector<OID> ex_constraints() const; - - /** - * Find out whether this is a CA request. - * @result true if it is a CA request, false otherwise. - */ - bool is_CA() const; - - /** - * Return the constraint on the path length defined - * in the BasicConstraints extension. - * @return path limit - */ - u32bit path_limit() const; - - /** - * Get the challenge password for this request - * @return challenge password for this request - */ - std::string challenge_password() const; - - /** - * Create a PKCS#10 Request from a data source. - * @param source the data source providing the DER encoded request - */ - PKCS10_Request(DataSource& source); - - /** - * Create a PKCS#10 Request from a file. - * @param filename the name of the file containing the DER or PEM - * encoded request file - */ - PKCS10_Request(const std::string& filename); - - /** - * Create a PKCS#10 Request from binary data. - * @param vec a std::vector containing the DER value - */ - PKCS10_Request(const std::vector<byte>& vec); - private: - void force_decode(); - void handle_attribute(const Attribute&); - - Data_Store info; - }; - -} - -#endif diff --git a/src/cert/x509/x509_ca.cpp b/src/cert/x509/x509_ca.cpp deleted file mode 100644 index 486d769ef..000000000 --- a/src/cert/x509/x509_ca.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* -* X.509 Certificate Authority -* (C) 1999-2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/x509_ca.h> -#include <botan/pubkey.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/bigint.h> -#include <botan/parsing.h> -#include <botan/lookup.h> -#include <botan/oids.h> -#include <botan/key_constraint.h> -#include <algorithm> -#include <typeinfo> -#include <iterator> -#include <memory> -#include <set> - -namespace Botan { - -/* -* Load the certificate and private key -*/ -X509_CA::X509_CA(const X509_Certificate& c, - const Private_Key& key, - const std::string& hash_fn) : cert(c) - { - if(!cert.is_CA_cert()) - throw Invalid_Argument("X509_CA: This certificate is not for a CA"); - - signer = choose_sig_format(key, hash_fn, ca_sig_algo); - } - -/* -* X509_CA Destructor -*/ -X509_CA::~X509_CA() - { - delete signer; - } - -/* -* Sign a PKCS #10 certificate request -*/ -X509_Certificate X509_CA::sign_request(const PKCS10_Request& req, - RandomNumberGenerator& rng, - const X509_Time& not_before, - const X509_Time& not_after) - { - Key_Constraints constraints; - if(req.is_CA()) - constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN); - else - { - std::unique_ptr<Public_Key> key(req.subject_public_key()); - constraints = find_constraints(*key, req.constraints()); - } - - Extensions extensions; - - extensions.add( - new Cert_Extension::Basic_Constraints(req.is_CA(), req.path_limit()), - true); - - extensions.add(new Cert_Extension::Key_Usage(constraints), true); - - extensions.add(new Cert_Extension::Authority_Key_ID(cert.subject_key_id())); - extensions.add(new Cert_Extension::Subject_Key_ID(req.raw_public_key())); - - extensions.add( - new Cert_Extension::Subject_Alternative_Name(req.subject_alt_name())); - - extensions.add( - new Cert_Extension::Extended_Key_Usage(req.ex_constraints())); - - return make_cert(signer, rng, ca_sig_algo, - req.raw_public_key(), - not_before, not_after, - cert.subject_dn(), req.subject_dn(), - extensions); - } - -/* -* Create a new certificate -*/ -X509_Certificate X509_CA::make_cert(PK_Signer* signer, - RandomNumberGenerator& rng, - const AlgorithmIdentifier& sig_algo, - const std::vector<byte>& pub_key, - const X509_Time& not_before, - const X509_Time& not_after, - const X509_DN& issuer_dn, - const X509_DN& subject_dn, - const Extensions& extensions) - { - const size_t X509_CERT_VERSION = 3; - const size_t SERIAL_BITS = 128; - - BigInt serial_no(rng, SERIAL_BITS); - - const std::vector<byte> cert = X509_Object::make_signed( - signer, rng, sig_algo, - DER_Encoder().start_cons(SEQUENCE) - .start_explicit(0) - .encode(X509_CERT_VERSION-1) - .end_explicit() - - .encode(serial_no) - - .encode(sig_algo) - .encode(issuer_dn) - - .start_cons(SEQUENCE) - .encode(not_before) - .encode(not_after) - .end_cons() - - .encode(subject_dn) - .raw_bytes(pub_key) - - .start_explicit(3) - .start_cons(SEQUENCE) - .encode(extensions) - .end_cons() - .end_explicit() - .end_cons() - .get_contents()); - - return X509_Certificate(cert); - } - -/* -* Create a new, empty CRL -*/ -X509_CRL X509_CA::new_crl(RandomNumberGenerator& rng, - u32bit next_update) const - { - std::vector<CRL_Entry> empty; - return make_crl(empty, 1, next_update, rng); - } - -/* -* Update a CRL with new entries -*/ -X509_CRL X509_CA::update_crl(const X509_CRL& crl, - const std::vector<CRL_Entry>& new_revoked, - RandomNumberGenerator& rng, - u32bit next_update) const - { - std::vector<CRL_Entry> revoked = crl.get_revoked(); - - std::copy(new_revoked.begin(), new_revoked.end(), - std::back_inserter(revoked)); - - return make_crl(revoked, crl.crl_number() + 1, next_update, rng); - } - -/* -* Create a CRL -*/ -X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked, - u32bit crl_number, u32bit next_update, - RandomNumberGenerator& rng) const - { - const size_t X509_CRL_VERSION = 2; - - if(next_update == 0) - next_update = timespec_to_u32bit("7d"); - - // Totally stupid: ties encoding logic to the return of std::time!! - auto current_time = std::chrono::system_clock::now(); - auto expire_time = current_time + std::chrono::seconds(next_update); - - Extensions extensions; - extensions.add( - new Cert_Extension::Authority_Key_ID(cert.subject_key_id())); - extensions.add(new Cert_Extension::CRL_Number(crl_number)); - - const std::vector<byte> crl = X509_Object::make_signed( - signer, rng, ca_sig_algo, - DER_Encoder().start_cons(SEQUENCE) - .encode(X509_CRL_VERSION-1) - .encode(ca_sig_algo) - .encode(cert.issuer_dn()) - .encode(X509_Time(current_time)) - .encode(X509_Time(expire_time)) - .encode_if(revoked.size() > 0, - DER_Encoder() - .start_cons(SEQUENCE) - .encode_list(revoked) - .end_cons() - ) - .start_explicit(0) - .start_cons(SEQUENCE) - .encode(extensions) - .end_cons() - .end_explicit() - .end_cons() - .get_contents()); - - return X509_CRL(crl); - } - -/* -* Return the CA's certificate -*/ -X509_Certificate X509_CA::ca_certificate() const - { - return cert; - } - -/* -* Choose a signing format for the key -*/ -PK_Signer* choose_sig_format(const Private_Key& key, - const std::string& hash_fn, - AlgorithmIdentifier& sig_algo) - { - std::string padding; - - const std::string algo_name = key.algo_name(); - - const HashFunction* proto_hash = retrieve_hash(hash_fn); - if(!proto_hash) - throw Algorithm_Not_Found(hash_fn); - - if(key.max_input_bits() < proto_hash->output_length()*8) - throw Invalid_Argument("Key is too small for chosen hash function"); - - if(algo_name == "RSA") - padding = "EMSA3"; - else if(algo_name == "DSA") - padding = "EMSA1"; - else if(algo_name == "ECDSA") - padding = "EMSA1_BSI"; - else - throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name); - - Signature_Format format = - (key.message_parts() > 1) ? DER_SEQUENCE : IEEE_1363; - - padding = padding + '(' + proto_hash->name() + ')'; - - sig_algo.oid = OIDS::lookup(algo_name + "/" + padding); - sig_algo.parameters = key.algorithm_identifier().parameters; - - return new PK_Signer(key, padding, format); - } - -} diff --git a/src/cert/x509/x509_ca.h b/src/cert/x509/x509_ca.h deleted file mode 100644 index d37b02eaf..000000000 --- a/src/cert/x509/x509_ca.h +++ /dev/null @@ -1,130 +0,0 @@ -/* -* X.509 Certificate Authority -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_X509_CA_H__ -#define BOTAN_X509_CA_H__ - -#include <botan/x509cert.h> -#include <botan/x509_crl.h> -#include <botan/x509_ext.h> -#include <botan/pkcs8.h> -#include <botan/pkcs10.h> -#include <botan/pubkey.h> - -namespace Botan { - -/** -* This class represents X.509 Certificate Authorities (CAs). -*/ -class BOTAN_DLL X509_CA - { - public: - - /** - * Sign a PKCS#10 Request. - * @param req the request to sign - * @param rng the rng to use - * @param not_before the starting time for the certificate - * @param not_after the expiration time for the certificate - * @return resulting certificate - */ - X509_Certificate sign_request(const PKCS10_Request& req, - RandomNumberGenerator& rng, - const X509_Time& not_before, - const X509_Time& not_after); - - /** - * Get the certificate of this CA. - * @return CA certificate - */ - X509_Certificate ca_certificate() const; - - /** - * Create a new and empty CRL for this CA. - * @param rng the random number generator to use - * @param next_update the time to set in next update in seconds - * as the offset from the current time - * @return new CRL - */ - X509_CRL new_crl(RandomNumberGenerator& rng, - u32bit next_update = 0) const; - - /** - * Create a new CRL by with additional entries. - * @param last_crl the last CRL of this CA to add the new entries to - * @param new_entries contains the new CRL entries to be added to the CRL - * @param rng the random number generator to use - * @param next_update the time to set in next update in seconds - * as the offset from the current time - */ - X509_CRL update_crl(const X509_CRL& last_crl, - const std::vector<CRL_Entry>& new_entries, - RandomNumberGenerator& rng, - u32bit next_update = 0) const; - - /** - * Interface for creating new certificates - * @param signer a signing object - * @param rng a random number generator - * @param sig_algo the signature algorithm identifier - * @param pub_key the serialized public key - * @param not_before the start time of the certificate - * @param not_after the end time of the certificate - * @param issuer_dn the DN of the issuer - * @param subject_dn the DN of the subject - * @param extensions an optional list of certificate extensions - * @returns newly minted certificate - */ - static X509_Certificate make_cert(PK_Signer* signer, - RandomNumberGenerator& rng, - const AlgorithmIdentifier& sig_algo, - const std::vector<byte>& pub_key, - const X509_Time& not_before, - const X509_Time& not_after, - const X509_DN& issuer_dn, - const X509_DN& subject_dn, - const Extensions& extensions); - - /** - * Create a new CA object. - * @param ca_certificate the certificate of the CA - * @param key the private key of the CA - * @param hash_fn name of a hash function to use for signing - */ - X509_CA(const X509_Certificate& ca_certificate, - const Private_Key& key, - const std::string& hash_fn); - - X509_CA(const X509_CA&) = delete; - X509_CA& operator=(const X509_CA&) = delete; - - ~X509_CA(); - private: - X509_CRL make_crl(const std::vector<CRL_Entry>& entries, - u32bit crl_number, u32bit next_update, - RandomNumberGenerator& rng) const; - - AlgorithmIdentifier ca_sig_algo; - X509_Certificate cert; - PK_Signer* signer; - }; - -/** -* Choose the default signature format for a certain public key signature -* scheme. -* @param key will be the key to choose a padding scheme for -* @param hash_fn is the desired hash function -* @param alg_id will be set to the chosen scheme -* @return A PK_Signer object for generating signatures -*/ -BOTAN_DLL PK_Signer* choose_sig_format(const Private_Key& key, - const std::string& hash_fn, - AlgorithmIdentifier& alg_id); - -} - -#endif diff --git a/src/cert/x509/x509_crl.cpp b/src/cert/x509/x509_crl.cpp deleted file mode 100644 index 29495a627..000000000 --- a/src/cert/x509/x509_crl.cpp +++ /dev/null @@ -1,191 +0,0 @@ -/* -* X.509 CRL -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#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> -#include <botan/oids.h> - -namespace Botan { - -/* -* Load a X.509 CRL -*/ -X509_CRL::X509_CRL(DataSource& in, bool touc) : - X509_Object(in, "X509 CRL/CRL"), throw_on_unknown_critical(touc) - { - do_decode(); - } - -/* -* Load a X.509 CRL -*/ -X509_CRL::X509_CRL(const std::string& in, bool touc) : - X509_Object(in, "CRL/X509 CRL"), throw_on_unknown_critical(touc) - { - do_decode(); - } - -X509_CRL::X509_CRL(const std::vector<byte>& in, bool touc) : - X509_Object(in, "CRL/X509 CRL"), throw_on_unknown_critical(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; - - std::vector<byte> crl_akid = authority_key_id(); - std::vector<byte> cert_akid = cert.authority_key_id(); - - if(!crl_akid.empty() && !cert_akid.empty()) - if(crl_akid != cert_akid) - return false; - - std::vector<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 -*/ -void X509_CRL::force_decode() - { - BER_Decoder tbs_crl(tbs_bits); - - size_t version; - tbs_crl.decode_optional(version, INTEGER, UNIVERSAL); - - if(version != 0 && version != 1) - throw X509_CRL_Error("Unknown X.509 CRL version " + - std::to_string(version+1)); - - AlgorithmIdentifier sig_algo_inner; - tbs_crl.decode(sig_algo_inner); - - if(sig_algo != sig_algo_inner) - throw X509_CRL_Error("Algorithm identifier mismatch"); - - X509_DN dn_issuer; - tbs_crl.decode(dn_issuer); - info.add(dn_issuer.contents()); - - X509_Time start, end; - tbs_crl.decode(start).decode(end); - info.add("X509.CRL.start", start.readable_string()); - info.add("X509.CRL.end", end.readable_string()); - - BER_Object next = tbs_crl.get_next_object(); - - if(next.type_tag == SEQUENCE && next.class_tag == CONSTRUCTED) - { - BER_Decoder cert_list(next.value); - - while(cert_list.more_items()) - { - CRL_Entry entry(throw_on_unknown_critical); - cert_list.decode(entry); - revoked.push_back(entry); - } - next = tbs_crl.get_next_object(); - } - - if(next.type_tag == 0 && - next.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) - { - BER_Decoder crl_options(next.value); - - Extensions extensions(throw_on_unknown_critical); - - crl_options.decode(extensions).verify_end(); - - extensions.contents_to(info, info); - - next = tbs_crl.get_next_object(); - } - - if(next.type_tag != NO_OBJECT) - throw X509_CRL_Error("Unknown tag in CRL"); - - tbs_crl.verify_end(); - } - -/* -* Return the list of revoked certificates -*/ -std::vector<CRL_Entry> X509_CRL::get_revoked() const - { - return revoked; - } - -/* -* Return the distinguished name of the issuer -*/ -X509_DN X509_CRL::issuer_dn() const - { - return create_dn(info); - } - -/* -* Return the key identifier of the issuer -*/ -std::vector<byte> X509_CRL::authority_key_id() const - { - return info.get1_memvec("X509v3.AuthorityKeyIdentifier"); - } - -/* -* Return the CRL number of this CRL -*/ -u32bit X509_CRL::crl_number() const - { - return info.get1_u32bit("X509v3.CRLNumber"); - } - -/* -* Return the issue data of the CRL -*/ -X509_Time X509_CRL::this_update() const - { - return info.get1("X509.CRL.start"); - } - -/* -* Return the date when a new CRL will be issued -*/ -X509_Time X509_CRL::next_update() const - { - return info.get1("X509.CRL.end"); - } - -} diff --git a/src/cert/x509/x509_crl.h b/src/cert/x509/x509_crl.h deleted file mode 100644 index 3e45df121..000000000 --- a/src/cert/x509/x509_crl.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -* X.509 CRL -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_X509_CRL_H__ -#define BOTAN_X509_CRL_H__ - -#include <botan/x509_obj.h> -#include <botan/crl_ent.h> -#include <vector> - -namespace Botan { - -class X509_Certificate; - -/** -* This class represents X.509 Certificate Revocation Lists (CRLs). -*/ -class BOTAN_DLL X509_CRL : public X509_Object - { - public: - /** - * This class represents CRL related errors. - */ - struct BOTAN_DLL X509_CRL_Error : public Exception - { - X509_CRL_Error(const std::string& error) : - Exception("X509_CRL: " + error) {} - }; - - /** - * 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. - */ - std::vector<CRL_Entry> get_revoked() const; - - /** - * Get the issuer DN of this CRL. - * @return CRLs issuer DN - */ - X509_DN issuer_dn() const; - - /** - * Get the AuthorityKeyIdentifier of this CRL. - * @return this CRLs AuthorityKeyIdentifier - */ - std::vector<byte> authority_key_id() const; - - /** - * Get the serial number of this CRL. - * @return CRLs serial number - */ - u32bit crl_number() const; - - /** - * Get the CRL's thisUpdate value. - * @return CRLs thisUpdate - */ - X509_Time this_update() const; - - /** - * Get the CRL's nextUpdate value. - * @return CRLs nextdUpdate - */ - X509_Time next_update() const; - - /** - * Construct a CRL from a data source. - * @param source the data source providing the DER or PEM encoded CRL. - * @param throw_on_unknown_critical should we throw an exception - * if an unknown CRL extension marked as critical is encountered. - */ - X509_CRL(DataSource& source, bool throw_on_unknown_critical = false); - - /** - * Construct a CRL from a file containing the DER or PEM encoded CRL. - * @param filename the name of the CRL file - * @param throw_on_unknown_critical should we throw an exception - * if an unknown CRL extension marked as critical is encountered. - */ - X509_CRL(const std::string& filename, - bool throw_on_unknown_critical = false); - - /** - * Construct a CRL from a binary vector - * @param vec the binary (DER) representation of the CRL - * @param throw_on_unknown_critical should we throw an exception - * if an unknown CRL extension marked as critical is encountered. - */ - X509_CRL(const std::vector<byte>& vec, - bool throw_on_unknown_critical = false); - - private: - void force_decode(); - - bool throw_on_unknown_critical; - std::vector<CRL_Entry> revoked; - Data_Store info; - }; - -} - -#endif diff --git a/src/cert/x509/x509_ext.cpp b/src/cert/x509/x509_ext.cpp deleted file mode 100644 index 7cef2969b..000000000 --- a/src/cert/x509/x509_ext.cpp +++ /dev/null @@ -1,660 +0,0 @@ -/* -* X.509 Certificate Extensions -* (C) 1999-2010,2012 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/x509_ext.h> -#include <botan/sha160.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/oids.h> -#include <botan/charset.h> -#include <botan/internal/bit_ops.h> -#include <algorithm> -#include <memory> - -namespace Botan { - -/* -* List of X.509 Certificate Extensions -*/ -Certificate_Extension* Extensions::get_extension(const OID& oid) - { -#define X509_EXTENSION(NAME, TYPE) \ - if(OIDS::name_of(oid, NAME)) \ - return new Cert_Extension::TYPE(); - - X509_EXTENSION("X509v3.KeyUsage", Key_Usage); - X509_EXTENSION("X509v3.BasicConstraints", Basic_Constraints); - X509_EXTENSION("X509v3.SubjectKeyIdentifier", Subject_Key_ID); - X509_EXTENSION("X509v3.AuthorityKeyIdentifier", Authority_Key_ID); - X509_EXTENSION("X509v3.ExtendedKeyUsage", Extended_Key_Usage); - X509_EXTENSION("X509v3.IssuerAlternativeName", Issuer_Alternative_Name); - X509_EXTENSION("X509v3.SubjectAlternativeName", Subject_Alternative_Name); - X509_EXTENSION("X509v3.CertificatePolicies", Certificate_Policies); - X509_EXTENSION("X509v3.CRLDistributionPoints", CRL_Distribution_Points); - X509_EXTENSION("PKIX.AuthorityInformationAccess", Authority_Information_Access); - X509_EXTENSION("X509v3.CRLNumber", CRL_Number); - X509_EXTENSION("X509v3.ReasonCode", CRL_ReasonCode); - - return nullptr; - } - -/* -* Extensions Copy Constructor -*/ -Extensions::Extensions(const Extensions& extensions) : ASN1_Object() - { - *this = extensions; - } - -/* -* Extensions Assignment Operator -*/ -Extensions& Extensions::operator=(const Extensions& other) - { - for(size_t i = 0; i != extensions.size(); ++i) - delete extensions[i].first; - extensions.clear(); - - for(size_t i = 0; i != other.extensions.size(); ++i) - extensions.push_back( - std::make_pair(other.extensions[i].first->copy(), - other.extensions[i].second)); - - return (*this); - } - -/* -* Return the OID of this extension -*/ -OID Certificate_Extension::oid_of() const - { - return OIDS::lookup(oid_name()); - } - -void Extensions::add(Certificate_Extension* extn, bool critical) - { - extensions.push_back(std::make_pair(extn, critical)); - } - -/* -* Encode an Extensions list -*/ -void Extensions::encode_into(DER_Encoder& to_object) const - { - for(size_t i = 0; i != extensions.size(); ++i) - { - const Certificate_Extension* ext = extensions[i].first; - const bool is_critical = extensions[i].second; - - const bool should_encode = ext->should_encode(); - - if(should_encode) - { - to_object.start_cons(SEQUENCE) - .encode(ext->oid_of()) - .encode_optional(is_critical, false) - .encode(ext->encode_inner(), OCTET_STRING) - .end_cons(); - } - } - } - -/* -* Decode a list of Extensions -*/ -void Extensions::decode_from(BER_Decoder& from_source) - { - for(size_t i = 0; i != extensions.size(); ++i) - delete extensions[i].first; - extensions.clear(); - - BER_Decoder sequence = from_source.start_cons(SEQUENCE); - - while(sequence.more_items()) - { - OID oid; - std::vector<byte> value; - bool critical; - - sequence.start_cons(SEQUENCE) - .decode(oid) - .decode_optional(critical, BOOLEAN, UNIVERSAL, false) - .decode(value, OCTET_STRING) - .verify_end() - .end_cons(); - - Certificate_Extension* ext = get_extension(oid); - - if(!ext) - { - if(!critical || !should_throw) - continue; - - throw Decoding_Error("Encountered unknown X.509 extension marked " - "as critical; OID = " + oid.as_string()); - } - - ext->decode_inner(value); - - extensions.push_back(std::make_pair(ext, critical)); - } - sequence.verify_end(); - } - -/* -* Write the extensions to an info store -*/ -void Extensions::contents_to(Data_Store& subject_info, - Data_Store& issuer_info) const - { - for(size_t i = 0; i != extensions.size(); ++i) - extensions[i].first->contents_to(subject_info, issuer_info); - } - -/* -* Delete an Extensions list -*/ -Extensions::~Extensions() - { - for(size_t i = 0; i != extensions.size(); ++i) - delete extensions[i].first; - } - -namespace Cert_Extension { - -/* -* Checked accessor for the path_limit member -*/ -size_t Basic_Constraints::get_path_limit() const - { - if(!is_ca) - throw Invalid_State("Basic_Constraints::get_path_limit: Not a CA"); - return path_limit; - } - -/* -* Encode the extension -*/ -std::vector<byte> Basic_Constraints::encode_inner() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode_if(is_ca, - DER_Encoder() - .encode(is_ca) - .encode_optional(path_limit, NO_CERT_PATH_LIMIT) - ) - .end_cons() - .get_contents_unlocked(); - } - -/* -* Decode the extension -*/ -void Basic_Constraints::decode_inner(const std::vector<byte>& in) - { - BER_Decoder(in) - .start_cons(SEQUENCE) - .decode_optional(is_ca, BOOLEAN, UNIVERSAL, false) - .decode_optional(path_limit, INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT) - .verify_end() - .end_cons(); - - if(is_ca == false) - path_limit = 0; - } - -/* -* Return a textual representation -*/ -void Basic_Constraints::contents_to(Data_Store& subject, Data_Store&) const - { - subject.add("X509v3.BasicConstraints.is_ca", (is_ca ? 1 : 0)); - subject.add("X509v3.BasicConstraints.path_constraint", path_limit); - } - -/* -* Encode the extension -*/ -std::vector<byte> Key_Usage::encode_inner() const - { - if(constraints == NO_CONSTRAINTS) - throw Encoding_Error("Cannot encode zero usage constraints"); - - const size_t unused_bits = low_bit(constraints) - 1; - - std::vector<byte> der; - der.push_back(BIT_STRING); - der.push_back(2 + ((unused_bits < 8) ? 1 : 0)); - der.push_back(unused_bits % 8); - der.push_back((constraints >> 8) & 0xFF); - if(constraints & 0xFF) - der.push_back(constraints & 0xFF); - - return der; - } - -/* -* Decode the extension -*/ -void Key_Usage::decode_inner(const std::vector<byte>& in) - { - BER_Decoder ber(in); - - BER_Object obj = ber.get_next_object(); - - if(obj.type_tag != BIT_STRING || obj.class_tag != UNIVERSAL) - throw BER_Bad_Tag("Bad tag for usage constraint", - obj.type_tag, obj.class_tag); - - if(obj.value.size() != 2 && obj.value.size() != 3) - throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint"); - - if(obj.value[0] >= 8) - throw BER_Decoding_Error("Invalid unused bits in usage constraint"); - - obj.value[obj.value.size()-1] &= (0xFF << obj.value[0]); - - u16bit usage = 0; - for(size_t i = 1; i != obj.value.size(); ++i) - usage = (obj.value[i] << 8) | usage; - - constraints = Key_Constraints(usage); - } - -/* -* Return a textual representation -*/ -void Key_Usage::contents_to(Data_Store& subject, Data_Store&) const - { - subject.add("X509v3.KeyUsage", constraints); - } - -/* -* Encode the extension -*/ -std::vector<byte> Subject_Key_ID::encode_inner() const - { - return DER_Encoder().encode(key_id, OCTET_STRING).get_contents_unlocked(); - } - -/* -* Decode the extension -*/ -void Subject_Key_ID::decode_inner(const std::vector<byte>& in) - { - BER_Decoder(in).decode(key_id, OCTET_STRING).verify_end(); - } - -/* -* Return a textual representation -*/ -void Subject_Key_ID::contents_to(Data_Store& subject, Data_Store&) const - { - subject.add("X509v3.SubjectKeyIdentifier", key_id); - } - -/* -* Subject_Key_ID Constructor -*/ -Subject_Key_ID::Subject_Key_ID(const std::vector<byte>& pub_key) - { - SHA_160 hash; - key_id = unlock(hash.process(pub_key)); - } - -/* -* Encode the extension -*/ -std::vector<byte> Authority_Key_ID::encode_inner() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode(key_id, OCTET_STRING, ASN1_Tag(0), CONTEXT_SPECIFIC) - .end_cons() - .get_contents_unlocked(); - } - -/* -* Decode the extension -*/ -void Authority_Key_ID::decode_inner(const std::vector<byte>& in) - { - BER_Decoder(in) - .start_cons(SEQUENCE) - .decode_optional_string(key_id, OCTET_STRING, 0); - } - -/* -* Return a textual representation -*/ -void Authority_Key_ID::contents_to(Data_Store&, Data_Store& issuer) const - { - if(key_id.size()) - issuer.add("X509v3.AuthorityKeyIdentifier", key_id); - } - -/* -* Encode the extension -*/ -std::vector<byte> Alternative_Name::encode_inner() const - { - return DER_Encoder().encode(alt_name).get_contents_unlocked(); - } - -/* -* Decode the extension -*/ -void Alternative_Name::decode_inner(const std::vector<byte>& in) - { - BER_Decoder(in).decode(alt_name); - } - -/* -* Return a textual representation -*/ -void Alternative_Name::contents_to(Data_Store& subject_info, - Data_Store& issuer_info) const - { - std::multimap<std::string, std::string> contents = - get_alt_name().contents(); - - if(oid_name_str == "X509v3.SubjectAlternativeName") - subject_info.add(contents); - else if(oid_name_str == "X509v3.IssuerAlternativeName") - issuer_info.add(contents); - else - throw Internal_Error("In Alternative_Name, unknown type " + - oid_name_str); - } - -/* -* Alternative_Name Constructor -*/ -Alternative_Name::Alternative_Name(const AlternativeName& alt_name, - const std::string& oid_name_str) - { - this->alt_name = alt_name; - this->oid_name_str = oid_name_str; - } - -/* -* Subject_Alternative_Name Constructor -*/ -Subject_Alternative_Name::Subject_Alternative_Name( - const AlternativeName& name) : - Alternative_Name(name, "X509v3.SubjectAlternativeName") - { - } - -/* -* Issuer_Alternative_Name Constructor -*/ -Issuer_Alternative_Name::Issuer_Alternative_Name(const AlternativeName& name) : - Alternative_Name(name, "X509v3.IssuerAlternativeName") - { - } - -/* -* Encode the extension -*/ -std::vector<byte> Extended_Key_Usage::encode_inner() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode_list(oids) - .end_cons() - .get_contents_unlocked(); - } - -/* -* Decode the extension -*/ -void Extended_Key_Usage::decode_inner(const std::vector<byte>& in) - { - BER_Decoder(in).decode_list(oids); - } - -/* -* Return a textual representation -*/ -void Extended_Key_Usage::contents_to(Data_Store& subject, Data_Store&) const - { - for(size_t i = 0; i != oids.size(); ++i) - subject.add("X509v3.ExtendedKeyUsage", oids[i].as_string()); - } - -namespace { - -/* -* A policy specifier -*/ -class Policy_Information : public ASN1_Object - { - public: - OID oid; - - Policy_Information() {} - Policy_Information(const OID& oid) : oid(oid) {} - - void encode_into(DER_Encoder& codec) const - { - codec.start_cons(SEQUENCE) - .encode(oid) - .end_cons(); - } - - void decode_from(BER_Decoder& codec) - { - codec.start_cons(SEQUENCE) - .decode(oid) - .discard_remaining() - .end_cons(); - } - }; - -} - -/* -* Encode the extension -*/ -std::vector<byte> Certificate_Policies::encode_inner() const - { - std::vector<Policy_Information> policies; - - for(size_t i = 0; i != oids.size(); ++i) - policies.push_back(oids[i]); - - return DER_Encoder() - .start_cons(SEQUENCE) - .encode_list(policies) - .end_cons() - .get_contents_unlocked(); - } - -/* -* Decode the extension -*/ -void Certificate_Policies::decode_inner(const std::vector<byte>& in) - { - std::vector<Policy_Information> policies; - - BER_Decoder(in).decode_list(policies); - - oids.clear(); - for(size_t i = 0; i != policies.size(); ++i) - oids.push_back(policies[i].oid); - } - -/* -* Return a textual representation -*/ -void Certificate_Policies::contents_to(Data_Store& info, Data_Store&) const - { - for(size_t i = 0; i != oids.size(); ++i) - info.add("X509v3.CertificatePolicies", oids[i].as_string()); - } - -std::vector<byte> Authority_Information_Access::encode_inner() const - { - ASN1_String url(m_ocsp_responder, IA5_STRING); - - return DER_Encoder() - .start_cons(SEQUENCE) - .start_cons(SEQUENCE) - .encode(OIDS::lookup("PKIX.OCSP")) - .add_object(ASN1_Tag(6), CONTEXT_SPECIFIC, url.iso_8859()) - .end_cons() - .end_cons().get_contents_unlocked(); - } - -void Authority_Information_Access::decode_inner(const std::vector<byte>& in) - { - BER_Decoder ber = BER_Decoder(in).start_cons(SEQUENCE); - - while(ber.more_items()) - { - OID oid; - - BER_Decoder info = ber.start_cons(SEQUENCE); - - info.decode(oid); - - if(oid == OIDS::lookup("PKIX.OCSP")) - { - BER_Object name = info.get_next_object(); - - if(name.type_tag == 6 && name.class_tag == CONTEXT_SPECIFIC) - { - m_ocsp_responder = Charset::transcode(ASN1::to_string(name), - LATIN1_CHARSET, - LOCAL_CHARSET); - } - - } - } - } - -void Authority_Information_Access::contents_to(Data_Store& subject, Data_Store&) const - { - if(m_ocsp_responder != "") - subject.add("OCSP.responder", m_ocsp_responder); - } - -/* -* Checked accessor for the crl_number member -*/ -size_t CRL_Number::get_crl_number() const - { - if(!has_value) - throw Invalid_State("CRL_Number::get_crl_number: Not set"); - return crl_number; - } - -/* -* Copy a CRL_Number extension -*/ -CRL_Number* CRL_Number::copy() const - { - if(!has_value) - throw Invalid_State("CRL_Number::copy: Not set"); - return new CRL_Number(crl_number); - } - -/* -* Encode the extension -*/ -std::vector<byte> CRL_Number::encode_inner() const - { - return DER_Encoder().encode(crl_number).get_contents_unlocked(); - } - -/* -* Decode the extension -*/ -void CRL_Number::decode_inner(const std::vector<byte>& in) - { - BER_Decoder(in).decode(crl_number); - } - -/* -* Return a textual representation -*/ -void CRL_Number::contents_to(Data_Store& info, Data_Store&) const - { - info.add("X509v3.CRLNumber", crl_number); - } - -/* -* Encode the extension -*/ -std::vector<byte> CRL_ReasonCode::encode_inner() const - { - return DER_Encoder() - .encode(static_cast<size_t>(reason), ENUMERATED, UNIVERSAL) - .get_contents_unlocked(); - } - -/* -* Decode the extension -*/ -void CRL_ReasonCode::decode_inner(const std::vector<byte>& in) - { - size_t reason_code = 0; - BER_Decoder(in).decode(reason_code, ENUMERATED, UNIVERSAL); - reason = static_cast<CRL_Code>(reason_code); - } - -/* -* Return a textual representation -*/ -void CRL_ReasonCode::contents_to(Data_Store& info, Data_Store&) const - { - info.add("X509v3.CRLReasonCode", reason); - } - -std::vector<byte> CRL_Distribution_Points::encode_inner() const - { - throw std::runtime_error("CRL_Distribution_Points encoding not implemented"); - } - -void CRL_Distribution_Points::decode_inner(const std::vector<byte>& buf) - { - BER_Decoder(buf).decode_list(m_distribution_points).verify_end(); - } - -void CRL_Distribution_Points::contents_to(Data_Store& info, Data_Store&) const - { - for(size_t i = 0; i != m_distribution_points.size(); ++i) - { - auto point = m_distribution_points[i].point().contents(); - - auto uris = point.equal_range("URI"); - - for(auto uri = uris.first; uri != uris.second; ++uri) - info.add("CRL.DistributionPoint", uri->second); - } - } - -void CRL_Distribution_Points::Distribution_Point::encode_into(class DER_Encoder&) const - { - throw std::runtime_error("CRL_Distribution_Points encoding not implemented"); - } - -void CRL_Distribution_Points::Distribution_Point::decode_from(class BER_Decoder& ber) - { - ber.start_cons(SEQUENCE) - .start_cons(ASN1_Tag(0), CONTEXT_SPECIFIC) - .decode_optional_implicit(m_point, ASN1_Tag(0), - ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED), - SEQUENCE, CONSTRUCTED) - .end_cons().end_cons(); - } - -} - -} diff --git a/src/cert/x509/x509_ext.h b/src/cert/x509/x509_ext.h deleted file mode 100644 index 20be18a71..000000000 --- a/src/cert/x509/x509_ext.h +++ /dev/null @@ -1,388 +0,0 @@ -/* -* X.509 Certificate Extensions -* (C) 1999-2007,2012 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_X509_EXTENSIONS_H__ -#define BOTAN_X509_EXTENSIONS_H__ - -#include <botan/asn1_obj.h> -#include <botan/asn1_oid.h> -#include <botan/datastor.h> -#include <botan/crl_ent.h> - -namespace Botan { - -/** -* X.509 Certificate Extension -*/ -class BOTAN_DLL Certificate_Extension - { - public: - /** - * @return OID representing this extension - */ - OID oid_of() const; - - /** - * Make a copy of this extension - * @return copy of this - */ - virtual Certificate_Extension* copy() const = 0; - - /* - * Add the contents of this extension into the information - * for the subject and/or issuer, as necessary. - * @param subject the subject info - * @param issuer the issuer info - */ - virtual void contents_to(Data_Store& subject, - Data_Store& issuer) const = 0; - - /* - * @return specific OID name - */ - virtual std::string oid_name() const = 0; - - virtual ~Certificate_Extension() {} - protected: - friend class Extensions; - virtual bool should_encode() const { return true; } - virtual std::vector<byte> encode_inner() const = 0; - virtual void decode_inner(const std::vector<byte>&) = 0; - }; - -/** -* X.509 Certificate Extension List -*/ -class BOTAN_DLL Extensions : public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - void contents_to(Data_Store&, Data_Store&) const; - - void add(Certificate_Extension* extn, bool critical = false); - - Extensions& operator=(const Extensions&); - - Extensions(const Extensions&); - Extensions(bool st = true) : should_throw(st) {} - ~Extensions(); - private: - static Certificate_Extension* get_extension(const OID&); - - std::vector<std::pair<Certificate_Extension*, bool> > extensions; - bool should_throw; - }; - -namespace Cert_Extension { - -static const size_t NO_CERT_PATH_LIMIT = 0xFFFFFFF0; - -/** -* Basic Constraints Extension -*/ -class BOTAN_DLL Basic_Constraints : public Certificate_Extension - { - public: - Basic_Constraints* copy() const - { return new Basic_Constraints(is_ca, path_limit); } - - Basic_Constraints(bool ca = false, size_t limit = 0) : - is_ca(ca), path_limit(limit) {} - - bool get_is_ca() const { return is_ca; } - size_t get_path_limit() const; - private: - std::string oid_name() const { return "X509v3.BasicConstraints"; } - - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - void contents_to(Data_Store&, Data_Store&) const; - - bool is_ca; - size_t path_limit; - }; - -/** -* Key Usage Constraints Extension -*/ -class BOTAN_DLL Key_Usage : public Certificate_Extension - { - public: - Key_Usage* copy() const { return new Key_Usage(constraints); } - - Key_Usage(Key_Constraints c = NO_CONSTRAINTS) : constraints(c) {} - - Key_Constraints get_constraints() const { return constraints; } - private: - std::string oid_name() const { return "X509v3.KeyUsage"; } - - bool should_encode() const { return (constraints != NO_CONSTRAINTS); } - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - void contents_to(Data_Store&, Data_Store&) const; - - Key_Constraints constraints; - }; - -/** -* Subject Key Identifier Extension -*/ -class BOTAN_DLL Subject_Key_ID : public Certificate_Extension - { - public: - Subject_Key_ID* copy() const { return new Subject_Key_ID(key_id); } - - Subject_Key_ID() {} - Subject_Key_ID(const std::vector<byte>&); - - std::vector<byte> get_key_id() const { return key_id; } - private: - std::string oid_name() const { return "X509v3.SubjectKeyIdentifier"; } - - bool should_encode() const { return (key_id.size() > 0); } - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - void contents_to(Data_Store&, Data_Store&) const; - - std::vector<byte> key_id; - }; - -/** -* Authority Key Identifier Extension -*/ -class BOTAN_DLL Authority_Key_ID : public Certificate_Extension - { - public: - Authority_Key_ID* copy() const { return new Authority_Key_ID(key_id); } - - Authority_Key_ID() {} - Authority_Key_ID(const std::vector<byte>& k) : key_id(k) {} - - std::vector<byte> get_key_id() const { return key_id; } - private: - std::string oid_name() const { return "X509v3.AuthorityKeyIdentifier"; } - - bool should_encode() const { return (key_id.size() > 0); } - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - void contents_to(Data_Store&, Data_Store&) const; - - std::vector<byte> key_id; - }; - -/** -* Alternative Name Extension Base Class -*/ -class BOTAN_DLL Alternative_Name : public Certificate_Extension - { - public: - AlternativeName get_alt_name() const { return alt_name; } - - protected: - Alternative_Name(const AlternativeName&, const std::string& oid_name); - - Alternative_Name(const std::string&, const std::string&); - private: - std::string oid_name() const { return oid_name_str; } - - bool should_encode() const { return alt_name.has_items(); } - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - void contents_to(Data_Store&, Data_Store&) const; - - std::string oid_name_str; - AlternativeName alt_name; - }; - -/** -* Subject Alternative Name Extension -*/ -class BOTAN_DLL Subject_Alternative_Name : public Alternative_Name - { - public: - Subject_Alternative_Name* copy() const - { return new Subject_Alternative_Name(get_alt_name()); } - - Subject_Alternative_Name(const AlternativeName& = AlternativeName()); - }; - -/** -* Issuer Alternative Name Extension -*/ -class BOTAN_DLL Issuer_Alternative_Name : public Alternative_Name - { - public: - Issuer_Alternative_Name* copy() const - { return new Issuer_Alternative_Name(get_alt_name()); } - - Issuer_Alternative_Name(const AlternativeName& = AlternativeName()); - }; - -/** -* Extended Key Usage Extension -*/ -class BOTAN_DLL Extended_Key_Usage : public Certificate_Extension - { - public: - Extended_Key_Usage* copy() const { return new Extended_Key_Usage(oids); } - - Extended_Key_Usage() {} - Extended_Key_Usage(const std::vector<OID>& o) : oids(o) {} - - std::vector<OID> get_oids() const { return oids; } - private: - std::string oid_name() const { return "X509v3.ExtendedKeyUsage"; } - - bool should_encode() const { return (oids.size() > 0); } - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - void contents_to(Data_Store&, Data_Store&) const; - - std::vector<OID> oids; - }; - -/** -* Certificate Policies Extension -*/ -class BOTAN_DLL Certificate_Policies : public Certificate_Extension - { - public: - Certificate_Policies* copy() const - { return new Certificate_Policies(oids); } - - Certificate_Policies() {} - Certificate_Policies(const std::vector<OID>& o) : oids(o) {} - - std::vector<OID> get_oids() const { return oids; } - private: - std::string oid_name() const { return "X509v3.CertificatePolicies"; } - - bool should_encode() const { return (oids.size() > 0); } - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - void contents_to(Data_Store&, Data_Store&) const; - - std::vector<OID> oids; - }; - -class BOTAN_DLL Authority_Information_Access : public Certificate_Extension - { - public: - Authority_Information_Access* copy() const - { return new Authority_Information_Access(m_ocsp_responder); } - - Authority_Information_Access() {} - - Authority_Information_Access(const std::string& ocsp) : - m_ocsp_responder(ocsp) {} - - private: - std::string oid_name() const { return "PKIX.AuthorityInformationAccess"; } - - bool should_encode() const { return (m_ocsp_responder != ""); } - - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - - void contents_to(Data_Store&, Data_Store&) const; - - std::string m_ocsp_responder; - }; - -/** -* CRL Number Extension -*/ -class BOTAN_DLL CRL_Number : public Certificate_Extension - { - public: - CRL_Number* copy() const; - - CRL_Number() : has_value(false), crl_number(0) {} - CRL_Number(size_t n) : has_value(true), crl_number(n) {} - - size_t get_crl_number() const; - private: - std::string oid_name() const { return "X509v3.CRLNumber"; } - - bool should_encode() const { return has_value; } - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - void contents_to(Data_Store&, Data_Store&) const; - - bool has_value; - size_t crl_number; - }; - -/** -* CRL Entry Reason Code Extension -*/ -class BOTAN_DLL CRL_ReasonCode : public Certificate_Extension - { - public: - CRL_ReasonCode* copy() const { return new CRL_ReasonCode(reason); } - - CRL_ReasonCode(CRL_Code r = UNSPECIFIED) : reason(r) {} - - CRL_Code get_reason() const { return reason; } - private: - std::string oid_name() const { return "X509v3.ReasonCode"; } - - bool should_encode() const { return (reason != UNSPECIFIED); } - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - void contents_to(Data_Store&, Data_Store&) const; - - CRL_Code reason; - }; - -/** -* CRL Distribution Points Extension -*/ -class BOTAN_DLL CRL_Distribution_Points : public Certificate_Extension - { - public: - class BOTAN_DLL Distribution_Point : public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - const AlternativeName& point() const { return m_point; } - private: - AlternativeName m_point; - }; - - CRL_Distribution_Points* copy() const - { return new CRL_Distribution_Points(m_distribution_points); } - - CRL_Distribution_Points() {} - - CRL_Distribution_Points(const std::vector<Distribution_Point>& points) : - m_distribution_points(points) {} - - std::vector<Distribution_Point> distribution_points() const - { return m_distribution_points; } - - private: - std::string oid_name() const { return "X509v3.CRLDistributionPoints"; } - - bool should_encode() const { return !m_distribution_points.empty(); } - - std::vector<byte> encode_inner() const; - void decode_inner(const std::vector<byte>&); - void contents_to(Data_Store&, Data_Store&) const; - - std::vector<Distribution_Point> m_distribution_points; - }; - -} - -} - -#endif diff --git a/src/cert/x509/x509_obj.cpp b/src/cert/x509/x509_obj.cpp deleted file mode 100644 index 37d814ce6..000000000 --- a/src/cert/x509/x509_obj.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* -* X.509 SIGNED Object -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/x509_obj.h> -#include <botan/x509_key.h> -#include <botan/pubkey.h> -#include <botan/oids.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/parsing.h> -#include <botan/pem.h> -#include <algorithm> -#include <memory> - -namespace Botan { - -/* -* Create a generic X.509 object -*/ -X509_Object::X509_Object(DataSource& stream, const std::string& labels) - { - init(stream, labels); - } - -/* -* Create a generic X.509 object -*/ -X509_Object::X509_Object(const std::string& file, const std::string& labels) - { - DataSource_Stream stream(file, true); - init(stream, labels); - } - -/* -* Create a generic X.509 object -*/ -X509_Object::X509_Object(const std::vector<byte>& vec, const std::string& labels) - { - DataSource_Memory stream(&vec[0], vec.size()); - init(stream, labels); - } - -/* -* Read a PEM or BER X.509 object -*/ -void X509_Object::init(DataSource& in, const std::string& labels) - { - PEM_labels_allowed = split_on(labels, '/'); - if(PEM_labels_allowed.size() < 1) - throw Invalid_Argument("Bad labels argument to X509_Object"); - - PEM_label_pref = PEM_labels_allowed[0]; - std::sort(PEM_labels_allowed.begin(), PEM_labels_allowed.end()); - - try { - if(ASN1::maybe_BER(in) && !PEM_Code::matches(in)) - { - BER_Decoder dec(in); - decode_from(dec); - } - else - { - std::string got_label; - DataSource_Memory ber(PEM_Code::decode(in, got_label)); - - if(!std::binary_search(PEM_labels_allowed.begin(), - PEM_labels_allowed.end(), got_label)) - throw Decoding_Error("Invalid PEM label: " + got_label); - - BER_Decoder dec(ber); - decode_from(dec); - } - } - catch(Decoding_Error& e) - { - throw Decoding_Error(PEM_label_pref + " decoding failed: " + e.what()); - } - } - - -void X509_Object::encode_into(DER_Encoder& to) const - { - to.start_cons(SEQUENCE) - .start_cons(SEQUENCE) - .raw_bytes(tbs_bits) - .end_cons() - .encode(sig_algo) - .encode(sig, BIT_STRING) - .end_cons(); - } - -/* -* Read a BER encoded X.509 object -*/ -void X509_Object::decode_from(BER_Decoder& from) - { - from.start_cons(SEQUENCE) - .start_cons(SEQUENCE) - .raw_bytes(tbs_bits) - .end_cons() - .decode(sig_algo) - .decode(sig, BIT_STRING) - .verify_end() - .end_cons(); - } - -/* -* Return a BER encoded X.509 object -*/ -std::vector<byte> X509_Object::BER_encode() const - { - DER_Encoder der; - encode_into(der); - return der.get_contents_unlocked(); - } - -/* -* Return a PEM encoded X.509 object -*/ -std::string X509_Object::PEM_encode() const - { - return PEM_Code::encode(BER_encode(), PEM_label_pref); - } - -/* -* Return the TBS data -*/ -std::vector<byte> X509_Object::tbs_data() const - { - return ASN1::put_in_sequence(tbs_bits); - } - -/* -* Return the signature of this object -*/ -std::vector<byte> X509_Object::signature() const - { - return sig; - } - -/* -* Return the algorithm used to sign this object -*/ -AlgorithmIdentifier X509_Object::signature_algorithm() const - { - return sig_algo; - } - -/* -* Return the hash used in generating the signature -*/ -std::string X509_Object::hash_used_for_signature() const - { - std::vector<std::string> sig_info = - split_on(OIDS::lookup(sig_algo.oid), '/'); - - if(sig_info.size() != 2) - throw Internal_Error("Invalid name format found for " + - sig_algo.oid.as_string()); - - std::vector<std::string> pad_and_hash = - parse_algorithm_name(sig_info[1]); - - if(pad_and_hash.size() != 2) - throw Internal_Error("Invalid name format " + sig_info[1]); - - return pad_and_hash[1]; - } - -/* -* Check the signature on an object -*/ -bool X509_Object::check_signature(const Public_Key* pub_key) const - { - std::unique_ptr<const Public_Key> key(pub_key); - return check_signature(*key); - } - -/* -* Check the signature on an object -*/ -bool X509_Object::check_signature(const Public_Key& pub_key) const - { - try { - std::vector<std::string> sig_info = - split_on(OIDS::lookup(sig_algo.oid), '/'); - - if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) - return false; - - std::string padding = sig_info[1]; - Signature_Format format = - (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; - - PK_Verifier verifier(pub_key, padding, format); - - return verifier.verify_message(tbs_data(), signature()); - } - catch(std::exception& e) - { - return false; - } - } - -/* -* Apply the X.509 SIGNED macro -*/ -std::vector<byte> X509_Object::make_signed(PK_Signer* signer, - RandomNumberGenerator& rng, - const AlgorithmIdentifier& algo, - const secure_vector<byte>& tbs_bits) - { - return DER_Encoder() - .start_cons(SEQUENCE) - .raw_bytes(tbs_bits) - .encode(algo) - .encode(signer->sign_message(tbs_bits, rng), BIT_STRING) - .end_cons() - .get_contents_unlocked(); - } - -/* -* Try to decode the actual information -*/ -void X509_Object::do_decode() - { - try { - force_decode(); - } - catch(Decoding_Error& e) - { - throw Decoding_Error(PEM_label_pref + " decoding failed (" + - e.what() + ")"); - } - catch(Invalid_Argument& e) - { - throw Decoding_Error(PEM_label_pref + " decoding failed (" + - e.what() + ")"); - } - } - -} diff --git a/src/cert/x509/x509_obj.h b/src/cert/x509/x509_obj.h deleted file mode 100644 index 5905e1b37..000000000 --- a/src/cert/x509/x509_obj.h +++ /dev/null @@ -1,109 +0,0 @@ -/* -* X.509 SIGNED Object -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_X509_OBJECT_H__ -#define BOTAN_X509_OBJECT_H__ - -#include <botan/asn1_obj.h> -#include <botan/pipe.h> -#include <botan/x509_key.h> -#include <botan/rng.h> -#include <vector> - -namespace Botan { - -/** -* This class represents abstract X.509 signed objects as -* in the X.500 SIGNED macro -*/ -class BOTAN_DLL X509_Object : public ASN1_Object - { - public: - /** - * The underlying data that is to be or was signed - * @return data that is or was signed - */ - std::vector<byte> tbs_data() const; - - /** - * @return signature on tbs_data() - */ - std::vector<byte> signature() const; - - /** - * @return signature algorithm that was used to generate signature - */ - AlgorithmIdentifier signature_algorithm() const; - - /** - * @return hash algorithm that was used to generate signature - */ - std::string hash_used_for_signature() const; - - /** - * Create a signed X509 object. - * @param signer the signer used to sign the object - * @param rng the random number generator to use - * @param alg_id the algorithm identifier of the signature scheme - * @param tbs the tbs bits to be signed - * @return signed X509 object - */ - static std::vector<byte> make_signed(class PK_Signer* signer, - RandomNumberGenerator& rng, - const AlgorithmIdentifier& alg_id, - const secure_vector<byte>& tbs); - - /** - * Check the signature on this data - * @param key the public key purportedly used to sign this data - * @return true if the signature is valid, otherwise false - */ - bool check_signature(const Public_Key& key) const; - - /** - * Check the signature on this data - * @param key the public key purportedly used to sign this data - * the pointer will be deleted after use - * @return true if the signature is valid, otherwise false - */ - bool check_signature(const Public_Key* key) const; - - void encode_into(class DER_Encoder& to) const override; - - void decode_from(class BER_Decoder& from) override; - - /** - * @return BER encoding of this - */ - std::vector<byte> BER_encode() const; - - /** - * @return PEM encoding of this - */ - std::string PEM_encode() const; - - virtual ~X509_Object() {} - protected: - X509_Object(DataSource& src, const std::string& pem_labels); - X509_Object(const std::string& file, const std::string& pem_labels); - X509_Object(const std::vector<byte>& vec, const std::string& labels); - - void do_decode(); - X509_Object() {} - AlgorithmIdentifier sig_algo; - std::vector<byte> tbs_bits, sig; - private: - virtual void force_decode() = 0; - void init(DataSource&, const std::string&); - - std::vector<std::string> PEM_labels_allowed; - std::string PEM_label_pref; - }; - -} - -#endif diff --git a/src/cert/x509/x509cert.cpp b/src/cert/x509/x509cert.cpp deleted file mode 100644 index 2362cd0cf..000000000 --- a/src/cert/x509/x509cert.cpp +++ /dev/null @@ -1,587 +0,0 @@ -/* -* X.509 Certificates -* (C) 1999-2010 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/x509cert.h> -#include <botan/x509_ext.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/internal/stl_util.h> -#include <botan/parsing.h> -#include <botan/bigint.h> -#include <botan/lookup.h> -#include <botan/oids.h> -#include <botan/pem.h> -#include <botan/hex.h> -#include <algorithm> -#include <iterator> -#include <sstream> -#include <memory> - -namespace Botan { - -namespace { - -/* -* Lookup each OID in the vector -*/ -std::vector<std::string> lookup_oids(const std::vector<std::string>& in) - { - std::vector<std::string> out; - - for(auto i = in.begin(); i != in.end(); ++i) - out.push_back(OIDS::lookup(OID(*i))); - return out; - } - -} - -/* -* X509_Certificate Constructor -*/ -X509_Certificate::X509_Certificate(DataSource& in) : - X509_Object(in, "CERTIFICATE/X509 CERTIFICATE") - { - self_signed = false; - do_decode(); - } - -/* -* X509_Certificate Constructor -*/ -X509_Certificate::X509_Certificate(const std::string& in) : - X509_Object(in, "CERTIFICATE/X509 CERTIFICATE") - { - self_signed = false; - do_decode(); - } - -/* -* X509_Certificate Constructor -*/ -X509_Certificate::X509_Certificate(const std::vector<byte>& in) : - X509_Object(in, "CERTIFICATE/X509 CERTIFICATE") - { - self_signed = false; - do_decode(); - } - -/* -* Decode the TBSCertificate data -*/ -void X509_Certificate::force_decode() - { - size_t version; - BigInt serial_bn; - AlgorithmIdentifier sig_algo_inner; - X509_DN dn_issuer, dn_subject; - X509_Time start, end; - - BER_Decoder tbs_cert(tbs_bits); - - tbs_cert.decode_optional(version, ASN1_Tag(0), - ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) - .decode(serial_bn) - .decode(sig_algo_inner) - .decode(dn_issuer) - .start_cons(SEQUENCE) - .decode(start) - .decode(end) - .verify_end() - .end_cons() - .decode(dn_subject); - - if(version > 2) - throw Decoding_Error("Unknown X.509 cert version " + std::to_string(version)); - if(sig_algo != sig_algo_inner) - throw Decoding_Error("Algorithm identifier mismatch"); - - self_signed = (dn_subject == dn_issuer); - - subject.add(dn_subject.contents()); - issuer.add(dn_issuer.contents()); - - subject.add("X509.Certificate.dn_bits", ASN1::put_in_sequence(dn_subject.get_bits())); - issuer.add("X509.Certificate.dn_bits", ASN1::put_in_sequence(dn_issuer.get_bits())); - - BER_Object public_key = tbs_cert.get_next_object(); - if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED) - throw BER_Bad_Tag("X509_Certificate: Unexpected tag for public key", - public_key.type_tag, public_key.class_tag); - - std::vector<byte> v2_issuer_key_id, v2_subject_key_id; - - tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1); - tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2); - - BER_Object v3_exts_data = tbs_cert.get_next_object(); - if(v3_exts_data.type_tag == 3 && - v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) - { - Extensions extensions; - - BER_Decoder(v3_exts_data.value).decode(extensions).verify_end(); - - extensions.contents_to(subject, issuer); - } - else if(v3_exts_data.type_tag != NO_OBJECT) - throw BER_Bad_Tag("Unknown tag in X.509 cert", - v3_exts_data.type_tag, v3_exts_data.class_tag); - - if(tbs_cert.more_items()) - throw Decoding_Error("TBSCertificate has more items that expected"); - - subject.add("X509.Certificate.version", version); - subject.add("X509.Certificate.serial", BigInt::encode(serial_bn)); - subject.add("X509.Certificate.start", start.readable_string()); - subject.add("X509.Certificate.end", end.readable_string()); - - issuer.add("X509.Certificate.v2.key_id", v2_issuer_key_id); - subject.add("X509.Certificate.v2.key_id", v2_subject_key_id); - - subject.add("X509.Certificate.public_key", - hex_encode(public_key.value)); - - if(self_signed && version == 0) - { - subject.add("X509v3.BasicConstraints.is_ca", 1); - subject.add("X509v3.BasicConstraints.path_constraint", Cert_Extension::NO_CERT_PATH_LIMIT); - } - - if(is_CA_cert() && - !subject.has_value("X509v3.BasicConstraints.path_constraint")) - { - const size_t limit = (x509_version() < 3) ? - Cert_Extension::NO_CERT_PATH_LIMIT : 0; - - subject.add("X509v3.BasicConstraints.path_constraint", limit); - } - } - -/* -* Return the X.509 version in use -*/ -u32bit X509_Certificate::x509_version() const - { - return (subject.get1_u32bit("X509.Certificate.version") + 1); - } - -/* -* Return the time this cert becomes valid -*/ -std::string X509_Certificate::start_time() const - { - return subject.get1("X509.Certificate.start"); - } - -/* -* Return the time this cert becomes invalid -*/ -std::string X509_Certificate::end_time() const - { - return subject.get1("X509.Certificate.end"); - } - -/* -* Return information about the subject -*/ -std::vector<std::string> -X509_Certificate::subject_info(const std::string& what) const - { - return subject.get(X509_DN::deref_info_field(what)); - } - -/* -* Return information about the issuer -*/ -std::vector<std::string> -X509_Certificate::issuer_info(const std::string& what) const - { - return issuer.get(X509_DN::deref_info_field(what)); - } - -/* -* Return the public key in this certificate -*/ -Public_Key* X509_Certificate::subject_public_key() const - { - return X509::load_key( - ASN1::put_in_sequence(this->subject_public_key_bits())); - } - -std::vector<byte> X509_Certificate::subject_public_key_bits() const - { - return hex_decode(subject.get1("X509.Certificate.public_key")); - } - -/* -* Check if the certificate is for a CA -*/ -bool X509_Certificate::is_CA_cert() const - { - if(!subject.get1_u32bit("X509v3.BasicConstraints.is_ca")) - return false; - - return allowed_usage(KEY_CERT_SIGN); - } - -bool X509_Certificate::allowed_usage(Key_Constraints usage) const - { - if(constraints() == NO_CONSTRAINTS) - return true; - return (constraints() & usage); - } - -bool X509_Certificate::allowed_usage(const std::string& usage) const - { - for(auto constraint : ex_constraints()) - if(constraint == usage) - return true; - - return false; - } - -/* -* Return the path length constraint -*/ -u32bit X509_Certificate::path_limit() const - { - return subject.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0); - } - -/* -* Return the key usage constraints -*/ -Key_Constraints X509_Certificate::constraints() const - { - return Key_Constraints(subject.get1_u32bit("X509v3.KeyUsage", - NO_CONSTRAINTS)); - } - -/* -* Return the list of extended key usage OIDs -*/ -std::vector<std::string> X509_Certificate::ex_constraints() const - { - return lookup_oids(subject.get("X509v3.ExtendedKeyUsage")); - } - -/* -* Return the list of certificate policies -*/ -std::vector<std::string> X509_Certificate::policies() const - { - return lookup_oids(subject.get("X509v3.CertificatePolicies")); - } - -std::string X509_Certificate::ocsp_responder() const - { - return subject.get1("OCSP.responder", ""); - } - -std::string X509_Certificate::crl_distribution_point() const - { - return subject.get1("CRL.DistributionPoint", ""); - } - -/* -* Return the authority key id -*/ -std::vector<byte> X509_Certificate::authority_key_id() const - { - return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier"); - } - -/* -* Return the subject key id -*/ -std::vector<byte> X509_Certificate::subject_key_id() const - { - return subject.get1_memvec("X509v3.SubjectKeyIdentifier"); - } - -/* -* Return the certificate serial number -*/ -std::vector<byte> X509_Certificate::serial_number() const - { - return subject.get1_memvec("X509.Certificate.serial"); - } - -/* -* Return the distinguished name of the issuer -*/ -X509_DN X509_Certificate::issuer_dn() const - { - return create_dn(issuer); - } - -std::vector<byte> X509_Certificate::raw_issuer_dn() const - { - return issuer.get1_memvec("X509.Certificate.dn_bits"); - } - -/* -* Return the distinguished name of the subject -*/ -X509_DN X509_Certificate::subject_dn() const - { - return create_dn(subject); - } - -std::vector<byte> X509_Certificate::raw_subject_dn() const - { - return subject.get1_memvec("X509.Certificate.dn_bits"); - } - -namespace { - -bool cert_subject_dns_match(const std::string& name, - const std::vector<std::string>& cert_names) - { - for(size_t i = 0; i != cert_names.size(); ++i) - { - const std::string cn = cert_names[i]; - - if(cn == name) - return true; - - /* - * Possible wildcard match. We only support the most basic form of - * cert wildcarding ala RFC 2595 - */ - if(cn.size() > 2 && cn[0] == '*' && cn[1] == '.' && name.size() > cn.size()) - { - const std::string base = cn.substr(1, std::string::npos); - - if(name.compare(name.size() - base.size(), base.size(), base) == 0) - return true; - } - } - - return false; - } - -} - -std::string X509_Certificate::fingerprint(const std::string& hash_name) const - { - std::unique_ptr<HashFunction> hash(get_hash(hash_name)); - hash->update(this->BER_encode()); - const auto hex_print = hex_encode(hash->final()); - - std::string formatted_print; - - for(size_t i = 0; i != hex_print.size(); i += 2) - { - formatted_print.push_back(hex_print[i]); - formatted_print.push_back(hex_print[i+1]); - - if(i != hex_print.size() - 2) - formatted_print.push_back(':'); - } - - return formatted_print; - } - -bool X509_Certificate::matches_dns_name(const std::string& name) const - { - if(name == "") - return false; - - if(cert_subject_dns_match(name, subject_info("DNS"))) - return true; - - if(cert_subject_dns_match(name, subject_info("Name"))) - return true; - - return false; - } - -/* -* Compare two certificates for equality -*/ -bool X509_Certificate::operator==(const X509_Certificate& other) const - { - return (sig == other.sig && - sig_algo == other.sig_algo && - self_signed == other.self_signed && - issuer == other.issuer && - subject == other.subject); - } - -bool X509_Certificate::operator<(const X509_Certificate& other) const - { - /* If signature values are not equal, sort by lexicographic ordering of that */ - if(sig != other.sig) - { - if(sig < other.sig) - return true; - return false; - } - - // Then compare the signed contents - return tbs_bits < other.tbs_bits; - } - -/* -* X.509 Certificate Comparison -*/ -bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2) - { - return !(cert1 == cert2); - } - -std::string X509_Certificate::to_string() const - { - const char* dn_fields[] = { "Name", - "Email", - "Organization", - "Organizational Unit", - "Locality", - "State", - "Country", - "IP", - "DNS", - "URI", - "PKIX.XMPPAddr", - nullptr }; - - std::ostringstream out; - - for(size_t i = 0; dn_fields[i]; ++i) - { - const std::vector<std::string> vals = this->subject_info(dn_fields[i]); - - if(vals.empty()) - continue; - - out << "Subject " << dn_fields[i] << ":"; - for(size_t j = 0; j != vals.size(); ++j) - out << " " << vals[j]; - out << "\n"; - } - - for(size_t i = 0; dn_fields[i]; ++i) - { - const std::vector<std::string> vals = this->issuer_info(dn_fields[i]); - - if(vals.empty()) - continue; - - out << "Issuer " << dn_fields[i] << ":"; - for(size_t j = 0; j != vals.size(); ++j) - out << " " << vals[j]; - out << "\n"; - } - - out << "Version: " << this->x509_version() << "\n"; - - out << "Not valid before: " << this->start_time() << "\n"; - out << "Not valid after: " << this->end_time() << "\n"; - - out << "Constraints:\n"; - Key_Constraints constraints = this->constraints(); - if(constraints == NO_CONSTRAINTS) - out << " None\n"; - else - { - if(constraints & DIGITAL_SIGNATURE) - out << " Digital Signature\n"; - if(constraints & NON_REPUDIATION) - out << " Non-Repuidation\n"; - if(constraints & KEY_ENCIPHERMENT) - out << " Key Encipherment\n"; - if(constraints & DATA_ENCIPHERMENT) - out << " Data Encipherment\n"; - if(constraints & KEY_AGREEMENT) - out << " Key Agreement\n"; - if(constraints & KEY_CERT_SIGN) - out << " Cert Sign\n"; - if(constraints & CRL_SIGN) - out << " CRL Sign\n"; - } - - std::vector<std::string> policies = this->policies(); - if(!policies.empty()) - { - out << "Policies: " << "\n"; - for(size_t i = 0; i != policies.size(); i++) - out << " " << policies[i] << "\n"; - } - - std::vector<std::string> ex_constraints = this->ex_constraints(); - if(!ex_constraints.empty()) - { - out << "Extended Constraints:\n"; - for(size_t i = 0; i != ex_constraints.size(); i++) - out << " " << ex_constraints[i] << "\n"; - } - - if(ocsp_responder() != "") - out << "OCSP responder " << ocsp_responder() << "\n"; - if(crl_distribution_point() != "") - out << "CRL " << crl_distribution_point() << "\n"; - - out << "Signature algorithm: " << - OIDS::lookup(this->signature_algorithm().oid) << "\n"; - - out << "Serial number: " << hex_encode(this->serial_number()) << "\n"; - - if(this->authority_key_id().size()) - out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n"; - - if(this->subject_key_id().size()) - out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n"; - - std::unique_ptr<X509_PublicKey> pubkey(this->subject_public_key()); - out << "Public Key:\n" << X509::PEM_encode(*pubkey); - - return out.str(); - } - -/* -* Create and populate a X509_DN -*/ -X509_DN create_dn(const Data_Store& info) - { - auto names = info.search_for( - [](const std::string& key, const std::string&) - { - return (key.find("X520.") != std::string::npos); - }); - - X509_DN dn; - - for(auto i = names.begin(); i != names.end(); ++i) - dn.add_attribute(i->first, i->second); - - return dn; - } - -/* -* Create and populate an AlternativeName -*/ -AlternativeName create_alt_name(const Data_Store& info) - { - auto names = info.search_for( - [](const std::string& key, const std::string&) - { - return (key == "RFC822" || - key == "DNS" || - key == "URI" || - key == "IP"); - }); - - AlternativeName alt_name; - - for(auto i = names.begin(); i != names.end(); ++i) - alt_name.add_attribute(i->first, i->second); - - return alt_name; - } - -} diff --git a/src/cert/x509/x509cert.h b/src/cert/x509/x509cert.h deleted file mode 100644 index bd341b6e0..000000000 --- a/src/cert/x509/x509cert.h +++ /dev/null @@ -1,249 +0,0 @@ -/* -* X.509 Certificates -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_X509_CERTS_H__ -#define BOTAN_X509_CERTS_H__ - -#include <botan/x509_obj.h> -#include <botan/x509_dn.h> -#include <botan/x509_key.h> -#include <botan/asn1_alt_name.h> -#include <botan/datastor.h> -#include <botan/key_constraint.h> -#include <map> - -namespace Botan { - -/** -* This class represents X.509 Certificate -*/ -class BOTAN_DLL X509_Certificate : public X509_Object - { - public: - /** - * Get the public key associated with this certificate. - * @return subject public key of this certificate - */ - Public_Key* subject_public_key() const; - - /** - * Get the public key associated with this certificate. - * @return subject public key of this certificate - */ - std::vector<byte> subject_public_key_bits() const; - - /** - * Get the issuer certificate DN. - * @return issuer DN of this certificate - */ - X509_DN issuer_dn() const; - - /** - * Get the subject certificate DN. - * @return subject DN of this certificate - */ - X509_DN subject_dn() const; - - /** - * Get a value for a specific subject_info parameter name. - * @param name the name of the paramter to look up. Possible names are - * "X509.Certificate.version", "X509.Certificate.serial", - * "X509.Certificate.start", "X509.Certificate.end", - * "X509.Certificate.v2.key_id", "X509.Certificate.public_key", - * "X509v3.BasicConstraints.path_constraint", - * "X509v3.BasicConstraints.is_ca", "X509v3.ExtendedKeyUsage", - * "X509v3.CertificatePolicies", "X509v3.SubjectKeyIdentifier" or - * "X509.Certificate.serial". - * @return value(s) of the specified parameter - */ - std::vector<std::string> subject_info(const std::string& name) const; - - /** - * Get a value for a specific subject_info parameter name. - * @param name the name of the paramter to look up. Possible names are - * "X509.Certificate.v2.key_id" or "X509v3.AuthorityKeyIdentifier". - * @return value(s) of the specified parameter - */ - std::vector<std::string> issuer_info(const std::string& name) const; - - /** - * Raw subject DN - */ - std::vector<byte> raw_issuer_dn() const; - - /** - * Raw issuer DN - */ - std::vector<byte> raw_subject_dn() const; - - /** - * Get the notBefore of the certificate. - * @return notBefore of the certificate - */ - std::string start_time() const; - - /** - * Get the notAfter of the certificate. - * @return notAfter of the certificate - */ - std::string end_time() const; - - /** - * Get the X509 version of this certificate object. - * @return X509 version - */ - u32bit x509_version() const; - - /** - * Get the serial number of this certificate. - * @return certificates serial number - */ - std::vector<byte> serial_number() const; - - /** - * Get the DER encoded AuthorityKeyIdentifier of this certificate. - * @return DER encoded AuthorityKeyIdentifier - */ - std::vector<byte> authority_key_id() const; - - /** - * Get the DER encoded SubjectKeyIdentifier of this certificate. - * @return DER encoded SubjectKeyIdentifier - */ - std::vector<byte> subject_key_id() const; - - /** - * Check whether this certificate is self signed. - * @return true if this certificate is self signed - */ - bool is_self_signed() const { return self_signed; } - - /** - * Check whether this certificate is a CA certificate. - * @return true if this certificate is a CA certificate - */ - bool is_CA_cert() const; - - bool allowed_usage(Key_Constraints usage) const; - - /** - * Returns true if and only if name (referring to an extended key - * constraint, eg "PKIX.ServerAuth") is included in the extended - * key extension. - */ - bool allowed_usage(const std::string& usage) const; - - /** - * Get the path limit as defined in the BasicConstraints extension of - * this certificate. - * @return path limit - */ - u32bit path_limit() const; - - /** - * Get the key constraints as defined in the KeyUsage extension of this - * certificate. - * @return key constraints - */ - Key_Constraints constraints() const; - - /** - * Get the key constraints as defined in the ExtendedKeyUsage - * extension of this - * certificate. - * @return key constraints - */ - std::vector<std::string> ex_constraints() const; - - /** - * Get the policies as defined in the CertificatePolicies extension - * of this certificate. - * @return certificate policies - */ - std::vector<std::string> policies() const; - - /** - * Return the listed address of an OCSP responder, or empty if not set - */ - std::string ocsp_responder() const; - - /** - * Return the CRL distribution point, or empty if not set - */ - std::string crl_distribution_point() const; - - /** - * @return a string describing the certificate - */ - std::string to_string() const; - - /** - * Return a fingerprint of the certificate - */ - std::string fingerprint(const std::string& = "SHA-1") const; - - /** - * Check if a certain DNS name matches up with the information in - * the cert - */ - bool matches_dns_name(const std::string& name) const; - - /** - * Check to certificates for equality. - * @return true both certificates are (binary) equal - */ - bool operator==(const X509_Certificate& other) const; - - /** - * Impose an arbitrary (but consistent) ordering - * @return true if this is less than other by some unspecified criteria - */ - bool operator<(const X509_Certificate& other) const; - - /** - * Create a certificate from a data source providing the DER or - * PEM encoded certificate. - * @param source the data source - */ - X509_Certificate(DataSource& source); - - /** - * Create a certificate from a file containing the DER or PEM - * encoded certificate. - * @param filename the name of the certificate file - */ - X509_Certificate(const std::string& filename); - - X509_Certificate(const std::vector<byte>& in); - - private: - void force_decode(); - friend class X509_CA; - friend class BER_Decoder; - - X509_Certificate() {} - - Data_Store subject, issuer; - bool self_signed; - }; - -/** -* Check two certificates for inequality -* @return true if the arguments represent different certificates, -* false if they are binary identical -*/ -BOTAN_DLL bool operator!=(const X509_Certificate&, const X509_Certificate&); - -/* -* Data Store Extraction Operations -*/ -BOTAN_DLL X509_DN create_dn(const Data_Store&); -BOTAN_DLL AlternativeName create_alt_name(const Data_Store&); - -} - -#endif diff --git a/src/cert/x509/x509opt.cpp b/src/cert/x509/x509opt.cpp deleted file mode 100644 index 8a27fdbde..000000000 --- a/src/cert/x509/x509opt.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* -* X.509 Certificate Options -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/x509self.h> -#include <botan/oids.h> -#include <botan/parsing.h> -#include <chrono> - -namespace Botan { - -/* -* Set when the certificate should become valid -*/ -void X509_Cert_Options::not_before(const std::string& time_string) - { - start = X509_Time(time_string); - } - -/* -* Set when the certificate should expire -*/ -void X509_Cert_Options::not_after(const std::string& time_string) - { - end = X509_Time(time_string); - } - -/* -* Set key constraint information -*/ -void X509_Cert_Options::add_constraints(Key_Constraints usage) - { - constraints = usage; - } - -/* -* Set key constraint information -*/ -void X509_Cert_Options::add_ex_constraint(const OID& oid) - { - ex_constraints.push_back(oid); - } - -/* -* Set key constraint information -*/ -void X509_Cert_Options::add_ex_constraint(const std::string& oid_str) - { - ex_constraints.push_back(OIDS::lookup(oid_str)); - } - -/* -* Mark this certificate for CA usage -*/ -void X509_Cert_Options::CA_key(size_t limit) - { - is_CA = true; - path_limit = limit; - } - -/* -* Do basic sanity checks -*/ -void X509_Cert_Options::sanity_check() const - { - if(common_name == "" || country == "") - throw Encoding_Error("X.509 certificate: name and country MUST be set"); - if(country.size() != 2) - throw Encoding_Error("Invalid ISO country code: " + country); - if(start >= end) - throw Encoding_Error("X509_Cert_Options: invalid time constraints"); - } - -/* -* Initialize the certificate options -*/ -X509_Cert_Options::X509_Cert_Options(const std::string& initial_opts, - u32bit expiration_time) - { - is_CA = false; - path_limit = 0; - constraints = NO_CONSTRAINTS; - - auto now = std::chrono::system_clock::now(); - - start = X509_Time(now); - end = X509_Time(now + std::chrono::seconds(expiration_time)); - - if(initial_opts == "") - return; - - std::vector<std::string> parsed = split_on(initial_opts, '/'); - - if(parsed.size() > 4) - throw Invalid_Argument("X.509 cert options: Too many names: " - + initial_opts); - - if(parsed.size() >= 1) common_name = parsed[0]; - if(parsed.size() >= 2) country = parsed[1]; - if(parsed.size() >= 3) organization = parsed[2]; - if(parsed.size() == 4) org_unit = parsed[3]; - } - -} diff --git a/src/cert/x509/x509path.cpp b/src/cert/x509/x509path.cpp deleted file mode 100644 index 28b4a6d99..000000000 --- a/src/cert/x509/x509path.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* -* X.509 Certificate Path Validation -* (C) 2010,2011,2012 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/x509path.h> -#include <botan/ocsp.h> -#include <botan/http_util.h> -#include <botan/parsing.h> -#include <botan/pubkey.h> -#include <botan/oids.h> -#include <algorithm> -#include <chrono> -#include <memory> -#include <iostream> - -namespace Botan { - -namespace { - -const X509_Certificate* find_issuing_cert(const X509_Certificate& cert, - const std::vector<Certificate_Store*>& certstores) - { - const X509_DN issuer_dn = cert.issuer_dn(); - const std::vector<byte> auth_key_id = cert.authority_key_id(); - - for(size_t i = 0; i != certstores.size(); ++i) - { - if(const X509_Certificate* cert = certstores[i]->find_cert(issuer_dn, auth_key_id)) - return cert; - } - - return nullptr; - } - -const X509_CRL* find_crls_from(const X509_Certificate& cert, - const std::vector<Certificate_Store*>& certstores) - { - const X509_DN issuer_dn = cert.subject_dn(); - const std::vector<byte> auth_key_id = cert.subject_key_id(); - - for(size_t i = 0; i != certstores.size(); ++i) - { - if(const X509_CRL* crl = certstores[i]->find_crl(cert)) - return crl; - } - -#if 0 - const std::string crl_url = cert.crl_distribution_point(); - if(crl_url != "") - { - std::cout << "Downloading CRL " << crl_url << "\n"; - auto http = HTTP::GET_sync(crl_url); - - std::cout << http.status_message() << "\n"; - - http.throw_unless_ok(); - // check the mime type - - std::unique_ptr<X509_CRL> crl(new X509_CRL(http.body())); - - return crl.release(); - } -#endif - - return nullptr; - } - -Certificate_Status_Code check_chain(const std::vector<X509_Certificate>& cert_path, - const Path_Validation_Restrictions& restrictions, - const std::vector<Certificate_Store*>& certstores) - { - const std::set<std::string>& trusted_hashes = restrictions.trusted_hashes(); - - const bool self_signed_ee_cert = (cert_path.size() == 1); - - X509_Time current_time(std::chrono::system_clock::now()); - - std::vector<std::future<OCSP::Response>> ocsp_responses; - - for(size_t i = 0; i != cert_path.size(); ++i) - { - const bool at_self_signed_root = (i == cert_path.size() - 1); - - const X509_Certificate& subject = cert_path[i]; - - const X509_Certificate& issuer = cert_path[at_self_signed_root ? (i) : (i + 1)]; - - const Certificate_Store* trusted = certstores[0]; // fixme - - if(i == 0 || restrictions.ocsp_all_intermediates()) - ocsp_responses.push_back( - std::async(std::launch::async, - OCSP::online_check, issuer, subject, trusted)); - - // Check all certs for valid time range - if(current_time < X509_Time(subject.start_time())) - return Certificate_Status_Code::CERT_NOT_YET_VALID; - - if(current_time > X509_Time(subject.end_time())) - return Certificate_Status_Code::CERT_HAS_EXPIRED; - - // Check issuer constraints - - // Don't require CA bit set on self-signed end entity cert - if(!issuer.is_CA_cert() && !self_signed_ee_cert) - return Certificate_Status_Code::CA_CERT_NOT_FOR_CERT_ISSUER; - - if(issuer.path_limit() < i) - return Certificate_Status_Code::CERT_CHAIN_TOO_LONG; - - std::unique_ptr<Public_Key> issuer_key(issuer.subject_public_key()); - - if(subject.check_signature(*issuer_key) == false) - return Certificate_Status_Code::SIGNATURE_ERROR; - - if(issuer_key->estimated_strength() < restrictions.minimum_key_strength()) - return Certificate_Status_Code::SIGNATURE_METHOD_TOO_WEAK; - - if(!trusted_hashes.empty() && !at_self_signed_root) - if(!trusted_hashes.count(subject.hash_used_for_signature())) - return Certificate_Status_Code::UNTRUSTED_HASH; - } - - for(size_t i = 0; i != cert_path.size() - 1; ++i) - { - const X509_Certificate& subject = cert_path[i]; - const X509_Certificate& ca = cert_path[i+1]; - - if(i < ocsp_responses.size()) - { - try - { - OCSP::Response ocsp = ocsp_responses[i].get(); - - auto status = ocsp.status_for(ca, subject); - - if(status == CERT_IS_REVOKED) - return status; - - if(status == OCSP_RESPONSE_GOOD) - { - if(i == 0 && !restrictions.ocsp_all_intermediates()) - return status; // return immediately to just OCSP end cert - else - continue; - } - } - catch(std::exception& e) - { - } - } - - const X509_CRL* crl_p = find_crls_from(ca, certstores); - - if(!crl_p) - { - if(restrictions.require_revocation_information()) - return Certificate_Status_Code::NO_REVOCATION_DATA; - continue; - } - - const X509_CRL& crl = *crl_p; - - if(!ca.allowed_usage(CRL_SIGN)) - return Certificate_Status_Code::CA_CERT_NOT_FOR_CRL_ISSUER; - - if(current_time < X509_Time(crl.this_update())) - return Certificate_Status_Code::CRL_NOT_YET_VALID; - - if(current_time > X509_Time(crl.next_update())) - return Certificate_Status_Code::CRL_HAS_EXPIRED; - - if(crl.check_signature(ca.subject_public_key()) == false) - return Certificate_Status_Code::SIGNATURE_ERROR; - - if(crl.is_revoked(subject)) - return Certificate_Status_Code::CERT_IS_REVOKED; - } - - if(self_signed_ee_cert) - return Certificate_Status_Code::CANNOT_ESTABLISH_TRUST; - - return Certificate_Status_Code::VERIFIED; - } - -} - -Path_Validation_Result x509_path_validate( - const std::vector<X509_Certificate>& end_certs, - const Path_Validation_Restrictions& restrictions, - const std::vector<Certificate_Store*>& certstores) - { - if(end_certs.empty()) - throw std::invalid_argument("x509_path_validate called with no subjects"); - - std::vector<X509_Certificate> cert_path = end_certs; - - // iterate until we reach a root or cannot find the issuer - while(!cert_path.back().is_self_signed()) - { - const X509_Certificate* cert = find_issuing_cert(cert_path.back(), certstores); - if(!cert) - return Path_Validation_Result(Certificate_Status_Code::CERT_ISSUER_NOT_FOUND); - cert_path.push_back(*cert); - } - - Certificate_Status_Code res = check_chain(cert_path, restrictions, certstores); - - return Path_Validation_Result(res, std::move(cert_path)); - } - -Path_Validation_Result x509_path_validate( - const X509_Certificate& end_cert, - const Path_Validation_Restrictions& restrictions, - const std::vector<Certificate_Store*>& certstores) - { - std::vector<X509_Certificate> certs; - certs.push_back(end_cert); - return x509_path_validate(certs, restrictions, certstores); - } - -Path_Validation_Result x509_path_validate( - const std::vector<X509_Certificate>& end_certs, - const Path_Validation_Restrictions& restrictions, - const Certificate_Store& store) - { - std::vector<Certificate_Store*> certstores; - certstores.push_back(const_cast<Certificate_Store*>(&store)); - - return x509_path_validate(end_certs, restrictions, certstores); - } - -Path_Validation_Result x509_path_validate( - const X509_Certificate& end_cert, - const Path_Validation_Restrictions& restrictions, - const Certificate_Store& store) - { - std::vector<X509_Certificate> certs; - certs.push_back(end_cert); - - std::vector<Certificate_Store*> certstores; - certstores.push_back(const_cast<Certificate_Store*>(&store)); - - return x509_path_validate(certs, restrictions, certstores); - } - -Path_Validation_Restrictions::Path_Validation_Restrictions(bool require_rev, - size_t key_strength, - bool ocsp_all) : - m_require_revocation_information(require_rev), - m_ocsp_all_intermediates(ocsp_all), - m_minimum_key_strength(key_strength) - { - if(key_strength <= 80) - m_trusted_hashes.insert("SHA-160"); - - m_trusted_hashes.insert("SHA-224"); - m_trusted_hashes.insert("SHA-256"); - m_trusted_hashes.insert("SHA-384"); - m_trusted_hashes.insert("SHA-512"); - } - -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; - } - -bool Path_Validation_Result::successful_validation() const - { - if(status() == VERIFIED || status() == OCSP_RESPONSE_GOOD) - return true; - return false; - } - -std::string Path_Validation_Result::result_string() const - { - return status_string(m_status); - } - -std::string Path_Validation_Result::status_string(Certificate_Status_Code code) - { - switch(code) - { - case VERIFIED: - return "verified"; - case UNKNOWN_X509_ERROR: - return "unknown error"; - case CANNOT_ESTABLISH_TRUST: - return "cannot establish trust"; - case CERT_CHAIN_TOO_LONG: - return "certificate chain too long"; - case SIGNATURE_ERROR: - return "signature error"; - case SIGNATURE_METHOD_TOO_WEAK: - return "signature method too weak"; - - case POLICY_ERROR: - return "policy error"; - case INVALID_USAGE: - return "invalid usage"; - case UNTRUSTED_HASH: - return "untrusted hash function"; - - case CERT_MULTIPLE_ISSUERS_FOUND: - return "Multiple certificate issuers found"; - case CERT_FORMAT_ERROR: - return "Certificate format error"; - case CERT_ISSUER_NOT_FOUND: - return "Certificate issuer not found"; - case CERT_NOT_YET_VALID: - return "Certificate is not yet valid"; - case CERT_HAS_EXPIRED: - return "Certificate has expired"; - case CERT_IS_REVOKED: - return "Certificate is revoked"; - case NO_REVOCATION_DATA: - return "No revocation data available"; - case CRL_FORMAT_ERROR: - return "CRL format error"; - case CRL_NOT_YET_VALID: - return "CRL is not yet valid"; - case CRL_HAS_EXPIRED: - return "CRL has expired"; - case CA_CERT_CANNOT_SIGN: - return "CA certificate cannot sign"; - case CA_CERT_NOT_FOR_CERT_ISSUER: - return "CA certificate not allowed to issue certs"; - case CA_CERT_NOT_FOR_CRL_ISSUER: - return "CA certificate not allowed to issue CRLs"; - - case OCSP_CERT_NOT_LISTED: - return "OCSP response does not included requested cert"; - case OCSP_NOT_YET_VALID: - return "OCSP response is from the future"; - case OCSP_EXPIRED: - return "OCSP response is expired"; - case OCSP_BAD_STATUS: - return "OCSP response had unknown/bad status"; - case OCSP_RESPONSE_GOOD: - return "OCSP response had good status"; - } - - // default case - return "Unknown code " + std::to_string(code); - } - -} diff --git a/src/cert/x509/x509path.h b/src/cert/x509/x509path.h deleted file mode 100644 index 2c3268529..000000000 --- a/src/cert/x509/x509path.h +++ /dev/null @@ -1,163 +0,0 @@ -/* -* 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/cert_status.h> -#include <botan/x509cert.h> -#include <botan/certstor.h> -#include <set> - -namespace Botan { - -/** -* Specifies restrictions on the PKIX path validation -*/ -class BOTAN_DLL Path_Validation_Restrictions - { - public: - /** - * @param require_rev if true, revocation information is required - * @param minimum_key_strength is the minimum strength (in terms of - * operations, eg 80 means 2^80) of a signature. Signatures - * weaker than this are rejected. If more than 80, SHA-1 - * signatures are also rejected. - */ - Path_Validation_Restrictions(bool require_rev = false, - size_t minimum_key_strength = 80, - bool ocsp_all_intermediates = false); - - /** - * @param require_rev if true, revocation information is required - * @param minimum_key_strength is the minimum strength (in terms of - * operations, eg 80 means 2^80) of a signature. Signatures - * weaker than this are rejected. - * @param trusted_hashes a set of trusted hashes. Any signatures - * created using a hash other than one of these will be - * rejected. - */ - Path_Validation_Restrictions(bool require_rev, - size_t minimum_key_strength, - bool ocsp_all_intermediates, - const std::set<std::string>& trusted_hashes) : - m_require_revocation_information(require_rev), - m_ocsp_all_intermediates(ocsp_all_intermediates), - m_trusted_hashes(trusted_hashes), - m_minimum_key_strength(minimum_key_strength) {} - - bool require_revocation_information() const - { return m_require_revocation_information; } - - bool ocsp_all_intermediates() const - { return m_ocsp_all_intermediates; } - - const std::set<std::string>& trusted_hashes() const - { return m_trusted_hashes; } - - size_t minimum_key_strength() const - { return m_minimum_key_strength; } - - private: - bool m_require_revocation_information; - bool m_ocsp_all_intermediates; - std::set<std::string> m_trusted_hashes; - size_t m_minimum_key_strength; - }; - -/** -* Represents the result of a PKIX path validation -*/ -class BOTAN_DLL Path_Validation_Result - { - public: - /** - * @return the set of hash functions you are implicitly - * trusting by trusting this result. - */ - std::set<std::string> trusted_hashes() const; - - /** - * @return the trust root of the validation - */ - const X509_Certificate& trust_root() const; - - /** - * @return the full path from subject to trust root - */ - const std::vector<X509_Certificate>& cert_path() const { return m_cert_path; } - - /** - * @return true iff the validation was succesful - */ - bool successful_validation() const; - - /** - * @return validation result code - */ - Certificate_Status_Code result() const { return m_status; } - - Certificate_Status_Code status() const { return m_status; } - - /** - * @return string representation of the validation result - */ - std::string result_string() const; - - static std::string status_string(Certificate_Status_Code code); - - Path_Validation_Result(Certificate_Status_Code status, - std::vector<X509_Certificate>&& cert_chain) : - m_status(status), m_cert_path(cert_chain) {} - - Path_Validation_Result(Certificate_Status_Code status) : m_status(status) {} - - private: - friend Path_Validation_Result x509_path_validate( - const std::vector<X509_Certificate>& end_certs, - const Path_Validation_Restrictions& restrictions, - const std::vector<Certificate_Store*>& certstores); - - Certificate_Status_Code m_status; - std::vector<X509_Certificate> m_cert_path; - }; - -/** -* PKIX Path Validation -*/ -Path_Validation_Result BOTAN_DLL x509_path_validate( - const std::vector<X509_Certificate>& end_certs, - const Path_Validation_Restrictions& restrictions, - const std::vector<Certificate_Store*>& certstores); - -/** -* PKIX Path Validation -*/ -Path_Validation_Result BOTAN_DLL x509_path_validate( - const X509_Certificate& end_cert, - const Path_Validation_Restrictions& restrictions, - const std::vector<Certificate_Store*>& certstores); - -/** -* PKIX Path Validation -*/ -Path_Validation_Result BOTAN_DLL x509_path_validate( - const X509_Certificate& end_cert, - const Path_Validation_Restrictions& restrictions, - const Certificate_Store& store); - -/** -* PKIX Path Validation -*/ -Path_Validation_Result BOTAN_DLL x509_path_validate( - const std::vector<X509_Certificate>& end_certs, - const Path_Validation_Restrictions& restrictions, - const Certificate_Store& store); - -} - -#endif diff --git a/src/cert/x509/x509self.cpp b/src/cert/x509/x509self.cpp deleted file mode 100644 index c13772382..000000000 --- a/src/cert/x509/x509self.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* -* PKCS #10/Self Signed Cert Creation -* (C) 1999-2008 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#include <botan/x509self.h> -#include <botan/x509_ext.h> -#include <botan/x509_ca.h> -#include <botan/der_enc.h> -#include <botan/oids.h> -#include <botan/pipe.h> -#include <memory> - -namespace Botan { - -namespace { - -/* -* Load information from the X509_Cert_Options -*/ -void load_info(const X509_Cert_Options& opts, X509_DN& subject_dn, - AlternativeName& subject_alt) - { - subject_dn.add_attribute("X520.CommonName", opts.common_name); - subject_dn.add_attribute("X520.Country", opts.country); - subject_dn.add_attribute("X520.State", opts.state); - subject_dn.add_attribute("X520.Locality", opts.locality); - subject_dn.add_attribute("X520.Organization", opts.organization); - subject_dn.add_attribute("X520.OrganizationalUnit", opts.org_unit); - subject_dn.add_attribute("X520.SerialNumber", opts.serial_number); - subject_alt = AlternativeName(opts.email, opts.uri, opts.dns, opts.ip); - subject_alt.add_othername(OIDS::lookup("PKIX.XMPPAddr"), - opts.xmpp, UTF8_STRING); - } - -} - -namespace X509 { - -/* -* Create a new self-signed X.509 certificate -*/ -X509_Certificate create_self_signed_cert(const X509_Cert_Options& opts, - const Private_Key& key, - const std::string& hash_fn, - RandomNumberGenerator& rng) - { - AlgorithmIdentifier sig_algo; - X509_DN subject_dn; - AlternativeName subject_alt; - - opts.sanity_check(); - - std::vector<byte> pub_key = X509::BER_encode(key); - std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo)); - load_info(opts, subject_dn, subject_alt); - - Key_Constraints constraints; - if(opts.is_CA) - constraints = Key_Constraints(KEY_CERT_SIGN | CRL_SIGN); - else - constraints = find_constraints(key, opts.constraints); - - Extensions extensions; - - extensions.add( - new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit), - true); - - extensions.add(new Cert_Extension::Key_Usage(constraints), true); - - extensions.add(new Cert_Extension::Subject_Key_ID(pub_key)); - - extensions.add( - new Cert_Extension::Subject_Alternative_Name(subject_alt)); - - extensions.add( - new Cert_Extension::Extended_Key_Usage(opts.ex_constraints)); - - return X509_CA::make_cert(signer.get(), rng, sig_algo, pub_key, - opts.start, opts.end, - subject_dn, subject_dn, - extensions); - } - -/* -* Create a PKCS #10 certificate request -*/ -PKCS10_Request create_cert_req(const X509_Cert_Options& opts, - const Private_Key& key, - const std::string& hash_fn, - RandomNumberGenerator& rng) - { - AlgorithmIdentifier sig_algo; - X509_DN subject_dn; - AlternativeName subject_alt; - - opts.sanity_check(); - - std::vector<byte> pub_key = X509::BER_encode(key); - std::unique_ptr<PK_Signer> signer(choose_sig_format(key, hash_fn, sig_algo)); - load_info(opts, subject_dn, subject_alt); - - const size_t PKCS10_VERSION = 0; - - Extensions extensions; - - extensions.add( - new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit)); - extensions.add( - new Cert_Extension::Key_Usage( - opts.is_CA ? Key_Constraints(KEY_CERT_SIGN | CRL_SIGN) : - find_constraints(key, opts.constraints) - ) - ); - extensions.add( - new Cert_Extension::Extended_Key_Usage(opts.ex_constraints)); - extensions.add( - new Cert_Extension::Subject_Alternative_Name(subject_alt)); - - DER_Encoder tbs_req; - - tbs_req.start_cons(SEQUENCE) - .encode(PKCS10_VERSION) - .encode(subject_dn) - .raw_bytes(pub_key) - .start_explicit(0); - - if(opts.challenge != "") - { - ASN1_String challenge(opts.challenge, DIRECTORY_STRING); - - tbs_req.encode( - Attribute("PKCS9.ChallengePassword", - DER_Encoder().encode(challenge).get_contents_unlocked() - ) - ); - } - - tbs_req.encode( - Attribute("PKCS9.ExtensionRequest", - DER_Encoder() - .start_cons(SEQUENCE) - .encode(extensions) - .end_cons() - .get_contents_unlocked() - ) - ) - .end_explicit() - .end_cons(); - - const std::vector<byte> req = - X509_Object::make_signed(signer.get(), rng, sig_algo, - tbs_req.get_contents()); - - return PKCS10_Request(req); - } - -} - -} diff --git a/src/cert/x509/x509self.h b/src/cert/x509/x509self.h deleted file mode 100644 index eee4d10c6..000000000 --- a/src/cert/x509/x509self.h +++ /dev/null @@ -1,203 +0,0 @@ -/* -* X.509 Self-Signed Certificate -* (C) 1999-2007 Jack Lloyd -* -* Distributed under the terms of the Botan license -*/ - -#ifndef BOTAN_X509_SELF_H__ -#define BOTAN_X509_SELF_H__ - -#include <botan/x509cert.h> -#include <botan/pkcs8.h> -#include <botan/pkcs10.h> -#include <botan/asn1_time.h> - -namespace Botan { - -/** -* Options for X.509 certificates. -*/ -class BOTAN_DLL X509_Cert_Options - { - public: - /** - * the subject common name - */ - std::string common_name; - - /** - * the subject counry - */ - std::string country; - - /** - * the subject organization - */ - std::string organization; - - /** - * the subject organizational unit - */ - std::string org_unit; - - /** - * the subject locality - */ - std::string locality; - - /** - * the subject state - */ - std::string state; - - /** - * the subject serial number - */ - std::string serial_number; - - /** - * the subject email adress - */ - std::string email; - - /** - * the subject URI - */ - std::string uri; - - /** - * the subject IPv4 address - */ - std::string ip; - - /** - * the subject DNS - */ - std::string dns; - - /** - * the subject XMPP - */ - std::string xmpp; - - /** - * the subject challenge password - */ - std::string challenge; - - /** - * the subject notBefore - */ - X509_Time start; - /** - * the subject notAfter - */ - X509_Time end; - - /** - * Indicates whether the certificate request - */ - bool is_CA; - - /** - * Indicates the BasicConstraints path limit - */ - size_t path_limit; - - /** - * The key constraints for the subject public key - */ - Key_Constraints constraints; - - /** - * The key extended constraints for the subject public key - */ - std::vector<OID> ex_constraints; - - /** - * Check the options set in this object for validity. - */ - void sanity_check() const; - - /** - * Mark the certificate as a CA certificate and set the path limit. - * @param limit the path limit to be set in the BasicConstraints extension. - */ - void CA_key(size_t limit = 1); - - /** - * Set the notBefore of the certificate. - * @param time the notBefore value of the certificate - */ - void not_before(const std::string& time); - - /** - * Set the notAfter of the certificate. - * @param time the notAfter value of the certificate - */ - void not_after(const std::string& time); - - /** - * Add the key constraints of the KeyUsage extension. - * @param constr the constraints to set - */ - void add_constraints(Key_Constraints constr); - - /** - * Add constraints to the ExtendedKeyUsage extension. - * @param oid the oid to add - */ - void add_ex_constraint(const OID& oid); - - /** - * Add constraints to the ExtendedKeyUsage extension. - * @param name the name to look up the oid to add - */ - void add_ex_constraint(const std::string& name); - - /** - * Construct a new options object - * @param opts define the common name of this object. An example for this - * parameter would be "common_name/country/organization/organizational_unit". - * @param expire_time the expiration time (from the current clock in seconds) - */ - X509_Cert_Options(const std::string& opts = "", - u32bit expire_time = 365 * 24 * 60 * 60); - }; - -namespace X509 { - -/** -* Create a self-signed X.509 certificate. -* @param opts the options defining the certificate to create -* @param key the private key used for signing, i.e. the key -* associated with this self-signed certificate -* @param hash_fn the hash function to use -* @param rng the rng to use -* @return newly created self-signed certificate -*/ -BOTAN_DLL X509_Certificate -create_self_signed_cert(const X509_Cert_Options& opts, - const Private_Key& key, - const std::string& hash_fn, - RandomNumberGenerator& rng); - -/** -* Create a PKCS#10 certificate request. -* @param opts the options defining the request to create -* @param key the key used to sign this request -* @param rng the rng to use -* @param hash_fn the hash function to use -* @return newly created PKCS#10 request -*/ -BOTAN_DLL PKCS10_Request create_cert_req(const X509_Cert_Options& opts, - const Private_Key& key, - const std::string& hash_fn, - RandomNumberGenerator& rng); - -} - -} - -#endif |