diff options
author | lloyd <[email protected]> | 2008-09-28 19:16:15 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-09-28 19:16:15 +0000 |
commit | 8534c9a67226ccffe7acbefbf3905aba10e88de3 (patch) | |
tree | 536e96a8b2763515104d6c90abddd3eb8aa74b19 /src | |
parent | 26ad026e8eb0521a9fb2f313f07f8fc7222d2ea8 (diff) |
Create an x509 module containing all of the X509 certificate and CA
code as well as the code for handling PKCS #10 requests.
Diffstat (limited to 'src')
-rw-r--r-- | src/certstor.cpp | 46 | ||||
-rw-r--r-- | src/crl_ent.cpp | 111 | ||||
-rw-r--r-- | src/pkcs10.cpp | 198 | ||||
-rw-r--r-- | src/x509_ca.cpp | 288 | ||||
-rw-r--r-- | src/x509_crl.cpp | 149 | ||||
-rw-r--r-- | src/x509_ext.cpp | 579 | ||||
-rw-r--r-- | src/x509_obj.cpp | 233 | ||||
-rw-r--r-- | src/x509cert.cpp | 364 | ||||
-rw-r--r-- | src/x509find.cpp | 109 | ||||
-rw-r--r-- | src/x509opt.cpp | 106 | ||||
-rw-r--r-- | src/x509self.cpp | 174 | ||||
-rw-r--r-- | src/x509stor.cpp | 693 |
12 files changed, 0 insertions, 3050 deletions
diff --git a/src/certstor.cpp b/src/certstor.cpp deleted file mode 100644 index 2b51590ad..000000000 --- a/src/certstor.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/************************************************* -* Certificate Store Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/certstor.h> - -namespace Botan { - -/************************************************* -* Search by name * -*************************************************/ -std::vector<X509_Certificate> -Certificate_Store::by_name(const std::string&) const - { - return std::vector<X509_Certificate>(); - } - -/************************************************* -* Search by email * -*************************************************/ -std::vector<X509_Certificate> -Certificate_Store::by_email(const std::string&) const - { - return std::vector<X509_Certificate>(); - } - -/************************************************* -* Search by X.500 distinguished name * -*************************************************/ -std::vector<X509_Certificate> -Certificate_Store::by_dn(const X509_DN&) const - { - return std::vector<X509_Certificate>(); - } - -/************************************************* -* Find any CRLs that might be useful * -*************************************************/ -std::vector<X509_CRL> -Certificate_Store::get_crls_for(const X509_Certificate&) const - { - return std::vector<X509_CRL>(); - } - -} diff --git a/src/crl_ent.cpp b/src/crl_ent.cpp deleted file mode 100644 index 4a85b99c2..000000000 --- a/src/crl_ent.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/************************************************* -* CRL Entry Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#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/libstate.h> -#include <botan/oids.h> -#include <botan/util.h> - -namespace Botan { - -/************************************************* -* Create a CRL_Entry * -*************************************************/ -CRL_Entry::CRL_Entry() - { - reason = UNSPECIFIED; - } - -/************************************************* -* Create a CRL_Entry * -*************************************************/ -CRL_Entry::CRL_Entry(const X509_Certificate& cert, CRL_Code why) - { - serial = cert.serial_number(); - time = X509_Time(system_time()); - 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); - } - -/************************************************* -* Compare two CRL_Entrys * -*************************************************/ -bool operator<(const CRL_Entry& a1, const CRL_Entry& a2) - { - return (a1.expire_time().cmp(a2.expire_time()) < 0); - } - -/************************************************* -* 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, serial.size())) - .encode(time) - .encode(extensions) - .end_cons(); - } - -/************************************************* -* Decode a BER encoded CRL_Entry * -*************************************************/ -void CRL_Entry::decode_from(BER_Decoder& source) - { - BigInt serial_number_bn; - - source.start_cons(SEQUENCE) - .decode(serial_number_bn) - .decode(time); - - if(source.more_items()) - { - std::string action = - global_state().option("x509/crl/unknown_critical"); - - if(action != "throw" && action != "ignore") - throw Invalid_Argument("Bad setting x509/crl/unknown_critical: " - + action); - - Extensions extensions(action == "throw"); - source.decode(extensions); - Data_Store info; - extensions.contents_to(info, info); - reason = CRL_Code(info.get1_u32bit("X509v3.CRLReasonCode")); - } - - serial = BigInt::encode(serial_number_bn); - } - -} diff --git a/src/pkcs10.cpp b/src/pkcs10.cpp deleted file mode 100644 index bd21cca7d..000000000 --- a/src/pkcs10.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/************************************************* -* PKCS #10 Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/pkcs10.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/parsing.h> -#include <botan/x509stor.h> -#include <botan/x509_ext.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(); - } - -/************************************************* -* Deocde the CertificateRequestInfo * -*************************************************/ -void PKCS10_Request::force_decode() - { - BER_Decoder cert_req_info(tbs_bits); - - u32bit version; - cert_req_info.decode(version); - if(version != 0) - throw Decoding_Error("Unknown version code in PKCS #10 request: " + - 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(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(); - - X509_Code sig_check = X509_Store::check_sig(*this, subject_public_key()); - if(sig_check != VERIFIED) - 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 * -*************************************************/ -MemoryVector<byte> PKCS10_Request::raw_public_key() const - { - DataSource_Memory source(info.get1("X509.Certificate.public_key")); - return 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(u32bit j = 0; j != oids.size(); ++j) - result.push_back(OID(oids[j])); - return result; - } - -/************************************************* -* Return is a CA certificate is requested * -*************************************************/ -bool PKCS10_Request::is_CA() const - { - return info.get1_u32bit("X509v3.BasicConstraints.is_ca"); - } - -/************************************************* -* 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/x509_ca.cpp b/src/x509_ca.cpp deleted file mode 100644 index d455e4988..000000000 --- a/src/x509_ca.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/************************************************* -* X.509 Certificate Authority Source File * -* (C) 1999-2008 Jack Lloyd * -*************************************************/ - -#include <botan/x509_ca.h> -#include <botan/x509stor.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/libstate.h> -#include <botan/lookup.h> -#include <botan/look_pk.h> -#include <botan/numthry.h> -#include <botan/parsing.h> -#include <botan/oids.h> -#include <botan/util.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) : cert(c) - { - const Private_Key* key_pointer = &key; - if(!dynamic_cast<const PK_Signing_Key*>(key_pointer)) - throw Invalid_Argument("X509_CA: " + key.algo_name() + " cannot sign"); - - if(!cert.is_CA_cert()) - throw Invalid_Argument("X509_CA: This certificate is not for a CA"); - - signer = choose_sig_format(key, ca_sig_algo); - } - -/************************************************* -* 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::auto_ptr<Public_Key> key(req.subject_public_key()); - constraints = X509::find_constraints(*key, req.constraints()); - } - - Extensions extensions; - - 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::Basic_Constraints(req.is_CA(), req.path_limit())); - - extensions.add(new Cert_Extension::Key_Usage(constraints)); - extensions.add( - new Cert_Extension::Extended_Key_Usage(req.ex_constraints())); - - extensions.add( - new Cert_Extension::Subject_Alternative_Name(req.subject_alt_name())); - - 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 MemoryRegion<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 u32bit X509_CERT_VERSION = 3; - const u32bit SERIAL_BITS = 128; - - BigInt serial_no(rng, SERIAL_BITS); - - DataSource_Memory source(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(source); - } - -/************************************************* -* 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> already_revoked = crl.get_revoked(); - std::vector<CRL_Entry> all_revoked; - - X509_Store store; - store.add_cert(cert, true); - if(store.add_crl(crl) != VERIFIED) - throw Invalid_Argument("X509_CA::update_crl: Invalid CRL provided"); - - std::set<SecureVector<byte> > removed_from_crl; - for(u32bit j = 0; j != new_revoked.size(); ++j) - { - if(new_revoked[j].reason_code() == DELETE_CRL_ENTRY) - removed_from_crl.insert(new_revoked[j].serial_number()); - else - all_revoked.push_back(new_revoked[j]); - } - - for(u32bit j = 0; j != already_revoked.size(); ++j) - { - std::set<SecureVector<byte> >::const_iterator i; - i = removed_from_crl.find(already_revoked[j].serial_number()); - - if(i == removed_from_crl.end()) - all_revoked.push_back(already_revoked[j]); - } - std::sort(all_revoked.begin(), all_revoked.end()); - - std::vector<CRL_Entry> cert_list; - std::unique_copy(all_revoked.begin(), all_revoked.end(), - std::back_inserter(cert_list)); - - return make_crl(cert_list, 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 u32bit X509_CRL_VERSION = 2; - - if(next_update == 0) - next_update = timespec_to_u32bit( - global_state().option("x509/crl/next_update")); - - // Totally stupid: ties encoding logic to the return of std::time!! - const u64bit current_time = system_time(); - - Extensions extensions; - extensions.add( - new Cert_Extension::Authority_Key_ID(cert.subject_key_id())); - extensions.add(new Cert_Extension::CRL_Number(crl_number)); - - DataSource_Memory source(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(current_time + next_update)) - .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(source); - } - -/************************************************* -* Return the CA's certificate * -*************************************************/ -X509_Certificate X509_CA::ca_certificate() const - { - return cert; - } - -/************************************************* -* X509_CA Destructor * -*************************************************/ -X509_CA::~X509_CA() - { - delete signer; - } - -/************************************************* -* Choose a signing format for the key * -*************************************************/ -PK_Signer* choose_sig_format(const Private_Key& key, - AlgorithmIdentifier& sig_algo) - { - std::string padding; - Signature_Format format; - - const std::string algo_name = key.algo_name(); - - if(algo_name == "RSA") - { - std::string hash = global_state().option("x509/ca/rsa_hash"); - - if(hash == "") - throw Invalid_State("No value set for x509/ca/rsa_hash"); - - hash = global_state().deref_alias(hash); - - padding = "EMSA3(" + hash + ")"; - format = IEEE_1363; - } - else if(algo_name == "DSA") - { - std::string hash = global_state().deref_alias("SHA-1"); - padding = "EMSA1(" + hash + ")"; - format = DER_SEQUENCE; - } - else - throw Invalid_Argument("Unknown X.509 signing key type: " + algo_name); - - sig_algo.oid = OIDS::lookup(algo_name + "/" + padding); - - std::auto_ptr<X509_Encoder> encoding(key.x509_encoder()); - if(!encoding.get()) - throw Encoding_Error("Key " + algo_name + " does not support " - "X.509 encoding"); - - sig_algo.parameters = encoding->alg_id().parameters; - - const PK_Signing_Key& sig_key = dynamic_cast<const PK_Signing_Key&>(key); - - return get_pk_signer(sig_key, padding, format); - } - -} diff --git a/src/x509_crl.cpp b/src/x509_crl.cpp deleted file mode 100644 index 306c78bd1..000000000 --- a/src/x509_crl.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/************************************************* -* X.509 CRL Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/x509_crl.h> -#include <botan/x509_ext.h> -#include <botan/ber_dec.h> -#include <botan/parsing.h> -#include <botan/bigint.h> -#include <botan/libstate.h> -#include <botan/oids.h> - -namespace Botan { - -/************************************************* -* Load a X.509 CRL * -*************************************************/ -X509_CRL::X509_CRL(DataSource& in) : X509_Object(in, "X509 CRL/CRL") - { - do_decode(); - } - -/************************************************* -* Load a X.509 CRL * -*************************************************/ -X509_CRL::X509_CRL(const std::string& in) : X509_Object(in, "CRL/X509 CRL") - { - do_decode(); - } - -/************************************************* -* Decode the TBSCertList data * -*************************************************/ -void X509_CRL::force_decode() - { - BER_Decoder tbs_crl(tbs_bits); - - u32bit version; - tbs_crl.decode_optional(version, INTEGER, UNIVERSAL); - - if(version != 0 && version != 1) - throw X509_CRL_Error("Unknown X.509 CRL version " + - 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; - 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); - - std::string action = global_state().option("x509/crl/unknown_critical"); - if(action != "throw" && action != "ignore") - throw Invalid_Argument("Bad value of x509/crl/unknown_critical: " - + action); - - Extensions extensions(action == "throw"); - - 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 * -*************************************************/ -MemoryVector<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/x509_ext.cpp b/src/x509_ext.cpp deleted file mode 100644 index 3595a0492..000000000 --- a/src/x509_ext.cpp +++ /dev/null @@ -1,579 +0,0 @@ -/************************************************* -* X.509 Certificate Extensions Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/x509_ext.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/lookup.h> -#include <botan/oids.h> -#include <botan/libstate.h> -#include <botan/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.CRLNumber", CRL_Number); - X509_EXTENSION("X509v3.CertificatePolicies", Certificate_Policies); - - return 0; - } - -/************************************************* -* Extensions Copy Constructor * -*************************************************/ -Extensions::Extensions(const Extensions& extensions) : ASN1_Object() - { - *this = extensions; - } - -/************************************************* -* Extensions Assignment Operator * -*************************************************/ -Extensions& Extensions::operator=(const Extensions& other) - { - for(u32bit j = 0; j != extensions.size(); ++j) - delete extensions[j]; - extensions.clear(); - - for(u32bit j = 0; j != other.extensions.size(); ++j) - extensions.push_back(other.extensions[j]->copy()); - - return (*this); - } - -/************************************************* -* Return the OID of this extension * -*************************************************/ -OID Certificate_Extension::oid_of() const - { - return OIDS::lookup(oid_name()); - } - -/************************************************* -* Encode an Extensions list * -*************************************************/ -void Extensions::encode_into(DER_Encoder& to_object) const - { - for(u32bit j = 0; j != extensions.size(); ++j) - { - const Certificate_Extension* ext = extensions[j]; - - std::string setting; - - if(ext->config_id() != "") - setting = global_state().option("x509/exts/" + ext->config_id()); - - if(setting == "") - setting = "yes"; - - if(setting != "yes" && setting != "no" && setting != "critical") - throw Invalid_Argument("X509_CA:: Invalid value for option " - "x509/exts/" + ext->config_id() + " of " + - setting); - - bool is_critical = (setting == "critical"); - bool should_encode = ext->should_encode() && (setting != "no"); - - 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(u32bit j = 0; j != extensions.size(); ++j) - delete extensions[j]; - extensions.clear(); - - BER_Decoder sequence = from_source.start_cons(SEQUENCE); - while(sequence.more_items()) - { - OID oid; - MemoryVector<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(ext); - } - sequence.verify_end(); - } - -/************************************************* -* Write the extensions to an info store * -*************************************************/ -void Extensions::contents_to(Data_Store& subject_info, - Data_Store& issuer_info) const - { - for(u32bit j = 0; j != extensions.size(); ++j) - extensions[j]->contents_to(subject_info, issuer_info); - } - -/************************************************* -* Delete an Extensions list * -*************************************************/ -Extensions::~Extensions() - { - for(u32bit j = 0; j != extensions.size(); ++j) - delete extensions[j]; - } - -namespace Cert_Extension { - -/************************************************* -* Checked accessor for the path_limit member * -*************************************************/ -u32bit 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 * -*************************************************/ -MemoryVector<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(); - } - -/************************************************* -* Decode the extension * -*************************************************/ -void Basic_Constraints::decode_inner(const MemoryRegion<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 * -*************************************************/ -MemoryVector<byte> Key_Usage::encode_inner() const - { - if(constraints == NO_CONSTRAINTS) - throw Encoding_Error("Cannot encode zero usage constraints"); - - const u32bit unused_bits = low_bit(constraints) - 1; - - SecureVector<byte> der; - der.append(BIT_STRING); - der.append(2 + ((unused_bits < 8) ? 1 : 0)); - der.append(unused_bits % 8); - der.append((constraints >> 8) & 0xFF); - if(constraints & 0xFF) - der.append(constraints & 0xFF); - - return der; - } - -/************************************************* -* Decode the extension * -*************************************************/ -void Key_Usage::decode_inner(const MemoryRegion<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(u32bit j = 1; j != obj.value.size(); ++j) - usage = (obj.value[j] << 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 * -*************************************************/ -MemoryVector<byte> Subject_Key_ID::encode_inner() const - { - return DER_Encoder().encode(key_id, OCTET_STRING).get_contents(); - } - -/************************************************* -* Decode the extension * -*************************************************/ -void Subject_Key_ID::decode_inner(const MemoryRegion<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 MemoryRegion<byte>& pub_key) - { - std::auto_ptr<HashFunction> hash(get_hash("SHA-1")); - key_id = hash->process(pub_key); - } - -/************************************************* -* Encode the extension * -*************************************************/ -MemoryVector<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(); - } - -/************************************************* -* Decode the extension * -*************************************************/ -void Authority_Key_ID::decode_inner(const MemoryRegion<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 * -*************************************************/ -MemoryVector<byte> Alternative_Name::encode_inner() const - { - return DER_Encoder().encode(alt_name).get_contents(); - } - -/************************************************* -* Decode the extension * -*************************************************/ -void Alternative_Name::decode_inner(const MemoryRegion<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, - const std::string& config_name_str) - { - this->alt_name = alt_name; - this->oid_name_str = oid_name_str; - this->config_name_str = config_name_str; - } - -/************************************************* -* Subject_Alternative_Name Constructor * -*************************************************/ -Subject_Alternative_Name::Subject_Alternative_Name( - const AlternativeName& name) : - - Alternative_Name(name, "X509v3.SubjectAlternativeName", - "subject_alternative_name") - { - } - -/************************************************* -* Issuer_Alternative_Name Constructor * -*************************************************/ -Issuer_Alternative_Name::Issuer_Alternative_Name(const AlternativeName& name) : - Alternative_Name(name, "X509v3.IssuerAlternativeName", - "issuer_alternative_name") - { - } - -/************************************************* -* Encode the extension * -*************************************************/ -MemoryVector<byte> Extended_Key_Usage::encode_inner() const - { - return DER_Encoder() - .start_cons(SEQUENCE) - .encode_list(oids) - .end_cons() - .get_contents(); - } - -/************************************************* -* Decode the extension * -*************************************************/ -void Extended_Key_Usage::decode_inner(const MemoryRegion<byte>& in) - { - BER_Decoder(in) - .start_cons(SEQUENCE) - .decode_list(oids) - .end_cons(); - } - -/************************************************* -* Return a textual representation * -*************************************************/ -void Extended_Key_Usage::contents_to(Data_Store& subject, Data_Store&) const - { - for(u32bit j = 0; j != oids.size(); ++j) - subject.add("X509v3.ExtendedKeyUsage", oids[j].as_string()); - } - -namespace { - -/************************************************* -* A policy specifier * -*************************************************/ -class Policy_Information : public ASN1_Object - { - public: - 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 * -*************************************************/ -MemoryVector<byte> Certificate_Policies::encode_inner() const - { - throw Exception("Certificate_Policies::encode_inner: Bugged"); - - std::vector<Policy_Information> policies; - - return DER_Encoder() - .start_cons(SEQUENCE) - .encode_list(policies) - .end_cons() - .get_contents(); - } - -/************************************************* -* Decode the extension * -*************************************************/ -void Certificate_Policies::decode_inner(const MemoryRegion<byte>& in) - { - std::vector<Policy_Information> policies; - - BER_Decoder(in) - .start_cons(SEQUENCE) - .decode_list(policies) - .end_cons(); - } - -/************************************************* -* Return a textual representation * -*************************************************/ -void Certificate_Policies::contents_to(Data_Store& info, Data_Store&) const - { - for(u32bit j = 0; j != oids.size(); ++j) - info.add("X509v3.ExtendedKeyUsage", oids[j].as_string()); - } - -/************************************************* -* Checked accessor for the crl_number member * -*************************************************/ -u32bit 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 * -*************************************************/ -MemoryVector<byte> CRL_Number::encode_inner() const - { - return DER_Encoder().encode(crl_number).get_contents(); - } - -/************************************************* -* Decode the extension * -*************************************************/ -void CRL_Number::decode_inner(const MemoryRegion<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 * -*************************************************/ -MemoryVector<byte> CRL_ReasonCode::encode_inner() const - { - return DER_Encoder() - .encode(static_cast<u32bit>(reason), ENUMERATED, UNIVERSAL) - .get_contents(); - } - -/************************************************* -* Decode the extension * -*************************************************/ -void CRL_ReasonCode::decode_inner(const MemoryRegion<byte>& in) - { - u32bit 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); - } - -} - -} diff --git a/src/x509_obj.cpp b/src/x509_obj.cpp deleted file mode 100644 index e78790949..000000000 --- a/src/x509_obj.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/************************************************* -* X.509 SIGNED Object Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/x509_obj.h> -#include <botan/x509_key.h> -#include <botan/look_pk.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); - } - -/************************************************* -* Createa 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); - } - -/************************************************* -* 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)) - decode_info(in); - 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); - decode_info(ber); - } - } - catch(Decoding_Error) - { - throw Decoding_Error(PEM_label_pref + " decoding failed"); - } - } - -/************************************************* -* Read a BER encoded X.509 object * -*************************************************/ -void X509_Object::decode_info(DataSource& source) - { - BER_Decoder(source) - .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 or PEM encoded X.509 object * -*************************************************/ -void X509_Object::encode(Pipe& out, X509_Encoding encoding) const - { - SecureVector<byte> der = DER_Encoder() - .start_cons(SEQUENCE) - .start_cons(SEQUENCE) - .raw_bytes(tbs_bits) - .end_cons() - .encode(sig_algo) - .encode(sig, BIT_STRING) - .end_cons() - .get_contents(); - - if(encoding == PEM) - out.write(PEM_Code::encode(der, PEM_label_pref)); - else - out.write(der); - } - -/************************************************* -* Return a BER encoded X.509 object * -*************************************************/ -SecureVector<byte> X509_Object::BER_encode() const - { - Pipe ber; - ber.start_msg(); - encode(ber, RAW_BER); - ber.end_msg(); - return ber.read_all(); - } - -/************************************************* -* Return a PEM encoded X.509 object * -*************************************************/ -std::string X509_Object::PEM_encode() const - { - Pipe pem; - pem.start_msg(); - encode(pem, PEM); - pem.end_msg(); - return pem.read_all_as_string(); - } - -/************************************************* -* Return the TBS data * -*************************************************/ -SecureVector<byte> X509_Object::tbs_data() const - { - return ASN1::put_in_sequence(tbs_bits); - } - -/************************************************* -* Return the signature of this object * -*************************************************/ -SecureVector<byte> X509_Object::signature() const - { - return sig; - } - -/************************************************* -* Return the algorithm used to sign this object * -*************************************************/ -AlgorithmIdentifier X509_Object::signature_algorithm() const - { - return sig_algo; - } - -/************************************************* -* Check the signature on an object * -*************************************************/ -bool X509_Object::check_signature(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; - - std::auto_ptr<PK_Verifier> verifier; - - if(dynamic_cast<PK_Verifying_with_MR_Key*>(&pub_key)) - { - PK_Verifying_with_MR_Key& sig_key = - dynamic_cast<PK_Verifying_with_MR_Key&>(pub_key); - verifier.reset(get_pk_verifier(sig_key, padding, format)); - } - else if(dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key)) - { - PK_Verifying_wo_MR_Key& sig_key = - dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key); - verifier.reset(get_pk_verifier(sig_key, padding, format)); - } - else - return false; - - return verifier->verify_message(tbs_data(), signature()); - } - catch(...) - { - return false; - } - } - -/************************************************* -* Apply the X.509 SIGNED macro * -*************************************************/ -MemoryVector<byte> X509_Object::make_signed(PK_Signer* signer, - RandomNumberGenerator& rng, - const AlgorithmIdentifier& algo, - const MemoryRegion<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(); - } - -/************************************************* -* Try to decode the actual information * -*************************************************/ -void X509_Object::do_decode() - { - try { - force_decode(); - } - catch(Decoding_Error& e) - { - const std::string what = e.what(); - throw Decoding_Error(PEM_label_pref + " decoding failed (" + - what.substr(23, std::string::npos) + ")"); - } - catch(Invalid_Argument& e) - { - const std::string what = e.what(); - throw Decoding_Error(PEM_label_pref + " decoding failed (" + - what.substr(7, std::string::npos) + ")"); - } - } - -} diff --git a/src/x509cert.cpp b/src/x509cert.cpp deleted file mode 100644 index b24e6a036..000000000 --- a/src/x509cert.cpp +++ /dev/null @@ -1,364 +0,0 @@ -/************************************************* -* X.509 Certificates Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/x509cert.h> -#include <botan/x509_ext.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <botan/stl_util.h> -#include <botan/parsing.h> -#include <botan/bigint.h> -#include <botan/oids.h> -#include <botan/pem.h> -#include <algorithm> - -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; - - std::vector<std::string>::const_iterator i = in.begin(); - while(i != in.end()) - { - out.push_back(OIDS::lookup(OID(*i))); - ++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(); - } - -/************************************************* -* Decode the TBSCertificate data * -*************************************************/ -void X509_Certificate::force_decode() - { - u32bit 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 " + 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()); - - 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); - - MemoryVector<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", - PEM_Code::encode( - ASN1::put_in_sequence(public_key.value), - "PUBLIC KEY" - ) - ); - - if(is_CA_cert() && - !subject.has_value("X509v3.BasicConstraints.path_constraint")) - { - u32bit limit = (x509_version() < 3) ? 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 - { - DataSource_Memory source(subject.get1("X509.Certificate.public_key")); - return X509::load_key(source); - } - -/************************************************* -* 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; - if((constraints() & KEY_CERT_SIGN) || (constraints() == NO_CONSTRAINTS)) - 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")); - } - -/************************************************* -* Return the authority key id * -*************************************************/ -MemoryVector<byte> X509_Certificate::authority_key_id() const - { - return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier"); - } - -/************************************************* -* Return the subject key id * -*************************************************/ -MemoryVector<byte> X509_Certificate::subject_key_id() const - { - return subject.get1_memvec("X509v3.SubjectKeyIdentifier"); - } - -/************************************************* -* Return the certificate serial number * -*************************************************/ -MemoryVector<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); - } - -/************************************************* -* Return the distinguished name of the subject * -*************************************************/ -X509_DN X509_Certificate::subject_dn() const - { - return create_dn(subject); - } - -/************************************************* -* 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); - } - -/************************************************* -* X.509 Certificate Comparison * -*************************************************/ -bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2) - { - return !(cert1 == cert2); - } - -/************************************************* -* Create and populate a X509_DN * -*************************************************/ -X509_DN create_dn(const Data_Store& info) - { - class DN_Matcher : public Data_Store::Matcher - { - public: - bool operator()(const std::string& key, const std::string&) const - { - if(key.find("X520.") != std::string::npos) - return true; - return false; - } - }; - - std::multimap<std::string, std::string> names = - info.search_with(DN_Matcher()); - - X509_DN dn; - - std::multimap<std::string, std::string>::iterator j; - for(j = names.begin(); j != names.end(); ++j) - dn.add_attribute(j->first, j->second); - - return dn; - } - -/************************************************* -* Create and populate an AlternativeName * -*************************************************/ -AlternativeName create_alt_name(const Data_Store& info) - { - class AltName_Matcher : public Data_Store::Matcher - { - public: - bool operator()(const std::string& key, const std::string&) const - { - for(u32bit j = 0; j != matches.size(); ++j) - if(key.compare(matches[j]) == 0) - return true; - return false; - } - - AltName_Matcher(const std::string& match_any_of) - { - matches = split_on(match_any_of, '/'); - } - private: - std::vector<std::string> matches; - }; - - std::multimap<std::string, std::string> names = - info.search_with(AltName_Matcher("RFC822/DNS/URI/IP")); - - AlternativeName alt_name; - - std::multimap<std::string, std::string>::iterator j; - for(j = names.begin(); j != names.end(); ++j) - alt_name.add_attribute(j->first, j->second); - - return alt_name; - } - -} diff --git a/src/x509find.cpp b/src/x509find.cpp deleted file mode 100644 index 83d02449d..000000000 --- a/src/x509find.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/************************************************* -* X.509 Certificate Store Searching Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/x509find.h> -#include <botan/charset.h> -#include <algorithm> - -namespace Botan { - -namespace { - -/************************************************* -* Compare based on case-insensive substrings * -*************************************************/ -bool substring_match(const std::string& searching_for, - const std::string& found) - { - if(std::search(found.begin(), found.end(), searching_for.begin(), - searching_for.end(), Charset::caseless_cmp) != found.end()) - return true; - return false; - } - -/************************************************* -* Compare based on case-insensive match * -*************************************************/ -bool ignore_case(const std::string& searching_for, const std::string& found) - { - if(searching_for.size() != found.size()) - return false; - - return std::equal(found.begin(), found.end(), - searching_for.begin(), Charset::caseless_cmp); - } - -} - -/************************************************* -* Search based on the contents of a DN entry * -*************************************************/ -bool DN_Check::match(const X509_Certificate& cert) const - { - std::vector<std::string> info = cert.subject_info(dn_entry); - - for(u32bit j = 0; j != info.size(); ++j) - if(compare(info[j], looking_for)) - return true; - return false; - } - -/************************************************* -* DN_Check Constructor * -*************************************************/ -DN_Check::DN_Check(const std::string& dn_entry, const std::string& looking_for, - compare_fn func) - { - this->dn_entry = dn_entry; - this->looking_for = looking_for; - compare = func; - } - -/************************************************* -* DN_Check Constructor * -*************************************************/ -DN_Check::DN_Check(const std::string& dn_entry, const std::string& looking_for, - Search_Type method) - { - this->dn_entry = dn_entry; - this->looking_for = looking_for; - - if(method == SUBSTRING_MATCHING) - compare = &substring_match; - else if(method == IGNORE_CASE) - compare = &ignore_case; - else - throw Invalid_Argument("Unknown method argument to DN_Check()"); - } - -/************************************************* -* Match by issuer and serial number * -*************************************************/ -bool IandS_Match::match(const X509_Certificate& cert) const - { - if(cert.serial_number() != serial) - return false; - return (cert.issuer_dn() == issuer); - } - -/************************************************* -* IandS_Match Constructor * -*************************************************/ -IandS_Match::IandS_Match(const X509_DN& issuer, - const MemoryRegion<byte>& serial) - { - this->issuer = issuer; - this->serial = serial; - } - -/************************************************* -* Match by subject key identifier * -*************************************************/ -bool SKID_Match::match(const X509_Certificate& cert) const - { - return (cert.subject_key_id() == skid); - } - -} diff --git a/src/x509opt.cpp b/src/x509opt.cpp deleted file mode 100644 index 716884ed5..000000000 --- a/src/x509opt.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/************************************************* -* X.509 Certificate Options Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/x509self.h> -#include <botan/util.h> -#include <botan/parsing.h> -#include <botan/oids.h> -#include <ctime> - -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(u32bit 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_in_seconds) - { - is_CA = false; - path_limit = 0; - constraints = NO_CONSTRAINTS; - - const u32bit now = system_time(); - - start = X509_Time(now); - end = X509_Time(now + expiration_time_in_seconds); - - 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/x509self.cpp b/src/x509self.cpp deleted file mode 100644 index 6c3baae9b..000000000 --- a/src/x509self.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/************************************************* -* PKCS #10/Self Signed Cert Creation Source File * -* (C) 1999-2008 Jack Lloyd * -*************************************************/ - -#include <botan/x509self.h> -#include <botan/x509_ext.h> -#include <botan/x509_ca.h> -#include <botan/der_enc.h> -#include <botan/look_pk.h> -#include <botan/oids.h> -#include <botan/pipe.h> -#include <memory> - -namespace Botan { - -namespace { - -/************************************************* -* Shared setup for self-signed items * -*************************************************/ -MemoryVector<byte> shared_setup(const X509_Cert_Options& opts, - const Private_Key& key) - { - const Private_Key* key_pointer = &key; - if(!dynamic_cast<const PK_Signing_Key*>(key_pointer)) - throw Invalid_Argument("Key type " + key.algo_name() + " cannot sign"); - - opts.sanity_check(); - - Pipe key_encoder; - key_encoder.start_msg(); - X509::encode(key, key_encoder, RAW_BER); - key_encoder.end_msg(); - - return key_encoder.read_all(); - } - -/************************************************* -* 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, - RandomNumberGenerator& rng) - { - AlgorithmIdentifier sig_algo; - X509_DN subject_dn; - AlternativeName subject_alt; - - MemoryVector<byte> pub_key = shared_setup(opts, key); - std::auto_ptr<PK_Signer> signer(choose_sig_format(key, 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::Subject_Key_ID(pub_key)); - extensions.add(new Cert_Extension::Key_Usage(constraints)); - extensions.add( - new Cert_Extension::Extended_Key_Usage(opts.ex_constraints)); - extensions.add( - new Cert_Extension::Subject_Alternative_Name(subject_alt)); - extensions.add( - new Cert_Extension::Basic_Constraints(opts.is_CA, opts.path_limit)); - - 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, - RandomNumberGenerator& rng) - { - AlgorithmIdentifier sig_algo; - X509_DN subject_dn; - AlternativeName subject_alt; - - MemoryVector<byte> pub_key = shared_setup(opts, key); - std::auto_ptr<PK_Signer> signer(choose_sig_format(key, sig_algo)); - load_info(opts, subject_dn, subject_alt); - - const u32bit 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() - ) - ); - } - - tbs_req.encode( - Attribute("PKCS9.ExtensionRequest", - DER_Encoder() - .start_cons(SEQUENCE) - .encode(extensions) - .end_cons() - .get_contents() - ) - ) - .end_explicit() - .end_cons(); - - DataSource_Memory source( - X509_Object::make_signed(signer.get(), - rng, - sig_algo, - tbs_req.get_contents()) - ); - - return PKCS10_Request(source); - } - -} - -} diff --git a/src/x509stor.cpp b/src/x509stor.cpp deleted file mode 100644 index f050b33b1..000000000 --- a/src/x509stor.cpp +++ /dev/null @@ -1,693 +0,0 @@ -/************************************************* -* X.509 Certificate Store Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/x509stor.h> -#include <botan/parsing.h> -#include <botan/pubkey.h> -#include <botan/look_pk.h> -#include <botan/oids.h> -#include <botan/util.h> -#include <algorithm> -#include <memory> - -namespace Botan { - -namespace { - -/************************************************* -* Do a validity check * -*************************************************/ -s32bit validity_check(const X509_Time& start, const X509_Time& end, - u64bit current_time, u32bit slack) - { - const s32bit NOT_YET_VALID = -1, VALID_TIME = 0, EXPIRED = 1; - - if(start.cmp(current_time + slack) > 0) - return NOT_YET_VALID; - if(end.cmp(current_time - slack) < 0) - return EXPIRED; - return VALID_TIME; - } - -/************************************************* -* Compare the value of unique ID fields * -*************************************************/ -bool compare_ids(const MemoryVector<byte>& id1, - const MemoryVector<byte>& id2) - { - if(!id1.size() || !id2.size()) - return true; - return (id1 == id2); - } - -/************************************************* -* Check a particular usage restriction * -*************************************************/ -bool check_usage(const X509_Certificate& cert, X509_Store::Cert_Usage usage, - X509_Store::Cert_Usage check_for, Key_Constraints constraints) - { - if((usage & check_for) == 0) - return true; - if(cert.constraints() == NO_CONSTRAINTS) - return true; - if(cert.constraints() & constraints) - return true; - return false; - } - -/************************************************* -* Check a particular usage restriction * -*************************************************/ -bool check_usage(const X509_Certificate& cert, X509_Store::Cert_Usage usage, - X509_Store::Cert_Usage check_for, - const std::string& usage_oid) - { - if((usage & check_for) == 0) - return true; - - const std::vector<std::string> constraints = cert.ex_constraints(); - - if(constraints.empty()) - return true; - - return std::binary_search(constraints.begin(), constraints.end(), - usage_oid); - } - -/************************************************* -* Check the usage restrictions * -*************************************************/ -X509_Code usage_check(const X509_Certificate& cert, - X509_Store::Cert_Usage usage) - { - if(usage == X509_Store::ANY) - return VERIFIED; - - if(!check_usage(cert, usage, X509_Store::CRL_SIGNING, CRL_SIGN)) - return CA_CERT_NOT_FOR_CRL_ISSUER; - - if(!check_usage(cert, usage, X509_Store::TLS_SERVER, "PKIX.ServerAuth")) - return INVALID_USAGE; - if(!check_usage(cert, usage, X509_Store::TLS_CLIENT, "PKIX.ClientAuth")) - return INVALID_USAGE; - if(!check_usage(cert, usage, X509_Store::CODE_SIGNING, "PKIX.CodeSigning")) - return INVALID_USAGE; - if(!check_usage(cert, usage, X509_Store::EMAIL_PROTECTION, - "PKIX.EmailProtection")) - return INVALID_USAGE; - if(!check_usage(cert, usage, X509_Store::TIME_STAMPING, - "PKIX.TimeStamping")) - return INVALID_USAGE; - - return VERIFIED; - } - -} - -/************************************************* -* Define equality for revocation data * -*************************************************/ -bool X509_Store::CRL_Data::operator==(const CRL_Data& other) const - { - if(issuer != other.issuer) - return false; - if(serial != other.serial) - return false; - return compare_ids(auth_key_id, other.auth_key_id); - } - -/************************************************* -* Define inequality for revocation data * -*************************************************/ -bool X509_Store::CRL_Data::operator!=(const CRL_Data& other) const - { - return !((*this) == other); - } - -/************************************************* -* Define an ordering for revocation data * -*************************************************/ -bool X509_Store::CRL_Data::operator<(const X509_Store::CRL_Data& other) const - { - if(*this == other) - return false; - - const MemoryVector<byte>& serial1 = serial; - const MemoryVector<byte>& key_id1 = auth_key_id; - const MemoryVector<byte>& serial2 = other.serial; - const MemoryVector<byte>& key_id2 = other.auth_key_id; - - if(compare_ids(key_id1, key_id2) == false) - { - if(std::lexicographical_compare(key_id1.begin(), key_id1.end(), - key_id2.begin(), key_id2.end())) - return true; - - if(std::lexicographical_compare(key_id2.begin(), key_id2.end(), - key_id1.begin(), key_id1.end())) - return false; - } - - if(compare_ids(serial1, serial2) == false) - { - if(std::lexicographical_compare(serial1.begin(), serial1.end(), - serial2.begin(), serial2.end())) - return true; - - if(std::lexicographical_compare(serial2.begin(), serial2.end(), - serial1.begin(), serial1.end())) - return false; - } - - return (issuer < other.issuer); - } - -/************************************************* -* X509_Store Constructor * -*************************************************/ -X509_Store::X509_Store(u32bit slack, u32bit cache_timeout) - { - revoked_info_valid = true; - - validation_cache_timeout = cache_timeout; - time_slack = slack; - } - -/************************************************* -* X509_Store Copy Constructor * -*************************************************/ -X509_Store::X509_Store(const X509_Store& other) - { - certs = other.certs; - revoked = other.revoked; - revoked_info_valid = other.revoked_info_valid; - for(u32bit j = 0; j != other.stores.size(); ++j) - stores[j] = other.stores[j]->clone(); - time_slack = other.time_slack; - } - -/************************************************* -* X509_Store Destructor * -*************************************************/ -X509_Store::~X509_Store() - { - for(u32bit j = 0; j != stores.size(); ++j) - delete stores[j]; - } - -/************************************************* -* Verify a certificate's authenticity * -*************************************************/ -X509_Code X509_Store::validate_cert(const X509_Certificate& cert, - Cert_Usage cert_usage) - { - recompute_revoked_info(); - - std::vector<u32bit> indexes; - X509_Code chaining_result = construct_cert_chain(cert, indexes); - if(chaining_result != VERIFIED) - return chaining_result; - - const u64bit current_time = system_time(); - - s32bit time_check = validity_check(cert.start_time(), cert.end_time(), - current_time, time_slack); - if(time_check < 0) return CERT_NOT_YET_VALID; - else if(time_check > 0) return CERT_HAS_EXPIRED; - - X509_Code sig_check_result = check_sig(cert, certs[indexes[0]]); - if(sig_check_result != VERIFIED) - return sig_check_result; - - if(is_revoked(cert)) - return CERT_IS_REVOKED; - - for(u32bit j = 0; j != indexes.size() - 1; ++j) - { - const X509_Certificate& current_cert = certs[indexes[j]].cert; - - time_check = validity_check(current_cert.start_time(), - current_cert.end_time(), - current_time, - time_slack); - - if(time_check < 0) return CERT_NOT_YET_VALID; - else if(time_check > 0) return CERT_HAS_EXPIRED; - - sig_check_result = check_sig(certs[indexes[j]], certs[indexes[j+1]]); - if(sig_check_result != VERIFIED) - return sig_check_result; - } - - return usage_check(cert, cert_usage); - } - -/************************************************* -* Find this certificate * -*************************************************/ -u32bit X509_Store::find_cert(const X509_DN& subject_dn, - const MemoryRegion<byte>& subject_key_id) const - { - for(u32bit j = 0; j != certs.size(); ++j) - { - const X509_Certificate& this_cert = certs[j].cert; - if(compare_ids(this_cert.subject_key_id(), subject_key_id) && - this_cert.subject_dn() == subject_dn) - return j; - } - return NO_CERT_FOUND; - } - -/************************************************* -* Find the parent of this certificate * -*************************************************/ -u32bit X509_Store::find_parent_of(const X509_Certificate& cert) - { - const X509_DN issuer_dn = cert.issuer_dn(); - const MemoryVector<byte> auth_key_id = cert.authority_key_id(); - - u32bit index = find_cert(issuer_dn, auth_key_id); - - if(index != NO_CERT_FOUND) - return index; - - if(auth_key_id.size()) - { - for(u32bit j = 0; j != stores.size(); ++j) - { - std::vector<X509_Certificate> got = stores[j]->by_SKID(auth_key_id); - - if(got.empty()) - continue; - - for(u32bit k = 0; k != got.size(); ++k) - add_cert(got[k]); - return find_cert(issuer_dn, auth_key_id); - } - } - - return NO_CERT_FOUND; - } - -/************************************************* -* Construct a chain of certificate relationships * -*************************************************/ -X509_Code X509_Store::construct_cert_chain(const X509_Certificate& end_cert, - std::vector<u32bit>& indexes, - bool need_full_chain) - { - u32bit parent = find_parent_of(end_cert); - - while(true) - { - if(parent == NO_CERT_FOUND) - return CERT_ISSUER_NOT_FOUND; - indexes.push_back(parent); - - if(certs[parent].is_verified(validation_cache_timeout)) - if(certs[parent].verify_result() != VERIFIED) - return certs[parent].verify_result(); - - const X509_Certificate& parent_cert = certs[parent].cert; - if(!parent_cert.is_CA_cert()) - return CA_CERT_NOT_FOR_CERT_ISSUER; - - if(certs[parent].is_trusted()) - break; - if(parent_cert.is_self_signed()) - return CANNOT_ESTABLISH_TRUST; - - if(parent_cert.path_limit() < indexes.size() - 1) - return CERT_CHAIN_TOO_LONG; - - parent = find_parent_of(parent_cert); - } - - if(need_full_chain) - return VERIFIED; - - while(true) - { - if(indexes.size() < 2) - break; - - const u32bit cert = indexes.back(); - - if(certs[cert].is_verified(validation_cache_timeout)) - { - if(certs[cert].verify_result() != VERIFIED) - throw Internal_Error("X509_Store::construct_cert_chain"); - indexes.pop_back(); - } - else - break; - } - - const u32bit last_cert = indexes.back(); - const u32bit parent_of_last_cert = find_parent_of(certs[last_cert].cert); - if(parent_of_last_cert == NO_CERT_FOUND) - return CERT_ISSUER_NOT_FOUND; - indexes.push_back(parent_of_last_cert); - - return VERIFIED; - } - -/************************************************* -* Check the CAs signature on a certificate * -*************************************************/ -X509_Code X509_Store::check_sig(const Cert_Info& cert_info, - const Cert_Info& ca_cert_info) const - { - if(cert_info.is_verified(validation_cache_timeout)) - return cert_info.verify_result(); - - const X509_Certificate& cert = cert_info.cert; - const X509_Certificate& ca_cert = ca_cert_info.cert; - - X509_Code verify_code = check_sig(cert, ca_cert.subject_public_key()); - - cert_info.set_result(verify_code); - - return verify_code; - } - -/************************************************* -* Check a CA's signature * -*************************************************/ -X509_Code X509_Store::check_sig(const X509_Object& object, Public_Key* key) - { - std::auto_ptr<Public_Key> pub_key(key); - std::auto_ptr<PK_Verifier> verifier; - - try { - std::vector<std::string> sig_info = - split_on(OIDS::lookup(object.signature_algorithm().oid), '/'); - - if(sig_info.size() != 2 || sig_info[0] != pub_key->algo_name()) - return SIGNATURE_ERROR; - - std::string padding = sig_info[1]; - Signature_Format format; - if(key->message_parts() >= 2) format = DER_SEQUENCE; - else format = IEEE_1363; - - if(dynamic_cast<PK_Verifying_with_MR_Key*>(pub_key.get())) - { - PK_Verifying_with_MR_Key* sig_key = - dynamic_cast<PK_Verifying_with_MR_Key*>(pub_key.get()); - verifier.reset(get_pk_verifier(*sig_key, padding, format)); - } - else if(dynamic_cast<PK_Verifying_wo_MR_Key*>(pub_key.get())) - { - PK_Verifying_wo_MR_Key* sig_key = - dynamic_cast<PK_Verifying_wo_MR_Key*>(pub_key.get()); - verifier.reset(get_pk_verifier(*sig_key, padding, format)); - } - else - return CA_CERT_CANNOT_SIGN; - - bool valid = verifier->verify_message(object.tbs_data(), - object.signature()); - - if(valid) - return VERIFIED; - else - return SIGNATURE_ERROR; - } - catch(Decoding_Error) { return CERT_FORMAT_ERROR; } - catch(Exception) {} - - return UNKNOWN_X509_ERROR; - } - -/************************************************* -* Recompute the revocation status of the certs * -*************************************************/ -void X509_Store::recompute_revoked_info() const - { - if(revoked_info_valid) - return; - - for(u32bit j = 0; j != certs.size(); ++j) - { - if((certs[j].is_verified(validation_cache_timeout)) && - (certs[j].verify_result() != VERIFIED)) - continue; - - if(is_revoked(certs[j].cert)) - certs[j].set_result(CERT_IS_REVOKED); - } - - revoked_info_valid = true; - } - -/************************************************* -* Check if a certificate is revoked * -*************************************************/ -bool X509_Store::is_revoked(const X509_Certificate& cert) const - { - CRL_Data revoked_info; - revoked_info.issuer = cert.issuer_dn(); - revoked_info.serial = cert.serial_number(); - revoked_info.auth_key_id = cert.authority_key_id(); - - if(std::binary_search(revoked.begin(), revoked.end(), revoked_info)) - return true; - return false; - } - -/************************************************* -* Retrieve all the certificates in the store * -*************************************************/ -std::vector<X509_Certificate> -X509_Store::get_certs(const Search_Func& search) const - { - std::vector<X509_Certificate> found_certs; - for(u32bit j = 0; j != certs.size(); ++j) - { - if(search.match(certs[j].cert)) - found_certs.push_back(certs[j].cert); - } - return found_certs; - } - -/************************************************* -* Construct a path back to a root for this cert * -*************************************************/ -std::vector<X509_Certificate> -X509_Store::get_cert_chain(const X509_Certificate& cert) - { - std::vector<X509_Certificate> result; - std::vector<u32bit> indexes; - X509_Code chaining_result = construct_cert_chain(cert, indexes, true); - - if(chaining_result != VERIFIED) - throw Invalid_State("X509_Store::get_cert_chain: Can't construct chain"); - - for(u32bit j = 0; j != indexes.size(); ++j) - result.push_back(certs[indexes[j]].cert); - return result; - } - -/************************************************* -* Add a certificate store to the list of stores * -*************************************************/ -void X509_Store::add_new_certstore(Certificate_Store* certstore) - { - stores.push_back(certstore); - } - -/************************************************* -* Add a certificate to the store * -*************************************************/ -void X509_Store::add_cert(const X509_Certificate& cert, bool trusted) - { - if(trusted && !cert.is_self_signed()) - throw Invalid_Argument("X509_Store: Trusted certs must be self-signed"); - - if(find_cert(cert.subject_dn(), cert.subject_key_id()) == NO_CERT_FOUND) - { - revoked_info_valid = false; - Cert_Info info(cert, trusted); - certs.push_back(info); - } - else if(trusted) - { - for(u32bit j = 0; j != certs.size(); ++j) - { - const X509_Certificate& this_cert = certs[j].cert; - if(this_cert == cert) - certs[j].trusted = trusted; - } - } - } - -/************************************************* -* Add one or more certificates to the store * -*************************************************/ -void X509_Store::do_add_certs(DataSource& source, bool trusted) - { - while(!source.end_of_data()) - { - try { - X509_Certificate cert(source); - add_cert(cert, trusted); - } - catch(Decoding_Error) {} - catch(Invalid_Argument) {} - } - } - -/************************************************* -* Add one or more certificates to the store * -*************************************************/ -void X509_Store::add_certs(DataSource& source) - { - do_add_certs(source, false); - } - -/************************************************* -* Add one or more certificates to the store * -*************************************************/ -void X509_Store::add_trusted_certs(DataSource& source) - { - do_add_certs(source, true); - } - -/************************************************* -* Add one or more certificates to the store * -*************************************************/ -X509_Code X509_Store::add_crl(const X509_CRL& crl) - { - s32bit time_check = validity_check(crl.this_update(), crl.next_update(), - system_time(), time_slack); - - if(time_check < 0) return CRL_NOT_YET_VALID; - else if(time_check > 0) return CRL_HAS_EXPIRED; - - u32bit cert_index = NO_CERT_FOUND; - - for(u32bit j = 0; j != certs.size(); ++j) - { - const X509_Certificate& this_cert = certs[j].cert; - if(compare_ids(this_cert.subject_key_id(), crl.authority_key_id())) - { - if(this_cert.subject_dn() == crl.issuer_dn()) - cert_index = j; - } - } - - if(cert_index == NO_CERT_FOUND) - return CRL_ISSUER_NOT_FOUND; - - const X509_Certificate& ca_cert = certs[cert_index].cert; - - X509_Code verify_result = validate_cert(ca_cert, CRL_SIGNING); - if(verify_result != VERIFIED) - return verify_result; - - verify_result = check_sig(crl, ca_cert.subject_public_key()); - if(verify_result != VERIFIED) - return verify_result; - - std::vector<CRL_Entry> revoked_certs = crl.get_revoked(); - - for(u32bit j = 0; j != revoked_certs.size(); ++j) - { - CRL_Data revoked_info; - revoked_info.issuer = crl.issuer_dn(); - revoked_info.serial = revoked_certs[j].serial_number(); - revoked_info.auth_key_id = crl.authority_key_id(); - - std::vector<CRL_Data>::iterator p = - std::find(revoked.begin(), revoked.end(), revoked_info); - - if(revoked_certs[j].reason_code() == REMOVE_FROM_CRL) - { - if(p == revoked.end()) continue; - revoked.erase(p); - } - else - { - if(p != revoked.end()) continue; - revoked.push_back(revoked_info); - } - } - - std::sort(revoked.begin(), revoked.end()); - revoked_info_valid = false; - - return VERIFIED; - } - -/************************************************* -* PEM encode the set of certificates * -*************************************************/ -std::string X509_Store::PEM_encode() const - { - std::string cert_store; - for(u32bit j = 0; j != certs.size(); ++j) - cert_store += certs[j].cert.PEM_encode(); - return cert_store; - } - -/************************************************* -* Create a Cert_Info structure * -*************************************************/ -X509_Store::Cert_Info::Cert_Info(const X509_Certificate& c, - bool t) : cert(c), trusted(t) - { - checked = false; - result = UNKNOWN_X509_ERROR; - last_checked = 0; - } - -/************************************************* -* Return the verification results * -*************************************************/ -X509_Code X509_Store::Cert_Info::verify_result() const - { - if(!checked) - throw Invalid_State("Cert_Info::verify_result() called; not checked"); - return result; - } - -/************************************************* -* Set the verification results * -*************************************************/ -void X509_Store::Cert_Info::set_result(X509_Code code) const - { - result = code; - last_checked = system_time(); - checked = true; - } - -/************************************************* -* Check if this certificate can be trusted * -*************************************************/ -bool X509_Store::Cert_Info::is_trusted() const - { - return trusted; - } - -/************************************************* -* Check if this certificate has been verified * -*************************************************/ -bool X509_Store::Cert_Info::is_verified(u32bit timeout) const - { - if(!checked) - return false; - if(result != VERIFIED && result != CERT_NOT_YET_VALID) - return true; - - const u64bit current_time = system_time(); - - if(current_time > last_checked + timeout) - checked = false; - - return checked; - } - -} |