aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2008-09-28 19:16:15 +0000
committerlloyd <[email protected]>2008-09-28 19:16:15 +0000
commit8534c9a67226ccffe7acbefbf3905aba10e88de3 (patch)
tree536e96a8b2763515104d6c90abddd3eb8aa74b19 /src
parent26ad026e8eb0521a9fb2f313f07f8fc7222d2ea8 (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.cpp46
-rw-r--r--src/crl_ent.cpp111
-rw-r--r--src/pkcs10.cpp198
-rw-r--r--src/x509_ca.cpp288
-rw-r--r--src/x509_crl.cpp149
-rw-r--r--src/x509_ext.cpp579
-rw-r--r--src/x509_obj.cpp233
-rw-r--r--src/x509cert.cpp364
-rw-r--r--src/x509find.cpp109
-rw-r--r--src/x509opt.cpp106
-rw-r--r--src/x509self.cpp174
-rw-r--r--src/x509stor.cpp693
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;
- }
-
-}