aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorlloyd <[email protected]>2014-01-01 23:32:24 +0000
committerlloyd <[email protected]>2014-01-01 23:32:24 +0000
commit7323f3ff83ff2199b1090f9d5f729b08ccac3151 (patch)
tree84edcf72e8837ac328aae505f5059c95f4e459a5 /src
parent0c7008498790caea563ed3601df1943f8f7b6269 (diff)
Move base64, bzip, ca, and tls examples
Diffstat (limited to 'src')
-rw-r--r--src/apps/apps.h25
-rw-r--r--src/apps/asn1.cpp (renamed from src/examples/asn1.cpp)4
-rw-r--r--src/apps/base64.cpp85
-rw-r--r--src/apps/bcrypt.cpp (renamed from src/examples/bcrypt.cpp)4
-rw-r--r--src/apps/bzip.cpp115
-rw-r--r--src/apps/ca.cpp63
-rw-r--r--src/apps/credentials.h294
-rw-r--r--src/apps/factor.cpp (renamed from src/examples/factor.cpp)4
-rw-r--r--src/apps/fpe.cpp (renamed from src/examples/fpe.cpp)4
-rw-r--r--src/apps/hash.cpp58
-rw-r--r--src/apps/keygen.cpp53
-rw-r--r--src/apps/pkcs10.cpp48
-rw-r--r--src/apps/read_ssh.cpp (renamed from src/examples/read_ssh.cpp)4
-rw-r--r--src/apps/self_sig.cpp (renamed from src/examples/self_sig.cpp)4
-rw-r--r--src/apps/tls_client.cpp263
-rw-r--r--src/apps/tls_server.cpp262
-rw-r--r--src/apps/x509print.cpp (renamed from src/examples/x509print.cpp)4
-rw-r--r--src/build-data/cc/gcc.txt2
-rw-r--r--src/examples/examples.h17
-rw-r--r--src/main.cpp116
-rw-r--r--src/speed/speed.cpp40
-rw-r--r--src/speed/speed.h2
22 files changed, 1367 insertions, 104 deletions
diff --git a/src/apps/apps.h b/src/apps/apps.h
new file mode 100644
index 000000000..babbea080
--- /dev/null
+++ b/src/apps/apps.h
@@ -0,0 +1,25 @@
+
+#include "../common.h"
+#include <botan/auto_rng.h>
+#include <botan/hex.h>
+#include <iostream>
+
+using namespace Botan;
+
+#define DEFINE_EXAMPLE(cmd) int cmd (int argc, char* argv[]);
+
+DEFINE_EXAMPLE(asn1);
+DEFINE_EXAMPLE(bcrypt);
+DEFINE_EXAMPLE(bzip);
+DEFINE_EXAMPLE(base64);
+DEFINE_EXAMPLE(ca);
+DEFINE_EXAMPLE(factor);
+DEFINE_EXAMPLE(fpe);
+DEFINE_EXAMPLE(hash);
+DEFINE_EXAMPLE(keygen);
+DEFINE_EXAMPLE(pkcs10);
+DEFINE_EXAMPLE(read_ssh);
+DEFINE_EXAMPLE(self_sig);
+DEFINE_EXAMPLE(tls_client);
+DEFINE_EXAMPLE(tls_server);
+DEFINE_EXAMPLE(x509);
diff --git a/src/examples/asn1.cpp b/src/apps/asn1.cpp
index 40f597fc3..447462ae0 100644
--- a/src/examples/asn1.cpp
+++ b/src/apps/asn1.cpp
@@ -1,4 +1,4 @@
-#include "examples.h"
+#include "apps.h"
#include <botan/bigint.h>
#include <botan/der_enc.h>
@@ -47,7 +47,7 @@ std::string url_encode(const std::vector<byte>& in)
}
-int asn1_example(int argc, char* argv[])
+int asn1(int argc, char* argv[])
{
if(argc != 2)
{
diff --git a/src/apps/base64.cpp b/src/apps/base64.cpp
new file mode 100644
index 000000000..697fcb42c
--- /dev/null
+++ b/src/apps/base64.cpp
@@ -0,0 +1,85 @@
+/*
+* Encode/decode base64 strings
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include "apps.h"
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+#include <cstring>
+#include <cstdlib>
+#include <botan/b64_filt.h>
+#include <botan/pipe.h>
+
+int base64(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0] << " [-w] [-c n] [-e|-d] files...\n"
+ " -e : Encode input to base64 strings (default) \n"
+ " -d : Decode base64 input\n"
+ " -w : Wrap lines\n"
+ " -c n: Wrap lines at column n, default 78\n";
+ return 1;
+ }
+
+ int column = 78;
+ bool wrap = false;
+ bool encoding = true;
+ std::vector<std::string> files;
+
+ for(int j = 1; argv[j] != nullptr; j++)
+ {
+ std::string this_arg = argv[j];
+
+ if(this_arg == "-w")
+ wrap = true;
+ else if(this_arg == "-e");
+ else if(this_arg == "-d")
+ encoding = false;
+ else if(this_arg == "-c")
+ {
+ if(argv[j+1])
+ { column = atoi(argv[j+1]); j++; }
+ else
+ {
+ std::cout << "No argument for -c option" << std::endl;
+ return 1;
+ }
+ }
+ else files.push_back(argv[j]);
+ }
+
+ for(unsigned int j = 0; j != files.size(); j++)
+ {
+ std::istream* stream;
+ if(files[j] == "-") stream = &std::cin;
+ else stream = new std::ifstream(files[j].c_str());
+
+ if(!*stream)
+ {
+ std::cout << "ERROR, couldn't open " << files[j] << std::endl;
+ continue;
+ }
+
+ Botan::Filter* f = nullptr;
+
+ if(encoding)
+ f = new Botan::Base64_Encoder(wrap, column);
+ else
+ f = new Botan::Base64_Decoder;
+
+ Botan::Pipe pipe(f);
+ pipe.start_msg();
+ *stream >> pipe;
+ pipe.end_msg();
+ pipe.set_default_msg(j);
+ std::cout << pipe;
+ if(files[j] != "-") delete stream;
+ }
+ return 0;
+ }
diff --git a/src/examples/bcrypt.cpp b/src/apps/bcrypt.cpp
index 50205cd4d..497111363 100644
--- a/src/examples/bcrypt.cpp
+++ b/src/apps/bcrypt.cpp
@@ -1,7 +1,7 @@
-#include "examples.h"
+#include "apps.h"
#include <botan/bcrypt.h>
-int bcrypt_example(int argc, char* argv[])
+int bcrypt(int argc, char* argv[])
{
if(argc == 2)
{
diff --git a/src/apps/bzip.cpp b/src/apps/bzip.cpp
new file mode 100644
index 000000000..94a8bdff7
--- /dev/null
+++ b/src/apps/bzip.cpp
@@ -0,0 +1,115 @@
+/*
+* Bzip2 Compression/Decompression
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include "apps.h"
+
+#include <string>
+#include <cstring>
+#include <vector>
+#include <fstream>
+#include <iostream>
+#include <botan/botan.h>
+
+/*
+* If Bzip2 isn't included, we know nothing works at compile time, but
+* we wait to fail at runtime. Otherwise I would get 2-3 mails a month
+* about how this was failing to compile (even with an informative
+* #error message explaining the situation) because bzip2 wasn't
+* included in the build.
+*/
+
+#if defined(BOTAN_HAS_COMPRESSOR_BZIP2)
+ #include <botan/bzip2.h>
+#endif
+
+const std::string SUFFIX = ".bz2";
+
+int bzip(int argc, char* argv[])
+ {
+ if(argc < 2)
+ {
+ std::cout << "Usage: " << argv[0]
+ << " [-s] [-d] [-1...9] <filenames>" << std::endl;
+ return 1;
+ }
+
+#ifdef BOTAN_HAS_COMPRESSOR_BZIP2
+ std::vector<std::string> files;
+ bool decompress = false, small = false;
+ int level = 9;
+
+ for(int j = 1; argv[j] != 0; j++)
+ {
+ if(std::strcmp(argv[j], "-d") == 0) { decompress = true; continue; }
+ if(std::strcmp(argv[j], "-s") == 0) { small = true; continue; }
+ if(std::strcmp(argv[j], "-1") == 0) { level = 1; continue; }
+ if(std::strcmp(argv[j], "-2") == 0) { level = 2; continue; }
+ if(std::strcmp(argv[j], "-3") == 0) { level = 3; continue; }
+ if(std::strcmp(argv[j], "-4") == 0) { level = 4; continue; }
+ if(std::strcmp(argv[j], "-5") == 0) { level = 5; continue; }
+ if(std::strcmp(argv[j], "-6") == 0) { level = 6; continue; }
+ if(std::strcmp(argv[j], "-7") == 0) { level = 7; continue; }
+ if(std::strcmp(argv[j], "-8") == 0) { level = 8; continue; }
+ if(std::strcmp(argv[j], "-9") == 0) { level = 9; continue; }
+ files.push_back(argv[j]);
+ }
+
+ try {
+
+ Botan::Filter* bzip = 0;
+ if(decompress)
+ bzip = new Botan::Bzip_Decompression(small);
+ else
+ bzip = new Botan::Bzip_Compression(level);
+
+ Botan::Pipe pipe(bzip);
+
+ for(unsigned int j = 0; j != files.size(); j++)
+ {
+ std::string infile = files[j], outfile = files[j];
+ if(!decompress)
+ outfile = outfile += SUFFIX;
+ else
+ outfile = outfile.replace(outfile.find(SUFFIX),
+ SUFFIX.length(), "");
+
+ std::ifstream in(infile.c_str(), std::ios::binary);
+ std::ofstream out(outfile.c_str(), std::ios::binary);
+ if(!in)
+ {
+ std::cout << "ERROR: could not read " << infile << std::endl;
+ continue;
+ }
+ if(!out)
+ {
+ std::cout << "ERROR: could not write " << outfile << std::endl;
+ continue;
+ }
+
+ pipe.start_msg();
+ in >> pipe;
+ pipe.end_msg();
+ pipe.set_default_msg(j);
+ out << pipe;
+
+ in.close();
+ out.close();
+ return 0;
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ return 1;
+ }
+#else
+
+ std::cout << "Sorry, support for bzip2 not compiled into Botan\n";
+#endif
+
+ return 1;
+ }
diff --git a/src/apps/ca.cpp b/src/apps/ca.cpp
new file mode 100644
index 000000000..881036fc8
--- /dev/null
+++ b/src/apps/ca.cpp
@@ -0,0 +1,63 @@
+
+#include "apps.h"
+#include <botan/x509_ca.h>
+using namespace Botan;
+
+#include <iostream>
+#include <memory>
+#include <chrono>
+
+int ca(int argc, char* argv[])
+ {
+ if(argc != 5)
+ {
+ std::cout << "Usage: " << argv[0] << " <passphrase> "
+ << "<ca cert> <ca key> <pkcs10>" << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ const std::string arg_passphrase = argv[1];
+ const std::string arg_ca_cert = argv[2];
+ const std::string arg_ca_key = argv[3];
+ const std::string arg_req_file = argv[4];
+
+ AutoSeeded_RNG rng;
+
+ X509_Certificate ca_cert(arg_ca_cert);
+
+ std::auto_ptr<PKCS8_PrivateKey> privkey(
+ PKCS8::load_key(arg_ca_key, rng, arg_passphrase)
+ );
+
+ X509_CA ca(ca_cert, *privkey, "SHA-256");
+
+ // got a request
+ PKCS10_Request req(arg_req_file);
+
+ // you would insert checks here, and perhaps modify the request
+ // (this example should be extended to show how)
+
+ // now sign the request
+ auto now = std::chrono::system_clock::now();
+
+ X509_Time start_time(now);
+
+ typedef std::chrono::duration<int, std::ratio<31556926>> years;
+
+ X509_Time end_time(now + years(1));
+
+ X509_Certificate new_cert = ca.sign_request(req, rng,
+ start_time, end_time);
+
+ // send the new cert back to the requestor
+ std::cout << new_cert.PEM_encode();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/src/apps/credentials.h b/src/apps/credentials.h
new file mode 100644
index 000000000..6c150f881
--- /dev/null
+++ b/src/apps/credentials.h
@@ -0,0 +1,294 @@
+
+#ifndef EXAMPLE_CREDENTIALS_MANAGER_H__
+#define EXAMPLE_CREDENTIALS_MANAGER_H__
+
+#include <botan/credentials_manager.h>
+#include <botan/x509self.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#include <botan/srp6.h>
+#include <botan/srp6_files.h>
+#include <botan/ecdsa.h>
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+inline bool value_exists(const std::vector<std::string>& vec,
+ const std::string& val)
+ {
+ for(size_t i = 0; i != vec.size(); ++i)
+ if(vec[i] == val)
+ return true;
+ return false;
+ }
+
+class Credentials_Manager_Simple : public Botan::Credentials_Manager
+ {
+ public:
+ Credentials_Manager_Simple(Botan::RandomNumberGenerator& rng) :
+ rng(rng)
+ {
+ m_certstores.push_back(new Botan::Certificate_Store_In_Memory("/usr/share/ca-certificates"));
+ }
+
+ std::string srp_identifier(const std::string& type,
+ const std::string& hostname)
+ {
+ if(type == "tls-client" && hostname == "srp-host")
+ return "user";
+ return "";
+ }
+
+ bool attempt_srp(const std::string& type,
+ const std::string& hostname)
+ {
+ if(hostname == "srp-host" && (type == "tls-client" || type == "tls-server"))
+ return true;
+ return false;
+ }
+
+ std::vector<Botan::Certificate_Store*>
+ trusted_certificate_authorities(const std::string& type,
+ const std::string& /*hostname*/)
+ {
+ // don't ask for client cert
+ if(type == "tls-server")
+ return std::vector<Botan::Certificate_Store*>();
+
+ return m_certstores;
+ }
+
+ void verify_certificate_chain(
+ const std::string& type,
+ const std::string& purported_hostname,
+ const std::vector<Botan::X509_Certificate>& cert_chain)
+ {
+ try
+ {
+ Botan::Credentials_Manager::verify_certificate_chain(type,
+ purported_hostname,
+ cert_chain);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Certificate verification failed - " << e.what() << " - but will ignore\n";
+ }
+ }
+
+ std::string srp_password(const std::string& type,
+ const std::string& hostname,
+ const std::string& identifier)
+ {
+ if(type == "tls-client" && hostname == "srp-host" && identifier == "user")
+ return "password";
+
+ return "";
+ }
+
+ bool srp_verifier(const std::string& /*type*/,
+ const std::string& context,
+ const std::string& identifier,
+ std::string& group_id,
+ Botan::BigInt& verifier,
+ std::vector<Botan::byte>& salt,
+ bool generate_fake_on_unknown)
+ {
+
+ std::string pass = srp_password("tls-client", context, identifier);
+ if(pass == "")
+ {
+ if(!generate_fake_on_unknown)
+ return false;
+
+ pass.resize(16);
+ rng.randomize(reinterpret_cast<byte*>(&pass[0]), pass.size());
+ }
+
+ group_id = "modp/srp/2048";
+
+ salt.resize(16);
+ rng.randomize(&salt[0], salt.size());
+
+ verifier = Botan::generate_srp6_verifier(identifier,
+ pass,
+ salt,
+ group_id,
+ "SHA-1");
+
+ return true;
+ }
+
+ std::string psk_identity_hint(const std::string&,
+ const std::string&)
+ {
+ return "";
+ }
+
+ std::string psk_identity(const std::string&, const std::string&,
+ const std::string& identity_hint)
+ {
+ std::cout << "Server sent PSK identity_hint " << identity_hint << "\n";
+ return "Client_identity";
+ }
+
+ Botan::SymmetricKey psk(const std::string& type, const std::string& context,
+ const std::string& identity)
+ {
+ if(type == "tls-server" && context == "session-ticket")
+ {
+ if(session_ticket_key.length() == 0)
+ session_ticket_key = Botan::SymmetricKey(rng, 32);
+ return session_ticket_key;
+ }
+
+ if(identity == "Client_identity")
+ return Botan::SymmetricKey("b5a72e1387552e6dc10766dc0eda12961f5b21e17f98ef4c41e6572e53bd7527");
+ if(identity == "lloyd")
+ return Botan::SymmetricKey("85b3c1b7dc62b507636ac767999c9630");
+
+ throw Botan::Internal_Error("No PSK set for " + identity);
+ }
+
+ std::pair<Botan::X509_Certificate,Botan::Private_Key*>
+ load_or_make_cert(const std::string& hostname,
+ const std::string& key_type,
+ Botan::RandomNumberGenerator& rng)
+ {
+ using namespace Botan;
+
+ const std::string key_fsname_prefix = hostname + "." + key_type + ".";
+ const std::string key_file_name = key_fsname_prefix + "key";
+ const std::string cert_file_name = key_fsname_prefix + "crt";
+
+ try
+ {
+ X509_Certificate cert(cert_file_name);
+ Private_Key* key = PKCS8::load_key(key_file_name, rng);
+
+ //std::cout << "Loaded existing key/cert from " << cert_file_name << " and " << key_file_name << "\n";
+
+ return std::make_pair(cert, key);
+ }
+ catch(...) {}
+
+ // Failed. Instead, make a new one
+
+ std::cout << "Creating new certificate for identifier '" << hostname << "'\n";
+
+ X509_Cert_Options opts;
+
+ opts.common_name = hostname;
+ opts.country = "US";
+ opts.email = "root@" + hostname;
+ opts.dns = hostname;
+
+ std::unique_ptr<Private_Key> key;
+ if(key_type == "rsa")
+ key.reset(new RSA_PrivateKey(rng, 1024));
+ else if(key_type == "dsa")
+ key.reset(new DSA_PrivateKey(rng, DL_Group("dsa/jce/1024")));
+ else if(key_type == "ecdsa")
+ key.reset(new ECDSA_PrivateKey(rng, EC_Group("secp256r1")));
+ else
+ throw std::runtime_error("Don't know what to do about key type '" + key_type + "'");
+
+ X509_Certificate cert =
+ X509::create_self_signed_cert(opts, *key, "SHA-1", rng);
+
+ // Now save both
+
+ std::cout << "Saving new " << key_type << " key to " << key_file_name << "\n";
+ std::ofstream key_file(key_file_name.c_str());
+ key_file << PKCS8::PEM_encode(*key, rng, "");
+ key_file.close();
+
+ std::cout << "Saving new " << key_type << " cert to " << key_file_name << "\n";
+ std::ofstream cert_file(cert_file_name.c_str());
+ cert_file << cert.PEM_encode() << "\n";
+ cert_file.close();
+
+ return std::make_pair(cert, key.release());
+ }
+
+ std::vector<Botan::X509_Certificate> cert_chain(
+ const std::vector<std::string>& cert_key_types,
+ const std::string& type,
+ const std::string& context)
+ {
+ using namespace Botan;
+
+ std::vector<X509_Certificate> certs;
+
+ try
+ {
+ if(type == "tls-server")
+ {
+ const std::string hostname = (context == "" ? "localhost" : context);
+
+ if(hostname == "nosuchname")
+ return std::vector<Botan::X509_Certificate>();
+
+ for(auto i : certs_and_keys)
+ {
+ if(hostname != "" && !i.first.matches_dns_name(hostname))
+ continue;
+
+ if(!value_exists(cert_key_types, i.second->algo_name()))
+ continue;
+
+ certs.push_back(i.first);
+ }
+
+ if(!certs.empty())
+ return certs;
+
+ std::string key_name = "";
+
+ if(value_exists(cert_key_types, "RSA"))
+ key_name = "rsa";
+ else if(value_exists(cert_key_types, "DSA"))
+ key_name = "dsa";
+ else if(value_exists(cert_key_types, "ECDSA"))
+ key_name = "ecdsa";
+
+ std::pair<X509_Certificate, Private_Key*> cert_and_key =
+ load_or_make_cert(hostname, key_name, rng);
+
+ certs_and_keys[cert_and_key.first] = cert_and_key.second;
+ certs.push_back(cert_and_key.first);
+ }
+ else if(type == "tls-client")
+ {
+ X509_Certificate cert("user-rsa.crt");
+ Private_Key* key = PKCS8::load_key("user-rsa.key", rng);
+
+ certs_and_keys[cert] = key;
+ certs.push_back(cert);
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << "\n";
+ }
+
+ return certs;
+ }
+
+ Botan::Private_Key* private_key_for(const Botan::X509_Certificate& cert,
+ const std::string& /*type*/,
+ const std::string& /*context*/)
+ {
+ return certs_and_keys[cert];
+ }
+
+ private:
+ Botan::RandomNumberGenerator& rng;
+
+ Botan::SymmetricKey session_ticket_key;
+
+ std::map<Botan::X509_Certificate, Botan::Private_Key*> certs_and_keys;
+
+ std::vector<Botan::Certificate_Store*> m_certstores;
+ };
+
+#endif
diff --git a/src/examples/factor.cpp b/src/apps/factor.cpp
index 822b62b71..484f024d8 100644
--- a/src/examples/factor.cpp
+++ b/src/apps/factor.cpp
@@ -7,7 +7,7 @@
* primes, and Pollard's Rho algorithm
*/
-#include "examples.h"
+#include "apps.h"
#include <botan/reducer.h>
#include <botan/numthry.h>
@@ -121,7 +121,7 @@ std::vector<BigInt> factorize(const BigInt& n_in,
}
-int factor_example(int argc, char* argv[])
+int factor(int argc, char* argv[])
{
if(argc != 2)
{
diff --git a/src/examples/fpe.cpp b/src/apps/fpe.cpp
index cccb602fd..dd5b9b682 100644
--- a/src/examples/fpe.cpp
+++ b/src/apps/fpe.cpp
@@ -1,4 +1,4 @@
-#include "examples.h"
+#include "apps.h"
#include <botan/fpe_fe1.h>
#include <botan/sha160.h>
@@ -102,7 +102,7 @@ u64bit decrypt_cc_number(u64bit enc_cc,
}
-int fpe_example(int argc, char* argv[])
+int fpe(int argc, char* argv[])
{
if(argc != 4)
{
diff --git a/src/apps/hash.cpp b/src/apps/hash.cpp
new file mode 100644
index 000000000..c1e5aab3e
--- /dev/null
+++ b/src/apps/hash.cpp
@@ -0,0 +1,58 @@
+/*
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include "apps.h"
+#include <botan/lookup.h>
+#include <iostream>
+#include <fstream>
+
+using namespace Botan;
+
+int hash(int argc, char* argv[])
+ {
+ if(argc < 3)
+ {
+ std::cout << "Usage: " << argv[0] << " digest <filenames>" << std::endl;
+ return 1;
+ }
+
+ std::string hash = argv[1];
+ /* a couple of special cases, kind of a crock */
+ if(hash == "sha1") hash = "SHA-1";
+ if(hash == "md5") hash = "MD5";
+
+ try {
+ if(!have_hash(hash))
+ {
+ std::cout << "Unknown hash \"" << argv[1] << "\"" << std::endl;
+ return 1;
+ }
+
+ Pipe pipe(new Hash_Filter(hash), new Hex_Encoder);
+
+ int skipped = 0;
+ for(int j = 2; argv[j] != nullptr; j++)
+ {
+ std::ifstream file(argv[j], std::ios::binary);
+ if(!file)
+ {
+ std::cout << "ERROR: could not open " << argv[j] << std::endl;
+ skipped++;
+ continue;
+ }
+ pipe.start_msg();
+ file >> pipe;
+ pipe.end_msg();
+ pipe.set_default_msg(j-2-skipped);
+ std::cout << pipe << " " << argv[j] << std::endl;
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+ return 0;
+ }
diff --git a/src/apps/keygen.cpp b/src/apps/keygen.cpp
new file mode 100644
index 000000000..885364834
--- /dev/null
+++ b/src/apps/keygen.cpp
@@ -0,0 +1,53 @@
+#include "apps.h"
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cstdlib>
+#include <memory>
+
+#include <botan/rsa.h>
+using namespace Botan;
+
+int keygen(int argc, char* argv[])
+ {
+ if(argc != 2 && argc != 3)
+ {
+ std::cout << "Usage: " << argv[0] << " bitsize [passphrase]"
+ << std::endl;
+ return 1;
+ }
+
+ const size_t bits = std::atoi(argv[1]);
+ if(bits < 1024 || bits > 16384)
+ {
+ std::cout << "Invalid argument for bitsize" << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ std::ofstream pub("rsapub.pem");
+ std::ofstream priv("rsapriv.pem");
+ if(!priv || !pub)
+ {
+ std::cout << "Couldn't write output files" << std::endl;
+ return 1;
+ }
+
+ AutoSeeded_RNG rng;
+
+ RSA_PrivateKey key(rng, bits);
+ pub << X509::PEM_encode(key);
+
+ if(argc == 2)
+ priv << PKCS8::PEM_encode(key);
+ else
+ priv << PKCS8::PEM_encode(key, rng, argv[2]);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception caught: " << e.what() << std::endl;
+ }
+
+ return 0;
+ }
diff --git a/src/apps/pkcs10.cpp b/src/apps/pkcs10.cpp
new file mode 100644
index 000000000..6e36f73fb
--- /dev/null
+++ b/src/apps/pkcs10.cpp
@@ -0,0 +1,48 @@
+#include "apps.h"
+#include <botan/x509self.h>
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+#include <memory>
+
+int pkcs10(int argc, char* argv[])
+ {
+ if(argc != 6)
+ {
+ std::cout << "Usage: " << argv[0]
+ << " passphrase name country_code organization email" << std::endl;
+ return 1;
+ }
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ RSA_PrivateKey priv_key(rng, 1024);
+
+ std::ofstream key_file("private.pem");
+ key_file << PKCS8::PEM_encode(priv_key, rng, argv[1]);
+
+ X509_Cert_Options opts;
+
+ opts.common_name = argv[2];
+ opts.country = argv[3];
+ opts.organization = argv[4];
+ opts.email = argv[5];
+
+ PKCS10_Request req = X509::create_cert_req(opts, priv_key,
+ "SHA-256", rng);
+
+ std::ofstream req_file("req.pem");
+ req_file << req.PEM_encode();
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << std::endl;
+ return 1;
+ }
+ return 0;
+ }
diff --git a/src/examples/read_ssh.cpp b/src/apps/read_ssh.cpp
index 83f7ff89e..ce72fa064 100644
--- a/src/examples/read_ssh.cpp
+++ b/src/apps/read_ssh.cpp
@@ -8,7 +8,7 @@
* Example of reading SSH2 format public keys (see RFC 4716)
*/
-#include "examples.h"
+#include "apps.h"
#include <botan/x509_key.h>
#include <botan/filters.h>
@@ -111,7 +111,7 @@ Public_Key* read_ssh_pubkey(const std::string& file)
}
-int read_ssh_example(int argc, char* argv[])
+int read_ssh(int argc, char* argv[])
{
if(argc != 2)
{
diff --git a/src/examples/self_sig.cpp b/src/apps/self_sig.cpp
index 89d9f84e7..c4202442c 100644
--- a/src/examples/self_sig.cpp
+++ b/src/apps/self_sig.cpp
@@ -1,4 +1,4 @@
-#include "examples.h"
+#include "apps.h"
#include <botan/x509self.h>
#include <botan/rsa.h>
#include <botan/dsa.h>
@@ -8,7 +8,7 @@ using namespace Botan;
#include <fstream>
#include <memory>
-int self_sig_example(int argc, char* argv[])
+int self_sig(int argc, char* argv[])
{
if(argc != 7)
{
diff --git a/src/apps/tls_client.cpp b/src/apps/tls_client.cpp
new file mode 100644
index 000000000..24c8197f6
--- /dev/null
+++ b/src/apps/tls_client.cpp
@@ -0,0 +1,263 @@
+#include "apps.h"
+#include <botan/tls_client.h>
+#include <botan/pkcs8.h>
+#include <botan/hex.h>
+#include <stdio.h>
+#include <string>
+#include <iostream>
+#include <memory>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#if !defined(MSG_NOSIGNAL)
+ #define MSG_NOSIGNAL 0
+#endif
+
+#if defined(BOTAN_HAS_TLS_SQLITE3_SESSION_MANAGER)
+ #include <botan/tls_session_manager_sqlite.h>
+#endif
+
+#include "credentials.h"
+
+using namespace Botan;
+
+using namespace std::placeholders;
+
+namespace {
+
+int connect_to_host(const std::string& host, u16bit port, const std::string& transport)
+ {
+ hostent* host_addr = ::gethostbyname(host.c_str());
+
+ if(host_addr == 0)
+ throw std::runtime_error("gethostbyname failed for " + host);
+
+ if(host_addr->h_addrtype != AF_INET) // FIXME
+ throw std::runtime_error(host + " has IPv6 address");
+
+ int type = (transport == "tcp") ? SOCK_STREAM : SOCK_DGRAM;
+
+ int fd = ::socket(PF_INET, type, 0);
+ if(fd == -1)
+ throw std::runtime_error("Unable to acquire socket");
+
+ sockaddr_in socket_info;
+ ::memset(&socket_info, 0, sizeof(socket_info));
+ socket_info.sin_family = AF_INET;
+ socket_info.sin_port = htons(port);
+
+ ::memcpy(&socket_info.sin_addr,
+ host_addr->h_addr,
+ host_addr->h_length);
+
+ socket_info.sin_addr = *(struct in_addr*)host_addr->h_addr; // FIXME
+
+ if(::connect(fd, (sockaddr*)&socket_info, sizeof(struct sockaddr)) != 0)
+ {
+ ::close(fd);
+ throw std::runtime_error("connect failed");
+ }
+
+ return fd;
+ }
+
+bool handshake_complete(const TLS::Session& session)
+ {
+ std::cout << "Handshake complete, " << session.version().to_string()
+ << " using " << session.ciphersuite().to_string() << "\n";
+
+ if(!session.session_id().empty())
+ std::cout << "Session ID " << hex_encode(session.session_id()) << "\n";
+
+ if(!session.session_ticket().empty())
+ std::cout << "Session ticket " << hex_encode(session.session_ticket()) << "\n";
+
+ return true;
+ }
+
+void dgram_socket_write(int sockfd, const byte buf[], size_t length)
+ {
+ send(sockfd, buf, length, MSG_NOSIGNAL);
+ }
+
+void stream_socket_write(int sockfd, const byte buf[], size_t length)
+ {
+ size_t offset = 0;
+
+ while(length)
+ {
+ ssize_t sent = ::send(sockfd, (const char*)buf + offset,
+ length, MSG_NOSIGNAL);
+
+ if(sent == -1)
+ {
+ if(errno == EINTR)
+ sent = 0;
+ else
+ throw std::runtime_error("Socket::write: Socket write failed");
+ }
+
+ offset += sent;
+ length -= sent;
+ }
+ }
+
+bool got_alert = false;
+
+void alert_received(TLS::Alert alert, const byte [], size_t )
+ {
+ std::cout << "Alert: " << alert.type_string() << "\n";
+ got_alert = true;
+ }
+
+void process_data(const byte buf[], size_t buf_size)
+ {
+ for(size_t i = 0; i != buf_size; ++i)
+ std::cout << buf[i];
+ }
+
+std::string protocol_chooser(const std::vector<std::string>& protocols)
+ {
+ for(size_t i = 0; i != protocols.size(); ++i)
+ std::cout << "Protocol " << i << " = " << protocols[i] << "\n";
+ return "http/1.1";
+ }
+
+}
+
+int tls_client(int argc, char* argv[])
+ {
+ if(argc != 2 && argc != 3 && argc != 4)
+ {
+ std::cout << "Usage " << argv[0] << " host [port] [udp|tcp]\n";
+ return 1;
+ }
+
+ try
+ {
+ AutoSeeded_RNG rng;
+ TLS::Policy policy;
+
+#if defined(BOTAN_HAS_TLS_SQLITE3_SESSION_MANAGER)
+ TLS::Session_Manager_SQLite session_manager("my secret passphrase",
+ rng,
+ "sessions.db");
+#else
+ TLS::Session_Manager_In_Memory session_manager(rng);
+#endif
+
+ Credentials_Manager_Simple creds(rng);
+
+ std::string host = argv[1];
+ u32bit port = argc >= 3 ? Botan::to_u32bit(argv[2]) : 443;
+ std::string transport = argc >= 4 ? argv[3] : "tcp";
+
+ int sockfd = connect_to_host(host, port, transport);
+
+ auto socket_write =
+ (transport == "tcp") ?
+ std::bind(stream_socket_write, sockfd, _1, _2) :
+ std::bind(dgram_socket_write, sockfd, _1, _2);
+
+ auto version =
+ (transport == "tcp") ?
+ TLS::Protocol_Version::latest_tls_version() :
+ TLS::Protocol_Version::latest_dtls_version();
+
+ TLS::Client client(socket_write,
+ process_data,
+ alert_received,
+ handshake_complete,
+ session_manager,
+ creds,
+ policy,
+ rng,
+ TLS::Server_Information(host, port),
+ version,
+ protocol_chooser);
+
+ while(!client.is_closed())
+ {
+ fd_set readfds;
+ FD_ZERO(&readfds);
+ FD_SET(sockfd, &readfds);
+ FD_SET(STDIN_FILENO, &readfds);
+
+ ::select(sockfd + 1, &readfds, NULL, NULL, NULL);
+
+ if(FD_ISSET(sockfd, &readfds))
+ {
+ byte buf[4*1024] = { 0 };
+
+ ssize_t got = ::read(sockfd, buf, sizeof(buf));
+
+ if(got == 0)
+ {
+ std::cout << "EOF on socket\n";
+ break;
+ }
+ else if(got == -1)
+ {
+ std::cout << "Socket error: " << errno << " " << strerror(errno) << "\n";
+ continue;
+ }
+
+ //std::cout << "Socket - got " << got << " bytes\n";
+ client.received_data(buf, got);
+ }
+ else if(FD_ISSET(STDIN_FILENO, &readfds))
+ {
+ byte buf[1024] = { 0 };
+ ssize_t got = read(STDIN_FILENO, buf, sizeof(buf));
+
+ if(got == 0)
+ {
+ std::cout << "EOF on stdin\n";
+ client.close();
+ break;
+ }
+ else if(got == -1)
+ {
+ std::cout << "Stdin error: " << errno << " " << strerror(errno) << "\n";
+ continue;
+ }
+
+ if(got == 2 && buf[1] == '\n')
+ {
+ char cmd = buf[0];
+
+ if(cmd == 'R' || cmd == 'r')
+ {
+ std::cout << "Client initiated renegotiation\n";
+ client.renegotiate(cmd == 'R');
+ }
+ else if(cmd == 'Q')
+ {
+ std::cout << "Client initiated close\n";
+ client.close();
+ }
+ }
+ else if(buf[0] == 'H')
+ client.heartbeat(&buf[1], got-1);
+ else
+ client.send(buf, got);
+ }
+ }
+
+ ::close(sockfd);
+
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Exception: " << e.what() << "\n";
+ return 1;
+ }
+ return 0;
+ }
diff --git a/src/apps/tls_server.cpp b/src/apps/tls_server.cpp
new file mode 100644
index 000000000..cb212fef6
--- /dev/null
+++ b/src/apps/tls_server.cpp
@@ -0,0 +1,262 @@
+#include "apps.h"
+#include <botan/tls_server.h>
+#include <botan/hex.h>
+
+#include <botan/rsa.h>
+#include <botan/dsa.h>
+#include <botan/x509self.h>
+#include <botan/secqueue.h>
+
+#include "credentials.h"
+
+using namespace Botan;
+
+using namespace std::placeholders;
+
+#include <stdio.h>
+#include <string>
+#include <iostream>
+#include <memory>
+#include <list>
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#if !defined(MSG_NOSIGNAL)
+ #define MSG_NOSIGNAL 0
+#endif
+
+namespace {
+
+int make_server_socket(const std::string& transport, u16bit port)
+ {
+ int type = (transport == "tcp") ? SOCK_STREAM : SOCK_DGRAM;
+
+ int fd = ::socket(PF_INET, type, 0);
+ if(fd == -1)
+ throw std::runtime_error("Unable to acquire socket");
+
+ sockaddr_in socket_info;
+ ::memset(&socket_info, 0, sizeof(socket_info));
+ socket_info.sin_family = AF_INET;
+ socket_info.sin_port = htons(port);
+
+ // FIXME: support limiting listeners
+ socket_info.sin_addr.s_addr = INADDR_ANY;
+
+ if(::bind(fd, (sockaddr*)&socket_info, sizeof(struct sockaddr)) != 0)
+ {
+ ::close(fd);
+ throw std::runtime_error("server bind failed");
+ }
+
+ if(transport != "udp")
+ {
+ if(::listen(fd, 100) != 0)
+ {
+ ::close(fd);
+ throw std::runtime_error("listen failed");
+ }
+ }
+
+ return fd;
+ }
+
+bool handshake_complete(const TLS::Session& session)
+ {
+ std::cout << "Handshake complete, " << session.version().to_string()
+ << " using " << session.ciphersuite().to_string() << "\n";
+
+ if(!session.session_id().empty())
+ std::cout << "Session ID " << hex_encode(session.session_id()) << "\n";
+
+ if(!session.session_ticket().empty())
+ std::cout << "Session ticket " << hex_encode(session.session_ticket()) << "\n";
+
+ return true;
+ }
+
+void dgram_socket_write(int sockfd, const byte buf[], size_t length)
+ {
+ ssize_t sent = ::send(sockfd, buf, length, MSG_NOSIGNAL);
+
+ if(sent == -1)
+ std::cout << "Error writing to socket - " << strerror(errno) << "\n";
+ else if(sent != static_cast<ssize_t>(length))
+ std::cout << "Packet of length " << length << " truncated to " << sent << "\n";
+ }
+
+void stream_socket_write(int sockfd, const byte buf[], size_t length)
+ {
+ size_t offset = 0;
+
+ while(length)
+ {
+ ssize_t sent = ::send(sockfd, (const char*)buf + offset,
+ length, MSG_NOSIGNAL);
+
+ if(sent == -1)
+ {
+ if(errno == EINTR)
+ sent = 0;
+ else
+ throw std::runtime_error("Socket::write: Socket write failed");
+ }
+
+ offset += sent;
+ length -= sent;
+ }
+ }
+
+void alert_received(TLS::Alert alert, const byte buf[], size_t buf_size)
+ {
+ std::cout << "Alert: " << alert.type_string() << "\n";
+ }
+
+}
+
+int tls_server(int argc, char* argv[])
+ {
+ int port = 4433;
+ std::string transport = "tcp";
+
+ if(argc >= 2)
+ port = to_u32bit(argv[1]);
+ if(argc >= 3)
+ transport = argv[2];
+
+ try
+ {
+ AutoSeeded_RNG rng;
+
+ TLS::Policy policy;
+
+ TLS::Session_Manager_In_Memory session_manager(rng);
+
+ Credentials_Manager_Simple creds(rng);
+
+ /*
+ * These are the protocols we advertise to the client, but the
+ * client will send back whatever it actually plans on talking,
+ * which may or may not take into account what we advertise.
+ */
+ const std::vector<std::string> protocols = { "echo/1.0", "echo/1.1" };
+
+ std::cout << "Listening for new connections on " << transport << " port " << port << "\n";
+
+ int server_fd = make_server_socket(transport, port);
+
+ while(true)
+ {
+ try
+ {
+ int fd;
+
+ if(transport == "tcp")
+ fd = ::accept(server_fd, NULL, NULL);
+ else
+ {
+ struct sockaddr_in from;
+ socklen_t from_len = sizeof(sockaddr_in);
+
+ if(::recvfrom(server_fd, NULL, 0, MSG_PEEK,
+ (struct sockaddr*)&from, &from_len) != 0)
+ throw std::runtime_error("Could not peek next packet");
+
+ if(::connect(server_fd, (struct sockaddr*)&from, from_len) != 0)
+ throw std::runtime_error("Could not connect UDP socket");
+
+ fd = server_fd;
+ }
+
+ std::cout << "New connection received\n";
+
+ auto socket_write =
+ (transport == "tcp") ?
+ std::bind(stream_socket_write, fd, _1, _2) :
+ std::bind(dgram_socket_write, fd, _1, _2);
+
+ std::string s;
+ std::list<std::string> pending_output;
+
+ pending_output.push_back("Welcome to the best echo server evar\n");
+
+ auto proc_fn = [&](const byte input[], size_t input_len)
+ {
+ for(size_t i = 0; i != input_len; ++i)
+ {
+ char c = (char)input[i];
+ s += c;
+ if(c == '\n')
+ {
+ pending_output.push_back(s);
+ s.clear();
+ }
+ }
+ };
+
+ TLS::Server server(socket_write,
+ proc_fn,
+ alert_received,
+ handshake_complete,
+ session_manager,
+ creds,
+ policy,
+ rng,
+ protocols);
+
+ while(!server.is_closed())
+ {
+ byte buf[4*1024] = { 0 };
+ ssize_t got = ::read(fd, buf, sizeof(buf));
+
+ if(got == -1)
+ {
+ std::cout << "Error in socket read - " << strerror(errno) << "\n";
+ break;
+ }
+
+ if(got == 0)
+ {
+ std::cout << "EOF on socket\n";
+ break;
+ }
+
+ server.received_data(buf, got);
+
+ while(server.is_active() && !pending_output.empty())
+ {
+ std::string s = pending_output.front();
+ pending_output.pop_front();
+ server.send(s);
+
+ if(s == "quit\n")
+ server.close();
+ }
+ }
+
+ if(transport == "tcp")
+ ::close(fd);
+
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Connection problem: " << e.what() << "\n";
+ return 1;
+ }
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << e.what() << "\n";
+ return 1;
+ }
+
+ return 0;
+ }
diff --git a/src/examples/x509print.cpp b/src/apps/x509print.cpp
index 88e1dfbaa..c79ae7a6b 100644
--- a/src/examples/x509print.cpp
+++ b/src/apps/x509print.cpp
@@ -1,7 +1,7 @@
-#include "examples.h"
+#include "apps.h"
#include <botan/x509cert.h>
-int x509_example(int argc, char* argv[])
+int x509(int argc, char* argv[])
{
if(argc < 1)
{
diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt
index fe89512c0..be51a46ad 100644
--- a/src/build-data/cc/gcc.txt
+++ b/src/build-data/cc/gcc.txt
@@ -9,7 +9,7 @@ add_lib_dir_option -L
add_lib_option -l
lang_flags "-std=c++11 -D_REENTRANT -fstack-protector"
-maintainer_warning_flags "-Werror -Wno-error=old-style-cast -Wno-error=zero-as-null-pointer-constant"
+maintainer_warning_flags "-Werror -Wno-error=old-style-cast -Wno-error=zero-as-null-pointer-constant -Wno-error=unused-parameter"
warning_flags "-Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast -Wzero-as-null-pointer-constant"
lib_opt_flags "-O3"
diff --git a/src/examples/examples.h b/src/examples/examples.h
deleted file mode 100644
index 2a9a361c7..000000000
--- a/src/examples/examples.h
+++ /dev/null
@@ -1,17 +0,0 @@
-
-#include "../common.h"
-#include <botan/auto_rng.h>
-#include <botan/hex.h>
-#include <iostream>
-
-using namespace Botan;
-
-int asn1_example(int argc, char* argv[]);
-int bcrypt_example(int argc, char* argv[]);
-int factor_example(int argc, char* argv[]);
-int fpe_example(int argc, char* argv[]);
-int read_ssh_example(int argc, char* argv[]);
-
-int self_sig_example(int argc, char* argv[]);
-
-int x509_example(int argc, char* argv[]);
diff --git a/src/main.cpp b/src/main.cpp
index baf37e895..956413d4c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -29,7 +29,7 @@ using namespace Botan;
#include "common.h"
#include "speed/speed.h"
#include "tests/tests.h"
-#include "examples/examples.h"
+#include "apps/apps.h"
// from common.h
void strip_comments(std::string& line)
@@ -76,6 +76,18 @@ std::vector<std::string> parse(const std::string& line)
return substr;
}
+namespace {
+
+int help(int , char* argv[])
+ {
+ std::cout << "Usage: " << argv[0] << " subcommand\n";
+ std::cout << "Common commands: help version test speed\n";
+ std::cout << "Other commands: cpuid bcrypt x509 factor tls_client asn1 base64 hash self_sig\n";
+ return 1;
+ }
+
+}
+
int main(int argc, char* argv[])
{
if(BOTAN_VERSION_MAJOR != version_major() ||
@@ -94,37 +106,36 @@ int main(int argc, char* argv[])
try
{
- OptionParser opts("help|test|validate|"
- "algo=|seconds=|buf-size=");
- opts.parse(argv);
-
Botan::LibraryInitializer init;
- if(opts.is_set("help") || argc < 2)
- {
- std::cout << "Commands: test version time bcrypt\n";
- return 1;
- }
+ if(argc < 2)
+ return help(argc, argv);
const std::string cmd = argv[1];
+ if(cmd == "help")
+ return help(argc, argv);
+
if(cmd == "version")
{
std::cout << Botan::version_string() << "\n";
return 0;
}
+ if(cmd == "cpuid")
+ {
+ CPUID::print(std::cout);
+ return 0;
+ }
+
if(cmd == "test")
{
const size_t failures = run_all_tests();
return failures ? 1 : 0;
}
- if(cmd == "cpuid")
- {
- CPUID::print(std::cout);
- return 0;
- }
+ if(cmd == "speed")
+ return speed_main(argc - 1, argv + 1);
if(cmd == "http_get")
{
@@ -132,63 +143,24 @@ int main(int argc, char* argv[])
std::cout << resp << "\n";
}
- if(cmd == "bcrypt")
- return bcrypt_example(argc - 1, argv + 1);
-
- if(cmd == "fpe")
- return fpe_example(argc - 1, argv + 1);
-
- if(cmd == "read_ssh_key")
- return read_ssh_example(argc - 1, argv + 1);
-
- if(cmd == "self_sig")
- return self_sig_example(argc - 1, argv + 1);
-
- if(cmd == "x509")
- return x509_example(argc - 1, argv + 1);
-
- if(cmd == "factor")
- return factor_example(argc - 1, argv + 1);
-
- if(cmd == "asn1")
- return asn1_example(argc - 1, argv + 1);
-
- if(cmd == "speed")
- {
- double seconds = 5;
- u32bit buf_size = 16;
-
- if(opts.is_set("seconds"))
- {
- seconds = std::atof(opts.value("seconds").c_str());
- if(seconds < 0.1 || seconds > (5 * 60))
- {
- std::cout << "Invalid argument to --seconds\n";
- return 2;
- }
- }
-
- if(opts.is_set("buf-size"))
- {
- buf_size = std::atoi(opts.value("buf-size").c_str());
- if(buf_size == 0 || buf_size > 1024)
- {
- std::cout << "Invalid argument to --buf-size\n";
- return 2;
- }
- }
-
- if(opts.is_set("--algo"))
- {
- AutoSeeded_RNG rng;
- for(auto alg: Botan::split_on(opts.value("algo"), ','))
- bench_algo(alg, rng, seconds, buf_size);
- }
- /*
- else
- benchmark(seconds, buf_size);
- */
- }
+#define CALL_CMD(cmdsym) \
+ do { if(cmd == #cmdsym) { return cmdsym (argc - 1, argv + 1); } } while(0)
+
+ CALL_CMD(asn1);
+ CALL_CMD(base64);
+ CALL_CMD(bcrypt);
+ CALL_CMD(bzip);
+ CALL_CMD(ca);
+ CALL_CMD(factor);
+ CALL_CMD(fpe);
+ CALL_CMD(hash);
+ CALL_CMD(keygen);
+ CALL_CMD(pkcs10);
+ CALL_CMD(read_ssh);
+ CALL_CMD(self_sig);
+ CALL_CMD(tls_client);
+ CALL_CMD(tls_server);
+ CALL_CMD(x509);
}
catch(std::exception& e)
{
diff --git a/src/speed/speed.cpp b/src/speed/speed.cpp
index b8c14ee59..1cd3ec0f7 100644
--- a/src/speed/speed.cpp
+++ b/src/speed/speed.cpp
@@ -198,3 +198,43 @@ void benchmark(double seconds, size_t buf_size)
for(size_t i = 0; algos[i] != ""; ++i)
bench_algo(algos[i], rng, seconds, buf_size);
}
+
+int speed_main(int , char* argv[])
+ {
+ OptionParser opts("algo=|seconds=|buf-size=");
+ opts.parse(argv);
+
+ double seconds = .5;
+ u32bit buf_size = 16;
+
+ if(opts.is_set("seconds"))
+ {
+ seconds = std::atof(opts.value("seconds").c_str());
+ if(seconds < 0.1 || seconds > (5 * 60))
+ {
+ std::cout << "Invalid argument to --seconds\n";
+ return 2;
+ }
+ }
+
+ if(opts.is_set("buf-size"))
+ {
+ buf_size = std::atoi(opts.value("buf-size").c_str());
+ if(buf_size == 0 || buf_size > 1024)
+ {
+ std::cout << "Invalid argument to --buf-size\n";
+ return 2;
+ }
+ }
+
+ if(opts.is_set("algo"))
+ {
+ AutoSeeded_RNG rng;
+ for(auto alg: Botan::split_on(opts.value("algo"), ','))
+ bench_algo(alg, rng, seconds, buf_size);
+ }
+ else
+ benchmark(seconds, buf_size);
+
+ return 0;
+ }
diff --git a/src/speed/speed.h b/src/speed/speed.h
index d115960fb..ec0d06733 100644
--- a/src/speed/speed.h
+++ b/src/speed/speed.h
@@ -9,6 +9,8 @@
using namespace Botan;
+int speed_main(int argc, char* argv[]);
+
void benchmark(double seconds,
size_t buf_size);