aboutsummaryrefslogtreecommitdiffstats
path: root/src/cert/x509/x509cert.cpp
diff options
context:
space:
mode:
authorlloyd <[email protected]>2014-01-01 21:20:55 +0000
committerlloyd <[email protected]>2014-01-01 21:20:55 +0000
commit197dc467dec28a04c3b2f30da7cef122dfbb13e9 (patch)
treecdbd3ddaec051c72f0a757db461973d90c37b97a /src/cert/x509/x509cert.cpp
parent62faac373c07cfe10bc8c309e89ebdd30d8e5eaa (diff)
Shuffle things around. Add NIST X.509 test to build.
Diffstat (limited to 'src/cert/x509/x509cert.cpp')
-rw-r--r--src/cert/x509/x509cert.cpp587
1 files changed, 0 insertions, 587 deletions
diff --git a/src/cert/x509/x509cert.cpp b/src/cert/x509/x509cert.cpp
deleted file mode 100644
index 2362cd0cf..000000000
--- a/src/cert/x509/x509cert.cpp
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
-* X.509 Certificates
-* (C) 1999-2010 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-#include <botan/x509cert.h>
-#include <botan/x509_ext.h>
-#include <botan/der_enc.h>
-#include <botan/ber_dec.h>
-#include <botan/internal/stl_util.h>
-#include <botan/parsing.h>
-#include <botan/bigint.h>
-#include <botan/lookup.h>
-#include <botan/oids.h>
-#include <botan/pem.h>
-#include <botan/hex.h>
-#include <algorithm>
-#include <iterator>
-#include <sstream>
-#include <memory>
-
-namespace Botan {
-
-namespace {
-
-/*
-* Lookup each OID in the vector
-*/
-std::vector<std::string> lookup_oids(const std::vector<std::string>& in)
- {
- std::vector<std::string> out;
-
- for(auto i = in.begin(); i != in.end(); ++i)
- out.push_back(OIDS::lookup(OID(*i)));
- return out;
- }
-
-}
-
-/*
-* X509_Certificate Constructor
-*/
-X509_Certificate::X509_Certificate(DataSource& in) :
- X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
- {
- self_signed = false;
- do_decode();
- }
-
-/*
-* X509_Certificate Constructor
-*/
-X509_Certificate::X509_Certificate(const std::string& in) :
- X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
- {
- self_signed = false;
- do_decode();
- }
-
-/*
-* X509_Certificate Constructor
-*/
-X509_Certificate::X509_Certificate(const std::vector<byte>& in) :
- X509_Object(in, "CERTIFICATE/X509 CERTIFICATE")
- {
- self_signed = false;
- do_decode();
- }
-
-/*
-* Decode the TBSCertificate data
-*/
-void X509_Certificate::force_decode()
- {
- size_t version;
- BigInt serial_bn;
- AlgorithmIdentifier sig_algo_inner;
- X509_DN dn_issuer, dn_subject;
- X509_Time start, end;
-
- BER_Decoder tbs_cert(tbs_bits);
-
- tbs_cert.decode_optional(version, ASN1_Tag(0),
- ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
- .decode(serial_bn)
- .decode(sig_algo_inner)
- .decode(dn_issuer)
- .start_cons(SEQUENCE)
- .decode(start)
- .decode(end)
- .verify_end()
- .end_cons()
- .decode(dn_subject);
-
- if(version > 2)
- throw Decoding_Error("Unknown X.509 cert version " + std::to_string(version));
- if(sig_algo != sig_algo_inner)
- throw Decoding_Error("Algorithm identifier mismatch");
-
- self_signed = (dn_subject == dn_issuer);
-
- subject.add(dn_subject.contents());
- issuer.add(dn_issuer.contents());
-
- subject.add("X509.Certificate.dn_bits", ASN1::put_in_sequence(dn_subject.get_bits()));
- issuer.add("X509.Certificate.dn_bits", ASN1::put_in_sequence(dn_issuer.get_bits()));
-
- BER_Object public_key = tbs_cert.get_next_object();
- if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED)
- throw BER_Bad_Tag("X509_Certificate: Unexpected tag for public key",
- public_key.type_tag, public_key.class_tag);
-
- std::vector<byte> v2_issuer_key_id, v2_subject_key_id;
-
- tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1);
- tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2);
-
- BER_Object v3_exts_data = tbs_cert.get_next_object();
- if(v3_exts_data.type_tag == 3 &&
- v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC))
- {
- Extensions extensions;
-
- BER_Decoder(v3_exts_data.value).decode(extensions).verify_end();
-
- extensions.contents_to(subject, issuer);
- }
- else if(v3_exts_data.type_tag != NO_OBJECT)
- throw BER_Bad_Tag("Unknown tag in X.509 cert",
- v3_exts_data.type_tag, v3_exts_data.class_tag);
-
- if(tbs_cert.more_items())
- throw Decoding_Error("TBSCertificate has more items that expected");
-
- subject.add("X509.Certificate.version", version);
- subject.add("X509.Certificate.serial", BigInt::encode(serial_bn));
- subject.add("X509.Certificate.start", start.readable_string());
- subject.add("X509.Certificate.end", end.readable_string());
-
- issuer.add("X509.Certificate.v2.key_id", v2_issuer_key_id);
- subject.add("X509.Certificate.v2.key_id", v2_subject_key_id);
-
- subject.add("X509.Certificate.public_key",
- hex_encode(public_key.value));
-
- if(self_signed && version == 0)
- {
- subject.add("X509v3.BasicConstraints.is_ca", 1);
- subject.add("X509v3.BasicConstraints.path_constraint", Cert_Extension::NO_CERT_PATH_LIMIT);
- }
-
- if(is_CA_cert() &&
- !subject.has_value("X509v3.BasicConstraints.path_constraint"))
- {
- const size_t limit = (x509_version() < 3) ?
- Cert_Extension::NO_CERT_PATH_LIMIT : 0;
-
- subject.add("X509v3.BasicConstraints.path_constraint", limit);
- }
- }
-
-/*
-* Return the X.509 version in use
-*/
-u32bit X509_Certificate::x509_version() const
- {
- return (subject.get1_u32bit("X509.Certificate.version") + 1);
- }
-
-/*
-* Return the time this cert becomes valid
-*/
-std::string X509_Certificate::start_time() const
- {
- return subject.get1("X509.Certificate.start");
- }
-
-/*
-* Return the time this cert becomes invalid
-*/
-std::string X509_Certificate::end_time() const
- {
- return subject.get1("X509.Certificate.end");
- }
-
-/*
-* Return information about the subject
-*/
-std::vector<std::string>
-X509_Certificate::subject_info(const std::string& what) const
- {
- return subject.get(X509_DN::deref_info_field(what));
- }
-
-/*
-* Return information about the issuer
-*/
-std::vector<std::string>
-X509_Certificate::issuer_info(const std::string& what) const
- {
- return issuer.get(X509_DN::deref_info_field(what));
- }
-
-/*
-* Return the public key in this certificate
-*/
-Public_Key* X509_Certificate::subject_public_key() const
- {
- return X509::load_key(
- ASN1::put_in_sequence(this->subject_public_key_bits()));
- }
-
-std::vector<byte> X509_Certificate::subject_public_key_bits() const
- {
- return hex_decode(subject.get1("X509.Certificate.public_key"));
- }
-
-/*
-* Check if the certificate is for a CA
-*/
-bool X509_Certificate::is_CA_cert() const
- {
- if(!subject.get1_u32bit("X509v3.BasicConstraints.is_ca"))
- return false;
-
- return allowed_usage(KEY_CERT_SIGN);
- }
-
-bool X509_Certificate::allowed_usage(Key_Constraints usage) const
- {
- if(constraints() == NO_CONSTRAINTS)
- return true;
- return (constraints() & usage);
- }
-
-bool X509_Certificate::allowed_usage(const std::string& usage) const
- {
- for(auto constraint : ex_constraints())
- if(constraint == usage)
- return true;
-
- return false;
- }
-
-/*
-* Return the path length constraint
-*/
-u32bit X509_Certificate::path_limit() const
- {
- return subject.get1_u32bit("X509v3.BasicConstraints.path_constraint", 0);
- }
-
-/*
-* Return the key usage constraints
-*/
-Key_Constraints X509_Certificate::constraints() const
- {
- return Key_Constraints(subject.get1_u32bit("X509v3.KeyUsage",
- NO_CONSTRAINTS));
- }
-
-/*
-* Return the list of extended key usage OIDs
-*/
-std::vector<std::string> X509_Certificate::ex_constraints() const
- {
- return lookup_oids(subject.get("X509v3.ExtendedKeyUsage"));
- }
-
-/*
-* Return the list of certificate policies
-*/
-std::vector<std::string> X509_Certificate::policies() const
- {
- return lookup_oids(subject.get("X509v3.CertificatePolicies"));
- }
-
-std::string X509_Certificate::ocsp_responder() const
- {
- return subject.get1("OCSP.responder", "");
- }
-
-std::string X509_Certificate::crl_distribution_point() const
- {
- return subject.get1("CRL.DistributionPoint", "");
- }
-
-/*
-* Return the authority key id
-*/
-std::vector<byte> X509_Certificate::authority_key_id() const
- {
- return issuer.get1_memvec("X509v3.AuthorityKeyIdentifier");
- }
-
-/*
-* Return the subject key id
-*/
-std::vector<byte> X509_Certificate::subject_key_id() const
- {
- return subject.get1_memvec("X509v3.SubjectKeyIdentifier");
- }
-
-/*
-* Return the certificate serial number
-*/
-std::vector<byte> X509_Certificate::serial_number() const
- {
- return subject.get1_memvec("X509.Certificate.serial");
- }
-
-/*
-* Return the distinguished name of the issuer
-*/
-X509_DN X509_Certificate::issuer_dn() const
- {
- return create_dn(issuer);
- }
-
-std::vector<byte> X509_Certificate::raw_issuer_dn() const
- {
- return issuer.get1_memvec("X509.Certificate.dn_bits");
- }
-
-/*
-* Return the distinguished name of the subject
-*/
-X509_DN X509_Certificate::subject_dn() const
- {
- return create_dn(subject);
- }
-
-std::vector<byte> X509_Certificate::raw_subject_dn() const
- {
- return subject.get1_memvec("X509.Certificate.dn_bits");
- }
-
-namespace {
-
-bool cert_subject_dns_match(const std::string& name,
- const std::vector<std::string>& cert_names)
- {
- for(size_t i = 0; i != cert_names.size(); ++i)
- {
- const std::string cn = cert_names[i];
-
- if(cn == name)
- return true;
-
- /*
- * Possible wildcard match. We only support the most basic form of
- * cert wildcarding ala RFC 2595
- */
- if(cn.size() > 2 && cn[0] == '*' && cn[1] == '.' && name.size() > cn.size())
- {
- const std::string base = cn.substr(1, std::string::npos);
-
- if(name.compare(name.size() - base.size(), base.size(), base) == 0)
- return true;
- }
- }
-
- return false;
- }
-
-}
-
-std::string X509_Certificate::fingerprint(const std::string& hash_name) const
- {
- std::unique_ptr<HashFunction> hash(get_hash(hash_name));
- hash->update(this->BER_encode());
- const auto hex_print = hex_encode(hash->final());
-
- std::string formatted_print;
-
- for(size_t i = 0; i != hex_print.size(); i += 2)
- {
- formatted_print.push_back(hex_print[i]);
- formatted_print.push_back(hex_print[i+1]);
-
- if(i != hex_print.size() - 2)
- formatted_print.push_back(':');
- }
-
- return formatted_print;
- }
-
-bool X509_Certificate::matches_dns_name(const std::string& name) const
- {
- if(name == "")
- return false;
-
- if(cert_subject_dns_match(name, subject_info("DNS")))
- return true;
-
- if(cert_subject_dns_match(name, subject_info("Name")))
- return true;
-
- return false;
- }
-
-/*
-* Compare two certificates for equality
-*/
-bool X509_Certificate::operator==(const X509_Certificate& other) const
- {
- return (sig == other.sig &&
- sig_algo == other.sig_algo &&
- self_signed == other.self_signed &&
- issuer == other.issuer &&
- subject == other.subject);
- }
-
-bool X509_Certificate::operator<(const X509_Certificate& other) const
- {
- /* If signature values are not equal, sort by lexicographic ordering of that */
- if(sig != other.sig)
- {
- if(sig < other.sig)
- return true;
- return false;
- }
-
- // Then compare the signed contents
- return tbs_bits < other.tbs_bits;
- }
-
-/*
-* X.509 Certificate Comparison
-*/
-bool operator!=(const X509_Certificate& cert1, const X509_Certificate& cert2)
- {
- return !(cert1 == cert2);
- }
-
-std::string X509_Certificate::to_string() const
- {
- const char* dn_fields[] = { "Name",
- "Email",
- "Organization",
- "Organizational Unit",
- "Locality",
- "State",
- "Country",
- "IP",
- "DNS",
- "URI",
- "PKIX.XMPPAddr",
- nullptr };
-
- std::ostringstream out;
-
- for(size_t i = 0; dn_fields[i]; ++i)
- {
- const std::vector<std::string> vals = this->subject_info(dn_fields[i]);
-
- if(vals.empty())
- continue;
-
- out << "Subject " << dn_fields[i] << ":";
- for(size_t j = 0; j != vals.size(); ++j)
- out << " " << vals[j];
- out << "\n";
- }
-
- for(size_t i = 0; dn_fields[i]; ++i)
- {
- const std::vector<std::string> vals = this->issuer_info(dn_fields[i]);
-
- if(vals.empty())
- continue;
-
- out << "Issuer " << dn_fields[i] << ":";
- for(size_t j = 0; j != vals.size(); ++j)
- out << " " << vals[j];
- out << "\n";
- }
-
- out << "Version: " << this->x509_version() << "\n";
-
- out << "Not valid before: " << this->start_time() << "\n";
- out << "Not valid after: " << this->end_time() << "\n";
-
- out << "Constraints:\n";
- Key_Constraints constraints = this->constraints();
- if(constraints == NO_CONSTRAINTS)
- out << " None\n";
- else
- {
- if(constraints & DIGITAL_SIGNATURE)
- out << " Digital Signature\n";
- if(constraints & NON_REPUDIATION)
- out << " Non-Repuidation\n";
- if(constraints & KEY_ENCIPHERMENT)
- out << " Key Encipherment\n";
- if(constraints & DATA_ENCIPHERMENT)
- out << " Data Encipherment\n";
- if(constraints & KEY_AGREEMENT)
- out << " Key Agreement\n";
- if(constraints & KEY_CERT_SIGN)
- out << " Cert Sign\n";
- if(constraints & CRL_SIGN)
- out << " CRL Sign\n";
- }
-
- std::vector<std::string> policies = this->policies();
- if(!policies.empty())
- {
- out << "Policies: " << "\n";
- for(size_t i = 0; i != policies.size(); i++)
- out << " " << policies[i] << "\n";
- }
-
- std::vector<std::string> ex_constraints = this->ex_constraints();
- if(!ex_constraints.empty())
- {
- out << "Extended Constraints:\n";
- for(size_t i = 0; i != ex_constraints.size(); i++)
- out << " " << ex_constraints[i] << "\n";
- }
-
- if(ocsp_responder() != "")
- out << "OCSP responder " << ocsp_responder() << "\n";
- if(crl_distribution_point() != "")
- out << "CRL " << crl_distribution_point() << "\n";
-
- out << "Signature algorithm: " <<
- OIDS::lookup(this->signature_algorithm().oid) << "\n";
-
- out << "Serial number: " << hex_encode(this->serial_number()) << "\n";
-
- if(this->authority_key_id().size())
- out << "Authority keyid: " << hex_encode(this->authority_key_id()) << "\n";
-
- if(this->subject_key_id().size())
- out << "Subject keyid: " << hex_encode(this->subject_key_id()) << "\n";
-
- std::unique_ptr<X509_PublicKey> pubkey(this->subject_public_key());
- out << "Public Key:\n" << X509::PEM_encode(*pubkey);
-
- return out.str();
- }
-
-/*
-* Create and populate a X509_DN
-*/
-X509_DN create_dn(const Data_Store& info)
- {
- auto names = info.search_for(
- [](const std::string& key, const std::string&)
- {
- return (key.find("X520.") != std::string::npos);
- });
-
- X509_DN dn;
-
- for(auto i = names.begin(); i != names.end(); ++i)
- dn.add_attribute(i->first, i->second);
-
- return dn;
- }
-
-/*
-* Create and populate an AlternativeName
-*/
-AlternativeName create_alt_name(const Data_Store& info)
- {
- auto names = info.search_for(
- [](const std::string& key, const std::string&)
- {
- return (key == "RFC822" ||
- key == "DNS" ||
- key == "URI" ||
- key == "IP");
- });
-
- AlternativeName alt_name;
-
- for(auto i = names.begin(); i != names.end(); ++i)
- alt_name.add_attribute(i->first, i->second);
-
- return alt_name;
- }
-
-}