diff options
author | Jack Lloyd <[email protected]> | 2015-12-19 15:36:40 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2015-12-19 15:36:40 -0500 |
commit | b48e6fb097c62bb246629ee7a182c57e497e4130 (patch) | |
tree | 0cb8ea2d05a89f5e90467f323ae56268d4d3480e /src/cli/asn1.cpp | |
parent | d774a9edc46ffcebb28205a678058f083ea75c28 (diff) |
CLI rewrite
The command line tools' origin as a collection of examples and test
programs glued together led to some unfortunate problems; lots of
hardcoded values, missing parameters, and obsolete crypto.
Adds a small library for writing command line programs of the sort
needed here (cli.h), which cuts the length of many of the commands in
half and makes commands more pleasant to write and extend.
Generalizes a lot of the commands also, eg previously only
signing/verification with DSA/SHA-1 was included!
Removes the fuzzer entry point since that's fairly useless outside of
an instrumented build.
Removes the in-library API for benchmarking.
Diffstat (limited to 'src/cli/asn1.cpp')
-rw-r--r-- | src/cli/asn1.cpp | 227 |
1 files changed, 127 insertions, 100 deletions
diff --git a/src/cli/asn1.cpp b/src/cli/asn1.cpp index 2aa94cc39..8096f2d19 100644 --- a/src/cli/asn1.cpp +++ b/src/cli/asn1.cpp @@ -4,7 +4,7 @@ * Botan is released under the Simplified BSD License (see license.txt) */ -#include "apps.h" +#include "cli.h" #if defined(BOTAN_HAS_ASN1) && defined(BOTAN_HAS_PEM_CODEC) @@ -17,7 +17,6 @@ #include <botan/oids.h> #include <botan/pem.h> #include <botan/charset.h> -using namespace Botan; #include <iostream> #include <iomanip> @@ -34,9 +33,11 @@ using namespace Botan; */ #define INITIAL_LEVEL 0 +namespace Botan_CLI { + namespace { -std::string url_encode(const std::vector<byte>& in) +std::string url_encode(const std::vector<uint8_t>& in) { std::ostringstream out; @@ -55,7 +56,7 @@ std::string url_encode(const std::vector<byte>& in) } if(unprintable >= in.size() / 4) - return hex_encode(in); + return Botan::hex_encode(in); return out.str(); } @@ -95,57 +96,89 @@ void emit(const std::string& type, size_t level, size_t length, const std::strin std::cout << out.str() << std::endl; } -std::string type_name(ASN1_Tag type) +std::string type_name(Botan::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"; + switch(type) + { + case Botan::PRINTABLE_STRING: + return "PRINTABLE STRING"; + + case Botan::NUMERIC_STRING: + return "NUMERIC STRING"; + + case Botan::IA5_STRING: + return "IA5 STRING"; + + case Botan::T61_STRING: + return "T61 STRING"; + + case Botan::UTF8_STRING: + return "UTF8 STRING"; + + case Botan::VISIBLE_STRING: + return "VISIBLE STRING"; + + case Botan::BMP_STRING: + return "BMP STRING"; + + case Botan::UTC_TIME: + return "UTC TIME"; + + case Botan::GENERALIZED_TIME: + return "GENERALIZED TIME"; + + case Botan::OCTET_STRING: + return "OCTET STRING"; + + case Botan::BIT_STRING: + return "BIT STRING"; + + case Botan::ENUMERATED: + return "ENUMERATED"; + + case Botan::INTEGER: + return "INTEGER"; + + case Botan::NULL_TAG: + return "NULL"; + + case Botan::OBJECT_ID: + return "OBJECT"; + + case Botan::BOOLEAN: + return "BOOLEAN"; + } + return "(UNKNOWN)"; } -void decode(BER_Decoder& decoder, size_t level) +void decode(Botan::BER_Decoder& decoder, size_t level) { - BER_Object obj = decoder.get_next_object(); + Botan::BER_Object obj = decoder.get_next_object(); - while(obj.type_tag != NO_OBJECT) + while(obj.type_tag != Botan::NO_OBJECT) { - const ASN1_Tag type_tag = obj.type_tag; - const ASN1_Tag class_tag = obj.class_tag; + const Botan::ASN1_Tag type_tag = obj.type_tag; + const Botan::ASN1_Tag class_tag = obj.class_tag; const size_t length = obj.value.size(); /* hack to insert the tag+length back in front of the stuff now that we've gotten the type info */ - DER_Encoder encoder; + Botan::DER_Encoder encoder; encoder.add_object(type_tag, class_tag, obj.value); - std::vector<byte> bits = encoder.get_contents_unlocked(); + std::vector<uint8_t> bits = encoder.get_contents_unlocked(); - BER_Decoder data(bits); + Botan::BER_Decoder data(bits); - if(class_tag & CONSTRUCTED) + if(class_tag & Botan::CONSTRUCTED) { - BER_Decoder cons_info(obj.value); - if(type_tag == SEQUENCE) + Botan::BER_Decoder cons_info(obj.value); + if(type_tag == Botan::SEQUENCE) { emit("SEQUENCE", level, length); decode(cons_info, level+1); } - else if(type_tag == SET) + else if(type_tag == Botan::SET) { emit("SET", level, length); decode(cons_info, level+1); @@ -154,13 +187,13 @@ void decode(BER_Decoder& decoder, size_t level) { std::string name; - if((class_tag & APPLICATION) || (class_tag & CONTEXT_SPECIFIC)) + if((class_tag & Botan::APPLICATION) || (class_tag & Botan::CONTEXT_SPECIFIC)) { name = "cons [" + std::to_string(type_tag) + "]"; - if(class_tag & APPLICATION) + if(class_tag & Botan::APPLICATION) name += " appl"; - if(class_tag & CONTEXT_SPECIFIC) + if(class_tag & Botan::CONTEXT_SPECIFIC) name += " context"; } else @@ -170,15 +203,15 @@ void decode(BER_Decoder& decoder, size_t level) decode(cons_info, level+1); } } - else if((class_tag & APPLICATION) || (class_tag & CONTEXT_SPECIFIC)) + else if((class_tag & Botan::APPLICATION) || (class_tag & Botan::CONTEXT_SPECIFIC)) { #if 0 - std::vector<byte> bits; + std::vector<uint8_t> bits; data.decode(bits, type_tag); try { - BER_Decoder inner(bits); + Botan::BER_Decoder inner(bits); decode(inner, level + 1); } catch(...) @@ -191,33 +224,33 @@ void decode(BER_Decoder& decoder, size_t level) url_encode(bits)); #endif } - else if(type_tag == OBJECT_ID) + else if(type_tag == Botan::OBJECT_ID) { - OID oid; + Botan::OID oid; data.decode(oid); - std::string out = OIDS::lookup(oid); + std::string out = Botan::OIDS::lookup(oid); if(out != oid.as_string()) out += " [" + oid.as_string() + "]"; emit(type_name(type_tag), level, length, out); } - else if(type_tag == INTEGER || type_tag == ENUMERATED) + else if(type_tag == Botan::INTEGER || type_tag == Botan::ENUMERATED) { - BigInt number; + Botan::BigInt number; - if(type_tag == INTEGER) + if(type_tag == Botan::INTEGER) data.decode(number); - else if(type_tag == ENUMERATED) - data.decode(number, ENUMERATED, class_tag); + else if(type_tag == Botan::ENUMERATED) + data.decode(number, Botan::ENUMERATED, class_tag); - std::vector<byte> rep; + std::vector<uint8_t> rep; /* If it's small, it's probably a number, not a hash */ if(number.bits() <= 20) - rep = BigInt::encode(number, BigInt::Decimal); + rep = Botan::BigInt::encode(number, Botan::BigInt::Decimal); else - rep = BigInt::encode(number, BigInt::Hexadecimal); + rep = Botan::BigInt::encode(number, Botan::BigInt::Hexadecimal); std::string str; for(size_t i = 0; i != rep.size(); ++i) @@ -225,25 +258,25 @@ void decode(BER_Decoder& decoder, size_t level) emit(type_name(type_tag), level, length, str); } - else if(type_tag == BOOLEAN) + else if(type_tag == Botan::BOOLEAN) { bool boolean; data.decode(boolean); emit(type_name(type_tag), level, length, (boolean ? "true" : "false")); } - else if(type_tag == NULL_TAG) + else if(type_tag == Botan::NULL_TAG) { emit(type_name(type_tag), level, length); } - else if(type_tag == OCTET_STRING) + else if(type_tag == Botan::OCTET_STRING) { - std::vector<byte> bits; + std::vector<uint8_t> bits; data.decode(bits, type_tag); try { - BER_Decoder inner(bits); + Botan::BER_Decoder inner(bits); decode(inner, level + 1); } catch(...) @@ -252,9 +285,9 @@ void decode(BER_Decoder& decoder, size_t level) url_encode(bits)); } } - else if(type_tag == BIT_STRING) + else if(type_tag == Botan::BIT_STRING) { - std::vector<byte> bits; + std::vector<uint8_t> bits; data.decode(bits, type_tag); std::vector<bool> bit_set; @@ -278,30 +311,31 @@ void decode(BER_Decoder& decoder, size_t level) emit(type_name(type_tag), level, length, bit_str); } - else if(type_tag == PRINTABLE_STRING || - type_tag == NUMERIC_STRING || - type_tag == IA5_STRING || - type_tag == T61_STRING || - type_tag == VISIBLE_STRING || - type_tag == UTF8_STRING || - type_tag == BMP_STRING) + else if(type_tag == Botan::PRINTABLE_STRING || + type_tag == Botan::NUMERIC_STRING || + type_tag == Botan::IA5_STRING || + type_tag == Botan::T61_STRING || + type_tag == Botan::VISIBLE_STRING || + type_tag == Botan::UTF8_STRING || + type_tag == Botan::BMP_STRING) { - ASN1_String str; + Botan::ASN1_String str; data.decode(str); if(UTF8_TERMINAL) { emit(type_name(type_tag), level, length, - Charset::transcode(str.iso_8859(), - LATIN1_CHARSET, UTF8_CHARSET)); + Botan::Charset::transcode(str.iso_8859(), + Botan::LATIN1_CHARSET, + Botan::UTF8_CHARSET)); } else { emit(type_name(type_tag), level, length, str.iso_8859()); } } - else if(type_tag == UTC_TIME || type_tag == GENERALIZED_TIME) + else if(type_tag == Botan::UTC_TIME || type_tag == Botan::GENERALIZED_TIME) { - X509_Time time; + Botan::X509_Time time; data.decode(time); emit(type_name(type_tag), level, length, time.readable_string()); } @@ -317,39 +351,32 @@ void decode(BER_Decoder& decoder, size_t level) } } -int asn1(const std::vector<std::string> &args) - { - if(args.size() != 2) - { - std::cout << "Usage: " << args[0] << " <file>" << std::endl; - return 1; - } +} - try { - DataSource_Stream in(args[1]); +class ASN1_Printer : public Command + { + public: + ASN1_Printer() : Command("asn1print file") {} - if(!PEM_Code::matches(in)) + void go() { - 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() << std::endl; - return 2; - } + Botan::DataSource_Stream in(get_arg("file")); - return 0; - } + if(!Botan::PEM_Code::matches(in)) + { + Botan::BER_Decoder decoder(in); + decode(decoder, INITIAL_LEVEL); + } + else + { + std::string label; // ignored + Botan::BER_Decoder decoder(Botan::PEM_Code::decode(in, label)); + decode(decoder, INITIAL_LEVEL); + } + } + }; -REGISTER_APP(asn1); +BOTAN_REGISTER_COMMAND(ASN1_Printer); } |