aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2014-11-12 01:23:55 +0000
committerlloyd <[email protected]>2014-11-12 01:23:55 +0000
commit8b0cbccc7b11e545ed27bc6d7bda04b5cf632e60 (patch)
tree7ea9368d6ccaa85337a63b55e8bd15efa46fd357
parent67161b91163afad417f9483cb557b26c5f5f4bc0 (diff)
Command line prog cleanup
-rw-r--r--src/cmd/apps.h91
-rw-r--r--src/cmd/asn1.cpp160
-rw-r--r--src/cmd/base64.cpp8
-rw-r--r--src/cmd/bcrypt.cpp11
-rw-r--r--src/cmd/bzip.cpp38
-rw-r--r--src/cmd/ca.cpp15
-rw-r--r--src/cmd/cert_verify.cpp15
-rw-r--r--src/cmd/dsa_sign.cpp28
-rw-r--r--src/cmd/dsa_ver.cpp41
-rw-r--r--src/cmd/factor.cpp11
-rw-r--r--src/cmd/fpe.cpp17
-rw-r--r--src/cmd/getopt.h56
-rw-r--r--src/cmd/hash.cpp8
-rw-r--r--src/cmd/is_prime.cpp8
-rw-r--r--src/cmd/keygen.cpp84
-rw-r--r--src/cmd/main.cpp111
-rw-r--r--src/cmd/ocsp.cpp15
-rw-r--r--src/cmd/pkcs10.cpp11
-rw-r--r--src/cmd/read_ssh.cpp134
-rw-r--r--src/cmd/rng.cpp8
-rw-r--r--src/cmd/self_sig.cpp11
-rw-r--r--src/cmd/speed.cpp (renamed from src/cmd/speed/speed.cpp)9
-rw-r--r--src/cmd/speed.h11
-rw-r--r--src/cmd/speed/speed.h25
-rw-r--r--src/cmd/speed_pk.cpp (renamed from src/cmd/speed/pk_bench.cpp)0
-rw-r--r--src/cmd/timer.cpp (renamed from src/cmd/speed/timer.cpp)22
-rw-r--r--src/cmd/timer.h (renamed from src/cmd/speed/timer.h)16
-rw-r--r--src/cmd/tls_client.cpp8
-rw-r--r--src/cmd/tls_server.cpp11
-rw-r--r--src/cmd/tls_server_asio.cpp8
-rw-r--r--src/cmd/x509print.cpp9
31 files changed, 478 insertions, 522 deletions
diff --git a/src/cmd/apps.h b/src/cmd/apps.h
index 48f1f770e..5f866938f 100644
--- a/src/cmd/apps.h
+++ b/src/cmd/apps.h
@@ -1,39 +1,64 @@
-#include <botan/auto_rng.h>
-#include <botan/hex.h>
#include <iostream>
-
+#include <functional>
+#include <string>
+#include <set>
+#include <botan/hex.h>
+#include <botan/auto_rng.h>
#include "getopt.h"
using namespace Botan;
-int unimplemented(int argc, char* argv[], const char* what);
-
-#define UNIMPLEMENTED(main, prob) \
- int main(int argc, char* argv[]) { return unimplemented(argc, argv, prob); }
-
-#define DEFINE_APP(cmd) int cmd ## _main(int argc, char* argv[]);
-
-DEFINE_APP(asn1);
-DEFINE_APP(base64);
-DEFINE_APP(bcrypt);
-DEFINE_APP(bzip);
-DEFINE_APP(ca);
-DEFINE_APP(cert_verify);
-DEFINE_APP(dsa_sign);
-DEFINE_APP(dsa_verify);
-DEFINE_APP(factor);
-DEFINE_APP(fpe);
-DEFINE_APP(hash);
-DEFINE_APP(is_prime);
-DEFINE_APP(keygen);
-DEFINE_APP(ocsp_check);
-DEFINE_APP(pkcs10);
-DEFINE_APP(read_ssh);
-DEFINE_APP(rng);
-DEFINE_APP(self_sig);
-DEFINE_APP(speed);
-DEFINE_APP(tls_client);
-DEFINE_APP(tls_server);
-DEFINE_APP(tls_server_asio);
-DEFINE_APP(x509);
+typedef std::function<int (int, char*[])> main_fn;
+
+class AppRegistrations
+ {
+ public:
+ void add(const std::string& name, main_fn fn)
+ {
+ m_cmds[name] = fn;
+ }
+
+ bool has(const std::string& cmd) const
+ {
+ return m_cmds.count(cmd) > 0;
+ }
+
+ std::set<std::string> all_apps() const
+ {
+ std::set<std::string> apps;
+ for(auto i : m_cmds)
+ apps.insert(i.first);
+ return apps;
+ }
+
+ int run(const std::string& cmd, int argc, char* argv[]) const
+ {
+ auto i = m_cmds.find(cmd);
+ if(i != m_cmds.end())
+ return i->second(argc, argv);
+ return -1;
+ }
+
+ static AppRegistrations& instance()
+ {
+ static AppRegistrations s_apps;
+ return s_apps;
+ }
+
+ class AppRegistration
+ {
+ public:
+ AppRegistration(const std::string& name, main_fn fn)
+ {
+ AppRegistrations::instance().add(name, fn);
+ }
+ };
+
+ private:
+ AppRegistrations() {}
+
+ std::map<std::string, main_fn> m_cmds;
+ };
+
+#define REGISTER_APP(nm) AppRegistrations::AppRegistration g_ ## nm ## _registration(#nm, nm)
diff --git a/src/cmd/asn1.cpp b/src/cmd/asn1.cpp
index 02b73e415..cb68b2fcc 100644
--- a/src/cmd/asn1.cpp
+++ b/src/cmd/asn1.cpp
@@ -1,6 +1,7 @@
#include "apps.h"
#include <botan/bigint.h>
+#include <botan/hex.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/asn1_time.h>
@@ -25,10 +26,6 @@ using namespace Botan;
*/
#define INITIAL_LEVEL 0
-void decode(BER_Decoder&, size_t);
-void emit(const std::string&, size_t, size_t, const std::string& = "");
-std::string type_name(ASN1_Tag);
-
namespace {
std::string url_encode(const std::vector<byte>& in)
@@ -55,38 +52,63 @@ std::string url_encode(const std::vector<byte>& in)
return out.str();
}
-}
-
-int asn1_main(int argc, char* argv[])
+void emit(const std::string& type, size_t level, size_t length, const std::string& value = "")
{
- if(argc != 2)
- {
- std::cout << "Usage: " << argv[0] << " <file>\n";
- return 1;
- }
+ const size_t LIMIT = 4*1024;
+ const size_t BIN_LIMIT = 1024;
- try {
- DataSource_Stream in(argv[1]);
+ std::ostringstream out;
- if(!PEM_Code::matches(in))
- {
- BER_Decoder decoder(in);
- decode(decoder, INITIAL_LEVEL);
- }
- else
- {
- std::string label; // ignored
- BER_Decoder decoder(PEM_Code::decode(in, label));
- decode(decoder, INITIAL_LEVEL);
- }
- }
- catch(std::exception& e)
+ out << " d=" << std::setw(2) << level
+ << ", l=" << std::setw(4) << length << ": ";
+
+ for(size_t i = INITIAL_LEVEL; i != level; ++i)
+ out << ' ';
+
+ out << type;
+
+ bool should_skip = false;
+
+ if(value.length() > LIMIT)
+ should_skip = true;
+
+ if((type == "OCTET STRING" || type == "BIT STRING") && value.length() > BIN_LIMIT)
+ should_skip = true;
+
+ if(value != "" && !should_skip)
{
- std::cout << "Error: " << e.what() << "\n";
- return 2;
+ if(out.tellp() % 2 == 0) out << ' ';
+
+ while(out.tellp() < 50) out << ' ';
+
+ out << value;
}
- return 0;
+ std::cout << out.str() << "\n";
+ }
+
+std::string type_name(ASN1_Tag type)
+ {
+ if(type == PRINTABLE_STRING) return "PRINTABLE STRING";
+ if(type == NUMERIC_STRING) return "NUMERIC STRING";
+ if(type == IA5_STRING) return "IA5 STRING";
+ if(type == T61_STRING) return "T61 STRING";
+ if(type == UTF8_STRING) return "UTF8 STRING";
+ if(type == VISIBLE_STRING) return "VISIBLE STRING";
+ if(type == BMP_STRING) return "BMP STRING";
+
+ if(type == UTC_TIME) return "UTC TIME";
+ if(type == GENERALIZED_TIME) return "GENERALIZED TIME";
+
+ if(type == OCTET_STRING) return "OCTET STRING";
+ if(type == BIT_STRING) return "BIT STRING";
+
+ if(type == ENUMERATED) return "ENUMERATED";
+ if(type == INTEGER) return "INTEGER";
+ if(type == NULL_TAG) return "NULL";
+ if(type == OBJECT_ID) return "OBJECT";
+ if(type == BOOLEAN) return "BOOLEAN";
+ return "(UNKNOWN)";
}
void decode(BER_Decoder& decoder, size_t level)
@@ -184,7 +206,7 @@ void decode(BER_Decoder& decoder, size_t level)
std::vector<byte> rep;
/* If it's small, it's probably a number, not a hash */
- if(number.bits() <= 16)
+ if(number.bits() <= 20)
rep = BigInt::encode(number, BigInt::Decimal);
else
rep = BigInt::encode(number, BigInt::Hexadecimal);
@@ -283,62 +305,38 @@ void decode(BER_Decoder& decoder, size_t level)
}
}
-void emit(const std::string& type, size_t level, size_t length,
- const std::string& value)
+int asn1(int argc, char* argv[])
{
- const size_t LIMIT = 128;
- const size_t BIN_LIMIT = 64;
-
- std::ostringstream out;
-
- out << " d=" << std::setw(2) << level
- << ", l=" << std::setw(4) << length << ": ";
-
- for(size_t i = INITIAL_LEVEL; i != level; ++i)
- out << ' ';
-
- out << type;
-
- bool should_skip = false;
-
- if(value.length() > LIMIT)
- should_skip = true;
-
- if((type == "OCTET STRING" || type == "BIT STRING") && value.length() > BIN_LIMIT)
- should_skip = true;
-
- if(value != "" && !should_skip)
+ if(argc != 2)
{
- if(out.tellp() % 2 == 0) out << ' ';
+ std::cout << "Usage: " << argv[0] << " <file>\n";
+ return 1;
+ }
- while(out.tellp() < 50) out << ' ';
+ try {
+ DataSource_Stream in(argv[1]);
- out << value;
+ if(!PEM_Code::matches(in))
+ {
+ BER_Decoder decoder(in);
+ decode(decoder, INITIAL_LEVEL);
+ }
+ else
+ {
+ std::string label; // ignored
+ BER_Decoder decoder(PEM_Code::decode(in, label));
+ decode(decoder, INITIAL_LEVEL);
+ }
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Error: " << e.what() << "\n";
+ return 2;
}
- std::cout << out.str() << "\n";
+ return 0;
}
-std::string type_name(ASN1_Tag type)
- {
- if(type == PRINTABLE_STRING) return "PRINTABLE STRING";
- if(type == NUMERIC_STRING) return "NUMERIC STRING";
- if(type == IA5_STRING) return "IA5 STRING";
- if(type == T61_STRING) return "T61 STRING";
- if(type == UTF8_STRING) return "UTF8 STRING";
- if(type == VISIBLE_STRING) return "VISIBLE STRING";
- if(type == BMP_STRING) return "BMP STRING";
-
- if(type == UTC_TIME) return "UTC TIME";
- if(type == GENERALIZED_TIME) return "GENERALIZED TIME";
-
- if(type == OCTET_STRING) return "OCTET STRING";
- if(type == BIT_STRING) return "BIT STRING";
+REGISTER_APP(asn1);
- if(type == ENUMERATED) return "ENUMERATED";
- if(type == INTEGER) return "INTEGER";
- if(type == NULL_TAG) return "NULL";
- if(type == OBJECT_ID) return "OBJECT";
- if(type == BOOLEAN) return "BOOLEAN";
- return "(UNKNOWN)";
- }
+}
diff --git a/src/cmd/base64.cpp b/src/cmd/base64.cpp
index 34711857c..de9954bab 100644
--- a/src/cmd/base64.cpp
+++ b/src/cmd/base64.cpp
@@ -15,7 +15,9 @@
#include <botan/b64_filt.h>
#include <botan/pipe.h>
-int base64_main(int argc, char* argv[])
+namespace {
+
+int base64(int argc, char* argv[])
{
if(argc < 2)
{
@@ -83,3 +85,7 @@ int base64_main(int argc, char* argv[])
}
return 0;
}
+
+REGISTER_APP(base64);
+
+}
diff --git a/src/cmd/bcrypt.cpp b/src/cmd/bcrypt.cpp
index 2b4b4e61d..30b0c425a 100644
--- a/src/cmd/bcrypt.cpp
+++ b/src/cmd/bcrypt.cpp
@@ -3,7 +3,9 @@
#if defined(BOTAN_HAS_BCRYPT)
#include <botan/bcrypt.h>
-int bcrypt_main(int argc, char* argv[])
+namespace {
+
+int bcrypt(int argc, char* argv[])
{
if(argc == 2)
{
@@ -32,6 +34,9 @@ int bcrypt_main(int argc, char* argv[])
<< " " << argv[0] << " password passhash\n";
return 1;
}
-#else
-UNIMPLEMENTED(bcrypt_main, "bcrypt");
+
+REGISTER_APP(bcrypt);
+
+}
+
#endif
diff --git a/src/cmd/bzip.cpp b/src/cmd/bzip.cpp
index 3b8c7cdc2..15403ea88 100644
--- a/src/cmd/bzip.cpp
+++ b/src/cmd/bzip.cpp
@@ -7,29 +7,16 @@
#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";
+#include <botan/bzip2.h>
+
+namespace {
-int bzip_main(int argc, char* argv[])
+int bzip2(int argc, char* argv[])
{
+ const std::string SUFFIX = ".bz2";
+
if(argc < 2)
{
std::cout << "Usage: " << argv[0]
@@ -37,7 +24,6 @@ int bzip_main(int argc, char* argv[])
return 1;
}
-#ifdef BOTAN_HAS_COMPRESSOR_BZIP2
std::vector<std::string> files;
bool decompress = false, small = false;
int level = 9;
@@ -104,12 +90,14 @@ int bzip_main(int argc, char* argv[])
catch(std::exception& e)
{
std::cout << "Exception caught: " << e.what() << std::endl;
- return 1;
+ return 2;
}
-#else
-
- std::cout << "Sorry, support for bzip2 not compiled into Botan\n";
-#endif
return 1;
}
+
+REGISTER_APP(bzip2);
+
+}
+
+#endif
diff --git a/src/cmd/ca.cpp b/src/cmd/ca.cpp
index 7dba4c7fe..453258ac6 100644
--- a/src/cmd/ca.cpp
+++ b/src/cmd/ca.cpp
@@ -1,14 +1,14 @@
#include "apps.h"
+
#if defined(BOTAN_HAS_X509_CERTIFICATES)
#include <botan/x509_ca.h>
-using namespace Botan;
-#include <iostream>
-#include <memory>
-#include <chrono>
+namespace {
-int ca_main(int argc, char* argv[])
+int ca(int argc, char* argv[])
{
+ using namespace Botan;
+
if(argc != 5)
{
std::cout << "Usage: " << argv[0] << " <passphrase> "
@@ -61,4 +61,9 @@ int ca_main(int argc, char* argv[])
}
return 0;
}
+
+REGISTER_APP(ca);
+
+}
+
#endif
diff --git a/src/cmd/cert_verify.cpp b/src/cmd/cert_verify.cpp
index daf7240f2..800ac8f6c 100644
--- a/src/cmd/cert_verify.cpp
+++ b/src/cmd/cert_verify.cpp
@@ -6,15 +6,17 @@
*/
#include "apps.h"
+
#if defined(BOTAN_HAS_X509_CERTIFICATES)
-#include <botan/x509cert.h>
+
#include <botan/x509path.h>
-#include <iostream>
-using namespace Botan;
+namespace {
-int cert_verify_main(int argc, char* argv[])
+int cert_verify(int argc, char* argv[])
{
+ using namespace Botan;
+
if(argc <= 2)
{
std::cout << "Usage: " << argv[0] << " subject.pem [CA certificates...]\n";
@@ -42,4 +44,9 @@ int cert_verify_main(int argc, char* argv[])
return 0;
}
+
+}
+
+REGISTER_APP(cert_verify);
+
#endif
diff --git a/src/cmd/dsa_sign.cpp b/src/cmd/dsa_sign.cpp
index 365e91a37..edbf135c3 100644
--- a/src/cmd/dsa_sign.cpp
+++ b/src/cmd/dsa_sign.cpp
@@ -1,23 +1,20 @@
#include "apps.h"
-#include <iostream>
-#include <iomanip>
-#include <fstream>
-#include <string>
-#include <memory>
-
-#include <botan/base64.h>
-#include <botan/pubkey.h>
#if defined(BOTAN_HAS_DSA)
#include <botan/dsa.h>
+#include <botan/pubkey.h>
+#include <botan/base64.h>
+#include <fstream>
-using namespace Botan;
-
-const std::string SUFFIX = ".sig";
+namespace {
-int dsa_sign_main(int argc, char* argv[])
+int dsa_sign(int argc, char* argv[])
{
+ using namespace Botan;
+
+ const std::string SUFFIX = ".sig";
+
if(argc != 4)
{
std::cout << "Usage: " << argv[0] << " keyfile messagefile passphrase"
@@ -73,6 +70,9 @@ int dsa_sign_main(int argc, char* argv[])
}
return 0;
}
-#else
-UNIMPLEMENTED(dsa_sign_main, "DSA");
+
+REGISTER_APP(dsa_sign);
+
+}
+
#endif
diff --git a/src/cmd/dsa_ver.cpp b/src/cmd/dsa_ver.cpp
index a5d0ca271..dddf34dbf 100644
--- a/src/cmd/dsa_ver.cpp
+++ b/src/cmd/dsa_ver.cpp
@@ -1,28 +1,17 @@
#include "apps.h"
-#include <iostream>
-#include <iomanip>
-#include <fstream>
-#include <cstdlib>
-#include <string>
-#include <memory>
+#if defined(BOTAN_HAS_DSA)
+
+#include <fstream>
#include <botan/pubkey.h>
#include <botan/dsa.h>
-#include <botan/b64_filt.h>
+#include <botan/base64.h>
+
using namespace Botan;
namespace {
-secure_vector<byte> b64_decode(const std::string& in)
- {
- Pipe pipe(new Base64_Decoder);
- pipe.process_msg(in);
- return pipe.read_all();
- }
-
-}
-
-int dsa_verify_main(int argc, char* argv[])
+int dsa_verify(int argc, char* argv[])
{
if(argc != 4)
{
@@ -59,7 +48,7 @@ int dsa_verify_main(int argc, char* argv[])
return 1;
}
- secure_vector<byte> sig = b64_decode(sigstr);
+ secure_vector<byte> sig = base64_decode(sigstr);
PK_Verifier ver(*dsakey, "EMSA1(SHA-1)");
@@ -71,14 +60,26 @@ int dsa_verify_main(int argc, char* argv[])
const bool ok = ver.check_signature(sig);
if(ok)
+ {
std::cout << "Signature verified\n";
+ return 0;
+ }
else
+ {
std::cout << "Signature did NOT verify\n";
+ return 1;
+ }
}
catch(std::exception& e)
{
std::cout << "Exception caught: " << e.what() << std::endl;
- return 1;
+ return 2;
}
- return 0;
}
+
+REGISTER_APP(dsa_verify);
+
+}
+
+#endif
+
diff --git a/src/cmd/factor.cpp b/src/cmd/factor.cpp
index 5f6d82f8c..b95b8ea95 100644
--- a/src/cmd/factor.cpp
+++ b/src/cmd/factor.cpp
@@ -11,12 +11,13 @@
#include <botan/reducer.h>
#include <botan/numthry.h>
-using namespace Botan;
#include <algorithm>
#include <iostream>
#include <iterator>
+using namespace Botan;
+
namespace {
/*
@@ -119,9 +120,7 @@ std::vector<BigInt> factorize(const BigInt& n_in,
return factors;
}
-}
-
-int factor_main(int argc, char* argv[])
+int factor(int argc, char* argv[])
{
if(argc != 2)
{
@@ -151,3 +150,7 @@ int factor_main(int argc, char* argv[])
}
return 0;
}
+
+REGISTER_APP(factor);
+
+}
diff --git a/src/cmd/fpe.cpp b/src/cmd/fpe.cpp
index d1e748b4c..088b10e82 100644
--- a/src/cmd/fpe.cpp
+++ b/src/cmd/fpe.cpp
@@ -1,14 +1,13 @@
#include "apps.h"
#if defined(BOTAN_HAS_FPE_FE1)
+
#include <botan/fpe_fe1.h>
#include <botan/sha160.h>
+#include <stdexcept>
using namespace Botan;
-#include <iostream>
-#include <stdexcept>
-
namespace {
byte luhn_checksum(u64bit cc_number)
@@ -102,9 +101,7 @@ u64bit decrypt_cc_number(u64bit enc_cc,
return cc_derank(dec_cc);
}
-}
-
-int fpe_main(int argc, char* argv[])
+int fpe(int argc, char* argv[])
{
if(argc != 4)
{
@@ -143,6 +140,10 @@ int fpe_main(int argc, char* argv[])
return 0;
}
-#else
-UNIMPLEMENTED(fpe_main, "FPE");
+
+REGISTER_APP(fpe);
+
+}
+
#endif
+
diff --git a/src/cmd/getopt.h b/src/cmd/getopt.h
index a4f5f4d6f..4fecada2a 100644
--- a/src/cmd/getopt.h
+++ b/src/cmd/getopt.h
@@ -43,50 +43,30 @@ class OptionParser
return is_set(key) ? value(key) : or_else;
}
- void parse(char* argv[])
+ size_t int_value_or_else(const std::string& key, size_t or_else) const
{
- std::vector<std::string> args;
- for(int j = 1; argv[j]; j++)
- args.push_back(argv[j]);
-
- for(size_t j = 0; j != args.size(); j++)
- {
- std::string arg = args[j];
-
- if(arg.size() > 2 && arg[0] == '-' && arg[1] == '-')
- {
- const std::string opt_name = arg.substr(0, arg.find('='));
-
- arg = arg.substr(2);
-
- std::string::size_type mark = arg.find('=');
- OptionFlag opt = find_option(arg.substr(0, mark));
-
- if(opt.takes_arg())
- {
- if(mark == std::string::npos)
- throw std::runtime_error("Option " + opt_name +
- " requires an argument");
-
- std::string name = arg.substr(0, mark);
- std::string value = arg.substr(mark+1);
+ return is_set(key) ? Botan::to_u32bit(value(key)) : or_else;
+ }
- options[name] = value;
- }
- else
- {
- if(mark != std::string::npos)
- throw std::runtime_error("Option " + opt_name +
- " does not take an argument");
+ void help(std::ostream& o, const char* cmd = nullptr)
+ {
+ o << "Usage: ";
+ if(cmd)
+ o << cmd << " ";
- options[arg] = "";
- }
- }
- else
- leftover.push_back(arg);
+ for(auto flag : flags)
+ {
+ o << flag.name();
+ if(flag.takes_arg())
+ o << "=";
+ o << " ";
}
+
+ o << "\n";
}
+ void parse(char* argv[]);
+
OptionParser(const std::string& opt_string)
{
std::vector<std::string> opts = Botan::split_on(opt_string, '|');
diff --git a/src/cmd/hash.cpp b/src/cmd/hash.cpp
index 5c5705210..869eb5797 100644
--- a/src/cmd/hash.cpp
+++ b/src/cmd/hash.cpp
@@ -11,7 +11,9 @@
using namespace Botan;
-int hash_main(int argc, char* argv[])
+namespace {
+
+int hash(int argc, char* argv[])
{
if(argc < 3)
{
@@ -56,3 +58,7 @@ int hash_main(int argc, char* argv[])
}
return 0;
}
+
+REGISTER_APP(hash);
+
+}
diff --git a/src/cmd/is_prime.cpp b/src/cmd/is_prime.cpp
index 658401690..8bfa4421a 100644
--- a/src/cmd/is_prime.cpp
+++ b/src/cmd/is_prime.cpp
@@ -1,7 +1,9 @@
#include "apps.h"
#include <botan/numthry.h>
-int is_prime_main(int argc, char* argv[])
+namespace {
+
+int is_prime(int argc, char* argv[])
{
if(argc != 2 && argc != 3)
{
@@ -31,3 +33,7 @@ int is_prime_main(int argc, char* argv[])
return 1;
}
}
+
+REGISTER_APP(is_prime);
+
+}
diff --git a/src/cmd/keygen.cpp b/src/cmd/keygen.cpp
index 40055f6cf..6aa74a08f 100644
--- a/src/cmd/keygen.cpp
+++ b/src/cmd/keygen.cpp
@@ -5,29 +5,74 @@
#include <cstdlib>
#include <memory>
+#if defined(BOTAN_HAS_RSA)
#include <botan/rsa.h>
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+#include <botan/dsa.h>
+#endif
+
+#if defined(BOTAN_HAS_ECDSA)
+#include <botan/ecdsa.h>
+#endif
+
using namespace Botan;
-int keygen_main(int argc, char* argv[])
+namespace {
+
+std::string dsa_group_for(size_t bits)
+ {
+ if(bits == 1024)
+ return "dsa/jce/1024";
+ if(bits == 2048)
+ return "dsa/botan/2048";
+ if(bits == 3072)
+ return "dsa/botan/3072";
+ throw std::runtime_error("No registered DSA group for " + std::to_string(bits) + " bits");
+ }
+
+Private_Key* gen_key(RandomNumberGenerator& rng, const std::string& algo, size_t bits)
{
- if(argc != 2 && argc != 3)
+#if defined(BOTAN_HAS_RSA)
+ if(algo == "rsa")
+ return new RSA_PrivateKey(rng, bits);
+#endif
+
+#if defined(BOTAN_HAS_DSA)
+ if(algo == "dsa")
{
- std::cout << "Usage: " << argv[0] << " bitsize [passphrase]"
- << std::endl;
- return 1;
+ DL_Group grp(dsa_group_for(bits));
+ return new DSA_PrivateKey(rng, grp);
}
+#endif
- const size_t bits = std::atoi(argv[1]);
- if(bits < 1024 || bits > 16384)
+#if defined(BOTAN_HAS_ECDSA)
+ if(algo == "ecdsa")
{
- std::cout << "Invalid argument for bitsize" << std::endl;
- return 1;
+ EC_Group grp("secp" + std::to_string(bits) + "r1");
+ return new ECDSA_PrivateKey(rng, grp);
}
+#endif
+
+ throw std::runtime_error("Unknown algorithm " + algo);
+ }
+
+
+int keygen(int argc, char* argv[])
+ {
+ OptionParser opts("algo=|bits=|passphrase=");
+ opts.parse(argv);
+
+ const std::string algo = opts.value_or_else("algo", "rsa");
+ const size_t bits = opts.int_value_or_else("bits", 1024);
+ const std::string pass = opts.value_or_else("passphrase", "");
try
{
- std::ofstream pub("rsapub.pem");
- std::ofstream priv("rsapriv.pem");
+ std::ofstream pub("public.pem");
+ std::ofstream priv("private.pem");
+
if(!priv || !pub)
{
std::cout << "Couldn't write output files" << std::endl;
@@ -36,13 +81,16 @@ int keygen_main(int argc, char* argv[])
AutoSeeded_RNG rng;
- RSA_PrivateKey key(rng, bits);
- pub << X509::PEM_encode(key);
+ std::auto_ptr<Private_Key> key(gen_key(rng, algo, bits));
- if(argc == 2)
- priv << PKCS8::PEM_encode(key);
+ pub << X509::PEM_encode(*key);
+
+ if(pass == "")
+ priv << PKCS8::PEM_encode(*key);
else
- priv << PKCS8::PEM_encode(key, rng, argv[2]);
+ priv << PKCS8::PEM_encode(*key, rng, pass);
+
+ std::cout << "Wrote " << bits << " bit " << algo << " key to public.pem / private.pem\n";
}
catch(std::exception& e)
{
@@ -51,3 +99,7 @@ int keygen_main(int argc, char* argv[])
return 0;
}
+
+REGISTER_APP(keygen);
+
+}
diff --git a/src/cmd/main.cpp b/src/cmd/main.cpp
index f04c7daee..65530b23a 100644
--- a/src/cmd/main.cpp
+++ b/src/cmd/main.cpp
@@ -30,12 +30,30 @@ namespace {
int help(int , char* argv[])
{
- std::cout << "Usage: " << argv[0] << " [subcommand]\n";
- std::cout << "version config speed cpuid bcrypt x509 factor tls_client tls_server asn1 base64 hash self_sig ...\n";
+ std::cout << "Usage: " << argv[0] << " [subcommand] [subcommand-options]\n";
+
+ std::set<std::string> apps = AppRegistrations::instance().all_apps();
+
+ std::cout << "Available commands:\n";
+
+ size_t idx = 1;
+ for(auto&& app: apps)
+ {
+ std::cout << app;
+
+ if(idx % 3 == 0)
+ std::cout << "\n";
+ else
+ std::cout << std::string(18-app.size(), ' ');
+
+ ++idx;
+ }
+ std::cout << "\n";
+
return 1;
}
-int config_main(int argc, char* argv[])
+int config(int argc, char* argv[])
{
if(argc != 2)
{
@@ -70,8 +88,9 @@ int config_main(int argc, char* argv[])
return 0;
}
+REGISTER_APP(config);
-int version_main(int argc, char* argv[])
+int version(int argc, char* argv[])
{
if(BOTAN_VERSION_MAJOR != version_major() ||
BOTAN_VERSION_MINOR != version_minor() ||
@@ -99,20 +118,39 @@ int version_main(int argc, char* argv[])
}
else
{
- std::cout << "Usage: " << argv[0] << " [--full]\n";
+ std::cout << "Usage: " << argv[0] << " version [--full]\n";
return 1;
}
return 0;
}
+REGISTER_APP(version);
-}
+int cpuid(int, char*[])
+ {
+ CPUID::print(std::cout);
+ return 0;
+ }
+REGISTER_APP(cpuid);
-int unimplemented(int , char* argv[], const char* what)
+#if defined(BOTAN_HAS_HTTP_UTIL)
+int http_get(int argc, char* argv[])
{
- std::cout << argv[0] << " command not implemented - library missing " << what << "\n";
- return 1;
+ if(argc != 2)
+ {
+ std::cout << "Usage " << argv[0] << " <url>\n";
+ return 1;
+ }
+
+ auto resp = HTTP::GET_sync(argv[2]);
+ std::cout << resp << "\n";
+ return 0;
}
+REGISTER_APP(http_get);
+
+#endif
+
+}
int main(int argc, char* argv[])
{
@@ -125,59 +163,12 @@ int main(int argc, char* argv[])
const std::string cmd = argv[1];
- if(cmd == "help")
+ if(cmd == "help" || cmd == "-h")
return help(argc, argv);
- if(cmd == "config" && argc > 1)
- return config_main(argc - 1, argv + 1);
-
- if(cmd == "version" && argc > 1)
- return version_main(argc - 1, argv + 1);
-
- if(cmd == "cpuid")
- {
- CPUID::print(std::cout);
- return 0;
- }
-
-#if defined(BOTAN_HAS_HTTP_UTIL)
- if(cmd == "http_get")
- {
- auto resp = HTTP::GET_sync(argv[2]);
- std::cout << resp << "\n";
- }
-#endif
-
-#define CALL_APP(cmdsym) \
- do { if(cmd == #cmdsym) { return cmdsym ##_main (argc - 1, argv + 1); } } while(0)
-
- CALL_APP(asn1);
- CALL_APP(base64);
- CALL_APP(bcrypt);
- CALL_APP(bzip);
- CALL_APP(dsa_sign);
- CALL_APP(dsa_verify);
- CALL_APP(factor);
- CALL_APP(fpe);
- CALL_APP(hash);
- CALL_APP(is_prime);
- CALL_APP(keygen);
- CALL_APP(read_ssh);
- CALL_APP(rng);
- CALL_APP(speed);
-
-#if defined(BOTAN_HAS_TLS)
- CALL_APP(tls_client);
- CALL_APP(tls_server);
- CALL_APP(tls_server_asio);
-#endif
-
-#if defined(BOTAN_HAS_X509_CERTIFICATES)
- CALL_APP(ca);
- CALL_APP(pkcs10);
- CALL_APP(self_sig);
- CALL_APP(x509);
-#endif
+ AppRegistrations& apps = AppRegistrations::instance();
+ if(apps.has(cmd))
+ return apps.run(cmd, argc - 1, argv + 1);
std::cout << "Unknown command " << cmd << "\n";
return help(argc, argv);
diff --git a/src/cmd/ocsp.cpp b/src/cmd/ocsp.cpp
index a36dd73f6..dba49b600 100644
--- a/src/cmd/ocsp.cpp
+++ b/src/cmd/ocsp.cpp
@@ -1,15 +1,17 @@
#include "apps.h"
-#if defined(BOTAN_HAS_X509_CERTIFICATES)
+
+#if defined(BOTAN_HAS_OCSP)
+
#include <botan/x509cert.h>
#include <botan/certstor.h>
#include <botan/x509path.h>
#include <botan/ocsp.h>
-#include <iostream>
-
using namespace Botan;
-int ocsp_check_main(int argc, char* argv[])
+namespace {
+
+int ocsp_check(int argc, char* argv[])
{
if(argc != 2)
{
@@ -37,4 +39,9 @@ int ocsp_check_main(int argc, char* argv[])
return 1;
}
}
+
+REGISTER_APP(ocsp_check);
+
+}
+
#endif
diff --git a/src/cmd/pkcs10.cpp b/src/cmd/pkcs10.cpp
index 2dad14575..0cdb47878 100644
--- a/src/cmd/pkcs10.cpp
+++ b/src/cmd/pkcs10.cpp
@@ -1,15 +1,17 @@
#include "apps.h"
+
#if defined(BOTAN_HAS_X509_CERTIFICATES)
#include <botan/x509self.h>
#include <botan/rsa.h>
#include <botan/dsa.h>
using namespace Botan;
-#include <iostream>
#include <fstream>
#include <memory>
-int pkcs10_main(int argc, char* argv[])
+namespace {
+
+int pkcs10(int argc, char* argv[])
{
if(argc != 6)
{
@@ -47,4 +49,9 @@ int pkcs10_main(int argc, char* argv[])
}
return 0;
}
+
+REGISTER_APP(pkcs10);
+
+}
+
#endif
diff --git a/src/cmd/read_ssh.cpp b/src/cmd/read_ssh.cpp
deleted file mode 100644
index bca4a2a0a..000000000
--- a/src/cmd/read_ssh.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
-* (C) 2009 Jack Lloyd
-*
-* Distributed under the terms of the Botan license
-*/
-
-/*
-* Example of reading SSH2 format public keys (see RFC 4716)
-*/
-
-#include "apps.h"
-
-#include <botan/x509_key.h>
-#include <botan/filters.h>
-#include <botan/loadstor.h>
-#include <botan/rsa.h>
-#include <botan/dsa.h>
-#include <fstream>
-#include <memory>
-
-using namespace Botan;
-
-namespace {
-
-u32bit read_u32bit(Pipe& pipe)
- {
- byte out[4] = { 0 };
- pipe.read(out, 4);
- u32bit len = load_be<u32bit>(out, 0);
- if(len > 10000)
- throw Decoding_Error("Huge size in read_u32bit, something went wrong");
- return len;
- }
-
-std::string read_string(Pipe& pipe)
- {
- u32bit len = read_u32bit(pipe);
-
- std::string out(len, 'X');
- pipe.read(reinterpret_cast<byte*>(&out[0]), len);
- return out;
- }
-
-BigInt read_bigint(Pipe& pipe)
- {
- u32bit len = read_u32bit(pipe);
-
- secure_vector<byte> buf(len);
- pipe.read(&buf[0], len);
- return BigInt::decode(buf);
- }
-
-Public_Key* read_ssh_pubkey(const std::string& file)
- {
- std::ifstream in(file.c_str());
-
- const std::string ssh_header = "---- BEGIN SSH2 PUBLIC KEY ----";
- const std::string ssh_trailer = "---- END SSH2 PUBLIC KEY ----";
-
- std::string hex_bits;
-
- std::string line;
- std::getline(in, line);
-
- if(line != ssh_header)
- return nullptr;
-
- while(in.good())
- {
- std::getline(in, line);
-
- if(line.find("Comment: ") == 0)
- {
- while(line[line.size()-1] == '\\')
- std::getline(in, line);
- std::getline(in, line);
- }
-
- if(line == ssh_trailer)
- break;
-
- hex_bits += line;
- }
-
- Pipe pipe(new Base64_Decoder);
- pipe.process_msg(hex_bits);
-
- std::string key_type = read_string(pipe);
-
- if(key_type != "ssh-rsa" && key_type != "ssh-dss")
- return nullptr;
-
- if(key_type == "ssh-rsa")
- {
- BigInt e = read_bigint(pipe);
- BigInt n = read_bigint(pipe);
- return new RSA_PublicKey(n, e);
- }
- else if(key_type == "ssh-dss")
- {
- BigInt p = read_bigint(pipe);
- BigInt q = read_bigint(pipe);
- BigInt g = read_bigint(pipe);
- BigInt y = read_bigint(pipe);
-
- return new DSA_PublicKey(DL_Group(p, q, g), y);
- }
-
- return nullptr;
- }
-
-}
-
-int read_ssh_main(int argc, char* argv[])
- {
- if(argc != 2)
- {
- std::cout << "Usage: " << argv[0] << " file";
- return 1;
- }
-
- const std::string filename = argv[1];
- std::unique_ptr<Public_Key> key(read_ssh_pubkey(filename));
-
- if(!key)
- {
- std::cout << "Failed to read" << filename << "\n";
- return 1;
- }
-
- std::cout << X509::PEM_encode(*key);
-
- return 0;
- }
diff --git a/src/cmd/rng.cpp b/src/cmd/rng.cpp
index e2a7a8270..187fbad1e 100644
--- a/src/cmd/rng.cpp
+++ b/src/cmd/rng.cpp
@@ -7,7 +7,9 @@
#include "apps.h"
#include <botan/libstate.h>
-int rng_main(int argc, char* argv[])
+namespace {
+
+int rng(int argc, char* argv[])
{
if(argc == 1)
{
@@ -49,3 +51,7 @@ int rng_main(int argc, char* argv[])
return 0;
}
+
+REGISTER_APP(rng);
+
+}
diff --git a/src/cmd/self_sig.cpp b/src/cmd/self_sig.cpp
index 592a7f279..2bef9492d 100644
--- a/src/cmd/self_sig.cpp
+++ b/src/cmd/self_sig.cpp
@@ -1,15 +1,17 @@
#include "apps.h"
+
#if defined(BOTAN_HAS_X509_CERTIFICATES)
#include <botan/x509self.h>
#include <botan/rsa.h>
#include <botan/dsa.h>
using namespace Botan;
-#include <iostream>
#include <fstream>
#include <memory>
-int self_sig_main(int argc, char* argv[])
+namespace {
+
+int self_sig(int argc, char* argv[])
{
if(argc != 7)
{
@@ -69,4 +71,9 @@ int self_sig_main(int argc, char* argv[])
return 0;
}
+
+REGISTER_APP(self_sig);
+
+}
+
#endif
diff --git a/src/cmd/speed/speed.cpp b/src/cmd/speed.cpp
index e7e3e5ff7..9c6d8a585 100644
--- a/src/cmd/speed/speed.cpp
+++ b/src/cmd/speed.cpp
@@ -5,6 +5,7 @@
*/
#include "speed.h"
+#include "apps.h"
#include <iostream>
#include <iomanip>
@@ -170,8 +171,6 @@ void time_transform(const std::string& algo, RandomNumberGenerator& rng)
time_transform(std::move(tf), rng);
}
-}
-
void bench_algo(const std::string& algo,
RandomNumberGenerator& rng,
double seconds,
@@ -193,7 +192,7 @@ void bench_algo(const std::string& algo,
bench_pk(rng, algo, seconds);
}
-int speed_main(int argc, char* argv[])
+int speed(int argc, char* argv[])
{
OptionParser opts("seconds=|buf-size=");
opts.parse(argv);
@@ -239,3 +238,7 @@ int speed_main(int argc, char* argv[])
return 0;
}
+
+REGISTER_APP(speed);
+
+}
diff --git a/src/cmd/speed.h b/src/cmd/speed.h
new file mode 100644
index 000000000..97aa0ecc1
--- /dev/null
+++ b/src/cmd/speed.h
@@ -0,0 +1,11 @@
+
+#ifndef BOTAN_CHECK_BENCHMARK_H__
+#define BOTAN_CHECK_BENCHMARK_H__
+
+#include <botan/rng.h>
+#include <string>
+
+void bench_pk(Botan::RandomNumberGenerator& rng,
+ const std::string& algo, double seconds);
+
+#endif
diff --git a/src/cmd/speed/speed.h b/src/cmd/speed/speed.h
deleted file mode 100644
index b4aabca8a..000000000
--- a/src/cmd/speed/speed.h
+++ /dev/null
@@ -1,25 +0,0 @@
-
-#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/cmd/speed/pk_bench.cpp b/src/cmd/speed_pk.cpp
index 6ebb366c5..6ebb366c5 100644
--- a/src/cmd/speed/pk_bench.cpp
+++ b/src/cmd/speed_pk.cpp
diff --git a/src/cmd/speed/timer.cpp b/src/cmd/timer.cpp
index 9f3d34607..14eb47524 100644
--- a/src/cmd/speed/timer.cpp
+++ b/src/cmd/timer.cpp
@@ -8,31 +8,23 @@
#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();
+ m_timer_start = get_clock();
}
void Timer::stop()
{
- if(timer_start)
+ if(m_timer_start)
{
- u64bit now = get_clock();
+ const u64bit now = get_clock();
- if(now > timer_start)
- time_used += (now - timer_start);
+ if(now > m_timer_start)
+ m_time_used += (now - m_timer_start);
- timer_start = 0;
- ++event_count;
+ m_timer_start = 0;
+ ++m_event_count;
}
}
diff --git a/src/cmd/speed/timer.h b/src/cmd/timer.h
index 48d6b6805..8e3dc6b26 100644
--- a/src/cmd/speed/timer.h
+++ b/src/cmd/timer.h
@@ -14,25 +14,25 @@ class Timer
public:
static u64bit get_clock();
- Timer(const std::string& name, u32bit event_mult = 1);
+ Timer(const std::string& name, u32bit event_mult = 1) :
+ m_name(name), m_event_mult(event_mult) {}
void start();
-
void stop();
- u64bit value() { stop(); return time_used; }
+ u64bit value() { stop(); return m_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; }
+ u64bit events() const { return m_event_count * m_event_mult; }
+ std::string get_name() const { return m_name; }
private:
- std::string name;
- u64bit time_used, timer_start;
- u64bit event_count, event_mult;
+ std::string m_name;
+ u64bit m_time_used = 0, m_timer_start = 0;
+ u64bit m_event_count = 0, m_event_mult = 0;
};
inline bool operator<(const Timer& x, const Timer& y)
diff --git a/src/cmd/tls_client.cpp b/src/cmd/tls_client.cpp
index 5df6e72c5..072d674ea 100644
--- a/src/cmd/tls_client.cpp
+++ b/src/cmd/tls_client.cpp
@@ -10,7 +10,6 @@
#endif
#include <string>
-#include <iostream>
#include <memory>
#include <sys/types.h>
@@ -132,9 +131,7 @@ std::string protocol_chooser(const std::vector<std::string>& protocols)
return "http/1.1";
}
-}
-
-int tls_client_main(int argc, char* argv[])
+int tls_client(int argc, char* argv[])
{
if(argc != 2 && argc != 3 && argc != 4)
{
@@ -272,4 +269,7 @@ int tls_client_main(int argc, char* argv[])
return 0;
}
+REGISTER_APP(tls_client);
+
+}
#endif
diff --git a/src/cmd/tls_server.cpp b/src/cmd/tls_server.cpp
index 9db250859..fd9f7ef5d 100644
--- a/src/cmd/tls_server.cpp
+++ b/src/cmd/tls_server.cpp
@@ -15,9 +15,6 @@ using namespace Botan;
using namespace std::placeholders;
-#include <string>
-#include <iostream>
-#include <memory>
#include <list>
#include <sys/types.h>
@@ -120,9 +117,7 @@ void alert_received(TLS::Alert alert, const byte[], size_t)
std::cout << "Alert: " << alert.type_string() << "\n";
}
-}
-
-int tls_server_main(int argc, char* argv[])
+int tls_server(int argc, char* argv[])
{
int port = 4433;
std::string transport = "tcp";
@@ -262,4 +257,8 @@ int tls_server_main(int argc, char* argv[])
return 0;
}
+REGISTER_APP(tls_server);
+
+}
+
#endif
diff --git a/src/cmd/tls_server_asio.cpp b/src/cmd/tls_server_asio.cpp
index f0847b9e0..33d743e4f 100644
--- a/src/cmd/tls_server_asio.cpp
+++ b/src/cmd/tls_server_asio.cpp
@@ -276,9 +276,7 @@ size_t choose_thread_count()
return 2;
}
-}
-
-int tls_server_asio_main(int argc, char* argv[])
+int tls_server_asio(int argc, char* argv[])
{
try
{
@@ -315,4 +313,8 @@ int tls_server_asio_main(int argc, char* argv[])
return 0;
}
+}
+
+REGISTER_APP(tls_server_asio);
+
#endif
diff --git a/src/cmd/x509print.cpp b/src/cmd/x509print.cpp
index c2c63021c..006c51de8 100644
--- a/src/cmd/x509print.cpp
+++ b/src/cmd/x509print.cpp
@@ -2,7 +2,9 @@
#if defined(BOTAN_HAS_X509_CERTIFICATES)
#include <botan/x509cert.h>
-int x509_main(int argc, char* argv[])
+namespace {
+
+int x509print(int argc, char* argv[])
{
if(argc < 1)
{
@@ -16,4 +18,9 @@ int x509_main(int argc, char* argv[])
return 0;
}
+
+REGISTER_APP(x509print);
+
+}
+
#endif