aboutsummaryrefslogtreecommitdiffstats
path: root/src/apps
diff options
context:
space:
mode:
Diffstat (limited to 'src/apps')
-rw-r--r--src/apps/apps.h4
-rw-r--r--src/apps/asn1.cpp2
-rw-r--r--src/apps/base64.cpp2
-rw-r--r--src/apps/bcrypt.cpp2
-rw-r--r--src/apps/bzip.cpp2
-rw-r--r--src/apps/ca.cpp2
-rw-r--r--src/apps/cert_verify.cpp2
-rw-r--r--src/apps/dsa_sign.cpp2
-rw-r--r--src/apps/dsa_ver.cpp2
-rw-r--r--src/apps/factor.cpp2
-rw-r--r--src/apps/fpe.cpp2
-rw-r--r--src/apps/hash.cpp2
-rw-r--r--src/apps/keygen.cpp2
-rw-r--r--src/apps/ocsp.cpp2
-rw-r--r--src/apps/pkcs10.cpp2
-rw-r--r--src/apps/read_ssh.cpp2
-rw-r--r--src/apps/self_sig.cpp2
-rw-r--r--src/apps/speed/pk_bench.cpp755
-rw-r--r--src/apps/speed/speed.cpp240
-rw-r--r--src/apps/speed/speed.h25
-rw-r--r--src/apps/speed/timer.cpp64
-rw-r--r--src/apps/speed/timer.h50
-rw-r--r--src/apps/tls_client.cpp2
-rw-r--r--src/apps/tls_server.cpp2
-rw-r--r--src/apps/tls_server_asio.cpp2
-rw-r--r--src/apps/x509print.cpp2
26 files changed, 1157 insertions, 21 deletions
diff --git a/src/apps/apps.h b/src/apps/apps.h
index ae4f884b6..cf77923fe 100644
--- a/src/apps/apps.h
+++ b/src/apps/apps.h
@@ -6,7 +6,7 @@
using namespace Botan;
-#define DEFINE_EXAMPLE(cmd) int cmd (int argc, char* argv[]);
+#define DEFINE_EXAMPLE(cmd) int cmd ## _main(int argc, char* argv[]);
DEFINE_EXAMPLE(asn1);
DEFINE_EXAMPLE(bcrypt);
@@ -28,3 +28,5 @@ DEFINE_EXAMPLE(tls_client);
DEFINE_EXAMPLE(tls_server);
DEFINE_EXAMPLE(tls_server_asio);
DEFINE_EXAMPLE(x509);
+
+int speed_main(int argc, char* argv[]);
diff --git a/src/apps/asn1.cpp b/src/apps/asn1.cpp
index 447462ae0..79d52d485 100644
--- a/src/apps/asn1.cpp
+++ b/src/apps/asn1.cpp
@@ -47,7 +47,7 @@ std::string url_encode(const std::vector<byte>& in)
}
-int asn1(int argc, char* argv[])
+int asn1_main(int argc, char* argv[])
{
if(argc != 2)
{
diff --git a/src/apps/base64.cpp b/src/apps/base64.cpp
index 697fcb42c..34711857c 100644
--- a/src/apps/base64.cpp
+++ b/src/apps/base64.cpp
@@ -15,7 +15,7 @@
#include <botan/b64_filt.h>
#include <botan/pipe.h>
-int base64(int argc, char* argv[])
+int base64_main(int argc, char* argv[])
{
if(argc < 2)
{
diff --git a/src/apps/bcrypt.cpp b/src/apps/bcrypt.cpp
index 497111363..2b0bfa132 100644
--- a/src/apps/bcrypt.cpp
+++ b/src/apps/bcrypt.cpp
@@ -1,7 +1,7 @@
#include "apps.h"
#include <botan/bcrypt.h>
-int bcrypt(int argc, char* argv[])
+int bcrypt_main(int argc, char* argv[])
{
if(argc == 2)
{
diff --git a/src/apps/bzip.cpp b/src/apps/bzip.cpp
index 94a8bdff7..3b8c7cdc2 100644
--- a/src/apps/bzip.cpp
+++ b/src/apps/bzip.cpp
@@ -28,7 +28,7 @@
const std::string SUFFIX = ".bz2";
-int bzip(int argc, char* argv[])
+int bzip_main(int argc, char* argv[])
{
if(argc < 2)
{
diff --git a/src/apps/ca.cpp b/src/apps/ca.cpp
index 881036fc8..17d930358 100644
--- a/src/apps/ca.cpp
+++ b/src/apps/ca.cpp
@@ -7,7 +7,7 @@ using namespace Botan;
#include <memory>
#include <chrono>
-int ca(int argc, char* argv[])
+int ca_main(int argc, char* argv[])
{
if(argc != 5)
{
diff --git a/src/apps/cert_verify.cpp b/src/apps/cert_verify.cpp
index 78d82e9a5..154267fe1 100644
--- a/src/apps/cert_verify.cpp
+++ b/src/apps/cert_verify.cpp
@@ -12,7 +12,7 @@
using namespace Botan;
-int cert_verify(int argc, char* argv[])
+int cert_verify_main(int argc, char* argv[])
{
if(argc <= 2)
{
diff --git a/src/apps/dsa_sign.cpp b/src/apps/dsa_sign.cpp
index 31aaf7aeb..308e68814 100644
--- a/src/apps/dsa_sign.cpp
+++ b/src/apps/dsa_sign.cpp
@@ -12,7 +12,7 @@ using namespace Botan;
const std::string SUFFIX = ".sig";
-int dsa_sign(int argc, char* argv[])
+int dsa_sign_main(int argc, char* argv[])
{
if(argc != 4)
{
diff --git a/src/apps/dsa_ver.cpp b/src/apps/dsa_ver.cpp
index 9cf0ed969..a5d0ca271 100644
--- a/src/apps/dsa_ver.cpp
+++ b/src/apps/dsa_ver.cpp
@@ -22,7 +22,7 @@ secure_vector<byte> b64_decode(const std::string& in)
}
-int dsa_verify(int argc, char* argv[])
+int dsa_verify_main(int argc, char* argv[])
{
if(argc != 4)
{
diff --git a/src/apps/factor.cpp b/src/apps/factor.cpp
index 484f024d8..7a5018d62 100644
--- a/src/apps/factor.cpp
+++ b/src/apps/factor.cpp
@@ -121,7 +121,7 @@ std::vector<BigInt> factorize(const BigInt& n_in,
}
-int factor(int argc, char* argv[])
+int factor_main(int argc, char* argv[])
{
if(argc != 2)
{
diff --git a/src/apps/fpe.cpp b/src/apps/fpe.cpp
index dd5b9b682..e40db8a32 100644
--- a/src/apps/fpe.cpp
+++ b/src/apps/fpe.cpp
@@ -102,7 +102,7 @@ u64bit decrypt_cc_number(u64bit enc_cc,
}
-int fpe(int argc, char* argv[])
+int fpe_main(int argc, char* argv[])
{
if(argc != 4)
{
diff --git a/src/apps/hash.cpp b/src/apps/hash.cpp
index c1e5aab3e..5c5705210 100644
--- a/src/apps/hash.cpp
+++ b/src/apps/hash.cpp
@@ -11,7 +11,7 @@
using namespace Botan;
-int hash(int argc, char* argv[])
+int hash_main(int argc, char* argv[])
{
if(argc < 3)
{
diff --git a/src/apps/keygen.cpp b/src/apps/keygen.cpp
index 885364834..40055f6cf 100644
--- a/src/apps/keygen.cpp
+++ b/src/apps/keygen.cpp
@@ -8,7 +8,7 @@
#include <botan/rsa.h>
using namespace Botan;
-int keygen(int argc, char* argv[])
+int keygen_main(int argc, char* argv[])
{
if(argc != 2 && argc != 3)
{
diff --git a/src/apps/ocsp.cpp b/src/apps/ocsp.cpp
index 853debbe3..98324caff 100644
--- a/src/apps/ocsp.cpp
+++ b/src/apps/ocsp.cpp
@@ -8,7 +8,7 @@
using namespace Botan;
-int ocsp_check(int argc, char* argv[])
+int ocsp_check_main(int argc, char* argv[])
{
if(argc != 2)
{
diff --git a/src/apps/pkcs10.cpp b/src/apps/pkcs10.cpp
index 6e36f73fb..cb1d44436 100644
--- a/src/apps/pkcs10.cpp
+++ b/src/apps/pkcs10.cpp
@@ -8,7 +8,7 @@ using namespace Botan;
#include <fstream>
#include <memory>
-int pkcs10(int argc, char* argv[])
+int pkcs10_main(int argc, char* argv[])
{
if(argc != 6)
{
diff --git a/src/apps/read_ssh.cpp b/src/apps/read_ssh.cpp
index ce72fa064..2745f3209 100644
--- a/src/apps/read_ssh.cpp
+++ b/src/apps/read_ssh.cpp
@@ -111,7 +111,7 @@ Public_Key* read_ssh_pubkey(const std::string& file)
}
-int read_ssh(int argc, char* argv[])
+int read_ssh_main(int argc, char* argv[])
{
if(argc != 2)
{
diff --git a/src/apps/self_sig.cpp b/src/apps/self_sig.cpp
index c4202442c..7d05aed60 100644
--- a/src/apps/self_sig.cpp
+++ b/src/apps/self_sig.cpp
@@ -8,7 +8,7 @@ using namespace Botan;
#include <fstream>
#include <memory>
-int self_sig(int argc, char* argv[])
+int self_sig_main(int argc, char* argv[])
{
if(argc != 7)
{
diff --git a/src/apps/speed/pk_bench.cpp b/src/apps/speed/pk_bench.cpp
new file mode 100644
index 000000000..6ebb366c5
--- /dev/null
+++ b/src/apps/speed/pk_bench.cpp
@@ -0,0 +1,755 @@
+/*
+* (C) 2009-2010 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include "speed.h"
+#include "timer.h"
+
+#include <botan/pkcs8.h>
+#include <botan/mem_ops.h>
+#include <botan/parsing.h>
+#include <botan/oids.h>
+#include <map>
+
+#if defined(BOTAN_HAS_PUBLIC_KEY_CRYPTO)
+ #include <botan/x509_key.h>
+ #include <botan/pkcs8.h>
+ #include <botan/pubkey.h>
+#endif
+
+#if defined(BOTAN_HAS_RSA)
+ #include <botan/rsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ #include <botan/dsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ #include <botan/dh.h>
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ #include <botan/nr.h>
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ #include <botan/rw.h>
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ #include <botan/elgamal.h>
+#endif
+
+#if defined(BOTAN_HAS_DLIES)
+ #include <botan/dlies.h>
+ #include <botan/kdf2.h>
+ #include <botan/hmac.h>
+ #include <botan/sha160.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ #include <botan/ecdsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ #include <botan/ecdh.h>
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ #include <botan/gost_3410.h>
+#endif
+
+using namespace Botan;
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <memory>
+#include <set>
+
+#define BENCH_FAULT_PROT DISABLE_FAULT_PROTECTION
+//#define BENCH_FAULT_PROT ENABLE_FAULT_PROTECTION
+
+namespace {
+
+const char* ec_domains[] = {
+ "secp160r2",
+ "secp192r1",
+ "secp224r1",
+ "secp256r1",
+ "secp384r1",
+ "secp521r1",
+ nullptr
+};
+
+class Benchmark_Report
+ {
+ public:
+ void report(const std::string& name, Timer timer)
+ {
+ std::cout << name << " " << timer << std::endl;
+ data[name].insert(timer);
+ }
+
+ private:
+ std::map<std::string, std::set<Timer> > data;
+ };
+
+void benchmark_enc_dec(PK_Encryptor& enc, PK_Decryptor& dec,
+ Timer& enc_timer, Timer& dec_timer,
+ RandomNumberGenerator& rng,
+ u32bit runs, double seconds)
+ {
+ std::vector<byte> plaintext, ciphertext;
+
+ for(u32bit i = 0; i != runs; ++i)
+ {
+ if(enc_timer.seconds() < seconds || ciphertext.size() == 0)
+ {
+ plaintext.resize(enc.maximum_input_size());
+
+ // Ensure for Raw, etc, it stays large
+ if((i % 100) == 0)
+ {
+ rng.randomize(&plaintext[0], plaintext.size());
+ plaintext[0] |= 0x80;
+ }
+
+ enc_timer.start();
+ ciphertext = enc.encrypt(plaintext, rng);
+ enc_timer.stop();
+ }
+
+ if(dec_timer.seconds() < seconds)
+ {
+ dec_timer.start();
+ std::vector<byte> plaintext_out = unlock(dec.decrypt(ciphertext));
+ dec_timer.stop();
+
+ if(plaintext_out != plaintext)
+ { // has never happened...
+ std::cerr << "Contents mismatched on decryption during benchmark!\n";
+ }
+ }
+ }
+ }
+
+void benchmark_sig_ver(PK_Verifier& ver, PK_Signer& sig,
+ Timer& verify_timer, Timer& sig_timer,
+ RandomNumberGenerator& rng,
+ u32bit runs, double seconds)
+ {
+ std::vector<byte> message, signature, sig_random;
+
+ for(u32bit i = 0; i != runs; ++i)
+ {
+ if(sig_timer.seconds() < seconds || signature.size() == 0)
+ {
+ if((i % 100) == 0)
+ {
+ message.resize(48);
+ rng.randomize(&message[0], message.size());
+ }
+
+ sig_timer.start();
+ signature = sig.sign_message(message, rng);
+ sig_timer.stop();
+ }
+
+ if(verify_timer.seconds() < seconds)
+ {
+ verify_timer.start();
+ const bool verified = ver.verify_message(message, signature);
+ verify_timer.stop();
+
+ if(!verified)
+ std::cerr << "Signature verification failure\n";
+
+ if((i % 100) == 0)
+ {
+ sig_random = unlock(rng.random_vec(signature.size()));
+
+ verify_timer.start();
+ const bool verified_bad = ver.verify_message(message, sig_random);
+ verify_timer.stop();
+
+ if(verified_bad)
+ std::cerr << "Signature verification failure (bad sig OK)\n";
+ }
+ }
+ }
+ }
+
+/*
+ Between benchmark_rsa_rw + benchmark_dsa_nr:
+ Type of the key
+ Arguments to the constructor (A list of some arbitrary type?)
+ Type of padding
+*/
+
+#if defined(BOTAN_HAS_RSA)
+void benchmark_rsa(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+
+ size_t keylens[] = { 1024, 2048, 4096, 6144, 0 };
+
+ for(size_t i = 0; keylens[i]; ++i)
+ {
+ size_t keylen = keylens[i];
+
+ //const std::string sig_padding = "EMSA4(SHA-1)";
+ //const std::string enc_padding = "EME1(SHA-1)";
+ const std::string sig_padding = "EMSA-PKCS1-v1_5(SHA-1)";
+ const std::string enc_padding = "EME-PKCS1-v1_5";
+
+ Timer keygen_timer("keygen");
+ Timer verify_timer(sig_padding + " verify");
+ Timer sig_timer(sig_padding + " signature");
+ Timer enc_timer(enc_padding + " encrypt");
+ Timer dec_timer(enc_padding + " decrypt");
+
+ try
+ {
+
+#if 0
+ // for profiling
+ PKCS8_PrivateKey* pkcs8_key =
+ PKCS8::load_key("rsa/" + to_string(keylen) + ".pem", rng);
+ RSA_PrivateKey* key_ptr = dynamic_cast<RSA_PrivateKey*>(pkcs8_key);
+
+ RSA_PrivateKey key = *key_ptr;
+#else
+ keygen_timer.start();
+ RSA_PrivateKey key(rng, keylen);
+ keygen_timer.stop();
+#endif
+
+ while(verify_timer.seconds() < seconds ||
+ sig_timer.seconds() < seconds)
+ {
+ PK_Encryptor_EME enc(key, enc_padding);
+ PK_Decryptor_EME dec(key, enc_padding);
+
+ benchmark_enc_dec(enc, dec, enc_timer, dec_timer,
+ rng, 10000, seconds);
+
+ PK_Signer sig(key, sig_padding);
+ PK_Verifier ver(key, sig_padding);
+
+ benchmark_sig_ver(ver, sig, verify_timer,
+ sig_timer, rng, 10000, seconds);
+ }
+
+ const std::string rsa_keylen = "RSA-" + std::to_string(keylen);
+
+ report.report(rsa_keylen, keygen_timer);
+ report.report(rsa_keylen, verify_timer);
+ report.report(rsa_keylen, sig_timer);
+ report.report(rsa_keylen, enc_timer);
+ report.report(rsa_keylen, dec_timer);
+ }
+ catch(Stream_IO_Error)
+ {
+ }
+ catch(Exception& e)
+ {
+ std::cout << e.what() << "\n";
+ }
+ }
+
+ }
+#endif
+
+#if defined(BOTAN_HAS_RW)
+void benchmark_rw(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+
+ const u32bit keylens[] = { 1024, 2048, 4096, 6144, 0 };
+
+ for(size_t j = 0; keylens[j]; j++)
+ {
+ u32bit keylen = keylens[j];
+
+ std::string padding = "EMSA2(SHA-256)";
+
+ Timer keygen_timer("keygen");
+ Timer verify_timer(padding + " verify");
+ Timer sig_timer(padding + " signature");
+
+ while(verify_timer.seconds() < seconds ||
+ sig_timer.seconds() < seconds)
+ {
+ keygen_timer.start();
+ RW_PrivateKey key(rng, keylen);
+ keygen_timer.stop();
+
+ PK_Signer sig(key, padding);
+ PK_Verifier ver(key, padding);
+
+ benchmark_sig_ver(ver, sig, verify_timer, sig_timer,
+ rng, 10000, seconds);
+ }
+
+ const std::string nm = "RW-" + std::to_string(keylen);
+ report.report(nm, keygen_timer);
+ report.report(nm, verify_timer);
+ report.report(nm, sig_timer);
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+
+void benchmark_ecdsa(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ for(size_t j = 0; ec_domains[j]; j++)
+ {
+ EC_Group params(ec_domains[j]);
+
+ const size_t pbits = params.get_curve().get_p().bits();
+
+ size_t hashbits = pbits;
+
+ if(hashbits <= 192)
+ hashbits = 160;
+ if(hashbits == 521)
+ hashbits = 512;
+
+ const std::string padding = "EMSA1(SHA-" + std::to_string(hashbits) + ")";
+
+ Timer keygen_timer("keygen");
+ Timer verify_timer(padding + " verify");
+ Timer sig_timer(padding + " signature");
+
+ while(verify_timer.seconds() < seconds ||
+ sig_timer.seconds() < seconds)
+ {
+ keygen_timer.start();
+ ECDSA_PrivateKey key(rng, params);
+ keygen_timer.stop();
+
+ PK_Signer sig(key, padding, IEEE_1363, BENCH_FAULT_PROT);
+ PK_Verifier ver(key, padding);
+
+ benchmark_sig_ver(ver, sig, verify_timer,
+ sig_timer, rng, 1000, seconds);
+ }
+
+ const std::string nm = "ECDSA-" + std::to_string(pbits);
+
+ report.report(nm, keygen_timer);
+ report.report(nm, verify_timer);
+ report.report(nm, sig_timer);
+ }
+ }
+
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+
+void benchmark_gost_3410(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ for(size_t j = 0; ec_domains[j]; j++)
+ {
+ EC_Group params(ec_domains[j]);
+
+ const size_t pbits = params.get_curve().get_p().bits();
+
+ const std::string padding = "EMSA1(GOST-34.11)";
+
+ Timer keygen_timer("keygen");
+ Timer verify_timer(padding + " verify");
+ Timer sig_timer(padding + " signature");
+
+ while(verify_timer.seconds() < seconds ||
+ sig_timer.seconds() < seconds)
+ {
+ keygen_timer.start();
+ GOST_3410_PrivateKey key(rng, params);
+ keygen_timer.stop();
+
+ PK_Signer sig(key, padding, IEEE_1363, BENCH_FAULT_PROT);
+ PK_Verifier ver(key, padding);
+
+ benchmark_sig_ver(ver, sig, verify_timer,
+ sig_timer, rng, 1000, seconds);
+ }
+
+ const std::string nm = "GOST-34.10-" + std::to_string(pbits);
+
+ report.report(nm, keygen_timer);
+ report.report(nm, verify_timer);
+ report.report(nm, sig_timer);
+ }
+ }
+
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+
+void benchmark_ecdh(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ for(size_t j = 0; ec_domains[j]; j++)
+ {
+ EC_Group params(ec_domains[j]);
+
+ size_t pbits = params.get_curve().get_p().bits();
+
+ Timer keygen_timer("keygen");
+ Timer kex_timer("key exchange");
+
+ while(kex_timer.seconds() < seconds)
+ {
+ keygen_timer.start();
+ ECDH_PrivateKey ecdh1(rng, params);
+ keygen_timer.stop();
+
+ keygen_timer.start();
+ ECDH_PrivateKey ecdh2(rng, params);
+ keygen_timer.stop();
+
+ PK_Key_Agreement ka1(ecdh1, "KDF2(SHA-1)");
+ PK_Key_Agreement ka2(ecdh2, "KDF2(SHA-1)");
+
+ SymmetricKey secret1, secret2;
+
+ for(size_t i = 0; i != 1000; ++i)
+ {
+ if(kex_timer.seconds() > seconds)
+ break;
+
+ kex_timer.start();
+ secret1 = ka1.derive_key(32, ecdh2.public_value());
+ kex_timer.stop();
+
+ kex_timer.start();
+ secret2 = ka2.derive_key(32, ecdh1.public_value());
+ kex_timer.stop();
+
+ if(secret1 != secret2)
+ std::cerr << "ECDH secrets did not match\n";
+ }
+ }
+
+ const std::string nm = "ECDH-" + std::to_string(pbits);
+ report.report(nm, keygen_timer);
+ report.report(nm, kex_timer);
+ }
+ }
+
+#endif
+
+template<typename PRIV_KEY_TYPE>
+void benchmark_dsa_nr(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL) || defined(BOTAN_HAS_DSA)
+ const char* domains[] = { "dsa/jce/1024",
+ "dsa/botan/2048",
+ "dsa/botan/3072",
+ nullptr };
+
+ std::string algo_name;
+
+ for(size_t j = 0; domains[j]; j++)
+ {
+ size_t pbits = to_u32bit(split_on(domains[j], '/')[2]);
+ size_t qbits = (pbits <= 1024) ? 160 : 256;
+
+ const std::string padding = "EMSA1(SHA-" + std::to_string(qbits) + ")";
+
+ Timer keygen_timer("keygen");
+ Timer verify_timer(padding + " verify");
+ Timer sig_timer(padding + " signature");
+
+ while(verify_timer.seconds() < seconds ||
+ sig_timer.seconds() < seconds)
+ {
+ DL_Group group(domains[j]);
+
+ keygen_timer.start();
+ PRIV_KEY_TYPE key(rng, group);
+ algo_name = key.algo_name();
+ keygen_timer.stop();
+
+ PK_Signer sig(key, padding, IEEE_1363, BENCH_FAULT_PROT);
+ PK_Verifier ver(key, padding);
+
+ benchmark_sig_ver(ver, sig, verify_timer,
+ sig_timer, rng, 1000, seconds);
+ }
+
+ const std::string nm = algo_name + "-" + std::to_string(pbits);
+ report.report(nm, keygen_timer);
+ report.report(nm, verify_timer);
+ report.report(nm, sig_timer);
+ }
+#endif
+ }
+
+#ifdef BOTAN_HAS_DIFFIE_HELLMAN
+void benchmark_dh(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ const char* domains[] = { "modp/ietf/1024",
+ "modp/ietf/2048",
+ "modp/ietf/3072",
+ "modp/ietf/4096",
+ "modp/ietf/6144",
+ "modp/ietf/8192",
+ nullptr };
+
+ for(size_t j = 0; domains[j]; j++)
+ {
+ Timer keygen_timer("keygen");
+ Timer kex_timer("key exchange");
+
+ while(kex_timer.seconds() < seconds)
+ {
+ DL_Group group(domains[j]);
+
+ keygen_timer.start();
+ DH_PrivateKey dh1(rng, group);
+ keygen_timer.stop();
+
+ keygen_timer.start();
+ DH_PrivateKey dh2(rng, group);
+ keygen_timer.stop();
+
+ PK_Key_Agreement ka1(dh1, "KDF2(SHA-1)");
+ PK_Key_Agreement ka2(dh2, "KDF2(SHA-1)");
+
+ SymmetricKey secret1, secret2;
+
+ for(size_t i = 0; i != 1000; ++i)
+ {
+ if(kex_timer.seconds() > seconds)
+ break;
+
+ kex_timer.start();
+ secret1 = ka1.derive_key(32, dh2.public_value());
+ kex_timer.stop();
+
+ kex_timer.start();
+ secret2 = ka2.derive_key(32, dh1.public_value());
+ kex_timer.stop();
+
+ if(secret1 != secret2)
+ std::cerr << "DH secrets did not match\n";
+ }
+ }
+
+ const std::string nm = "DH-" + split_on(domains[j], '/')[2];
+ report.report(nm, keygen_timer);
+ report.report(nm, kex_timer);
+ }
+ }
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN) && defined(BOTAN_HAS_DLIES)
+void benchmark_dlies(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ const char* domains[] = { "modp/ietf/768",
+ "modp/ietf/1024",
+ "modp/ietf/2048",
+ "modp/ietf/3072",
+ "modp/ietf/4096",
+ "modp/ietf/6144",
+ "modp/ietf/8192",
+ nullptr };
+
+ for(size_t j = 0; domains[j]; j++)
+ {
+ Timer keygen_timer("keygen");
+ Timer kex_timer("key exchange");
+
+ Timer enc_timer("encrypt");
+ Timer dec_timer("decrypt");
+
+ while(enc_timer.seconds() < seconds || dec_timer.seconds() < seconds)
+ {
+ DL_Group group(domains[j]);
+
+ keygen_timer.start();
+ DH_PrivateKey dh1_priv(rng, group);
+ keygen_timer.stop();
+
+ keygen_timer.start();
+ DH_PrivateKey dh2_priv(rng, group);
+ keygen_timer.stop();
+
+ DH_PublicKey dh2_pub(dh2_priv);
+
+ DLIES_Encryptor dlies_enc(dh1_priv,
+ new KDF2(new SHA_160),
+ new HMAC(new SHA_160));
+
+ dlies_enc.set_other_key(dh2_pub.public_value());
+
+ DLIES_Decryptor dlies_dec(dh2_priv,
+ new KDF2(new SHA_160),
+ new HMAC(new SHA_160));
+
+ benchmark_enc_dec(dlies_enc, dlies_dec,
+ enc_timer, dec_timer, rng,
+ 1000, seconds);
+ }
+
+ const std::string nm = "DLIES-" + split_on(domains[j], '/')[2];
+ report.report(nm, keygen_timer);
+ report.report(nm, enc_timer);
+ report.report(nm, dec_timer);
+ }
+ }
+#endif
+
+#ifdef BOTAN_HAS_ELGAMAL
+void benchmark_elg(RandomNumberGenerator& rng,
+ double seconds,
+ Benchmark_Report& report)
+ {
+ const char* domains[] = { "modp/ietf/768",
+ "modp/ietf/1024",
+ "modp/ietf/2048",
+ "modp/ietf/3072",
+ "modp/ietf/4096",
+ "modp/ietf/6144",
+ "modp/ietf/8192",
+ nullptr };
+
+ const std::string algo_name = "ElGamal";
+
+ for(size_t j = 0; domains[j]; j++)
+ {
+ size_t pbits = to_u32bit(split_on(domains[j], '/')[2]);
+
+ const std::string padding = "EME1(SHA-1)";
+
+ Timer keygen_timer("keygen");
+ Timer enc_timer(padding + " encrypt");
+ Timer dec_timer(padding + " decrypt");
+
+ while(enc_timer.seconds() < seconds ||
+ dec_timer.seconds() < seconds)
+ {
+ DL_Group group(domains[j]);
+
+ keygen_timer.start();
+ ElGamal_PrivateKey key(rng, group);
+ keygen_timer.stop();
+
+ PK_Decryptor_EME dec(key, padding);
+ PK_Encryptor_EME enc(key, padding);
+
+ benchmark_enc_dec(enc, dec, enc_timer, dec_timer,
+ rng, 1000, seconds);
+ }
+
+ const std::string nm = algo_name + "-" + std::to_string(pbits);
+ report.report(nm, keygen_timer);
+ report.report(nm, enc_timer);
+ report.report(nm, dec_timer);
+ }
+ }
+#endif
+
+}
+
+void bench_pk(RandomNumberGenerator& rng,
+ const std::string& algo, double seconds)
+ {
+ /*
+ There is some strangeness going on here. It looks like algorithms
+ at the end take some kind of penalty. For example, running the RW tests
+ first got a result of:
+ RW-1024: 148.14 ms / private operation
+ but running them last output:
+ RW-1024: 363.54 ms / private operation
+
+ I think it's from memory fragmentation in the allocators, but I'm
+ not really sure. Need to investigate.
+
+ Until then, I've basically ordered the tests in order of most important
+ algorithms (RSA, DSA) to least important (NR, RW).
+
+ This strange behaviour does not seem to occur with DH (?)
+
+ To get more accurate runs, use --bench-algo (RSA|DSA|DH|ELG|NR); in this
+ case the distortion is less than 5%, which is good enough.
+
+ We do random keys with the DL schemes, since it's so easy and fast to
+ generate keys for them. For RSA and RW, we load the keys from a file. The
+ RSA keys are stored in a PKCS #8 structure, while RW is stored in a more
+ ad-hoc format (the RW algorithm has no assigned OID that I know of, so
+ there is no way to encode a RW key into a PKCS #8 structure).
+ */
+
+ Benchmark_Report report;
+
+#if defined(BOTAN_HAS_RSA)
+ if(algo == "All" || algo == "RSA")
+ benchmark_rsa(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(algo == "All" || algo == "DSA")
+ benchmark_dsa_nr<DSA_PrivateKey>(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+ if(algo == "All" || algo == "ECDSA")
+ benchmark_ecdsa(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_ECDH)
+ if(algo == "All" || algo == "ECDH")
+ benchmark_ecdh(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_GOST_34_10_2001)
+ if(algo == "All" || algo == "GOST-34.10")
+ benchmark_gost_3410(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
+ if(algo == "All" || algo == "DH")
+ benchmark_dh(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_DIFFIE_HELLMAN) && defined(BOTAN_HAS_DLIES)
+ if(algo == "All" || algo == "DLIES")
+ benchmark_dlies(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_ELGAMAL)
+ if(algo == "All" || algo == "ELG" || algo == "ElGamal")
+ benchmark_elg(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_NYBERG_RUEPPEL)
+ if(algo == "All" || algo == "NR")
+ benchmark_dsa_nr<NR_PrivateKey>(rng, seconds, report);
+#endif
+
+#if defined(BOTAN_HAS_RW)
+ if(algo == "All" || algo == "RW")
+ benchmark_rw(rng, seconds, report);
+#endif
+ }
diff --git a/src/apps/speed/speed.cpp b/src/apps/speed/speed.cpp
new file mode 100644
index 000000000..1cd3ec0f7
--- /dev/null
+++ b/src/apps/speed/speed.cpp
@@ -0,0 +1,240 @@
+/*
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include "speed.h"
+#include <iostream>
+#include <iomanip>
+
+#include <botan/benchmark.h>
+#include <botan/aead.h>
+#include <botan/auto_rng.h>
+#include <botan/libstate.h>
+#include <botan/pipe.h>
+#include <botan/filters.h>
+#include <botan/engine.h>
+#include <botan/parsing.h>
+#include <botan/symkey.h>
+#include <botan/hex.h>
+
+#include <chrono>
+
+typedef std::chrono::high_resolution_clock benchmark_clock;
+
+
+using namespace Botan;
+
+namespace {
+
+const std::string algos[] = {
+
+ /* Block ciphers */
+ "AES-128",
+ "AES-192",
+ "AES-256",
+ "Blowfish",
+ "CAST-128",
+ "CAST-256",
+ "DES",
+ "DESX",
+ "GOST",
+ "IDEA",
+ "KASUMI",
+ "MARS",
+ "MISTY1",
+ "Noekeon",
+ "RC2",
+ "RC5(12)",
+ "RC5(16)",
+ "RC6",
+ "SAFER-SK(10)",
+ "SEED",
+ "Serpent",
+ "Skipjack",
+ "Square",
+ "TEA",
+ "TripleDES",
+ "Twofish",
+ "XTEA",
+
+ /* Cipher modes */
+ "AES-128/CBC/PKCS7",
+ "AES-128/CTR-BE",
+ "AES-128/EAX",
+ "AES-128/OCB",
+ "AES-128/GCM",
+ "AES-128/XTS",
+
+ "Serpent/CBC/PKCS7",
+ "Serpent/CTR-BE",
+ "Serpent/EAX",
+ "Serpent/OCB",
+ "Serpent/GCM",
+ "Serpent/XTS",
+
+ /* Stream ciphers */
+ "RC4",
+ "Salsa20",
+
+ /* Hashes */
+ "HAS-160",
+ "Keccak-1600(224)",
+ "Keccak-1600(256)",
+ "Keccak-1600(384)",
+ "Keccak-1600(512)",
+ "MD5",
+ "RIPEMD-160",
+ "SHA-160",
+ "SHA-256",
+ "SHA-384",
+ "SHA-512",
+ "Skein-512",
+ "Tiger",
+ "Whirlpool",
+
+ /* MACs */
+ "CMAC(AES-128)",
+ "HMAC(SHA-1)",
+ "",
+};
+
+void report_results(const std::string& algo,
+ const std::map<std::string, double>& speeds)
+ {
+ if(speeds.empty())
+ return;
+
+ // invert, showing fastest impl first
+ std::map<double, std::string> results;
+
+ for(auto i = speeds.begin(); i != speeds.end(); ++i)
+ {
+ // Speeds might collide, tweak slightly to handle this
+ if(results[i->second] == "")
+ results[i->second] = i->first;
+ else
+ results[i->second - .01] = i->first;
+ }
+
+ std::cout << algo;
+
+ for(auto i = results.rbegin(); i != results.rend(); ++i)
+ {
+ std::cout << " [" << i->second << "] "
+ << std::fixed << std::setprecision(2) << i->first;
+ }
+ std::cout << std::endl;
+ }
+
+std::map<std::string, double> time_transform(std::unique_ptr<Transformation> tf,
+ RandomNumberGenerator& rng)
+ {
+ std::map<std::string, double> results;
+
+ if(!tf)
+ return results;
+
+ if(tf->maximum_keylength() > 0)
+ tf->set_key(rng.random_vec(tf->maximum_keylength()));
+
+ tf->start_vec(rng.random_vec(tf->default_nonce_length()));
+
+
+ for(size_t buf_size : { 16, 64, 256, 1024, 8192 })
+ {
+ secure_vector<byte> buffer(buf_size);
+
+ double res = time_op(std::chrono::seconds(1),
+ [&tf,&buffer,buf_size]{
+ tf->finish(buffer);
+ buffer.resize(buf_size);
+ });
+
+ const double Mbytes = (res * buf_size) / 1024 / 1024;
+
+ results[""] = Mbytes;
+ std::cout << tf->name() << " " << Mbytes << " MiB / sec with " << buf_size << " byte blocks\n";
+ }
+
+ return results;
+ }
+
+std::map<std::string, double> time_transform(const std::string& algo, RandomNumberGenerator& rng)
+ {
+ std::unique_ptr<Transformation> tf;
+ tf.reset(get_aead(algo, ENCRYPTION));
+ return time_transform(std::move(tf), rng);
+ }
+
+}
+
+void bench_algo(const std::string& algo,
+ RandomNumberGenerator& rng,
+ double seconds,
+ size_t buf_size)
+ {
+ Algorithm_Factory& af = global_state().algorithm_factory();
+
+ std::chrono::milliseconds ms(
+ static_cast<std::chrono::milliseconds::rep>(seconds * 1000));
+
+ std::map<std::string, double> speeds = algorithm_benchmark(algo, af, rng, ms, buf_size);
+
+ if(speeds.empty())
+ speeds = time_transform(algo, rng);
+
+ report_results(algo, speeds);
+
+ if(speeds.empty())
+ bench_pk(rng, algo, seconds);
+ }
+
+void benchmark(double seconds, size_t buf_size)
+ {
+ AutoSeeded_RNG rng;
+
+ 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/apps/speed/speed.h b/src/apps/speed/speed.h
new file mode 100644
index 000000000..b4aabca8a
--- /dev/null
+++ b/src/apps/speed/speed.h
@@ -0,0 +1,25 @@
+
+#ifndef BOTAN_CHECK_BENCHMARK_H__
+#define BOTAN_CHECK_BENCHMARK_H__
+
+#include "../apps.h"
+#include <botan/rng.h>
+#include <botan/transform.h>
+#include <string>
+
+using namespace Botan;
+
+int speed_main(int argc, char* argv[]);
+
+void benchmark(double seconds,
+ size_t buf_size);
+
+void bench_algo(const std::string& algo_name,
+ RandomNumberGenerator& rng,
+ double seconds,
+ size_t buf_size);
+
+void bench_pk(RandomNumberGenerator& rng,
+ const std::string& algo, double seconds);
+
+#endif
diff --git a/src/apps/speed/timer.cpp b/src/apps/speed/timer.cpp
new file mode 100644
index 000000000..9f3d34607
--- /dev/null
+++ b/src/apps/speed/timer.cpp
@@ -0,0 +1,64 @@
+/*
+* (C) 2009 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include "timer.h"
+#include <chrono>
+#include <iomanip>
+
+Timer::Timer(const std::string& n, u32bit e_mul) :
+ name(n), event_mult(e_mul)
+ {
+ time_used = 0;
+ timer_start = 0;
+ event_count = 0;
+ }
+
+void Timer::start()
+ {
+ stop();
+ timer_start = get_clock();
+ }
+
+void Timer::stop()
+ {
+ if(timer_start)
+ {
+ u64bit now = get_clock();
+
+ if(now > timer_start)
+ time_used += (now - timer_start);
+
+ timer_start = 0;
+ ++event_count;
+ }
+ }
+
+u64bit Timer::get_clock()
+ {
+ auto now = std::chrono::high_resolution_clock::now().time_since_epoch();
+ return std::chrono::duration_cast<std::chrono::nanoseconds>(now).count();
+ }
+
+std::ostream& operator<<(std::ostream& out, Timer& timer)
+ {
+ //out << timer.value() << " ";
+
+ double events_per_second_fl =
+ static_cast<double>(timer.events() / timer.seconds());
+
+ u64bit events_per_second = static_cast<u64bit>(events_per_second_fl);
+
+ out << events_per_second << " " << timer.get_name() << " per second; ";
+
+ std::string op_or_ops = (timer.events() == 1) ? "op" : "ops";
+
+ out << std::setprecision(2) << std::fixed
+ << timer.ms_per_event() << " ms/op"
+ << " (" << timer.events() << " " << op_or_ops << " in "
+ << timer.milliseconds() << " ms)";
+
+ return out;
+ }
diff --git a/src/apps/speed/timer.h b/src/apps/speed/timer.h
new file mode 100644
index 000000000..48d6b6805
--- /dev/null
+++ b/src/apps/speed/timer.h
@@ -0,0 +1,50 @@
+
+#ifndef BOTAN_BENCHMARK_TIMER_H__
+#define BOTAN_BENCHMARK_TIMER_H__
+
+#include <botan/types.h>
+#include <ostream>
+#include <string>
+
+using Botan::u64bit;
+using Botan::u32bit;
+
+class Timer
+ {
+ public:
+ static u64bit get_clock();
+
+ Timer(const std::string& name, u32bit event_mult = 1);
+
+ void start();
+
+ void stop();
+
+ u64bit value() { stop(); return time_used; }
+ double seconds() { return milliseconds() / 1000.0; }
+ double milliseconds() { return value() / 1000000.0; }
+
+ double ms_per_event() { return milliseconds() / events(); }
+ double seconds_per_event() { return seconds() / events(); }
+
+ u64bit events() const { return event_count * event_mult; }
+ std::string get_name() const { return name; }
+ private:
+ std::string name;
+ u64bit time_used, timer_start;
+ u64bit event_count, event_mult;
+ };
+
+inline bool operator<(const Timer& x, const Timer& y)
+ {
+ return (x.get_name() < y.get_name());
+ }
+
+inline bool operator==(const Timer& x, const Timer& y)
+ {
+ return (x.get_name() == y.get_name());
+ }
+
+std::ostream& operator<<(std::ostream&, Timer&);
+
+#endif
diff --git a/src/apps/tls_client.cpp b/src/apps/tls_client.cpp
index 24c8197f6..7f201d5a9 100644
--- a/src/apps/tls_client.cpp
+++ b/src/apps/tls_client.cpp
@@ -132,7 +132,7 @@ std::string protocol_chooser(const std::vector<std::string>& protocols)
}
-int tls_client(int argc, char* argv[])
+int tls_client_main(int argc, char* argv[])
{
if(argc != 2 && argc != 3 && argc != 4)
{
diff --git a/src/apps/tls_server.cpp b/src/apps/tls_server.cpp
index cb212fef6..819b9f380 100644
--- a/src/apps/tls_server.cpp
+++ b/src/apps/tls_server.cpp
@@ -121,7 +121,7 @@ void alert_received(TLS::Alert alert, const byte buf[], size_t buf_size)
}
-int tls_server(int argc, char* argv[])
+int tls_server_main(int argc, char* argv[])
{
int port = 4433;
std::string transport = "tcp";
diff --git a/src/apps/tls_server_asio.cpp b/src/apps/tls_server_asio.cpp
index 119e2154f..b49206136 100644
--- a/src/apps/tls_server_asio.cpp
+++ b/src/apps/tls_server_asio.cpp
@@ -275,7 +275,7 @@ size_t choose_thread_count()
}
-int tls_server_asio(int argc, char* argv[])
+int tls_server_asio_main(int argc, char* argv[])
{
try
{
diff --git a/src/apps/x509print.cpp b/src/apps/x509print.cpp
index c79ae7a6b..935b50668 100644
--- a/src/apps/x509print.cpp
+++ b/src/apps/x509print.cpp
@@ -1,7 +1,7 @@
#include "apps.h"
#include <botan/x509cert.h>
-int x509(int argc, char* argv[])
+int x509_main(int argc, char* argv[])
{
if(argc < 1)
{