diff options
author | Jack Lloyd <[email protected]> | 2015-12-19 15:36:40 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2015-12-19 15:36:40 -0500 |
commit | b48e6fb097c62bb246629ee7a182c57e497e4130 (patch) | |
tree | 0cb8ea2d05a89f5e90467f323ae56268d4d3480e /src/cli/x509.cpp | |
parent | d774a9edc46ffcebb28205a678058f083ea75c28 (diff) |
CLI rewrite
The command line tools' origin as a collection of examples and test
programs glued together led to some unfortunate problems; lots of
hardcoded values, missing parameters, and obsolete crypto.
Adds a small library for writing command line programs of the sort
needed here (cli.h), which cuts the length of many of the commands in
half and makes commands more pleasant to write and extend.
Generalizes a lot of the commands also, eg previously only
signing/verification with DSA/SHA-1 was included!
Removes the fuzzer entry point since that's fairly useless outside of
an instrumented build.
Removes the in-library API for benchmarking.
Diffstat (limited to 'src/cli/x509.cpp')
-rw-r--r-- | src/cli/x509.cpp | 224 |
1 files changed, 224 insertions, 0 deletions
diff --git a/src/cli/x509.cpp b/src/cli/x509.cpp new file mode 100644 index 000000000..add73a466 --- /dev/null +++ b/src/cli/x509.cpp @@ -0,0 +1,224 @@ +/* +* (C) 2010,2014,2015 Jack Lloyd +* +* Botan is released under the Simplified BSD License (see license.txt) +*/ + +#include "cli.h" + +#if defined(BOTAN_HAS_X509_CERTIFICATES) + +#include <botan/auto_rng.h> +#include <botan/certstor.h> +#include <botan/pkcs8.h> +#include <botan/x509_ca.h> +#include <botan/x509cert.h> +#include <botan/x509path.h> +#include <botan/x509self.h> + +#if defined(BOTAN_HAS_OCSP) + #include <botan/ocsp.h> +#endif + +namespace Botan_CLI { + +class Sign_Cert : public Command + { + public: + Sign_Cert() : Command("sign_cert --ca-key-pass= --hash=SHA-256 " + "--duration=365 ca_cert ca_key pkcs10_req") {} + + void go() override + { + Botan::AutoSeeded_RNG rng; + + Botan::X509_Certificate ca_cert(get_arg("ca_cert")); + + std::unique_ptr<Botan::PKCS8_PrivateKey> key( + Botan::PKCS8::load_key(get_arg("ca_key"), + rng, + get_arg("ca_key_pass"))); + + if(!key) + throw CLI_Error("Failed to load key from " + get_arg("ca_key")); + + Botan::X509_CA ca(ca_cert, *key, get_arg("hash")); + + Botan::PKCS10_Request req(get_arg("pkcs10_req")); + + auto now = std::chrono::system_clock::now(); + + Botan::X509_Time start_time(now); + + typedef std::chrono::duration<int, std::ratio<86400>> days; + + Botan::X509_Time end_time(now + days(get_arg_sz("duration"))); + + Botan::X509_Certificate new_cert = ca.sign_request(req, rng, + start_time, end_time); + + output() << new_cert.PEM_encode(); + } + }; + +BOTAN_REGISTER_COMMAND(Sign_Cert); + +class Cert_Info : public Command + { + public: + Cert_Info() : Command("cert_info file") {} + + void go() override + { + Botan::X509_Certificate cert(get_arg("file")); + output() << cert.to_string() << "\n"; + } + }; + +BOTAN_REGISTER_COMMAND(Cert_Info); + +#if defined(BOTAN_HAS_OCSP) +class OCSP_Check : public Command + { + public: + OCSP_Check() : Command("ocsp_check subject issuer") {} + + void go() override + { + Botan::X509_Certificate subject(get_arg("subject")); + Botan::X509_Certificate issuer(get_arg("issuer")); + + Botan::Certificate_Store_In_Memory cas; + cas.add_certificate(issuer); + Botan::OCSP::Response resp = Botan::OCSP::online_check(issuer, subject, &cas); + + auto status = resp.status_for(issuer, subject); + + if(status == Botan::Certificate_Status_Code::VERIFIED) + { + output() << "OCSP check OK\n"; + } + else + { + output() << "OCSP check failed " << + Botan::Path_Validation_Result::status_string(status) << "\n"; + } + } + }; + +BOTAN_REGISTER_COMMAND(OCSP_Check); + +#endif // OCSP + +class Cert_Verify : public Command + { + public: + Cert_Verify() : Command("cert_verify subject *ca_certs") {} + + void go() override + { + Botan::X509_Certificate subject_cert(get_arg("subject")); + Botan::Certificate_Store_In_Memory trusted; + + for(auto&& certfile : get_arg_list("ca_certs")) + { + trusted.add_certificate(Botan::X509_Certificate(certfile)); + } + + Botan::Path_Validation_Restrictions restrictions; + + Botan::Path_Validation_Result result = + Botan::x509_path_validate(subject_cert, + restrictions, + trusted); + + if(result.successful_validation()) + { + output() << "Certificate passes validation checks\n"; + } + else + { + output() << "Certificate did not validate - " << result.result_string() << "\n"; + } + } + }; + +BOTAN_REGISTER_COMMAND(Cert_Verify); + +class Gen_Self_Signed : public Command + { + public: + Gen_Self_Signed() : Command("gen_self_signed key CN --country= --dns= " + "--organization= --email= --key-pass= --ca --hash=SHA-256") {} + + void go() override + { + Botan::AutoSeeded_RNG rng; + + std::unique_ptr<Botan::Private_Key> key( + Botan::PKCS8::load_key(get_arg("key"), + rng, + get_arg("key-pass"))); + + if(!key) + throw CLI_Error("Failed to load key from " + get_arg("key")); + + Botan::X509_Cert_Options opts; + + opts.common_name = get_arg("CN"); + opts.country = get_arg("country"); + opts.organization = get_arg("organization"); + opts.email = get_arg("email"); + opts.dns = get_arg("dns"); + + if(flag_set("ca")) + opts.CA_key(); + + Botan::X509_Certificate cert = + Botan::X509::create_self_signed_cert(opts, *key, get_arg("hash"), rng); + + output() << cert.PEM_encode(); + } + }; + +BOTAN_REGISTER_COMMAND(Gen_Self_Signed); + +class Generate_PKCS10 : public Command + { + public: + Generate_PKCS10() : Command("gen_pkcs10 key CN --country= --organization= " + "--email= --key-pass= --hash=SHA-256") {} + + void go() override + { + Botan::AutoSeeded_RNG rng; + + std::unique_ptr<Botan::Private_Key> key( + Botan::PKCS8::load_key(get_arg("key"), + rng, + get_arg("key-pass"))); + + if(!key) + throw CLI_Error("Failed to load key from " + get_arg("key")); + + Botan::X509_Cert_Options opts; + + opts.common_name = get_arg("CN"); + opts.country = get_arg("country"); + opts.organization = get_arg("organization"); + opts.email = get_arg("email"); + + Botan::PKCS10_Request req = + Botan::X509::create_cert_req(opts, *key, + get_arg("hash"), + rng); + + output() << req.PEM_encode(); + } + }; + +BOTAN_REGISTER_COMMAND(Generate_PKCS10); + +} + +#endif |