From 31204986023619c385d378e79a6511bb81ef7b78 Mon Sep 17 00:00:00 2001 From: lloyd Date: Sun, 28 Sep 2008 22:14:54 +0000 Subject: Move almost all of the ASN.1, BER, and DER codec related code into new module asn1 Move hex and base64 codecs into new codecs directory. Also move zlib and bzip2 to codecs from compress. --- include/alg_id.h | 47 ----- include/asn1_int.h | 106 ---------- include/asn1_obj.h | 158 -------------- include/asn1_oid.h | 50 ----- include/base64.h | 60 ------ include/ber_dec.h | 130 ------------ include/der_enc.h | 89 -------- include/hex.h | 64 ------ src/alg_id.cpp | 101 --------- src/asn1/alg_id.cpp | 101 +++++++++ src/asn1/alg_id.h | 47 +++++ src/asn1/asn1_alt.cpp | 226 ++++++++++++++++++++ src/asn1/asn1_att.cpp | 58 +++++ src/asn1/asn1_dn.cpp | 302 ++++++++++++++++++++++++++ src/asn1/asn1_int.cpp | 66 ++++++ src/asn1/asn1_int.h | 106 ++++++++++ src/asn1/asn1_ku.cpp | 41 ++++ src/asn1/asn1_obj.h | 158 ++++++++++++++ src/asn1/asn1_oid.cpp | 174 +++++++++++++++ src/asn1/asn1_oid.h | 50 +++++ src/asn1/asn1_str.cpp | 161 ++++++++++++++ src/asn1/asn1_tm.cpp | 295 ++++++++++++++++++++++++++ src/asn1/ber_dec.cpp | 469 +++++++++++++++++++++++++++++++++++++++++ src/asn1/ber_dec.h | 130 ++++++++++++ src/asn1/der_enc.cpp | 391 ++++++++++++++++++++++++++++++++++ src/asn1/der_enc.h | 89 ++++++++ src/asn1/modinfo.txt | 23 ++ src/asn1_alt.cpp | 226 -------------------- src/asn1_att.cpp | 58 ----- src/asn1_dn.cpp | 302 -------------------------- src/asn1_int.cpp | 66 ------ src/asn1_ku.cpp | 41 ---- src/asn1_oid.cpp | 174 --------------- src/asn1_str.cpp | 161 -------------- src/asn1_tm.cpp | 295 -------------------------- src/base64.cpp | 225 -------------------- src/ber_dec.cpp | 469 ----------------------------------------- src/codec/base64/base64.cpp | 225 ++++++++++++++++++++ src/codec/base64/base64.h | 60 ++++++ src/codec/base64/modinfo.txt | 10 + src/codec/bzip2/bzip2.cpp | 271 ++++++++++++++++++++++++ src/codec/bzip2/bzip2.h | 59 ++++++ src/codec/bzip2/modinfo.txt | 17 ++ src/codec/hex/hex.cpp | 188 +++++++++++++++++ src/codec/hex/hex.h | 64 ++++++ src/codec/hex/modinfo.txt | 10 + src/codec/zlib/modinfo.txt | 19 ++ src/codec/zlib/zlib.cpp | 283 +++++++++++++++++++++++++ src/codec/zlib/zlib.h | 56 +++++ src/compress/bzip2/bzip2.cpp | 271 ------------------------ src/compress/bzip2/bzip2.h | 59 ------ src/compress/bzip2/modinfo.txt | 17 -- src/compress/zlib/modinfo.txt | 19 -- src/compress/zlib/zlib.cpp | 283 ------------------------- src/compress/zlib/zlib.h | 56 ----- src/der_enc.cpp | 391 ---------------------------------- src/hex.cpp | 188 ----------------- src/pk/dl_algo/modinfo.txt | 15 ++ src/pk/dl_group/modinfo.txt | 10 + src/pk/dlies/modinfo.txt | 4 + 60 files changed, 4178 insertions(+), 4106 deletions(-) delete mode 100644 include/alg_id.h delete mode 100644 include/asn1_int.h delete mode 100644 include/asn1_obj.h delete mode 100644 include/asn1_oid.h delete mode 100644 include/base64.h delete mode 100644 include/ber_dec.h delete mode 100644 include/der_enc.h delete mode 100644 include/hex.h delete mode 100644 src/alg_id.cpp create mode 100644 src/asn1/alg_id.cpp create mode 100644 src/asn1/alg_id.h create mode 100644 src/asn1/asn1_alt.cpp create mode 100644 src/asn1/asn1_att.cpp create mode 100644 src/asn1/asn1_dn.cpp create mode 100644 src/asn1/asn1_int.cpp create mode 100644 src/asn1/asn1_int.h create mode 100644 src/asn1/asn1_ku.cpp create mode 100644 src/asn1/asn1_obj.h create mode 100644 src/asn1/asn1_oid.cpp create mode 100644 src/asn1/asn1_oid.h create mode 100644 src/asn1/asn1_str.cpp create mode 100644 src/asn1/asn1_tm.cpp create mode 100644 src/asn1/ber_dec.cpp create mode 100644 src/asn1/ber_dec.h create mode 100644 src/asn1/der_enc.cpp create mode 100644 src/asn1/der_enc.h create mode 100644 src/asn1/modinfo.txt delete mode 100644 src/asn1_alt.cpp delete mode 100644 src/asn1_att.cpp delete mode 100644 src/asn1_dn.cpp delete mode 100644 src/asn1_int.cpp delete mode 100644 src/asn1_ku.cpp delete mode 100644 src/asn1_oid.cpp delete mode 100644 src/asn1_str.cpp delete mode 100644 src/asn1_tm.cpp delete mode 100644 src/base64.cpp delete mode 100644 src/ber_dec.cpp create mode 100644 src/codec/base64/base64.cpp create mode 100644 src/codec/base64/base64.h create mode 100644 src/codec/base64/modinfo.txt create mode 100644 src/codec/bzip2/bzip2.cpp create mode 100644 src/codec/bzip2/bzip2.h create mode 100644 src/codec/bzip2/modinfo.txt create mode 100644 src/codec/hex/hex.cpp create mode 100644 src/codec/hex/hex.h create mode 100644 src/codec/hex/modinfo.txt create mode 100644 src/codec/zlib/modinfo.txt create mode 100644 src/codec/zlib/zlib.cpp create mode 100644 src/codec/zlib/zlib.h delete mode 100644 src/compress/bzip2/bzip2.cpp delete mode 100644 src/compress/bzip2/bzip2.h delete mode 100644 src/compress/bzip2/modinfo.txt delete mode 100644 src/compress/zlib/modinfo.txt delete mode 100644 src/compress/zlib/zlib.cpp delete mode 100644 src/compress/zlib/zlib.h delete mode 100644 src/der_enc.cpp delete mode 100644 src/hex.cpp create mode 100644 src/pk/dl_algo/modinfo.txt create mode 100644 src/pk/dl_group/modinfo.txt diff --git a/include/alg_id.h b/include/alg_id.h deleted file mode 100644 index 8187fc070..000000000 --- a/include/alg_id.h +++ /dev/null @@ -1,47 +0,0 @@ -/************************************************* -* Algorithm Identifier Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_ALGORITHM_IDENTIFIER_H__ -#define BOTAN_ALGORITHM_IDENTIFIER_H__ - -#include -#include -#include - -namespace Botan { - -/************************************************* -* Algorithm Identifier * -*************************************************/ -class BOTAN_DLL AlgorithmIdentifier : public ASN1_Object - { - public: - enum Encoding_Option { USE_NULL_PARAM }; - - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - AlgorithmIdentifier() {} - AlgorithmIdentifier(const OID&, Encoding_Option); - AlgorithmIdentifier(const std::string&, Encoding_Option); - - AlgorithmIdentifier(const OID&, const MemoryRegion&); - AlgorithmIdentifier(const std::string&, const MemoryRegion&); - - OID oid; - SecureVector parameters; - }; - -/************************************************* -* Comparison Operations * -*************************************************/ -bool BOTAN_DLL operator==(const AlgorithmIdentifier&, - const AlgorithmIdentifier&); -bool BOTAN_DLL operator!=(const AlgorithmIdentifier&, - const AlgorithmIdentifier&); - -} - -#endif diff --git a/include/asn1_int.h b/include/asn1_int.h deleted file mode 100644 index 3e0562b9c..000000000 --- a/include/asn1_int.h +++ /dev/null @@ -1,106 +0,0 @@ -/************************************************* -* ASN.1 Internals Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_ASN1_H__ -#define BOTAN_ASN1_H__ - -#include -#include - -namespace Botan { - -/************************************************* -* ASN.1 Type and Class Tags * -*************************************************/ -enum ASN1_Tag { - UNIVERSAL = 0x00, - APPLICATION = 0x40, - CONTEXT_SPECIFIC = 0x80, - PRIVATE = 0xC0, - - CONSTRUCTED = 0x20, - - EOC = 0x00, - BOOLEAN = 0x01, - INTEGER = 0x02, - BIT_STRING = 0x03, - OCTET_STRING = 0x04, - NULL_TAG = 0x05, - OBJECT_ID = 0x06, - ENUMERATED = 0x0A, - SEQUENCE = 0x10, - SET = 0x11, - - UTF8_STRING = 0x0C, - NUMERIC_STRING = 0x12, - PRINTABLE_STRING = 0x13, - T61_STRING = 0x14, - IA5_STRING = 0x16, - VISIBLE_STRING = 0x1A, - BMP_STRING = 0x1E, - - UTC_TIME = 0x17, - GENERALIZED_TIME = 0x18, - - NO_OBJECT = 0xFF00, - DIRECTORY_STRING = 0xFF01 -}; - -/************************************************* -* Basic ASN.1 Object Interface * -*************************************************/ -class BOTAN_DLL ASN1_Object - { - public: - virtual void encode_into(class DER_Encoder&) const = 0; - virtual void decode_from(class BER_Decoder&) = 0; - virtual ~ASN1_Object() {} - }; - -/************************************************* -* BER Encoded Object * -*************************************************/ -class BOTAN_DLL BER_Object - { - public: - void assert_is_a(ASN1_Tag, ASN1_Tag); - - ASN1_Tag type_tag, class_tag; - SecureVector value; - }; - -/************************************************* -* ASN.1 Utility Functions * -*************************************************/ -class DataSource; - -namespace ASN1 { - -SecureVector put_in_sequence(const MemoryRegion&); -std::string to_string(const BER_Object&); -bool maybe_BER(DataSource&); - -} - -/************************************************* -* General BER Decoding Error Exception * -*************************************************/ -struct BER_Decoding_Error : public Decoding_Error - { - BER_Decoding_Error(const std::string&); - }; - -/************************************************* -* Exception For Incorrect BER Taggings * -*************************************************/ -struct BER_Bad_Tag : public BER_Decoding_Error - { - BER_Bad_Tag(const std::string&, ASN1_Tag); - BER_Bad_Tag(const std::string&, ASN1_Tag, ASN1_Tag); - }; - -} - -#endif diff --git a/include/asn1_obj.h b/include/asn1_obj.h deleted file mode 100644 index 67645ca08..000000000 --- a/include/asn1_obj.h +++ /dev/null @@ -1,158 +0,0 @@ -/************************************************* -* Common ASN.1 Objects Header File * -* (C) 1999-2007 Jack Lloyd * -* 2007 Yves Jerschow * -*************************************************/ - -#ifndef BOTAN_ASN1_OBJ_H__ -#define BOTAN_ASN1_OBJ_H__ - -#include -#include -#include -#include -#include - -namespace Botan { - -/************************************************* -* Attribute * -*************************************************/ -class BOTAN_DLL Attribute : public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - OID oid; - MemoryVector parameters; - - Attribute() {} - Attribute(const OID&, const MemoryRegion&); - Attribute(const std::string&, const MemoryRegion&); - }; - -/************************************************* -* X.509 Time * -*************************************************/ -class BOTAN_DLL X509_Time : public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - std::string as_string() const; - std::string readable_string() const; - bool time_is_set() const; - - s32bit cmp(const X509_Time&) const; - - void set_to(const std::string&); - void set_to(const std::string&, ASN1_Tag); - - X509_Time(u64bit); - X509_Time(const std::string& = ""); - X509_Time(const std::string&, ASN1_Tag); - private: - bool passes_sanity_check() const; - u32bit year, month, day, hour, minute, second; - ASN1_Tag tag; - }; - -/************************************************* -* Simple String * -*************************************************/ -class BOTAN_DLL ASN1_String : public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - std::string value() const; - std::string iso_8859() const; - - ASN1_Tag tagging() const; - - ASN1_String(const std::string& = ""); - ASN1_String(const std::string&, ASN1_Tag); - private: - std::string iso_8859_str; - ASN1_Tag tag; - }; - -/************************************************* -* Distinguished Name * -*************************************************/ -class BOTAN_DLL X509_DN : public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - std::multimap get_attributes() const; - std::vector get_attribute(const std::string&) const; - - std::multimap contents() const; - - void add_attribute(const std::string&, const std::string&); - void add_attribute(const OID&, const std::string&); - - static std::string deref_info_field(const std::string&); - - void do_decode(const MemoryRegion&); - MemoryVector get_bits() const; - - X509_DN(); - X509_DN(const std::multimap&); - X509_DN(const std::multimap&); - private: - std::multimap dn_info; - MemoryVector dn_bits; - }; - -/************************************************* -* Alternative Name * -*************************************************/ -class BOTAN_DLL AlternativeName : public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - std::multimap contents() const; - - void add_attribute(const std::string&, const std::string&); - std::multimap get_attributes() const; - - void add_othername(const OID&, const std::string&, ASN1_Tag); - std::multimap get_othernames() const; - - bool has_items() const; - - AlternativeName(const std::string& = "", const std::string& = "", - const std::string& = "", const std::string& = ""); - private: - std::multimap alt_info; - std::multimap othernames; - }; - -/************************************************* -* Comparison Operations * -*************************************************/ -bool BOTAN_DLL operator==(const X509_Time&, const X509_Time&); -bool BOTAN_DLL operator!=(const X509_Time&, const X509_Time&); -bool BOTAN_DLL operator<=(const X509_Time&, const X509_Time&); -bool BOTAN_DLL operator>=(const X509_Time&, const X509_Time&); - -bool BOTAN_DLL operator==(const X509_DN&, const X509_DN&); -bool BOTAN_DLL operator!=(const X509_DN&, const X509_DN&); -bool BOTAN_DLL operator<(const X509_DN&, const X509_DN&); - -/************************************************* -* Helper Functions * -*************************************************/ -bool BOTAN_DLL is_string_type(ASN1_Tag); - -} - -#endif diff --git a/include/asn1_oid.h b/include/asn1_oid.h deleted file mode 100644 index 73d0079a8..000000000 --- a/include/asn1_oid.h +++ /dev/null @@ -1,50 +0,0 @@ -/************************************************* -* ASN.1 OID Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_ASN1_OID_H__ -#define BOTAN_ASN1_OID_H__ - -#include -#include -#include - -namespace Botan { - -/************************************************* -* ASN.1 Object Identifier * -*************************************************/ -class BOTAN_DLL OID : public ASN1_Object - { - public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); - - bool is_empty() const { return id.size() == 0; } - std::vector get_id() const { return id; } - std::string as_string() const; - - bool operator==(const OID&) const; - void clear(); - - OID& operator+=(u32bit); - OID(const std::string& = ""); - private: - std::vector id; - }; - -/************************************************* -* Append another component onto the OID * -*************************************************/ -OID BOTAN_DLL operator+(const OID&, u32bit); - -/************************************************* -* Compare two OIDs * -*************************************************/ -bool BOTAN_DLL operator!=(const OID&, const OID&); -bool BOTAN_DLL operator<(const OID&, const OID&); - -} - -#endif diff --git a/include/base64.h b/include/base64.h deleted file mode 100644 index 0003875a6..000000000 --- a/include/base64.h +++ /dev/null @@ -1,60 +0,0 @@ -/************************************************* -* Base64 Encoder/Decoder Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_BASE64_H__ -#define BOTAN_BASE64_H__ - -#include -#include - -namespace Botan { - -/************************************************* -* Base64 Encoder * -*************************************************/ -class BOTAN_DLL Base64_Encoder : public Filter - { - public: - static void encode(const byte[3], byte[4]); - - void write(const byte[], u32bit); - void end_msg(); - Base64_Encoder(bool = false, u32bit = 72, bool = false); - private: - void encode_and_send(const byte[], u32bit); - void do_output(const byte[], u32bit); - static const byte BIN_TO_BASE64[64]; - - const u32bit line_length; - const bool trailing_newline; - SecureVector in, out; - u32bit position, counter; - }; - -/************************************************* -* Base64 Decoder * -*************************************************/ -class BOTAN_DLL Base64_Decoder : public Filter - { - public: - static void decode(const byte[4], byte[3]); - static bool is_valid(byte); - - void write(const byte[], u32bit); - void end_msg(); - Base64_Decoder(Decoder_Checking = NONE); - private: - void decode_and_send(const byte[], u32bit); - void handle_bad_char(byte); - static const byte BASE64_TO_BIN[256]; - - const Decoder_Checking checking; - SecureVector in, out; - u32bit position; - }; - -} - -#endif diff --git a/include/ber_dec.h b/include/ber_dec.h deleted file mode 100644 index 9fec75832..000000000 --- a/include/ber_dec.h +++ /dev/null @@ -1,130 +0,0 @@ -/************************************************* -* BER Decoder Header File * -* (C) 1999-2008 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_BER_DECODER_H__ -#define BOTAN_BER_DECODER_H__ - -#include -#include -#include - -namespace Botan { - -/************************************************* -* BER Decoding Object * -*************************************************/ -class BOTAN_DLL BER_Decoder - { - public: - BER_Object get_next_object(); - void push_back(const BER_Object&); - - bool more_items() const; - BER_Decoder& verify_end(); - BER_Decoder& discard_remaining(); - - BER_Decoder start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL); - BER_Decoder& end_cons(); - - BER_Decoder& raw_bytes(MemoryRegion&); - - BER_Decoder& decode_null(); - BER_Decoder& decode(bool&); - BER_Decoder& decode(u32bit&); - BER_Decoder& decode(class BigInt&); - BER_Decoder& decode(MemoryRegion&, ASN1_Tag); - - BER_Decoder& decode(bool&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - BER_Decoder& decode(u32bit&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - BER_Decoder& decode(class BigInt&, - ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - BER_Decoder& decode(MemoryRegion&, ASN1_Tag, - ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - - BER_Decoder& decode(class ASN1_Object&); - - template - BER_Decoder& decode_optional(T&, ASN1_Tag, ASN1_Tag, const T& = T()); - - template - BER_Decoder& decode_list(std::vector&, bool = true); - - BER_Decoder& decode_optional_string(MemoryRegion&, - ASN1_Tag, u16bit); - - BER_Decoder(DataSource&); - BER_Decoder(const byte[], u32bit); - BER_Decoder(const MemoryRegion&); - BER_Decoder(const BER_Decoder&); - ~BER_Decoder(); - private: - BER_Decoder& operator=(const BER_Decoder&) { return (*this); } - - BER_Decoder* parent; - DataSource* source; - BER_Object pushed; - mutable bool owns; - }; - -/************************************************* -* Decode an OPTIONAL or DEFAULT element * -*************************************************/ -template -BER_Decoder& BER_Decoder::decode_optional(T& out, - ASN1_Tag type_tag, - ASN1_Tag class_tag, - const T& default_value) - { - BER_Object obj = get_next_object(); - - if(obj.type_tag == type_tag && obj.class_tag == class_tag) - { - if(class_tag & CONSTRUCTED) - BER_Decoder(obj.value).decode(out).verify_end(); - else - { - push_back(obj); - decode(out, type_tag, class_tag); - } - } - else - { - out = default_value; - push_back(obj); - } - - return (*this); - } - -/************************************************* -* Decode a list of homogenously typed values * -*************************************************/ -template -BER_Decoder& BER_Decoder::decode_list(std::vector& vec, bool clear_it) - { - if(clear_it) - vec.clear(); - - while(more_items()) - { - T value; - decode(value); - vec.push_back(value); - } - return (*this); - } - -/************************************************* -* BER Decoding Functions * -*************************************************/ -namespace BER { - -void BOTAN_DLL decode(BER_Decoder&, Key_Constraints&); - -} - -} - -#endif diff --git a/include/der_enc.h b/include/der_enc.h deleted file mode 100644 index 5b3c11489..000000000 --- a/include/der_enc.h +++ /dev/null @@ -1,89 +0,0 @@ -/************************************************* -* DER Encoder Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_DER_ENCODER_H__ -#define BOTAN_DER_ENCODER_H__ - -#include -#include - -namespace Botan { - -/************************************************* -* General DER Encoding Object * -*************************************************/ -class BOTAN_DLL DER_Encoder - { - public: - SecureVector get_contents(); - - DER_Encoder& start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL); - DER_Encoder& end_cons(); - - DER_Encoder& start_explicit(u16bit); - DER_Encoder& end_explicit(); - - DER_Encoder& raw_bytes(const byte[], u32bit); - DER_Encoder& raw_bytes(const MemoryRegion&); - - DER_Encoder& encode_null(); - DER_Encoder& encode(bool); - DER_Encoder& encode(u32bit); - DER_Encoder& encode(const class BigInt&); - DER_Encoder& encode(const MemoryRegion&, ASN1_Tag); - DER_Encoder& encode(const byte[], u32bit, ASN1_Tag); - - DER_Encoder& encode(bool, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - DER_Encoder& encode(u32bit, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - DER_Encoder& encode(const class BigInt&, ASN1_Tag, - ASN1_Tag = CONTEXT_SPECIFIC); - DER_Encoder& encode(const MemoryRegion&, ASN1_Tag, - ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - DER_Encoder& encode(const byte[], u32bit, ASN1_Tag, - ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - - template - DER_Encoder& encode_optional(const T& value, const T& default_value) - { - if(value != default_value) - encode(value); - return (*this); - } - - template - DER_Encoder& encode_list(const std::vector& values) - { - for(u32bit j = 0; j != values.size(); ++j) - encode(values[j]); - return (*this); - } - - DER_Encoder& encode(const class ASN1_Object&); - DER_Encoder& encode_if(bool, DER_Encoder&); - - DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const byte[], u32bit); - DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const MemoryRegion&); - DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const std::string&); - DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, byte); - private: - class DER_Sequence - { - public: - ASN1_Tag tag_of() const; - SecureVector get_contents(); - void add_bytes(const byte[], u32bit); - DER_Sequence(ASN1_Tag, ASN1_Tag); - private: - ASN1_Tag type_tag, class_tag; - SecureVector contents; - std::vector< SecureVector > set_contents; - }; - SecureVector contents; - std::vector subsequences; - }; - -} - -#endif diff --git a/include/hex.h b/include/hex.h deleted file mode 100644 index 0ecddb588..000000000 --- a/include/hex.h +++ /dev/null @@ -1,64 +0,0 @@ -/************************************************* -* Hex Encoder/Decoder Header File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_HEX_H__ -#define BOTAN_HEX_H__ - -#include -#include - -namespace Botan { - -/************************************************* -* Hex Encoder * -*************************************************/ -class BOTAN_DLL Hex_Encoder : public Filter - { - public: - enum Case { Uppercase, Lowercase }; - static void encode(byte, byte[2], Case = Uppercase); - - void write(const byte[], u32bit); - void end_msg(); - - Hex_Encoder(Case); - Hex_Encoder(bool = false, u32bit = 72, Case = Uppercase); - private: - void encode_and_send(const byte[], u32bit); - static const byte BIN_TO_HEX_UPPER[16]; - static const byte BIN_TO_HEX_LOWER[16]; - - const Case casing; - const u32bit line_length; - SecureVector in, out; - u32bit position, counter; - }; - -/************************************************* -* Hex Decoder * -*************************************************/ -class BOTAN_DLL Hex_Decoder : public Filter - { - public: - static byte decode(const byte[2]); - static bool is_valid(byte); - - void write(const byte[], u32bit); - void end_msg(); - - Hex_Decoder(Decoder_Checking = NONE); - private: - void decode_and_send(const byte[], u32bit); - void handle_bad_char(byte); - static const byte HEX_TO_BIN[256]; - - const Decoder_Checking checking; - SecureVector in, out; - u32bit position; - }; - -} - -#endif diff --git a/src/alg_id.cpp b/src/alg_id.cpp deleted file mode 100644 index 5e5db73b3..000000000 --- a/src/alg_id.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/************************************************* -* Algorithm Identifier Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include -#include - -namespace Botan { - -/************************************************* -* Create an AlgorithmIdentifier * -*************************************************/ -AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id, - const MemoryRegion& param) - { - oid = alg_id; - parameters = param; - } - -/************************************************* -* Create an AlgorithmIdentifier * -*************************************************/ -AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id, - const MemoryRegion& param) - { - oid = OIDS::lookup(alg_id); - parameters = param; - } - -/************************************************* -* Create an AlgorithmIdentifier * -*************************************************/ -AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id, - Encoding_Option option) - { - const byte DER_NULL[] = { 0x05, 0x00 }; - - oid = alg_id; - if(option == USE_NULL_PARAM) - parameters.append(DER_NULL, sizeof(DER_NULL)); - } - -/************************************************* -* Create an AlgorithmIdentifier * -*************************************************/ -AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id, - Encoding_Option option) - { - const byte DER_NULL[] = { 0x05, 0x00 }; - - oid = OIDS::lookup(alg_id); - if(option == USE_NULL_PARAM) - parameters.append(DER_NULL, sizeof(DER_NULL)); - } - -/************************************************* -* Compare two AlgorithmIdentifiers * -*************************************************/ -bool operator==(const AlgorithmIdentifier& a1, const AlgorithmIdentifier& a2) - { - if(a1.oid != a2.oid) - return false; - if(a1.parameters != a2.parameters) - return false; - return true; - } - -/************************************************* -* Compare two AlgorithmIdentifiers * -*************************************************/ -bool operator!=(const AlgorithmIdentifier& a1, const AlgorithmIdentifier& a2) - { - return !(a1 == a2); - } - -/************************************************* -* DER encode an AlgorithmIdentifier * -*************************************************/ -void AlgorithmIdentifier::encode_into(DER_Encoder& codec) const - { - codec.start_cons(SEQUENCE) - .encode(oid) - .raw_bytes(parameters) - .end_cons(); - } - -/************************************************* -* Decode a BER encoded AlgorithmIdentifier * -*************************************************/ -void AlgorithmIdentifier::decode_from(BER_Decoder& codec) - { - codec.start_cons(SEQUENCE) - .decode(oid) - .raw_bytes(parameters) - .end_cons(); - } - -} diff --git a/src/asn1/alg_id.cpp b/src/asn1/alg_id.cpp new file mode 100644 index 000000000..5e5db73b3 --- /dev/null +++ b/src/asn1/alg_id.cpp @@ -0,0 +1,101 @@ +/************************************************* +* Algorithm Identifier Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include +#include + +namespace Botan { + +/************************************************* +* Create an AlgorithmIdentifier * +*************************************************/ +AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id, + const MemoryRegion& param) + { + oid = alg_id; + parameters = param; + } + +/************************************************* +* Create an AlgorithmIdentifier * +*************************************************/ +AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id, + const MemoryRegion& param) + { + oid = OIDS::lookup(alg_id); + parameters = param; + } + +/************************************************* +* Create an AlgorithmIdentifier * +*************************************************/ +AlgorithmIdentifier::AlgorithmIdentifier(const OID& alg_id, + Encoding_Option option) + { + const byte DER_NULL[] = { 0x05, 0x00 }; + + oid = alg_id; + if(option == USE_NULL_PARAM) + parameters.append(DER_NULL, sizeof(DER_NULL)); + } + +/************************************************* +* Create an AlgorithmIdentifier * +*************************************************/ +AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id, + Encoding_Option option) + { + const byte DER_NULL[] = { 0x05, 0x00 }; + + oid = OIDS::lookup(alg_id); + if(option == USE_NULL_PARAM) + parameters.append(DER_NULL, sizeof(DER_NULL)); + } + +/************************************************* +* Compare two AlgorithmIdentifiers * +*************************************************/ +bool operator==(const AlgorithmIdentifier& a1, const AlgorithmIdentifier& a2) + { + if(a1.oid != a2.oid) + return false; + if(a1.parameters != a2.parameters) + return false; + return true; + } + +/************************************************* +* Compare two AlgorithmIdentifiers * +*************************************************/ +bool operator!=(const AlgorithmIdentifier& a1, const AlgorithmIdentifier& a2) + { + return !(a1 == a2); + } + +/************************************************* +* DER encode an AlgorithmIdentifier * +*************************************************/ +void AlgorithmIdentifier::encode_into(DER_Encoder& codec) const + { + codec.start_cons(SEQUENCE) + .encode(oid) + .raw_bytes(parameters) + .end_cons(); + } + +/************************************************* +* Decode a BER encoded AlgorithmIdentifier * +*************************************************/ +void AlgorithmIdentifier::decode_from(BER_Decoder& codec) + { + codec.start_cons(SEQUENCE) + .decode(oid) + .raw_bytes(parameters) + .end_cons(); + } + +} diff --git a/src/asn1/alg_id.h b/src/asn1/alg_id.h new file mode 100644 index 000000000..8187fc070 --- /dev/null +++ b/src/asn1/alg_id.h @@ -0,0 +1,47 @@ +/************************************************* +* Algorithm Identifier Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ALGORITHM_IDENTIFIER_H__ +#define BOTAN_ALGORITHM_IDENTIFIER_H__ + +#include +#include +#include + +namespace Botan { + +/************************************************* +* Algorithm Identifier * +*************************************************/ +class BOTAN_DLL AlgorithmIdentifier : public ASN1_Object + { + public: + enum Encoding_Option { USE_NULL_PARAM }; + + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + + AlgorithmIdentifier() {} + AlgorithmIdentifier(const OID&, Encoding_Option); + AlgorithmIdentifier(const std::string&, Encoding_Option); + + AlgorithmIdentifier(const OID&, const MemoryRegion&); + AlgorithmIdentifier(const std::string&, const MemoryRegion&); + + OID oid; + SecureVector parameters; + }; + +/************************************************* +* Comparison Operations * +*************************************************/ +bool BOTAN_DLL operator==(const AlgorithmIdentifier&, + const AlgorithmIdentifier&); +bool BOTAN_DLL operator!=(const AlgorithmIdentifier&, + const AlgorithmIdentifier&); + +} + +#endif diff --git a/src/asn1/asn1_alt.cpp b/src/asn1/asn1_alt.cpp new file mode 100644 index 000000000..035f918cb --- /dev/null +++ b/src/asn1/asn1_alt.cpp @@ -0,0 +1,226 @@ +/************************************************* +* AlternativeName Source File * +* (C) 1999-2007 Jack Lloyd * +* 2007 Yves Jerschow * +*************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Botan { + +/************************************************* +* Create an AlternativeName * +*************************************************/ +AlternativeName::AlternativeName(const std::string& email_addr, + const std::string& uri, + const std::string& dns, + const std::string& ip) + { + add_attribute("RFC822", email_addr); + add_attribute("DNS", dns); + add_attribute("URI", uri); + add_attribute("IP", ip); + } + +/************************************************* +* Add an attribute to an alternative name * +*************************************************/ +void AlternativeName::add_attribute(const std::string& type, + const std::string& str) + { + if(type == "" || str == "") + return; + + typedef std::multimap::iterator iter; + std::pair range = alt_info.equal_range(type); + for(iter j = range.first; j != range.second; ++j) + if(j->second == str) + return; + + multimap_insert(alt_info, type, str); + } + +/************************************************* +* Add an OtherName field * +*************************************************/ +void AlternativeName::add_othername(const OID& oid, const std::string& value, + ASN1_Tag type) + { + if(value == "") + return; + multimap_insert(othernames, oid, ASN1_String(value, type)); + } + +/************************************************* +* Get the attributes of this alternative name * +*************************************************/ +std::multimap AlternativeName::get_attributes() const + { + return alt_info; + } + +/************************************************* +* Get the otherNames * +*************************************************/ +std::multimap AlternativeName::get_othernames() const + { + return othernames; + } + +/************************************************* +* Return all of the alternative names * +*************************************************/ +std::multimap AlternativeName::contents() const + { + std::multimap names; + + typedef std::multimap::const_iterator rdn_iter; + for(rdn_iter j = alt_info.begin(); j != alt_info.end(); ++j) + multimap_insert(names, j->first, j->second); + + typedef std::multimap::const_iterator on_iter; + for(on_iter j = othernames.begin(); j != othernames.end(); ++j) + multimap_insert(names, OIDS::lookup(j->first), j->second.value()); + + return names; + } + +/************************************************* +* Return if this object has anything useful * +*************************************************/ +bool AlternativeName::has_items() const + { + return (alt_info.size() > 0 || othernames.size() > 0); + } + +namespace { + +/************************************************* +* DER encode an AlternativeName entry * +*************************************************/ +void encode_entries(DER_Encoder& encoder, + const std::multimap& attr, + const std::string& type, ASN1_Tag tagging) + { + typedef std::multimap::const_iterator iter; + + std::pair range = attr.equal_range(type); + for(iter j = range.first; j != range.second; ++j) + { + if(type == "RFC822" || type == "DNS" || type == "URI") + { + ASN1_String asn1_string(j->second, IA5_STRING); + encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.iso_8859()); + } + else if(type == "IP") + { + u32bit ip = string_to_ipv4(j->second); + byte ip_buf[4] = { 0 }; + store_be(ip, ip_buf); + encoder.add_object(tagging, CONTEXT_SPECIFIC, ip_buf, 4); + } + } + } + +} + +/************************************************* +* DER encode an AlternativeName extension * +*************************************************/ +void AlternativeName::encode_into(DER_Encoder& der) const + { + der.start_cons(SEQUENCE); + + encode_entries(der, alt_info, "RFC822", ASN1_Tag(1)); + encode_entries(der, alt_info, "DNS", ASN1_Tag(2)); + encode_entries(der, alt_info, "URI", ASN1_Tag(6)); + encode_entries(der, alt_info, "IP", ASN1_Tag(7)); + + std::multimap::const_iterator i; + for(i = othernames.begin(); i != othernames.end(); ++i) + { + der.start_explicit(0) + .encode(i->first) + .start_explicit(0) + .encode(i->second) + .end_explicit() + .end_explicit(); + } + + der.end_cons(); + } + +/************************************************* +* Decode a BER encoded AlternativeName * +*************************************************/ +void AlternativeName::decode_from(BER_Decoder& source) + { + BER_Decoder names = source.start_cons(SEQUENCE); + + while(names.more_items()) + { + BER_Object obj = names.get_next_object(); + if((obj.class_tag != CONTEXT_SPECIFIC) && + (obj.class_tag != (CONTEXT_SPECIFIC | CONSTRUCTED))) + continue; + + ASN1_Tag tag = obj.type_tag; + + if(tag == 0) + { + BER_Decoder othername(obj.value); + + OID oid; + othername.decode(oid); + if(othername.more_items()) + { + BER_Object othername_value_outer = othername.get_next_object(); + othername.verify_end(); + + if(othername_value_outer.type_tag != ASN1_Tag(0) || + othername_value_outer.class_tag != + (CONTEXT_SPECIFIC | CONSTRUCTED) + ) + throw Decoding_Error("Invalid tags on otherName value"); + + BER_Decoder othername_value_inner(othername_value_outer.value); + + BER_Object value = othername_value_inner.get_next_object(); + othername_value_inner.verify_end(); + + ASN1_Tag value_type = value.type_tag; + + if(is_string_type(value_type) && value.class_tag == UNIVERSAL) + add_othername(oid, ASN1::to_string(value), value_type); + } + } + else if(tag == 1 || tag == 2 || tag == 6) + { + const std::string value = Charset::transcode(ASN1::to_string(obj), + LATIN1_CHARSET, + LOCAL_CHARSET); + + if(tag == 1) add_attribute("RFC822", value); + if(tag == 2) add_attribute("DNS", value); + if(tag == 6) add_attribute("URI", value); + } + else if(tag == 7) + { + if(obj.value.size() == 4) + { + u32bit ip = load_be(obj.value.begin(), 0); + add_attribute("IP", ipv4_to_string(ip)); + } + } + + } + } + +} diff --git a/src/asn1/asn1_att.cpp b/src/asn1/asn1_att.cpp new file mode 100644 index 000000000..7c16ff3a5 --- /dev/null +++ b/src/asn1/asn1_att.cpp @@ -0,0 +1,58 @@ +/************************************************* +* Attribute Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include +#include + +namespace Botan { + +/************************************************* +* Create an Attribute * +*************************************************/ +Attribute::Attribute(const OID& attr_oid, const MemoryRegion& attr_value) + { + oid = attr_oid; + parameters = attr_value; + } + +/************************************************* +* Create an Attribute * +*************************************************/ +Attribute::Attribute(const std::string& attr_oid, + const MemoryRegion& attr_value) + { + oid = OIDS::lookup(attr_oid); + parameters = attr_value; + } + +/************************************************* +* DER encode a Attribute * +*************************************************/ +void Attribute::encode_into(DER_Encoder& codec) const + { + codec.start_cons(SEQUENCE) + .encode(oid) + .start_cons(SET) + .raw_bytes(parameters) + .end_cons() + .end_cons(); + } + +/************************************************* +* Decode a BER encoded Attribute * +*************************************************/ +void Attribute::decode_from(BER_Decoder& codec) + { + codec.start_cons(SEQUENCE) + .decode(oid) + .start_cons(SET) + .raw_bytes(parameters) + .end_cons() + .end_cons(); + } + +} diff --git a/src/asn1/asn1_dn.cpp b/src/asn1/asn1_dn.cpp new file mode 100644 index 000000000..3fd0c09b0 --- /dev/null +++ b/src/asn1/asn1_dn.cpp @@ -0,0 +1,302 @@ +/************************************************* +* X509_DN Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include +#include +#include +#include + +namespace Botan { + +/************************************************* +* Create an empty X509_DN * +*************************************************/ +X509_DN::X509_DN() + { + } + +/************************************************* +* Create an X509_DN * +*************************************************/ +X509_DN::X509_DN(const std::multimap& args) + { + std::multimap::const_iterator j; + for(j = args.begin(); j != args.end(); ++j) + add_attribute(j->first, j->second); + } + +/************************************************* +* Create an X509_DN * +*************************************************/ +X509_DN::X509_DN(const std::multimap& args) + { + std::multimap::const_iterator j; + for(j = args.begin(); j != args.end(); ++j) + add_attribute(OIDS::lookup(j->first), j->second); + } + +/************************************************* +* Add an attribute to a X509_DN * +*************************************************/ +void X509_DN::add_attribute(const std::string& type, + const std::string& str) + { + OID oid = OIDS::lookup(type); + add_attribute(oid, str); + } + +/************************************************* +* Add an attribute to a X509_DN * +*************************************************/ +void X509_DN::add_attribute(const OID& oid, const std::string& str) + { + if(str == "") + return; + + typedef std::multimap::iterator rdn_iter; + + std::pair range = dn_info.equal_range(oid); + for(rdn_iter j = range.first; j != range.second; ++j) + if(j->second.value() == str) + return; + + multimap_insert(dn_info, oid, ASN1_String(str)); + dn_bits.destroy(); + } + +/************************************************* +* Get the attributes of this X509_DN * +*************************************************/ +std::multimap X509_DN::get_attributes() const + { + typedef std::multimap::const_iterator rdn_iter; + + std::multimap retval; + for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j) + multimap_insert(retval, j->first, j->second.value()); + return retval; + } + +/************************************************* +* Get the contents of this X.500 Name * +*************************************************/ +std::multimap X509_DN::contents() const + { + typedef std::multimap::const_iterator rdn_iter; + + std::multimap retval; + for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j) + multimap_insert(retval, OIDS::lookup(j->first), j->second.value()); + return retval; + } + +/************************************************* +* Get a single attribute type * +*************************************************/ +std::vector X509_DN::get_attribute(const std::string& attr) const + { + typedef std::multimap::const_iterator rdn_iter; + + const OID oid = OIDS::lookup(deref_info_field(attr)); + std::pair range = dn_info.equal_range(oid); + + std::vector values; + for(rdn_iter j = range.first; j != range.second; ++j) + values.push_back(j->second.value()); + return values; + } + +/************************************************* +* Handle the decoding operation of a DN * +*************************************************/ +void X509_DN::do_decode(const MemoryRegion& bits) + { + BER_Decoder sequence(bits); + + while(sequence.more_items()) + { + BER_Decoder rdn = sequence.start_cons(SET); + + while(rdn.more_items()) + { + OID oid; + ASN1_String str; + + rdn.start_cons(SEQUENCE) + .decode(oid) + .decode(str) + .verify_end() + .end_cons(); + + add_attribute(oid, str.value()); + } + } + + dn_bits = bits; + } + +/************************************************* +* Return the BER encoded data, if any * +*************************************************/ +MemoryVector X509_DN::get_bits() const + { + return dn_bits; + } + +/************************************************* +* Deref aliases in a subject/issuer info request * +*************************************************/ +std::string X509_DN::deref_info_field(const std::string& info) + { + if(info == "Name" || info == "CommonName") return "X520.CommonName"; + if(info == "SerialNumber") return "X520.SerialNumber"; + if(info == "Country") return "X520.Country"; + if(info == "Organization") return "X520.Organization"; + if(info == "Organizational Unit" || info == "OrgUnit") + return "X520.OrganizationalUnit"; + if(info == "Locality") return "X520.Locality"; + if(info == "State" || info == "Province") return "X520.State"; + if(info == "Email") return "RFC822"; + return info; + } + +/************************************************* +* Compare two X509_DNs for equality * +*************************************************/ +bool operator==(const X509_DN& dn1, const X509_DN& dn2) + { + typedef std::multimap::const_iterator rdn_iter; + + std::multimap attr1 = dn1.get_attributes(); + std::multimap attr2 = dn2.get_attributes(); + + if(attr1.size() != attr2.size()) return false; + + rdn_iter p1 = attr1.begin(); + rdn_iter p2 = attr2.begin(); + + while(true) + { + if(p1 == attr1.end() && p2 == attr2.end()) + break; + if(p1 == attr1.end()) return false; + if(p2 == attr2.end()) return false; + if(p1->first != p2->first) return false; + if(!x500_name_cmp(p1->second, p2->second)) + return false; + ++p1; + ++p2; + } + return true; + } + +/************************************************* +* Compare two X509_DNs for inequality * +*************************************************/ +bool operator!=(const X509_DN& dn1, const X509_DN& dn2) + { + return !(dn1 == dn2); + } + +/************************************************* +* Compare two X509_DNs * +*************************************************/ +bool operator<(const X509_DN& dn1, const X509_DN& dn2) + { + typedef std::multimap::const_iterator rdn_iter; + + std::multimap attr1 = dn1.get_attributes(); + std::multimap attr2 = dn2.get_attributes(); + + if(attr1.size() < attr2.size()) return true; + if(attr1.size() > attr2.size()) return false; + + for(rdn_iter p1 = attr1.begin(); p1 != attr1.end(); ++p1) + { + std::multimap::const_iterator p2; + p2 = attr2.find(p1->first); + if(p2 == attr2.end()) return false; + if(p1->second > p2->second) return false; + if(p1->second < p2->second) return true; + } + return false; + } + +namespace { + +/************************************************* +* DER encode a RelativeDistinguishedName * +*************************************************/ +void do_ava(DER_Encoder& encoder, + const std::multimap& dn_info, + ASN1_Tag string_type, const std::string& oid_str, + bool must_exist = false) + { + typedef std::multimap::const_iterator rdn_iter; + + const OID oid = OIDS::lookup(oid_str); + const bool exists = (dn_info.find(oid) != dn_info.end()); + + if(!exists && must_exist) + throw Encoding_Error("X509_DN: No entry for " + oid_str); + if(!exists) return; + + std::pair range = dn_info.equal_range(oid); + + for(rdn_iter j = range.first; j != range.second; ++j) + { + encoder.start_cons(SET) + .start_cons(SEQUENCE) + .encode(oid) + .encode(ASN1_String(j->second, string_type)) + .end_cons() + .end_cons(); + } + } + +} + +/************************************************* +* DER encode a DistinguishedName * +*************************************************/ +void X509_DN::encode_into(DER_Encoder& der) const + { + std::multimap dn_info = get_attributes(); + + der.start_cons(SEQUENCE); + + if(dn_bits.has_items()) + der.raw_bytes(dn_bits); + else + { + do_ava(der, dn_info, PRINTABLE_STRING, "X520.Country", true); + do_ava(der, dn_info, DIRECTORY_STRING, "X520.State"); + do_ava(der, dn_info, DIRECTORY_STRING, "X520.Locality"); + do_ava(der, dn_info, DIRECTORY_STRING, "X520.Organization"); + do_ava(der, dn_info, DIRECTORY_STRING, "X520.OrganizationalUnit"); + do_ava(der, dn_info, DIRECTORY_STRING, "X520.CommonName", true); + do_ava(der, dn_info, PRINTABLE_STRING, "X520.SerialNumber"); + } + + der.end_cons(); + } + +/************************************************* +* Decode a BER encoded DistinguishedName * +*************************************************/ +void X509_DN::decode_from(BER_Decoder& source) + { + dn_info.clear(); + + source.start_cons(SEQUENCE) + .raw_bytes(dn_bits) + .end_cons(); + + do_decode(dn_bits); + } + +} diff --git a/src/asn1/asn1_int.cpp b/src/asn1/asn1_int.cpp new file mode 100644 index 000000000..e837dedf0 --- /dev/null +++ b/src/asn1/asn1_int.cpp @@ -0,0 +1,66 @@ +/************************************************* +* ASN.1 Internals Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include +#include +#include + +namespace Botan { + +/************************************************* +* BER Decoding Exceptions * +*************************************************/ +BER_Decoding_Error::BER_Decoding_Error(const std::string& str) : + Decoding_Error("BER: " + str) {} + +BER_Bad_Tag::BER_Bad_Tag(const std::string& str, ASN1_Tag tag) : + BER_Decoding_Error(str + ": " + to_string(tag)) {} + +BER_Bad_Tag::BER_Bad_Tag(const std::string& str, + ASN1_Tag tag1, ASN1_Tag tag2) : + BER_Decoding_Error(str + ": " + to_string(tag1) + "/" + to_string(tag2)) {} + +namespace ASN1 { + +/************************************************* +* Put some arbitrary bytes into a SEQUENCE * +*************************************************/ +SecureVector put_in_sequence(const MemoryRegion& contents) + { + return DER_Encoder() + .start_cons(SEQUENCE) + .raw_bytes(contents) + .end_cons() + .get_contents(); + } + +/************************************************* +* Convert a BER object into a string object * +*************************************************/ +std::string to_string(const BER_Object& obj) + { + return std::string(reinterpret_cast(obj.value.begin()), + obj.value.size()); + } + +/************************************************* +* Do heuristic tests for BER data * +*************************************************/ +bool maybe_BER(DataSource& source) + { + byte first_byte; + if(!source.peek_byte(first_byte)) + throw Stream_IO_Error("ASN1::maybe_BER: Source was empty"); + + if(first_byte == (SEQUENCE | CONSTRUCTED)) + return true; + return false; + } + +} + +} diff --git a/src/asn1/asn1_int.h b/src/asn1/asn1_int.h new file mode 100644 index 000000000..3e0562b9c --- /dev/null +++ b/src/asn1/asn1_int.h @@ -0,0 +1,106 @@ +/************************************************* +* ASN.1 Internals Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ASN1_H__ +#define BOTAN_ASN1_H__ + +#include +#include + +namespace Botan { + +/************************************************* +* ASN.1 Type and Class Tags * +*************************************************/ +enum ASN1_Tag { + UNIVERSAL = 0x00, + APPLICATION = 0x40, + CONTEXT_SPECIFIC = 0x80, + PRIVATE = 0xC0, + + CONSTRUCTED = 0x20, + + EOC = 0x00, + BOOLEAN = 0x01, + INTEGER = 0x02, + BIT_STRING = 0x03, + OCTET_STRING = 0x04, + NULL_TAG = 0x05, + OBJECT_ID = 0x06, + ENUMERATED = 0x0A, + SEQUENCE = 0x10, + SET = 0x11, + + UTF8_STRING = 0x0C, + NUMERIC_STRING = 0x12, + PRINTABLE_STRING = 0x13, + T61_STRING = 0x14, + IA5_STRING = 0x16, + VISIBLE_STRING = 0x1A, + BMP_STRING = 0x1E, + + UTC_TIME = 0x17, + GENERALIZED_TIME = 0x18, + + NO_OBJECT = 0xFF00, + DIRECTORY_STRING = 0xFF01 +}; + +/************************************************* +* Basic ASN.1 Object Interface * +*************************************************/ +class BOTAN_DLL ASN1_Object + { + public: + virtual void encode_into(class DER_Encoder&) const = 0; + virtual void decode_from(class BER_Decoder&) = 0; + virtual ~ASN1_Object() {} + }; + +/************************************************* +* BER Encoded Object * +*************************************************/ +class BOTAN_DLL BER_Object + { + public: + void assert_is_a(ASN1_Tag, ASN1_Tag); + + ASN1_Tag type_tag, class_tag; + SecureVector value; + }; + +/************************************************* +* ASN.1 Utility Functions * +*************************************************/ +class DataSource; + +namespace ASN1 { + +SecureVector put_in_sequence(const MemoryRegion&); +std::string to_string(const BER_Object&); +bool maybe_BER(DataSource&); + +} + +/************************************************* +* General BER Decoding Error Exception * +*************************************************/ +struct BER_Decoding_Error : public Decoding_Error + { + BER_Decoding_Error(const std::string&); + }; + +/************************************************* +* Exception For Incorrect BER Taggings * +*************************************************/ +struct BER_Bad_Tag : public BER_Decoding_Error + { + BER_Bad_Tag(const std::string&, ASN1_Tag); + BER_Bad_Tag(const std::string&, ASN1_Tag, ASN1_Tag); + }; + +} + +#endif diff --git a/src/asn1/asn1_ku.cpp b/src/asn1/asn1_ku.cpp new file mode 100644 index 000000000..32c5944dd --- /dev/null +++ b/src/asn1/asn1_ku.cpp @@ -0,0 +1,41 @@ +/************************************************* +* KeyUsage Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include + +namespace Botan { + +namespace BER { + +/************************************************* +* Decode a BER encoded KeyUsage * +*************************************************/ +void decode(BER_Decoder& source, Key_Constraints& key_usage) + { + BER_Object obj = source.get_next_object(); + + if(obj.type_tag != BIT_STRING || obj.class_tag != UNIVERSAL) + throw BER_Bad_Tag("Bad tag for usage constraint", + obj.type_tag, obj.class_tag); + if(obj.value.size() != 2 && obj.value.size() != 3) + throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint"); + if(obj.value[0] >= 8) + throw BER_Decoding_Error("Invalid unused bits in usage constraint"); + + const byte mask = (0xFF << obj.value[0]); + obj.value[obj.value.size()-1] &= mask; + + u16bit usage = 0; + for(u32bit j = 1; j != obj.value.size(); ++j) + usage = (obj.value[j] << 8) | usage; + + key_usage = Key_Constraints(usage); + } + +} + +} diff --git a/src/asn1/asn1_obj.h b/src/asn1/asn1_obj.h new file mode 100644 index 000000000..67645ca08 --- /dev/null +++ b/src/asn1/asn1_obj.h @@ -0,0 +1,158 @@ +/************************************************* +* Common ASN.1 Objects Header File * +* (C) 1999-2007 Jack Lloyd * +* 2007 Yves Jerschow * +*************************************************/ + +#ifndef BOTAN_ASN1_OBJ_H__ +#define BOTAN_ASN1_OBJ_H__ + +#include +#include +#include +#include +#include + +namespace Botan { + +/************************************************* +* Attribute * +*************************************************/ +class BOTAN_DLL Attribute : public ASN1_Object + { + public: + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + + OID oid; + MemoryVector parameters; + + Attribute() {} + Attribute(const OID&, const MemoryRegion&); + Attribute(const std::string&, const MemoryRegion&); + }; + +/************************************************* +* X.509 Time * +*************************************************/ +class BOTAN_DLL X509_Time : public ASN1_Object + { + public: + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + + std::string as_string() const; + std::string readable_string() const; + bool time_is_set() const; + + s32bit cmp(const X509_Time&) const; + + void set_to(const std::string&); + void set_to(const std::string&, ASN1_Tag); + + X509_Time(u64bit); + X509_Time(const std::string& = ""); + X509_Time(const std::string&, ASN1_Tag); + private: + bool passes_sanity_check() const; + u32bit year, month, day, hour, minute, second; + ASN1_Tag tag; + }; + +/************************************************* +* Simple String * +*************************************************/ +class BOTAN_DLL ASN1_String : public ASN1_Object + { + public: + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + + std::string value() const; + std::string iso_8859() const; + + ASN1_Tag tagging() const; + + ASN1_String(const std::string& = ""); + ASN1_String(const std::string&, ASN1_Tag); + private: + std::string iso_8859_str; + ASN1_Tag tag; + }; + +/************************************************* +* Distinguished Name * +*************************************************/ +class BOTAN_DLL X509_DN : public ASN1_Object + { + public: + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + + std::multimap get_attributes() const; + std::vector get_attribute(const std::string&) const; + + std::multimap contents() const; + + void add_attribute(const std::string&, const std::string&); + void add_attribute(const OID&, const std::string&); + + static std::string deref_info_field(const std::string&); + + void do_decode(const MemoryRegion&); + MemoryVector get_bits() const; + + X509_DN(); + X509_DN(const std::multimap&); + X509_DN(const std::multimap&); + private: + std::multimap dn_info; + MemoryVector dn_bits; + }; + +/************************************************* +* Alternative Name * +*************************************************/ +class BOTAN_DLL AlternativeName : public ASN1_Object + { + public: + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + + std::multimap contents() const; + + void add_attribute(const std::string&, const std::string&); + std::multimap get_attributes() const; + + void add_othername(const OID&, const std::string&, ASN1_Tag); + std::multimap get_othernames() const; + + bool has_items() const; + + AlternativeName(const std::string& = "", const std::string& = "", + const std::string& = "", const std::string& = ""); + private: + std::multimap alt_info; + std::multimap othernames; + }; + +/************************************************* +* Comparison Operations * +*************************************************/ +bool BOTAN_DLL operator==(const X509_Time&, const X509_Time&); +bool BOTAN_DLL operator!=(const X509_Time&, const X509_Time&); +bool BOTAN_DLL operator<=(const X509_Time&, const X509_Time&); +bool BOTAN_DLL operator>=(const X509_Time&, const X509_Time&); + +bool BOTAN_DLL operator==(const X509_DN&, const X509_DN&); +bool BOTAN_DLL operator!=(const X509_DN&, const X509_DN&); +bool BOTAN_DLL operator<(const X509_DN&, const X509_DN&); + +/************************************************* +* Helper Functions * +*************************************************/ +bool BOTAN_DLL is_string_type(ASN1_Tag); + +} + +#endif diff --git a/src/asn1/asn1_oid.cpp b/src/asn1/asn1_oid.cpp new file mode 100644 index 000000000..80968ed8f --- /dev/null +++ b/src/asn1/asn1_oid.cpp @@ -0,0 +1,174 @@ +/************************************************* +* ASN.1 OID Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include +#include +#include + +namespace Botan { + +/************************************************* +* ASN.1 OID Constructor * +*************************************************/ +OID::OID(const std::string& oid_str) + { + if(oid_str != "") + { + id = parse_asn1_oid(oid_str); + if(id.size() < 2 || id[0] > 2) + throw Invalid_OID(oid_str); + if((id[0] == 0 || id[0] == 1) && id[1] > 39) + throw Invalid_OID(oid_str); + } + } + +/************************************************* +* Clear the current OID * +*************************************************/ +void OID::clear() + { + id.clear(); + } + +/************************************************* +* Return this OID as a string * +*************************************************/ +std::string OID::as_string() const + { + std::string oid_str; + for(u32bit j = 0; j != id.size(); ++j) + { + oid_str += to_string(id[j]); + if(j != id.size() - 1) + oid_str += '.'; + } + return oid_str; + } + +/************************************************* +* OID equality comparison * +*************************************************/ +bool OID::operator==(const OID& oid) const + { + if(id.size() != oid.id.size()) + return false; + for(u32bit j = 0; j != id.size(); ++j) + if(id[j] != oid.id[j]) + return false; + return true; + } + +/************************************************* +* Append another component to the OID * +*************************************************/ +OID& OID::operator+=(u32bit component) + { + id.push_back(component); + return (*this); + } + +/************************************************* +* Append another component to the OID * +*************************************************/ +OID operator+(const OID& oid, u32bit component) + { + OID new_oid(oid); + new_oid += component; + return new_oid; + } + +/************************************************* +* OID inequality comparison * +*************************************************/ +bool operator!=(const OID& a, const OID& b) + { + return !(a == b); + } + +/************************************************* +* Compare two OIDs * +*************************************************/ +bool operator<(const OID& a, const OID& b) + { + std::vector oid1 = a.get_id(); + std::vector oid2 = b.get_id(); + + if(oid1.size() < oid2.size()) + return true; + if(oid1.size() > oid2.size()) + return false; + for(u32bit j = 0; j != oid1.size(); ++j) + { + if(oid1[j] < oid2[j]) + return true; + if(oid1[j] > oid2[j]) + return false; + } + return false; + } + +/************************************************* +* DER encode an OBJECT IDENTIFIER * +*************************************************/ +void OID::encode_into(DER_Encoder& der) const + { + if(id.size() < 2) + throw Invalid_Argument("OID::encode_into: OID is invalid"); + + MemoryVector encoding; + encoding.append(40 * id[0] + id[1]); + + for(u32bit j = 2; j != id.size(); ++j) + { + if(id[j] == 0) + encoding.append(0); + else + { + u32bit blocks = high_bit(id[j]) + 6; + blocks = (blocks - (blocks % 7)) / 7; + + for(u32bit k = 0; k != blocks - 1; ++k) + encoding.append(0x80 | ((id[j] >> 7*(blocks-k-1)) & 0x7F)); + encoding.append(id[j] & 0x7F); + } + } + der.add_object(OBJECT_ID, UNIVERSAL, encoding); + } + +/************************************************* +* Decode a BER encoded OBJECT IDENTIFIER * +*************************************************/ +void OID::decode_from(BER_Decoder& decoder) + { + BER_Object obj = decoder.get_next_object(); + if(obj.type_tag != OBJECT_ID || obj.class_tag != UNIVERSAL) + throw BER_Bad_Tag("Error decoding OID, unknown tag", + obj.type_tag, obj.class_tag); + if(obj.value.size() < 2) + throw BER_Decoding_Error("OID encoding is too short"); + + + clear(); + id.push_back(obj.value[0] / 40); + id.push_back(obj.value[0] % 40); + + u32bit j = 0; + while(j != obj.value.size() - 1) + { + u32bit component = 0; + while(j != obj.value.size() - 1) + { + ++j; + component = (component << 7) + (obj.value[j] & 0x7F); + if(!(obj.value[j] & 0x80)) + break; + } + id.push_back(component); + } + } + +} diff --git a/src/asn1/asn1_oid.h b/src/asn1/asn1_oid.h new file mode 100644 index 000000000..73d0079a8 --- /dev/null +++ b/src/asn1/asn1_oid.h @@ -0,0 +1,50 @@ +/************************************************* +* ASN.1 OID Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ASN1_OID_H__ +#define BOTAN_ASN1_OID_H__ + +#include +#include +#include + +namespace Botan { + +/************************************************* +* ASN.1 Object Identifier * +*************************************************/ +class BOTAN_DLL OID : public ASN1_Object + { + public: + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + + bool is_empty() const { return id.size() == 0; } + std::vector get_id() const { return id; } + std::string as_string() const; + + bool operator==(const OID&) const; + void clear(); + + OID& operator+=(u32bit); + OID(const std::string& = ""); + private: + std::vector id; + }; + +/************************************************* +* Append another component onto the OID * +*************************************************/ +OID BOTAN_DLL operator+(const OID&, u32bit); + +/************************************************* +* Compare two OIDs * +*************************************************/ +bool BOTAN_DLL operator!=(const OID&, const OID&); +bool BOTAN_DLL operator<(const OID&, const OID&); + +} + +#endif diff --git a/src/asn1/asn1_str.cpp b/src/asn1/asn1_str.cpp new file mode 100644 index 000000000..52dcdc55e --- /dev/null +++ b/src/asn1/asn1_str.cpp @@ -0,0 +1,161 @@ +/************************************************* +* Simple ASN.1 String Types Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include +#include +#include +#include + +namespace Botan { + +namespace { + +/************************************************* +* Choose an encoding for the string * +*************************************************/ +ASN1_Tag choose_encoding(const std::string& str, + const std::string& type) + { + static const byte IS_PRINTABLE[256] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 }; + + for(u32bit j = 0; j != str.size(); ++j) + { + if(!IS_PRINTABLE[static_cast(str[j])]) + { + if(type == "utf8") return UTF8_STRING; + if(type == "latin1") return T61_STRING; + throw Invalid_Argument("Bad setting for x509/ca/str_type: " + type); + } + } + return PRINTABLE_STRING; + } + +} + +/************************************************* +* Check if type is a known ASN.1 string type * +*************************************************/ +bool is_string_type(ASN1_Tag tag) + { + if(tag == NUMERIC_STRING || tag == PRINTABLE_STRING || + tag == VISIBLE_STRING || tag == T61_STRING || tag == IA5_STRING || + tag == UTF8_STRING || tag == BMP_STRING) + return true; + return false; + } + +/************************************************* +* Create an ASN1_String * +*************************************************/ +ASN1_String::ASN1_String(const std::string& str, ASN1_Tag t) : tag(t) + { + iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET); + + if(tag == DIRECTORY_STRING) + tag = choose_encoding(iso_8859_str, + global_state().option("x509/ca/str_type")); + + if(tag != NUMERIC_STRING && + tag != PRINTABLE_STRING && + tag != VISIBLE_STRING && + tag != T61_STRING && + tag != IA5_STRING && + tag != UTF8_STRING && + tag != BMP_STRING) + throw Invalid_Argument("ASN1_String: Unknown string type " + + to_string(tag)); + } + +/************************************************* +* Create an ASN1_String * +*************************************************/ +ASN1_String::ASN1_String(const std::string& str) + { + iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET); + tag = choose_encoding(iso_8859_str, + global_state().option("x509/ca/str_type")); + } + +/************************************************* +* Return this string in ISO 8859-1 encoding * +*************************************************/ +std::string ASN1_String::iso_8859() const + { + return iso_8859_str; + } + +/************************************************* +* Return this string in local encoding * +*************************************************/ +std::string ASN1_String::value() const + { + return Charset::transcode(iso_8859_str, LATIN1_CHARSET, LOCAL_CHARSET); + } + +/************************************************* +* Return the type of this string object * +*************************************************/ +ASN1_Tag ASN1_String::tagging() const + { + return tag; + } + +/************************************************* +* DER encode an ASN1_String * +*************************************************/ +void ASN1_String::encode_into(DER_Encoder& encoder) const + { + std::string value = iso_8859(); + if(tagging() == UTF8_STRING) + value = Charset::transcode(value, LATIN1_CHARSET, UTF8_CHARSET); + encoder.add_object(tagging(), UNIVERSAL, value); + } + +/************************************************* +* Decode a BER encoded ASN1_String * +*************************************************/ +void ASN1_String::decode_from(BER_Decoder& source) + { + BER_Object obj = source.get_next_object(); + + Character_Set charset_is; + + if(obj.type_tag == BMP_STRING) + charset_is = UCS2_CHARSET; + else if(obj.type_tag == UTF8_STRING) + charset_is = UTF8_CHARSET; + else + charset_is = LATIN1_CHARSET; + + *this = ASN1_String( + Charset::transcode(ASN1::to_string(obj), charset_is, LOCAL_CHARSET), + obj.type_tag); + } + +} diff --git a/src/asn1/asn1_tm.cpp b/src/asn1/asn1_tm.cpp new file mode 100644 index 000000000..7cd051af7 --- /dev/null +++ b/src/asn1/asn1_tm.cpp @@ -0,0 +1,295 @@ +/************************************************* +* X.509 Time Types Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include +#include +#include +#include + +namespace Botan { + +namespace { + +/************************************************* +* Convert a time_t to a struct tm * +*************************************************/ +std::tm get_tm(u64bit timer) + { + std::time_t time_val = static_cast(timer); + + std::tm* tm_p = std::gmtime(&time_val); + if(tm_p == 0) + throw Encoding_Error("X509_Time: gmtime could not encode " + + to_string(timer)); + return (*tm_p); + } + +} + +/************************************************* +* Create an X509_Time * +*************************************************/ +X509_Time::X509_Time(const std::string& time_str) + { + set_to(time_str); + } + +/************************************************* +* Create an X509_Time * +*************************************************/ +X509_Time::X509_Time(u64bit timer) + { + std::tm time_info = get_tm(timer); + + year = time_info.tm_year + 1900; + month = time_info.tm_mon + 1; + day = time_info.tm_mday; + hour = time_info.tm_hour; + minute = time_info.tm_min; + second = time_info.tm_sec; + + if(year >= 2050) + tag = GENERALIZED_TIME; + else + tag = UTC_TIME; + } + +/************************************************* +* Create an X509_Time * +*************************************************/ +X509_Time::X509_Time(const std::string& t_spec, ASN1_Tag t) : tag(t) + { + set_to(t_spec, tag); + } + +/************************************************* +* Set the time with a human readable string * +*************************************************/ +void X509_Time::set_to(const std::string& time_str) + { + if(time_str == "") + { + year = month = day = hour = minute = second = 0; + return; + } + + std::vector params; + std::string current; + + for(u32bit j = 0; j != time_str.size(); ++j) + { + if(Charset::is_digit(time_str[j])) + current += time_str[j]; + else + { + if(current != "") + params.push_back(current); + current.clear(); + } + } + if(current != "") + params.push_back(current); + + if(params.size() < 3 || params.size() > 6) + throw Invalid_Argument("Invalid time specification " + time_str); + + year = to_u32bit(params[0]); + month = to_u32bit(params[1]); + day = to_u32bit(params[2]); + hour = (params.size() >= 4) ? to_u32bit(params[3]) : 0; + minute = (params.size() >= 5) ? to_u32bit(params[4]) : 0; + second = (params.size() == 6) ? to_u32bit(params[5]) : 0; + + if(year >= 2050) + tag = GENERALIZED_TIME; + else + tag = UTC_TIME; + + if(!passes_sanity_check()) + throw Invalid_Argument("Invalid time specification " + time_str); + } + +/************************************************* +* Set the time with an ISO time format string * +*************************************************/ +void X509_Time::set_to(const std::string& t_spec, ASN1_Tag tag) + { + if(tag != GENERALIZED_TIME && tag != UTC_TIME) + throw Invalid_Argument("X509_Time: Invalid tag " + to_string(tag)); + if(tag == GENERALIZED_TIME && t_spec.size() != 13 && t_spec.size() != 15) + throw Invalid_Argument("Invalid GeneralizedTime: " + t_spec); + if(tag == UTC_TIME && t_spec.size() != 11 && t_spec.size() != 13) + throw Invalid_Argument("Invalid UTCTime: " + t_spec); + if(t_spec[t_spec.size()-1] != 'Z') + throw Invalid_Argument("Invalid time encoding: " + t_spec); + + const u32bit YEAR_SIZE = (tag == UTC_TIME) ? 2 : 4; + + std::vector params; + std::string current; + + for(u32bit j = 0; j != YEAR_SIZE; ++j) + current += t_spec[j]; + params.push_back(current); + current.clear(); + + for(u32bit j = YEAR_SIZE; j != t_spec.size() - 1; ++j) + { + current += t_spec[j]; + if(current.size() == 2) + { + params.push_back(current); + current.clear(); + } + } + + year = to_u32bit(params[0]); + month = to_u32bit(params[1]); + day = to_u32bit(params[2]); + hour = to_u32bit(params[3]); + minute = to_u32bit(params[4]); + second = (params.size() == 6) ? to_u32bit(params[5]) : 0; + + if(tag == UTC_TIME) + { + if(year >= 50) year += 1900; + else year += 2000; + } + + if(!passes_sanity_check()) + throw Invalid_Argument("Invalid time specification " + t_spec); + } + +/************************************************* +* DER encode a X509_Time * +*************************************************/ +void X509_Time::encode_into(DER_Encoder& der) const + { + if(tag != GENERALIZED_TIME && tag != UTC_TIME) + throw Invalid_Argument("X509_Time: Bad encoding tag"); + der.add_object(tag, UNIVERSAL, + Charset::transcode(as_string(), + LOCAL_CHARSET, LATIN1_CHARSET)); + } + +/************************************************* +* Decode a BER encoded X509_Time * +*************************************************/ +void X509_Time::decode_from(BER_Decoder& source) + { + BER_Object ber_time = source.get_next_object(); + set_to(Charset::transcode(ASN1::to_string(ber_time), + LATIN1_CHARSET, LOCAL_CHARSET), + ber_time.type_tag); + } + +/************************************************* +* Return a string representation of the time * +*************************************************/ +std::string X509_Time::as_string() const + { + if(time_is_set() == false) + throw Invalid_State("X509_Time::as_string: No time set"); + + std::string asn1rep; + if(tag == GENERALIZED_TIME) + asn1rep = to_string(year, 4); + else + { + if(year < 1950 || year >= 2050) + throw Encoding_Error("X509_Time: The time " + readable_string() + + " cannot be encoded as a UTCTime"); + u32bit asn1year = (year >= 2000) ? (year - 2000) : (year - 1900); + asn1rep = to_string(asn1year, 2); + } + asn1rep += to_string(month, 2) + to_string(day, 2); + asn1rep += to_string(hour, 2) + to_string(minute, 2) + to_string(second, 2); + asn1rep += "Z"; + return asn1rep; + } + +/************************************************* +* Return if the time has been set somehow * +*************************************************/ +bool X509_Time::time_is_set() const + { + return (year != 0); + } + +/************************************************* +* Return a human readable string representation * +*************************************************/ +std::string X509_Time::readable_string() const + { + if(time_is_set() == false) + throw Invalid_State("X509_Time::readable_string: No time set"); + + std::string readable; + readable += to_string(year, 4) + "/"; + readable += to_string(month ) + "/"; + readable += to_string(day ) + " "; + readable += to_string(hour ) + ":"; + readable += to_string(minute, 2) + ":"; + readable += to_string(second, 2) + " UTC"; + return readable; + } + +/************************************************* +* Do a general sanity check on the time * +*************************************************/ +bool X509_Time::passes_sanity_check() const + { + if(year < 1950 || year > 2100) + return false; + if(month == 0 || month > 12) + return false; + if(day == 0 || day > 31) + return false; + if(hour >= 24 || minute > 60 || second > 60) + return false; + return true; + } + +/************************************************* +* Compare this time against another * +*************************************************/ +s32bit X509_Time::cmp(const X509_Time& other) const + { + if(time_is_set() == false) + throw Invalid_State("X509_Time::cmp: No time set"); + + const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0; + + if(year < other.year) return EARLIER; + if(year > other.year) return LATER; + if(month < other.month) return EARLIER; + if(month > other.month) return LATER; + if(day < other.day) return EARLIER; + if(day > other.day) return LATER; + if(hour < other.hour) return EARLIER; + if(hour > other.hour) return LATER; + if(minute < other.minute) return EARLIER; + if(minute > other.minute) return LATER; + if(second < other.second) return EARLIER; + if(second > other.second) return LATER; + + return SAME_TIME; + } + +/************************************************* +* Compare two X509_Times for in various ways * +*************************************************/ +bool operator==(const X509_Time& t1, const X509_Time& t2) + { return (t1.cmp(t2) == 0); } +bool operator!=(const X509_Time& t1, const X509_Time& t2) + { return (t1.cmp(t2) != 0); } +bool operator<=(const X509_Time& t1, const X509_Time& t2) + { return (t1.cmp(t2) <= 0); } +bool operator>=(const X509_Time& t1, const X509_Time& t2) + { return (t1.cmp(t2) >= 0); } + +} diff --git a/src/asn1/ber_dec.cpp b/src/asn1/ber_dec.cpp new file mode 100644 index 000000000..c725a5af9 --- /dev/null +++ b/src/asn1/ber_dec.cpp @@ -0,0 +1,469 @@ +/************************************************* +* BER Decoder Source File * +* (C) 1999-2008 Jack Lloyd * +*************************************************/ + +#include +#include +#include + +namespace Botan { + +namespace { + +/************************************************* +* BER decode an ASN.1 type tag * +*************************************************/ +u32bit decode_tag(DataSource* ber, ASN1_Tag& type_tag, ASN1_Tag& class_tag) + { + byte b; + if(!ber->read_byte(b)) + { + class_tag = type_tag = NO_OBJECT; + return 0; + } + + if((b & 0x1F) != 0x1F) + { + type_tag = ASN1_Tag(b & 0x1F); + class_tag = ASN1_Tag(b & 0xE0); + return 1; + } + + u32bit tag_bytes = 1; + class_tag = ASN1_Tag(b & 0xE0); + + u32bit tag_buf = 0; + while(true) + { + if(!ber->read_byte(b)) + throw BER_Decoding_Error("Long-form tag truncated"); + if(tag_buf & 0xFF000000) + throw BER_Decoding_Error("Long-form tag overflowed 32 bits"); + ++tag_bytes; + tag_buf = (tag_buf << 7) | (b & 0x7F); + if((b & 0x80) == 0) break; + } + type_tag = ASN1_Tag(tag_buf); + return tag_bytes; + } + +/************************************************* +* Find the EOC marker * +*************************************************/ +u32bit find_eoc(DataSource*); + +/************************************************* +* BER decode an ASN.1 length field * +*************************************************/ +u32bit decode_length(DataSource* ber, u32bit& field_size) + { + byte b; + if(!ber->read_byte(b)) + throw BER_Decoding_Error("Length field not found"); + field_size = 1; + if((b & 0x80) == 0) + return b; + + field_size += (b & 0x7F); + if(field_size == 1) return find_eoc(ber); + if(field_size > 5) + throw BER_Decoding_Error("Length field is too large"); + + u32bit length = 0; + + for(u32bit j = 0; j != field_size - 1; ++j) + { + if(get_byte(0, length) != 0) + throw BER_Decoding_Error("Field length overflow"); + if(!ber->read_byte(b)) + throw BER_Decoding_Error("Corrupted length field"); + length = (length << 8) | b; + } + return length; + } + +/************************************************* +* BER decode an ASN.1 length field * +*************************************************/ +u32bit decode_length(DataSource* ber) + { + u32bit dummy; + return decode_length(ber, dummy); + } + +/************************************************* +* Find the EOC marker * +*************************************************/ +u32bit find_eoc(DataSource* ber) + { + SecureVector buffer(DEFAULT_BUFFERSIZE), data; + + while(true) + { + const u32bit got = ber->peek(buffer, buffer.size(), data.size()); + if(got == 0) + break; + data.append(buffer, got); + } + + DataSource_Memory source(data); + data.destroy(); + + u32bit length = 0; + while(true) + { + ASN1_Tag type_tag, class_tag; + u32bit tag_size = decode_tag(&source, type_tag, class_tag); + if(type_tag == NO_OBJECT) + break; + + u32bit length_size = 0; + u32bit item_size = decode_length(&source, length_size); + source.discard_next(item_size); + + length += item_size + length_size + tag_size; + + if(type_tag == EOC) + break; + } + return length; + } + +} + +/************************************************* +* Check a type invariant on BER data * +*************************************************/ +void BER_Object::assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) + { + if(this->type_tag != type_tag || this->class_tag != class_tag) + throw BER_Decoding_Error("Tag mismatch when decoding"); + } + +/************************************************* +* Check if more objects are there * +*************************************************/ +bool BER_Decoder::more_items() const + { + if(source->end_of_data() && (pushed.type_tag == NO_OBJECT)) + return false; + return true; + } + +/************************************************* +* Verify that no bytes remain in the source * +*************************************************/ +BER_Decoder& BER_Decoder::verify_end() + { + if(!source->end_of_data() || (pushed.type_tag != NO_OBJECT)) + throw Invalid_State("BER_Decoder::verify_end called, but data remains"); + return (*this); + } + +/************************************************* +* Save all the bytes remaining in the source * +*************************************************/ +BER_Decoder& BER_Decoder::raw_bytes(MemoryRegion& out) + { + out.destroy(); + byte buf; + while(source->read_byte(buf)) + out.append(buf); + return (*this); + } + +/************************************************* +* Discard all the bytes remaining in the source * +*************************************************/ +BER_Decoder& BER_Decoder::discard_remaining() + { + byte buf; + while(source->read_byte(buf)) + ; + return (*this); + } + +/************************************************* +* Return the BER encoding of the next object * +*************************************************/ +BER_Object BER_Decoder::get_next_object() + { + BER_Object next; + + if(pushed.type_tag != NO_OBJECT) + { + next = pushed; + pushed.class_tag = pushed.type_tag = NO_OBJECT; + return next; + } + + decode_tag(source, next.type_tag, next.class_tag); + if(next.type_tag == NO_OBJECT) + return next; + + u32bit length = decode_length(source); + next.value.create(length); + if(source->read(next.value, length) != length) + throw BER_Decoding_Error("Value truncated"); + + if(next.type_tag == EOC && next.class_tag == UNIVERSAL) + return get_next_object(); + + return next; + } + +/************************************************* +* Push a object back into the stream * +*************************************************/ +void BER_Decoder::push_back(const BER_Object& obj) + { + if(pushed.type_tag != NO_OBJECT) + throw Invalid_State("BER_Decoder: Only one push back is allowed"); + pushed = obj; + } + +/************************************************* +* Begin decoding a CONSTRUCTED type * +*************************************************/ +BER_Decoder BER_Decoder::start_cons(ASN1_Tag type_tag, + ASN1_Tag class_tag) + { + BER_Object obj = get_next_object(); + obj.assert_is_a(type_tag, ASN1_Tag(class_tag | CONSTRUCTED)); + + BER_Decoder result(obj.value, obj.value.size()); + result.parent = this; + return result; + } + +/************************************************* +* Finish decoding a CONSTRUCTED type * +*************************************************/ +BER_Decoder& BER_Decoder::end_cons() + { + if(!parent) + throw Invalid_State("BER_Decoder::end_cons called with NULL parent"); + if(!source->end_of_data()) + throw Decoding_Error("BER_Decoder::end_cons called with data left"); + return (*parent); + } + +/************************************************* +* BER_Decoder Constructor * +*************************************************/ +BER_Decoder::BER_Decoder(DataSource& src) + { + source = &src; + owns = false; + pushed.type_tag = pushed.class_tag = NO_OBJECT; + parent = 0; + } + +/************************************************* +* BER_Decoder Constructor * + *************************************************/ +BER_Decoder::BER_Decoder(const byte data[], u32bit length) + { + source = new DataSource_Memory(data, length); + owns = true; + pushed.type_tag = pushed.class_tag = NO_OBJECT; + parent = 0; + } + +/************************************************* +* BER_Decoder Constructor * +*************************************************/ +BER_Decoder::BER_Decoder(const MemoryRegion& data) + { + source = new DataSource_Memory(data); + owns = true; + pushed.type_tag = pushed.class_tag = NO_OBJECT; + parent = 0; + } + +/************************************************* +* BER_Decoder Copy Constructor * +*************************************************/ +BER_Decoder::BER_Decoder(const BER_Decoder& other) + { + source = other.source; + owns = false; + if(other.owns) + { + other.owns = false; + owns = true; + } + pushed.type_tag = pushed.class_tag = NO_OBJECT; + parent = other.parent; + } + +/************************************************* +* BER_Decoder Destructor * +*************************************************/ +BER_Decoder::~BER_Decoder() + { + if(owns) + delete source; + source = 0; + } + +/************************************************* +* Request for an object to decode itself * +*************************************************/ +BER_Decoder& BER_Decoder::decode(ASN1_Object& obj) + { + obj.decode_from(*this); + return (*this); + } + +/************************************************* +* Decode a BER encoded NULL * +*************************************************/ +BER_Decoder& BER_Decoder::decode_null() + { + BER_Object obj = get_next_object(); + obj.assert_is_a(NULL_TAG, UNIVERSAL); + if(obj.value.size()) + throw BER_Decoding_Error("NULL object had nonzero size"); + return (*this); + } + +/************************************************* +* Decode a BER encoded BOOLEAN * +*************************************************/ +BER_Decoder& BER_Decoder::decode(bool& out) + { + return decode(out, BOOLEAN, UNIVERSAL); + } + +/************************************************* +* Decode a small BER encoded INTEGER * +*************************************************/ +BER_Decoder& BER_Decoder::decode(u32bit& out) + { + return decode(out, INTEGER, UNIVERSAL); + } + +/************************************************* +* Decode a BER encoded INTEGER * +*************************************************/ +BER_Decoder& BER_Decoder::decode(BigInt& out) + { + return decode(out, INTEGER, UNIVERSAL); + } + +/************************************************* +* Decode a BER encoded BOOLEAN * +*************************************************/ +BER_Decoder& BER_Decoder::decode(bool& out, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + BER_Object obj = get_next_object(); + obj.assert_is_a(type_tag, class_tag); + + if(obj.value.size() != 1) + throw BER_Decoding_Error("BER boolean value had invalid size"); + + out = (obj.value[0]) ? true : false; + return (*this); + } + +/************************************************* +* Decode a small BER encoded INTEGER * +*************************************************/ +BER_Decoder& BER_Decoder::decode(u32bit& out, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + BigInt integer; + decode(integer, type_tag, class_tag); + out = integer.to_u32bit(); + return (*this); + } + +/************************************************* +* Decode a BER encoded INTEGER * +*************************************************/ +BER_Decoder& BER_Decoder::decode(BigInt& out, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + BER_Object obj = get_next_object(); + obj.assert_is_a(type_tag, class_tag); + + if(obj.value.is_empty()) + out = 0; + else + { + const bool negative = (obj.value[0] & 0x80) ? true : false; + + if(negative) + { + for(u32bit j = obj.value.size(); j > 0; --j) + if(obj.value[j-1]--) + break; + for(u32bit j = 0; j != obj.value.size(); ++j) + obj.value[j] = ~obj.value[j]; + } + + out = BigInt(obj.value, obj.value.size()); + + if(negative) + out.flip_sign(); + } + + return (*this); + } + +/************************************************* +* BER decode a BIT STRING or OCTET STRING * +*************************************************/ +BER_Decoder& BER_Decoder::decode(MemoryRegion& out, ASN1_Tag real_type) + { + return decode(out, real_type, real_type, UNIVERSAL); + } + +/************************************************* +* BER decode a BIT STRING or OCTET STRING * +*************************************************/ +BER_Decoder& BER_Decoder::decode(MemoryRegion& buffer, + ASN1_Tag real_type, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + if(real_type != OCTET_STRING && real_type != BIT_STRING) + throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type); + + BER_Object obj = get_next_object(); + obj.assert_is_a(type_tag, class_tag); + + if(real_type == OCTET_STRING) + buffer = obj.value; + else + { + if(obj.value[0] >= 8) + throw BER_Decoding_Error("Bad number of unused bits in BIT STRING"); + buffer.set(obj.value + 1, obj.value.size() - 1); + } + return (*this); + } + +/************************************************* +* Decode an OPTIONAL string type * +*************************************************/ +BER_Decoder& BER_Decoder::decode_optional_string(MemoryRegion& out, + ASN1_Tag real_type, + u16bit type_no) + { + BER_Object obj = get_next_object(); + + ASN1_Tag type_tag = static_cast(type_no); + + out.clear(); + push_back(obj); + + if(obj.type_tag == type_tag && obj.class_tag == CONTEXT_SPECIFIC) + decode(out, real_type, type_tag, CONTEXT_SPECIFIC); + + return (*this); + } + +} diff --git a/src/asn1/ber_dec.h b/src/asn1/ber_dec.h new file mode 100644 index 000000000..9fec75832 --- /dev/null +++ b/src/asn1/ber_dec.h @@ -0,0 +1,130 @@ +/************************************************* +* BER Decoder Header File * +* (C) 1999-2008 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_BER_DECODER_H__ +#define BOTAN_BER_DECODER_H__ + +#include +#include +#include + +namespace Botan { + +/************************************************* +* BER Decoding Object * +*************************************************/ +class BOTAN_DLL BER_Decoder + { + public: + BER_Object get_next_object(); + void push_back(const BER_Object&); + + bool more_items() const; + BER_Decoder& verify_end(); + BER_Decoder& discard_remaining(); + + BER_Decoder start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL); + BER_Decoder& end_cons(); + + BER_Decoder& raw_bytes(MemoryRegion&); + + BER_Decoder& decode_null(); + BER_Decoder& decode(bool&); + BER_Decoder& decode(u32bit&); + BER_Decoder& decode(class BigInt&); + BER_Decoder& decode(MemoryRegion&, ASN1_Tag); + + BER_Decoder& decode(bool&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + BER_Decoder& decode(u32bit&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + BER_Decoder& decode(class BigInt&, + ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + BER_Decoder& decode(MemoryRegion&, ASN1_Tag, + ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + + BER_Decoder& decode(class ASN1_Object&); + + template + BER_Decoder& decode_optional(T&, ASN1_Tag, ASN1_Tag, const T& = T()); + + template + BER_Decoder& decode_list(std::vector&, bool = true); + + BER_Decoder& decode_optional_string(MemoryRegion&, + ASN1_Tag, u16bit); + + BER_Decoder(DataSource&); + BER_Decoder(const byte[], u32bit); + BER_Decoder(const MemoryRegion&); + BER_Decoder(const BER_Decoder&); + ~BER_Decoder(); + private: + BER_Decoder& operator=(const BER_Decoder&) { return (*this); } + + BER_Decoder* parent; + DataSource* source; + BER_Object pushed; + mutable bool owns; + }; + +/************************************************* +* Decode an OPTIONAL or DEFAULT element * +*************************************************/ +template +BER_Decoder& BER_Decoder::decode_optional(T& out, + ASN1_Tag type_tag, + ASN1_Tag class_tag, + const T& default_value) + { + BER_Object obj = get_next_object(); + + if(obj.type_tag == type_tag && obj.class_tag == class_tag) + { + if(class_tag & CONSTRUCTED) + BER_Decoder(obj.value).decode(out).verify_end(); + else + { + push_back(obj); + decode(out, type_tag, class_tag); + } + } + else + { + out = default_value; + push_back(obj); + } + + return (*this); + } + +/************************************************* +* Decode a list of homogenously typed values * +*************************************************/ +template +BER_Decoder& BER_Decoder::decode_list(std::vector& vec, bool clear_it) + { + if(clear_it) + vec.clear(); + + while(more_items()) + { + T value; + decode(value); + vec.push_back(value); + } + return (*this); + } + +/************************************************* +* BER Decoding Functions * +*************************************************/ +namespace BER { + +void BOTAN_DLL decode(BER_Decoder&, Key_Constraints&); + +} + +} + +#endif diff --git a/src/asn1/der_enc.cpp b/src/asn1/der_enc.cpp new file mode 100644 index 000000000..1ab5ddd4e --- /dev/null +++ b/src/asn1/der_enc.cpp @@ -0,0 +1,391 @@ +/************************************************* +* DER Encoder Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +namespace Botan { + +namespace { + +/************************************************* +* DER encode an ASN.1 type tag * +*************************************************/ +SecureVector encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag) + { + if((class_tag | 0xE0) != 0xE0) + throw Encoding_Error("DER_Encoder: Invalid class tag " + + to_string(class_tag)); + + SecureVector encoded_tag; + if(type_tag <= 30) + encoded_tag.append(static_cast(type_tag | class_tag)); + else + { + u32bit blocks = high_bit(type_tag) + 6; + blocks = (blocks - (blocks % 7)) / 7; + + encoded_tag.append(class_tag | 0x1F); + for(u32bit k = 0; k != blocks - 1; ++k) + encoded_tag.append(0x80 | ((type_tag >> 7*(blocks-k-1)) & 0x7F)); + encoded_tag.append(type_tag & 0x7F); + } + + return encoded_tag; + } + +/************************************************* +* DER encode an ASN.1 length field * +*************************************************/ +SecureVector encode_length(u32bit length) + { + SecureVector encoded_length; + if(length <= 127) + encoded_length.append(static_cast(length)); + else + { + const u32bit top_byte = significant_bytes(length); + encoded_length.append(static_cast(0x80 | top_byte)); + for(u32bit j = 4-top_byte; j != 4; ++j) + encoded_length.append(get_byte(j, length)); + } + return encoded_length; + } + +} + +/************************************************* +* Return the encoded SEQUENCE/SET * +*************************************************/ +SecureVector DER_Encoder::DER_Sequence::get_contents() + { + const ASN1_Tag real_class_tag = ASN1_Tag(class_tag | CONSTRUCTED); + + SecureVector encoded_tag = encode_tag(type_tag, real_class_tag); + + if(type_tag == SET) + { + std::sort(set_contents.begin(), set_contents.end()); + for(u32bit j = 0; j != set_contents.size(); ++j) + contents.append(set_contents[j]); + set_contents.clear(); + } + + SecureVector encoded_length = encode_length(contents.size()); + + SecureVector retval; + retval.append(encoded_tag); + retval.append(encoded_length); + retval.append(contents); + contents.destroy(); + return retval; + } + +/************************************************* +* Add an encoded value to the SEQUENCE/SET * +*************************************************/ +void DER_Encoder::DER_Sequence::add_bytes(const byte data[], u32bit length) + { + if(type_tag == SET) + set_contents.push_back(SecureVector(data, length)); + else + contents.append(data, length); + } + +/************************************************* +* Return the type and class taggings * +*************************************************/ +ASN1_Tag DER_Encoder::DER_Sequence::tag_of() const + { + return ASN1_Tag(type_tag | class_tag); + } + +/************************************************* +* DER_Sequence Constructor * +*************************************************/ +DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Tag t1, ASN1_Tag t2) : + type_tag(t1), class_tag(t2) + { + } + +/************************************************* +* Return the encoded contents * +*************************************************/ +SecureVector DER_Encoder::get_contents() + { + if(subsequences.size() != 0) + throw Invalid_State("DER_Encoder: Sequence hasn't been marked done"); + + SecureVector retval; + retval = contents; + contents.destroy(); + return retval; + } + +/************************************************* +* Start a new ASN.1 SEQUENCE/SET/EXPLICIT * +*************************************************/ +DER_Encoder& DER_Encoder::start_cons(ASN1_Tag type_tag, + ASN1_Tag class_tag) + { + subsequences.push_back(DER_Sequence(type_tag, class_tag)); + return (*this); + } + +/************************************************* +* Finish the current ASN.1 SEQUENCE/SET/EXPLICIT * +*************************************************/ +DER_Encoder& DER_Encoder::end_cons() + { + if(subsequences.empty()) + throw Invalid_State("DER_Encoder::end_cons: No such sequence"); + + SecureVector seq = subsequences[subsequences.size()-1].get_contents(); + subsequences.pop_back(); + raw_bytes(seq); + return (*this); + } + +/************************************************* +* Start a new ASN.1 EXPLICIT encoding * +*************************************************/ +DER_Encoder& DER_Encoder::start_explicit(u16bit type_no) + { + ASN1_Tag type_tag = static_cast(type_no); + + if(type_tag == SET) + throw Internal_Error("DER_Encoder.start_explicit(SET); cannot perform"); + + return start_cons(type_tag, CONTEXT_SPECIFIC); + } + +/************************************************* +* Finish the current ASN.1 EXPLICIT encoding * +*************************************************/ +DER_Encoder& DER_Encoder::end_explicit() + { + return end_cons(); + } + +/************************************************* +* Write raw bytes into the stream * +*************************************************/ +DER_Encoder& DER_Encoder::raw_bytes(const MemoryRegion& val) + { + return raw_bytes(val.begin(), val.size()); + } + +/************************************************* +* Write raw bytes into the stream * +*************************************************/ +DER_Encoder& DER_Encoder::raw_bytes(const byte bytes[], u32bit length) + { + if(subsequences.size()) + subsequences[subsequences.size()-1].add_bytes(bytes, length); + else + contents.append(bytes, length); + + return (*this); + } + +/************************************************* +* Encode a NULL object * +*************************************************/ +DER_Encoder& DER_Encoder::encode_null() + { + return add_object(NULL_TAG, UNIVERSAL, 0, 0); + } + +/************************************************* +* DER encode a BOOLEAN * +*************************************************/ +DER_Encoder& DER_Encoder::encode(bool is_true) + { + return encode(is_true, BOOLEAN, UNIVERSAL); + } + +/************************************************* +* DER encode a small INTEGER * +*************************************************/ +DER_Encoder& DER_Encoder::encode(u32bit n) + { + return encode(BigInt(n), INTEGER, UNIVERSAL); + } + +/************************************************* +* DER encode a small INTEGER * +*************************************************/ +DER_Encoder& DER_Encoder::encode(const BigInt& n) + { + return encode(n, INTEGER, UNIVERSAL); + } + +/************************************************* +* DER encode an OCTET STRING or BIT STRING * +*************************************************/ +DER_Encoder& DER_Encoder::encode(const MemoryRegion& bytes, + ASN1_Tag real_type) + { + return encode(bytes.begin(), bytes.size(), + real_type, real_type, UNIVERSAL); + } + +/************************************************* +* Encode this object * +*************************************************/ +DER_Encoder& DER_Encoder::encode(const byte bytes[], u32bit length, + ASN1_Tag real_type) + { + return encode(bytes, length, real_type, real_type, UNIVERSAL); + } + +/************************************************* +* DER encode a BOOLEAN * +*************************************************/ +DER_Encoder& DER_Encoder::encode(bool is_true, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + byte val = is_true ? 0xFF : 0x00; + return add_object(type_tag, class_tag, &val, 1); + } + +/************************************************* +* DER encode a small INTEGER * +*************************************************/ +DER_Encoder& DER_Encoder::encode(u32bit n, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + return encode(BigInt(n), type_tag, class_tag); + } + +/************************************************* +* DER encode an INTEGER * +*************************************************/ +DER_Encoder& DER_Encoder::encode(const BigInt& n, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + if(n == 0) + return add_object(type_tag, class_tag, 0); + + bool extra_zero = (n.bits() % 8 == 0); + SecureVector contents(extra_zero + n.bytes()); + BigInt::encode(contents.begin() + extra_zero, n); + if(n < 0) + { + for(u32bit j = 0; j != contents.size(); ++j) + contents[j] = ~contents[j]; + for(u32bit j = contents.size(); j > 0; --j) + if(++contents[j-1]) + break; + } + + return add_object(type_tag, class_tag, contents); + } + +/************************************************* +* DER encode an OCTET STRING or BIT STRING * +*************************************************/ +DER_Encoder& DER_Encoder::encode(const MemoryRegion& bytes, + ASN1_Tag real_type, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + return encode(bytes.begin(), bytes.size(), + real_type, type_tag, class_tag); + } + +/************************************************* +* DER encode an OCTET STRING or BIT STRING * +*************************************************/ +DER_Encoder& DER_Encoder::encode(const byte bytes[], u32bit length, + ASN1_Tag real_type, + ASN1_Tag type_tag, ASN1_Tag class_tag) + { + if(real_type != OCTET_STRING && real_type != BIT_STRING) + throw Invalid_Argument("DER_Encoder: Invalid tag for byte/bit string"); + + if(real_type == BIT_STRING) + { + SecureVector encoded; + encoded.append(0); + encoded.append(bytes, length); + return add_object(type_tag, class_tag, encoded); + } + else + return add_object(type_tag, class_tag, bytes, length); + } + +/************************************************* +* Conditionally write some values to the stream * +*************************************************/ +DER_Encoder& DER_Encoder::encode_if(bool cond, DER_Encoder& codec) + { + if(cond) + return raw_bytes(codec.get_contents()); + return (*this); + } + +/************************************************* +* Request for an object to encode itself * +*************************************************/ +DER_Encoder& DER_Encoder::encode(const ASN1_Object& obj) + { + obj.encode_into(*this); + return (*this); + } + +/************************************************* +* Write the encoding of the byte(s) * +*************************************************/ +DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, + const byte rep[], u32bit length) + { + SecureVector encoded_tag = encode_tag(type_tag, class_tag); + SecureVector encoded_length = encode_length(length); + + SecureVector buffer; + buffer.append(encoded_tag); + buffer.append(encoded_length); + buffer.append(rep, length); + + return raw_bytes(buffer); + } + +/************************************************* +* Write the encoding of the byte(s) * +*************************************************/ +DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, + const MemoryRegion& rep_buf) + { + const byte* rep = rep_buf.begin(); + const u32bit rep_len = rep_buf.size(); + return add_object(type_tag, class_tag, rep, rep_len); + } + +/************************************************* +* Write the encoding of the byte(s) * +*************************************************/ +DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, + const std::string& rep_str) + { + const byte* rep = reinterpret_cast(rep_str.data()); + const u32bit rep_len = rep_str.size(); + return add_object(type_tag, class_tag, rep, rep_len); + } + +/************************************************* +* Write the encoding of the byte * +*************************************************/ +DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, + ASN1_Tag class_tag, byte rep) + { + return add_object(type_tag, class_tag, &rep, 1); + } + +} diff --git a/src/asn1/der_enc.h b/src/asn1/der_enc.h new file mode 100644 index 000000000..5b3c11489 --- /dev/null +++ b/src/asn1/der_enc.h @@ -0,0 +1,89 @@ +/************************************************* +* DER Encoder Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_DER_ENCODER_H__ +#define BOTAN_DER_ENCODER_H__ + +#include +#include + +namespace Botan { + +/************************************************* +* General DER Encoding Object * +*************************************************/ +class BOTAN_DLL DER_Encoder + { + public: + SecureVector get_contents(); + + DER_Encoder& start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL); + DER_Encoder& end_cons(); + + DER_Encoder& start_explicit(u16bit); + DER_Encoder& end_explicit(); + + DER_Encoder& raw_bytes(const byte[], u32bit); + DER_Encoder& raw_bytes(const MemoryRegion&); + + DER_Encoder& encode_null(); + DER_Encoder& encode(bool); + DER_Encoder& encode(u32bit); + DER_Encoder& encode(const class BigInt&); + DER_Encoder& encode(const MemoryRegion&, ASN1_Tag); + DER_Encoder& encode(const byte[], u32bit, ASN1_Tag); + + DER_Encoder& encode(bool, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + DER_Encoder& encode(u32bit, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + DER_Encoder& encode(const class BigInt&, ASN1_Tag, + ASN1_Tag = CONTEXT_SPECIFIC); + DER_Encoder& encode(const MemoryRegion&, ASN1_Tag, + ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + DER_Encoder& encode(const byte[], u32bit, ASN1_Tag, + ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + + template + DER_Encoder& encode_optional(const T& value, const T& default_value) + { + if(value != default_value) + encode(value); + return (*this); + } + + template + DER_Encoder& encode_list(const std::vector& values) + { + for(u32bit j = 0; j != values.size(); ++j) + encode(values[j]); + return (*this); + } + + DER_Encoder& encode(const class ASN1_Object&); + DER_Encoder& encode_if(bool, DER_Encoder&); + + DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const byte[], u32bit); + DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const MemoryRegion&); + DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const std::string&); + DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, byte); + private: + class DER_Sequence + { + public: + ASN1_Tag tag_of() const; + SecureVector get_contents(); + void add_bytes(const byte[], u32bit); + DER_Sequence(ASN1_Tag, ASN1_Tag); + private: + ASN1_Tag type_tag, class_tag; + SecureVector contents; + std::vector< SecureVector > set_contents; + }; + SecureVector contents; + std::vector subsequences; + }; + +} + +#endif diff --git a/src/asn1/modinfo.txt b/src/asn1/modinfo.txt new file mode 100644 index 000000000..03284f48b --- /dev/null +++ b/src/asn1/modinfo.txt @@ -0,0 +1,23 @@ +realname "ASN.1/BER/DER module" + +define ASN1 + + +alg_id.cpp +asn1_alt.cpp +asn1_att.cpp +asn1_dn.cpp +asn1_int.cpp +asn1_ku.cpp +asn1_oid.cpp +asn1_str.cpp +asn1_tm.cpp +ber_dec.cpp +der_enc.cpp +alg_id.h +asn1_int.h +asn1_obj.h +asn1_oid.h +ber_dec.h +der_enc.h + diff --git a/src/asn1_alt.cpp b/src/asn1_alt.cpp deleted file mode 100644 index 035f918cb..000000000 --- a/src/asn1_alt.cpp +++ /dev/null @@ -1,226 +0,0 @@ -/************************************************* -* AlternativeName Source File * -* (C) 1999-2007 Jack Lloyd * -* 2007 Yves Jerschow * -*************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Botan { - -/************************************************* -* Create an AlternativeName * -*************************************************/ -AlternativeName::AlternativeName(const std::string& email_addr, - const std::string& uri, - const std::string& dns, - const std::string& ip) - { - add_attribute("RFC822", email_addr); - add_attribute("DNS", dns); - add_attribute("URI", uri); - add_attribute("IP", ip); - } - -/************************************************* -* Add an attribute to an alternative name * -*************************************************/ -void AlternativeName::add_attribute(const std::string& type, - const std::string& str) - { - if(type == "" || str == "") - return; - - typedef std::multimap::iterator iter; - std::pair range = alt_info.equal_range(type); - for(iter j = range.first; j != range.second; ++j) - if(j->second == str) - return; - - multimap_insert(alt_info, type, str); - } - -/************************************************* -* Add an OtherName field * -*************************************************/ -void AlternativeName::add_othername(const OID& oid, const std::string& value, - ASN1_Tag type) - { - if(value == "") - return; - multimap_insert(othernames, oid, ASN1_String(value, type)); - } - -/************************************************* -* Get the attributes of this alternative name * -*************************************************/ -std::multimap AlternativeName::get_attributes() const - { - return alt_info; - } - -/************************************************* -* Get the otherNames * -*************************************************/ -std::multimap AlternativeName::get_othernames() const - { - return othernames; - } - -/************************************************* -* Return all of the alternative names * -*************************************************/ -std::multimap AlternativeName::contents() const - { - std::multimap names; - - typedef std::multimap::const_iterator rdn_iter; - for(rdn_iter j = alt_info.begin(); j != alt_info.end(); ++j) - multimap_insert(names, j->first, j->second); - - typedef std::multimap::const_iterator on_iter; - for(on_iter j = othernames.begin(); j != othernames.end(); ++j) - multimap_insert(names, OIDS::lookup(j->first), j->second.value()); - - return names; - } - -/************************************************* -* Return if this object has anything useful * -*************************************************/ -bool AlternativeName::has_items() const - { - return (alt_info.size() > 0 || othernames.size() > 0); - } - -namespace { - -/************************************************* -* DER encode an AlternativeName entry * -*************************************************/ -void encode_entries(DER_Encoder& encoder, - const std::multimap& attr, - const std::string& type, ASN1_Tag tagging) - { - typedef std::multimap::const_iterator iter; - - std::pair range = attr.equal_range(type); - for(iter j = range.first; j != range.second; ++j) - { - if(type == "RFC822" || type == "DNS" || type == "URI") - { - ASN1_String asn1_string(j->second, IA5_STRING); - encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.iso_8859()); - } - else if(type == "IP") - { - u32bit ip = string_to_ipv4(j->second); - byte ip_buf[4] = { 0 }; - store_be(ip, ip_buf); - encoder.add_object(tagging, CONTEXT_SPECIFIC, ip_buf, 4); - } - } - } - -} - -/************************************************* -* DER encode an AlternativeName extension * -*************************************************/ -void AlternativeName::encode_into(DER_Encoder& der) const - { - der.start_cons(SEQUENCE); - - encode_entries(der, alt_info, "RFC822", ASN1_Tag(1)); - encode_entries(der, alt_info, "DNS", ASN1_Tag(2)); - encode_entries(der, alt_info, "URI", ASN1_Tag(6)); - encode_entries(der, alt_info, "IP", ASN1_Tag(7)); - - std::multimap::const_iterator i; - for(i = othernames.begin(); i != othernames.end(); ++i) - { - der.start_explicit(0) - .encode(i->first) - .start_explicit(0) - .encode(i->second) - .end_explicit() - .end_explicit(); - } - - der.end_cons(); - } - -/************************************************* -* Decode a BER encoded AlternativeName * -*************************************************/ -void AlternativeName::decode_from(BER_Decoder& source) - { - BER_Decoder names = source.start_cons(SEQUENCE); - - while(names.more_items()) - { - BER_Object obj = names.get_next_object(); - if((obj.class_tag != CONTEXT_SPECIFIC) && - (obj.class_tag != (CONTEXT_SPECIFIC | CONSTRUCTED))) - continue; - - ASN1_Tag tag = obj.type_tag; - - if(tag == 0) - { - BER_Decoder othername(obj.value); - - OID oid; - othername.decode(oid); - if(othername.more_items()) - { - BER_Object othername_value_outer = othername.get_next_object(); - othername.verify_end(); - - if(othername_value_outer.type_tag != ASN1_Tag(0) || - othername_value_outer.class_tag != - (CONTEXT_SPECIFIC | CONSTRUCTED) - ) - throw Decoding_Error("Invalid tags on otherName value"); - - BER_Decoder othername_value_inner(othername_value_outer.value); - - BER_Object value = othername_value_inner.get_next_object(); - othername_value_inner.verify_end(); - - ASN1_Tag value_type = value.type_tag; - - if(is_string_type(value_type) && value.class_tag == UNIVERSAL) - add_othername(oid, ASN1::to_string(value), value_type); - } - } - else if(tag == 1 || tag == 2 || tag == 6) - { - const std::string value = Charset::transcode(ASN1::to_string(obj), - LATIN1_CHARSET, - LOCAL_CHARSET); - - if(tag == 1) add_attribute("RFC822", value); - if(tag == 2) add_attribute("DNS", value); - if(tag == 6) add_attribute("URI", value); - } - else if(tag == 7) - { - if(obj.value.size() == 4) - { - u32bit ip = load_be(obj.value.begin(), 0); - add_attribute("IP", ipv4_to_string(ip)); - } - } - - } - } - -} diff --git a/src/asn1_att.cpp b/src/asn1_att.cpp deleted file mode 100644 index 7c16ff3a5..000000000 --- a/src/asn1_att.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/************************************************* -* Attribute Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include -#include - -namespace Botan { - -/************************************************* -* Create an Attribute * -*************************************************/ -Attribute::Attribute(const OID& attr_oid, const MemoryRegion& attr_value) - { - oid = attr_oid; - parameters = attr_value; - } - -/************************************************* -* Create an Attribute * -*************************************************/ -Attribute::Attribute(const std::string& attr_oid, - const MemoryRegion& attr_value) - { - oid = OIDS::lookup(attr_oid); - parameters = attr_value; - } - -/************************************************* -* DER encode a Attribute * -*************************************************/ -void Attribute::encode_into(DER_Encoder& codec) const - { - codec.start_cons(SEQUENCE) - .encode(oid) - .start_cons(SET) - .raw_bytes(parameters) - .end_cons() - .end_cons(); - } - -/************************************************* -* Decode a BER encoded Attribute * -*************************************************/ -void Attribute::decode_from(BER_Decoder& codec) - { - codec.start_cons(SEQUENCE) - .decode(oid) - .start_cons(SET) - .raw_bytes(parameters) - .end_cons() - .end_cons(); - } - -} diff --git a/src/asn1_dn.cpp b/src/asn1_dn.cpp deleted file mode 100644 index 3fd0c09b0..000000000 --- a/src/asn1_dn.cpp +++ /dev/null @@ -1,302 +0,0 @@ -/************************************************* -* X509_DN Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include -#include -#include -#include - -namespace Botan { - -/************************************************* -* Create an empty X509_DN * -*************************************************/ -X509_DN::X509_DN() - { - } - -/************************************************* -* Create an X509_DN * -*************************************************/ -X509_DN::X509_DN(const std::multimap& args) - { - std::multimap::const_iterator j; - for(j = args.begin(); j != args.end(); ++j) - add_attribute(j->first, j->second); - } - -/************************************************* -* Create an X509_DN * -*************************************************/ -X509_DN::X509_DN(const std::multimap& args) - { - std::multimap::const_iterator j; - for(j = args.begin(); j != args.end(); ++j) - add_attribute(OIDS::lookup(j->first), j->second); - } - -/************************************************* -* Add an attribute to a X509_DN * -*************************************************/ -void X509_DN::add_attribute(const std::string& type, - const std::string& str) - { - OID oid = OIDS::lookup(type); - add_attribute(oid, str); - } - -/************************************************* -* Add an attribute to a X509_DN * -*************************************************/ -void X509_DN::add_attribute(const OID& oid, const std::string& str) - { - if(str == "") - return; - - typedef std::multimap::iterator rdn_iter; - - std::pair range = dn_info.equal_range(oid); - for(rdn_iter j = range.first; j != range.second; ++j) - if(j->second.value() == str) - return; - - multimap_insert(dn_info, oid, ASN1_String(str)); - dn_bits.destroy(); - } - -/************************************************* -* Get the attributes of this X509_DN * -*************************************************/ -std::multimap X509_DN::get_attributes() const - { - typedef std::multimap::const_iterator rdn_iter; - - std::multimap retval; - for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j) - multimap_insert(retval, j->first, j->second.value()); - return retval; - } - -/************************************************* -* Get the contents of this X.500 Name * -*************************************************/ -std::multimap X509_DN::contents() const - { - typedef std::multimap::const_iterator rdn_iter; - - std::multimap retval; - for(rdn_iter j = dn_info.begin(); j != dn_info.end(); ++j) - multimap_insert(retval, OIDS::lookup(j->first), j->second.value()); - return retval; - } - -/************************************************* -* Get a single attribute type * -*************************************************/ -std::vector X509_DN::get_attribute(const std::string& attr) const - { - typedef std::multimap::const_iterator rdn_iter; - - const OID oid = OIDS::lookup(deref_info_field(attr)); - std::pair range = dn_info.equal_range(oid); - - std::vector values; - for(rdn_iter j = range.first; j != range.second; ++j) - values.push_back(j->second.value()); - return values; - } - -/************************************************* -* Handle the decoding operation of a DN * -*************************************************/ -void X509_DN::do_decode(const MemoryRegion& bits) - { - BER_Decoder sequence(bits); - - while(sequence.more_items()) - { - BER_Decoder rdn = sequence.start_cons(SET); - - while(rdn.more_items()) - { - OID oid; - ASN1_String str; - - rdn.start_cons(SEQUENCE) - .decode(oid) - .decode(str) - .verify_end() - .end_cons(); - - add_attribute(oid, str.value()); - } - } - - dn_bits = bits; - } - -/************************************************* -* Return the BER encoded data, if any * -*************************************************/ -MemoryVector X509_DN::get_bits() const - { - return dn_bits; - } - -/************************************************* -* Deref aliases in a subject/issuer info request * -*************************************************/ -std::string X509_DN::deref_info_field(const std::string& info) - { - if(info == "Name" || info == "CommonName") return "X520.CommonName"; - if(info == "SerialNumber") return "X520.SerialNumber"; - if(info == "Country") return "X520.Country"; - if(info == "Organization") return "X520.Organization"; - if(info == "Organizational Unit" || info == "OrgUnit") - return "X520.OrganizationalUnit"; - if(info == "Locality") return "X520.Locality"; - if(info == "State" || info == "Province") return "X520.State"; - if(info == "Email") return "RFC822"; - return info; - } - -/************************************************* -* Compare two X509_DNs for equality * -*************************************************/ -bool operator==(const X509_DN& dn1, const X509_DN& dn2) - { - typedef std::multimap::const_iterator rdn_iter; - - std::multimap attr1 = dn1.get_attributes(); - std::multimap attr2 = dn2.get_attributes(); - - if(attr1.size() != attr2.size()) return false; - - rdn_iter p1 = attr1.begin(); - rdn_iter p2 = attr2.begin(); - - while(true) - { - if(p1 == attr1.end() && p2 == attr2.end()) - break; - if(p1 == attr1.end()) return false; - if(p2 == attr2.end()) return false; - if(p1->first != p2->first) return false; - if(!x500_name_cmp(p1->second, p2->second)) - return false; - ++p1; - ++p2; - } - return true; - } - -/************************************************* -* Compare two X509_DNs for inequality * -*************************************************/ -bool operator!=(const X509_DN& dn1, const X509_DN& dn2) - { - return !(dn1 == dn2); - } - -/************************************************* -* Compare two X509_DNs * -*************************************************/ -bool operator<(const X509_DN& dn1, const X509_DN& dn2) - { - typedef std::multimap::const_iterator rdn_iter; - - std::multimap attr1 = dn1.get_attributes(); - std::multimap attr2 = dn2.get_attributes(); - - if(attr1.size() < attr2.size()) return true; - if(attr1.size() > attr2.size()) return false; - - for(rdn_iter p1 = attr1.begin(); p1 != attr1.end(); ++p1) - { - std::multimap::const_iterator p2; - p2 = attr2.find(p1->first); - if(p2 == attr2.end()) return false; - if(p1->second > p2->second) return false; - if(p1->second < p2->second) return true; - } - return false; - } - -namespace { - -/************************************************* -* DER encode a RelativeDistinguishedName * -*************************************************/ -void do_ava(DER_Encoder& encoder, - const std::multimap& dn_info, - ASN1_Tag string_type, const std::string& oid_str, - bool must_exist = false) - { - typedef std::multimap::const_iterator rdn_iter; - - const OID oid = OIDS::lookup(oid_str); - const bool exists = (dn_info.find(oid) != dn_info.end()); - - if(!exists && must_exist) - throw Encoding_Error("X509_DN: No entry for " + oid_str); - if(!exists) return; - - std::pair range = dn_info.equal_range(oid); - - for(rdn_iter j = range.first; j != range.second; ++j) - { - encoder.start_cons(SET) - .start_cons(SEQUENCE) - .encode(oid) - .encode(ASN1_String(j->second, string_type)) - .end_cons() - .end_cons(); - } - } - -} - -/************************************************* -* DER encode a DistinguishedName * -*************************************************/ -void X509_DN::encode_into(DER_Encoder& der) const - { - std::multimap dn_info = get_attributes(); - - der.start_cons(SEQUENCE); - - if(dn_bits.has_items()) - der.raw_bytes(dn_bits); - else - { - do_ava(der, dn_info, PRINTABLE_STRING, "X520.Country", true); - do_ava(der, dn_info, DIRECTORY_STRING, "X520.State"); - do_ava(der, dn_info, DIRECTORY_STRING, "X520.Locality"); - do_ava(der, dn_info, DIRECTORY_STRING, "X520.Organization"); - do_ava(der, dn_info, DIRECTORY_STRING, "X520.OrganizationalUnit"); - do_ava(der, dn_info, DIRECTORY_STRING, "X520.CommonName", true); - do_ava(der, dn_info, PRINTABLE_STRING, "X520.SerialNumber"); - } - - der.end_cons(); - } - -/************************************************* -* Decode a BER encoded DistinguishedName * -*************************************************/ -void X509_DN::decode_from(BER_Decoder& source) - { - dn_info.clear(); - - source.start_cons(SEQUENCE) - .raw_bytes(dn_bits) - .end_cons(); - - do_decode(dn_bits); - } - -} diff --git a/src/asn1_int.cpp b/src/asn1_int.cpp deleted file mode 100644 index e837dedf0..000000000 --- a/src/asn1_int.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/************************************************* -* ASN.1 Internals Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include -#include -#include - -namespace Botan { - -/************************************************* -* BER Decoding Exceptions * -*************************************************/ -BER_Decoding_Error::BER_Decoding_Error(const std::string& str) : - Decoding_Error("BER: " + str) {} - -BER_Bad_Tag::BER_Bad_Tag(const std::string& str, ASN1_Tag tag) : - BER_Decoding_Error(str + ": " + to_string(tag)) {} - -BER_Bad_Tag::BER_Bad_Tag(const std::string& str, - ASN1_Tag tag1, ASN1_Tag tag2) : - BER_Decoding_Error(str + ": " + to_string(tag1) + "/" + to_string(tag2)) {} - -namespace ASN1 { - -/************************************************* -* Put some arbitrary bytes into a SEQUENCE * -*************************************************/ -SecureVector put_in_sequence(const MemoryRegion& contents) - { - return DER_Encoder() - .start_cons(SEQUENCE) - .raw_bytes(contents) - .end_cons() - .get_contents(); - } - -/************************************************* -* Convert a BER object into a string object * -*************************************************/ -std::string to_string(const BER_Object& obj) - { - return std::string(reinterpret_cast(obj.value.begin()), - obj.value.size()); - } - -/************************************************* -* Do heuristic tests for BER data * -*************************************************/ -bool maybe_BER(DataSource& source) - { - byte first_byte; - if(!source.peek_byte(first_byte)) - throw Stream_IO_Error("ASN1::maybe_BER: Source was empty"); - - if(first_byte == (SEQUENCE | CONSTRUCTED)) - return true; - return false; - } - -} - -} diff --git a/src/asn1_ku.cpp b/src/asn1_ku.cpp deleted file mode 100644 index 32c5944dd..000000000 --- a/src/asn1_ku.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/************************************************* -* KeyUsage Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include - -namespace Botan { - -namespace BER { - -/************************************************* -* Decode a BER encoded KeyUsage * -*************************************************/ -void decode(BER_Decoder& source, Key_Constraints& key_usage) - { - BER_Object obj = source.get_next_object(); - - if(obj.type_tag != BIT_STRING || obj.class_tag != UNIVERSAL) - throw BER_Bad_Tag("Bad tag for usage constraint", - obj.type_tag, obj.class_tag); - if(obj.value.size() != 2 && obj.value.size() != 3) - throw BER_Decoding_Error("Bad size for BITSTRING in usage constraint"); - if(obj.value[0] >= 8) - throw BER_Decoding_Error("Invalid unused bits in usage constraint"); - - const byte mask = (0xFF << obj.value[0]); - obj.value[obj.value.size()-1] &= mask; - - u16bit usage = 0; - for(u32bit j = 1; j != obj.value.size(); ++j) - usage = (obj.value[j] << 8) | usage; - - key_usage = Key_Constraints(usage); - } - -} - -} diff --git a/src/asn1_oid.cpp b/src/asn1_oid.cpp deleted file mode 100644 index 80968ed8f..000000000 --- a/src/asn1_oid.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/************************************************* -* ASN.1 OID Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include -#include -#include - -namespace Botan { - -/************************************************* -* ASN.1 OID Constructor * -*************************************************/ -OID::OID(const std::string& oid_str) - { - if(oid_str != "") - { - id = parse_asn1_oid(oid_str); - if(id.size() < 2 || id[0] > 2) - throw Invalid_OID(oid_str); - if((id[0] == 0 || id[0] == 1) && id[1] > 39) - throw Invalid_OID(oid_str); - } - } - -/************************************************* -* Clear the current OID * -*************************************************/ -void OID::clear() - { - id.clear(); - } - -/************************************************* -* Return this OID as a string * -*************************************************/ -std::string OID::as_string() const - { - std::string oid_str; - for(u32bit j = 0; j != id.size(); ++j) - { - oid_str += to_string(id[j]); - if(j != id.size() - 1) - oid_str += '.'; - } - return oid_str; - } - -/************************************************* -* OID equality comparison * -*************************************************/ -bool OID::operator==(const OID& oid) const - { - if(id.size() != oid.id.size()) - return false; - for(u32bit j = 0; j != id.size(); ++j) - if(id[j] != oid.id[j]) - return false; - return true; - } - -/************************************************* -* Append another component to the OID * -*************************************************/ -OID& OID::operator+=(u32bit component) - { - id.push_back(component); - return (*this); - } - -/************************************************* -* Append another component to the OID * -*************************************************/ -OID operator+(const OID& oid, u32bit component) - { - OID new_oid(oid); - new_oid += component; - return new_oid; - } - -/************************************************* -* OID inequality comparison * -*************************************************/ -bool operator!=(const OID& a, const OID& b) - { - return !(a == b); - } - -/************************************************* -* Compare two OIDs * -*************************************************/ -bool operator<(const OID& a, const OID& b) - { - std::vector oid1 = a.get_id(); - std::vector oid2 = b.get_id(); - - if(oid1.size() < oid2.size()) - return true; - if(oid1.size() > oid2.size()) - return false; - for(u32bit j = 0; j != oid1.size(); ++j) - { - if(oid1[j] < oid2[j]) - return true; - if(oid1[j] > oid2[j]) - return false; - } - return false; - } - -/************************************************* -* DER encode an OBJECT IDENTIFIER * -*************************************************/ -void OID::encode_into(DER_Encoder& der) const - { - if(id.size() < 2) - throw Invalid_Argument("OID::encode_into: OID is invalid"); - - MemoryVector encoding; - encoding.append(40 * id[0] + id[1]); - - for(u32bit j = 2; j != id.size(); ++j) - { - if(id[j] == 0) - encoding.append(0); - else - { - u32bit blocks = high_bit(id[j]) + 6; - blocks = (blocks - (blocks % 7)) / 7; - - for(u32bit k = 0; k != blocks - 1; ++k) - encoding.append(0x80 | ((id[j] >> 7*(blocks-k-1)) & 0x7F)); - encoding.append(id[j] & 0x7F); - } - } - der.add_object(OBJECT_ID, UNIVERSAL, encoding); - } - -/************************************************* -* Decode a BER encoded OBJECT IDENTIFIER * -*************************************************/ -void OID::decode_from(BER_Decoder& decoder) - { - BER_Object obj = decoder.get_next_object(); - if(obj.type_tag != OBJECT_ID || obj.class_tag != UNIVERSAL) - throw BER_Bad_Tag("Error decoding OID, unknown tag", - obj.type_tag, obj.class_tag); - if(obj.value.size() < 2) - throw BER_Decoding_Error("OID encoding is too short"); - - - clear(); - id.push_back(obj.value[0] / 40); - id.push_back(obj.value[0] % 40); - - u32bit j = 0; - while(j != obj.value.size() - 1) - { - u32bit component = 0; - while(j != obj.value.size() - 1) - { - ++j; - component = (component << 7) + (obj.value[j] & 0x7F); - if(!(obj.value[j] & 0x80)) - break; - } - id.push_back(component); - } - } - -} diff --git a/src/asn1_str.cpp b/src/asn1_str.cpp deleted file mode 100644 index 52dcdc55e..000000000 --- a/src/asn1_str.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/************************************************* -* Simple ASN.1 String Types Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include -#include -#include -#include - -namespace Botan { - -namespace { - -/************************************************* -* Choose an encoding for the string * -*************************************************/ -ASN1_Tag choose_encoding(const std::string& str, - const std::string& type) - { - static const byte IS_PRINTABLE[256] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }; - - for(u32bit j = 0; j != str.size(); ++j) - { - if(!IS_PRINTABLE[static_cast(str[j])]) - { - if(type == "utf8") return UTF8_STRING; - if(type == "latin1") return T61_STRING; - throw Invalid_Argument("Bad setting for x509/ca/str_type: " + type); - } - } - return PRINTABLE_STRING; - } - -} - -/************************************************* -* Check if type is a known ASN.1 string type * -*************************************************/ -bool is_string_type(ASN1_Tag tag) - { - if(tag == NUMERIC_STRING || tag == PRINTABLE_STRING || - tag == VISIBLE_STRING || tag == T61_STRING || tag == IA5_STRING || - tag == UTF8_STRING || tag == BMP_STRING) - return true; - return false; - } - -/************************************************* -* Create an ASN1_String * -*************************************************/ -ASN1_String::ASN1_String(const std::string& str, ASN1_Tag t) : tag(t) - { - iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET); - - if(tag == DIRECTORY_STRING) - tag = choose_encoding(iso_8859_str, - global_state().option("x509/ca/str_type")); - - if(tag != NUMERIC_STRING && - tag != PRINTABLE_STRING && - tag != VISIBLE_STRING && - tag != T61_STRING && - tag != IA5_STRING && - tag != UTF8_STRING && - tag != BMP_STRING) - throw Invalid_Argument("ASN1_String: Unknown string type " + - to_string(tag)); - } - -/************************************************* -* Create an ASN1_String * -*************************************************/ -ASN1_String::ASN1_String(const std::string& str) - { - iso_8859_str = Charset::transcode(str, LOCAL_CHARSET, LATIN1_CHARSET); - tag = choose_encoding(iso_8859_str, - global_state().option("x509/ca/str_type")); - } - -/************************************************* -* Return this string in ISO 8859-1 encoding * -*************************************************/ -std::string ASN1_String::iso_8859() const - { - return iso_8859_str; - } - -/************************************************* -* Return this string in local encoding * -*************************************************/ -std::string ASN1_String::value() const - { - return Charset::transcode(iso_8859_str, LATIN1_CHARSET, LOCAL_CHARSET); - } - -/************************************************* -* Return the type of this string object * -*************************************************/ -ASN1_Tag ASN1_String::tagging() const - { - return tag; - } - -/************************************************* -* DER encode an ASN1_String * -*************************************************/ -void ASN1_String::encode_into(DER_Encoder& encoder) const - { - std::string value = iso_8859(); - if(tagging() == UTF8_STRING) - value = Charset::transcode(value, LATIN1_CHARSET, UTF8_CHARSET); - encoder.add_object(tagging(), UNIVERSAL, value); - } - -/************************************************* -* Decode a BER encoded ASN1_String * -*************************************************/ -void ASN1_String::decode_from(BER_Decoder& source) - { - BER_Object obj = source.get_next_object(); - - Character_Set charset_is; - - if(obj.type_tag == BMP_STRING) - charset_is = UCS2_CHARSET; - else if(obj.type_tag == UTF8_STRING) - charset_is = UTF8_CHARSET; - else - charset_is = LATIN1_CHARSET; - - *this = ASN1_String( - Charset::transcode(ASN1::to_string(obj), charset_is, LOCAL_CHARSET), - obj.type_tag); - } - -} diff --git a/src/asn1_tm.cpp b/src/asn1_tm.cpp deleted file mode 100644 index 7cd051af7..000000000 --- a/src/asn1_tm.cpp +++ /dev/null @@ -1,295 +0,0 @@ -/************************************************* -* X.509 Time Types Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include -#include -#include -#include - -namespace Botan { - -namespace { - -/************************************************* -* Convert a time_t to a struct tm * -*************************************************/ -std::tm get_tm(u64bit timer) - { - std::time_t time_val = static_cast(timer); - - std::tm* tm_p = std::gmtime(&time_val); - if(tm_p == 0) - throw Encoding_Error("X509_Time: gmtime could not encode " + - to_string(timer)); - return (*tm_p); - } - -} - -/************************************************* -* Create an X509_Time * -*************************************************/ -X509_Time::X509_Time(const std::string& time_str) - { - set_to(time_str); - } - -/************************************************* -* Create an X509_Time * -*************************************************/ -X509_Time::X509_Time(u64bit timer) - { - std::tm time_info = get_tm(timer); - - year = time_info.tm_year + 1900; - month = time_info.tm_mon + 1; - day = time_info.tm_mday; - hour = time_info.tm_hour; - minute = time_info.tm_min; - second = time_info.tm_sec; - - if(year >= 2050) - tag = GENERALIZED_TIME; - else - tag = UTC_TIME; - } - -/************************************************* -* Create an X509_Time * -*************************************************/ -X509_Time::X509_Time(const std::string& t_spec, ASN1_Tag t) : tag(t) - { - set_to(t_spec, tag); - } - -/************************************************* -* Set the time with a human readable string * -*************************************************/ -void X509_Time::set_to(const std::string& time_str) - { - if(time_str == "") - { - year = month = day = hour = minute = second = 0; - return; - } - - std::vector params; - std::string current; - - for(u32bit j = 0; j != time_str.size(); ++j) - { - if(Charset::is_digit(time_str[j])) - current += time_str[j]; - else - { - if(current != "") - params.push_back(current); - current.clear(); - } - } - if(current != "") - params.push_back(current); - - if(params.size() < 3 || params.size() > 6) - throw Invalid_Argument("Invalid time specification " + time_str); - - year = to_u32bit(params[0]); - month = to_u32bit(params[1]); - day = to_u32bit(params[2]); - hour = (params.size() >= 4) ? to_u32bit(params[3]) : 0; - minute = (params.size() >= 5) ? to_u32bit(params[4]) : 0; - second = (params.size() == 6) ? to_u32bit(params[5]) : 0; - - if(year >= 2050) - tag = GENERALIZED_TIME; - else - tag = UTC_TIME; - - if(!passes_sanity_check()) - throw Invalid_Argument("Invalid time specification " + time_str); - } - -/************************************************* -* Set the time with an ISO time format string * -*************************************************/ -void X509_Time::set_to(const std::string& t_spec, ASN1_Tag tag) - { - if(tag != GENERALIZED_TIME && tag != UTC_TIME) - throw Invalid_Argument("X509_Time: Invalid tag " + to_string(tag)); - if(tag == GENERALIZED_TIME && t_spec.size() != 13 && t_spec.size() != 15) - throw Invalid_Argument("Invalid GeneralizedTime: " + t_spec); - if(tag == UTC_TIME && t_spec.size() != 11 && t_spec.size() != 13) - throw Invalid_Argument("Invalid UTCTime: " + t_spec); - if(t_spec[t_spec.size()-1] != 'Z') - throw Invalid_Argument("Invalid time encoding: " + t_spec); - - const u32bit YEAR_SIZE = (tag == UTC_TIME) ? 2 : 4; - - std::vector params; - std::string current; - - for(u32bit j = 0; j != YEAR_SIZE; ++j) - current += t_spec[j]; - params.push_back(current); - current.clear(); - - for(u32bit j = YEAR_SIZE; j != t_spec.size() - 1; ++j) - { - current += t_spec[j]; - if(current.size() == 2) - { - params.push_back(current); - current.clear(); - } - } - - year = to_u32bit(params[0]); - month = to_u32bit(params[1]); - day = to_u32bit(params[2]); - hour = to_u32bit(params[3]); - minute = to_u32bit(params[4]); - second = (params.size() == 6) ? to_u32bit(params[5]) : 0; - - if(tag == UTC_TIME) - { - if(year >= 50) year += 1900; - else year += 2000; - } - - if(!passes_sanity_check()) - throw Invalid_Argument("Invalid time specification " + t_spec); - } - -/************************************************* -* DER encode a X509_Time * -*************************************************/ -void X509_Time::encode_into(DER_Encoder& der) const - { - if(tag != GENERALIZED_TIME && tag != UTC_TIME) - throw Invalid_Argument("X509_Time: Bad encoding tag"); - der.add_object(tag, UNIVERSAL, - Charset::transcode(as_string(), - LOCAL_CHARSET, LATIN1_CHARSET)); - } - -/************************************************* -* Decode a BER encoded X509_Time * -*************************************************/ -void X509_Time::decode_from(BER_Decoder& source) - { - BER_Object ber_time = source.get_next_object(); - set_to(Charset::transcode(ASN1::to_string(ber_time), - LATIN1_CHARSET, LOCAL_CHARSET), - ber_time.type_tag); - } - -/************************************************* -* Return a string representation of the time * -*************************************************/ -std::string X509_Time::as_string() const - { - if(time_is_set() == false) - throw Invalid_State("X509_Time::as_string: No time set"); - - std::string asn1rep; - if(tag == GENERALIZED_TIME) - asn1rep = to_string(year, 4); - else - { - if(year < 1950 || year >= 2050) - throw Encoding_Error("X509_Time: The time " + readable_string() + - " cannot be encoded as a UTCTime"); - u32bit asn1year = (year >= 2000) ? (year - 2000) : (year - 1900); - asn1rep = to_string(asn1year, 2); - } - asn1rep += to_string(month, 2) + to_string(day, 2); - asn1rep += to_string(hour, 2) + to_string(minute, 2) + to_string(second, 2); - asn1rep += "Z"; - return asn1rep; - } - -/************************************************* -* Return if the time has been set somehow * -*************************************************/ -bool X509_Time::time_is_set() const - { - return (year != 0); - } - -/************************************************* -* Return a human readable string representation * -*************************************************/ -std::string X509_Time::readable_string() const - { - if(time_is_set() == false) - throw Invalid_State("X509_Time::readable_string: No time set"); - - std::string readable; - readable += to_string(year, 4) + "/"; - readable += to_string(month ) + "/"; - readable += to_string(day ) + " "; - readable += to_string(hour ) + ":"; - readable += to_string(minute, 2) + ":"; - readable += to_string(second, 2) + " UTC"; - return readable; - } - -/************************************************* -* Do a general sanity check on the time * -*************************************************/ -bool X509_Time::passes_sanity_check() const - { - if(year < 1950 || year > 2100) - return false; - if(month == 0 || month > 12) - return false; - if(day == 0 || day > 31) - return false; - if(hour >= 24 || minute > 60 || second > 60) - return false; - return true; - } - -/************************************************* -* Compare this time against another * -*************************************************/ -s32bit X509_Time::cmp(const X509_Time& other) const - { - if(time_is_set() == false) - throw Invalid_State("X509_Time::cmp: No time set"); - - const s32bit EARLIER = -1, LATER = 1, SAME_TIME = 0; - - if(year < other.year) return EARLIER; - if(year > other.year) return LATER; - if(month < other.month) return EARLIER; - if(month > other.month) return LATER; - if(day < other.day) return EARLIER; - if(day > other.day) return LATER; - if(hour < other.hour) return EARLIER; - if(hour > other.hour) return LATER; - if(minute < other.minute) return EARLIER; - if(minute > other.minute) return LATER; - if(second < other.second) return EARLIER; - if(second > other.second) return LATER; - - return SAME_TIME; - } - -/************************************************* -* Compare two X509_Times for in various ways * -*************************************************/ -bool operator==(const X509_Time& t1, const X509_Time& t2) - { return (t1.cmp(t2) == 0); } -bool operator!=(const X509_Time& t1, const X509_Time& t2) - { return (t1.cmp(t2) != 0); } -bool operator<=(const X509_Time& t1, const X509_Time& t2) - { return (t1.cmp(t2) <= 0); } -bool operator>=(const X509_Time& t1, const X509_Time& t2) - { return (t1.cmp(t2) >= 0); } - -} diff --git a/src/base64.cpp b/src/base64.cpp deleted file mode 100644 index 0e01d94f3..000000000 --- a/src/base64.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/************************************************* -* Base64 Encoder/Decoder Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include - -namespace Botan { - -/************************************************* -* Base64_Encoder Constructor * -*************************************************/ -Base64_Encoder::Base64_Encoder(bool breaks, u32bit length, bool t_n) : - line_length(breaks ? length : 0), trailing_newline(t_n) - { - in.create(48); - out.create(4); - - counter = position = 0; - } - -/************************************************* -* Base64 Encoding Operation * -*************************************************/ -void Base64_Encoder::encode(const byte in[3], byte out[4]) - { - out[0] = BIN_TO_BASE64[((in[0] & 0xFC) >> 2)]; - out[1] = BIN_TO_BASE64[((in[0] & 0x03) << 4) | (in[1] >> 4)]; - out[2] = BIN_TO_BASE64[((in[1] & 0x0F) << 2) | (in[2] >> 6)]; - out[3] = BIN_TO_BASE64[((in[2] & 0x3F) )]; - } - -/************************************************* -* Encode and send a block * -*************************************************/ -void Base64_Encoder::encode_and_send(const byte block[], u32bit length) - { - for(u32bit j = 0; j != length; j += 3) - { - encode(block + j, out); - do_output(out, 4); - } - } - -/************************************************* -* Handle the output * -*************************************************/ -void Base64_Encoder::do_output(const byte input[], u32bit length) - { - if(line_length == 0) - send(input, length); - else - { - u32bit remaining = length, offset = 0; - while(remaining) - { - u32bit sent = std::min(line_length - counter, remaining); - send(input + offset, sent); - counter += sent; - remaining -= sent; - offset += sent; - if(counter == line_length) - { - send('\n'); - counter = 0; - } - } - } - } - -/************************************************* -* Convert some data into Base64 * -*************************************************/ -void Base64_Encoder::write(const byte input[], u32bit length) - { - in.copy(position, input, length); - if(position + length >= in.size()) - { - encode_and_send(in, in.size()); - input += (in.size() - position); - length -= (in.size() - position); - while(length >= in.size()) - { - encode_and_send(input, in.size()); - input += in.size(); - length -= in.size(); - } - in.copy(input, length); - position = 0; - } - position += length; - } - -/************************************************* -* Flush buffers * -*************************************************/ -void Base64_Encoder::end_msg() - { - u32bit start_of_last_block = 3 * (position / 3), - left_over = position % 3; - encode_and_send(in, start_of_last_block); - - if(left_over) - { - SecureBuffer remainder(in + start_of_last_block, left_over); - - encode(remainder, out); - - u32bit empty_bits = 8 * (3 - left_over), index = 4 - 1; - while(empty_bits >= 8) - { - out[index--] = '='; - empty_bits -= 6; - } - - do_output(out, 4); - } - - if(trailing_newline || (counter && line_length)) - send('\n'); - - counter = position = 0; - } - -/************************************************* -* Base64_Decoder Constructor * -*************************************************/ -Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c) - { - in.create(48); - out.create(3); - position = 0; - } - -/************************************************* -* Check if a character is a valid Base64 char * -*************************************************/ -bool Base64_Decoder::is_valid(byte in) - { - return (BASE64_TO_BIN[in] != 0x80); - } - -/************************************************* -* Base64 Decoding Operation * -*************************************************/ -void Base64_Decoder::decode(const byte in[4], byte out[3]) - { - out[0] = ((BASE64_TO_BIN[in[0]] << 2) | (BASE64_TO_BIN[in[1]] >> 4)); - out[1] = ((BASE64_TO_BIN[in[1]] << 4) | (BASE64_TO_BIN[in[2]] >> 2)); - out[2] = ((BASE64_TO_BIN[in[2]] << 6) | (BASE64_TO_BIN[in[3]])); - } - -/************************************************* -* Decode and send a block * -*************************************************/ -void Base64_Decoder::decode_and_send(const byte block[], u32bit length) - { - for(u32bit j = 0; j != length; j += 4) - { - decode(block + j, out); - send(out, 3); - } - } - -/************************************************* -* Handle processing an invalid character * -*************************************************/ -void Base64_Decoder::handle_bad_char(byte c) - { - if(c == '=' || checking == NONE) - return; - - if((checking == IGNORE_WS) && Charset::is_space(c)) - return; - - throw Decoding_Error( - std::string("Base64_Decoder: Invalid base64 character '") + - static_cast(c) + "'" - ); - } - -/************************************************* -* Convert some data from Base64 * -*************************************************/ -void Base64_Decoder::write(const byte input[], u32bit length) - { - for(u32bit j = 0; j != length; ++j) - { - if(is_valid(input[j])) - in[position++] = input[j]; - else - handle_bad_char(input[j]); - - if(position == in.size()) - { - decode_and_send(in, in.size()); - position = 0; - } - } - } - -/************************************************* -* Flush buffers * -*************************************************/ -void Base64_Decoder::end_msg() - { - if(position != 0) - { - u32bit start_of_last_block = 4 * (position / 4), - left_over = position % 4; - decode_and_send(in, start_of_last_block); - - if(left_over) - { - SecureBuffer remainder(in + start_of_last_block, left_over); - decode(remainder, out); - send(out, ((left_over == 1) ? (1) : (left_over - 1))); - } - } - position = 0; - } - -} diff --git a/src/ber_dec.cpp b/src/ber_dec.cpp deleted file mode 100644 index c725a5af9..000000000 --- a/src/ber_dec.cpp +++ /dev/null @@ -1,469 +0,0 @@ -/************************************************* -* BER Decoder Source File * -* (C) 1999-2008 Jack Lloyd * -*************************************************/ - -#include -#include -#include - -namespace Botan { - -namespace { - -/************************************************* -* BER decode an ASN.1 type tag * -*************************************************/ -u32bit decode_tag(DataSource* ber, ASN1_Tag& type_tag, ASN1_Tag& class_tag) - { - byte b; - if(!ber->read_byte(b)) - { - class_tag = type_tag = NO_OBJECT; - return 0; - } - - if((b & 0x1F) != 0x1F) - { - type_tag = ASN1_Tag(b & 0x1F); - class_tag = ASN1_Tag(b & 0xE0); - return 1; - } - - u32bit tag_bytes = 1; - class_tag = ASN1_Tag(b & 0xE0); - - u32bit tag_buf = 0; - while(true) - { - if(!ber->read_byte(b)) - throw BER_Decoding_Error("Long-form tag truncated"); - if(tag_buf & 0xFF000000) - throw BER_Decoding_Error("Long-form tag overflowed 32 bits"); - ++tag_bytes; - tag_buf = (tag_buf << 7) | (b & 0x7F); - if((b & 0x80) == 0) break; - } - type_tag = ASN1_Tag(tag_buf); - return tag_bytes; - } - -/************************************************* -* Find the EOC marker * -*************************************************/ -u32bit find_eoc(DataSource*); - -/************************************************* -* BER decode an ASN.1 length field * -*************************************************/ -u32bit decode_length(DataSource* ber, u32bit& field_size) - { - byte b; - if(!ber->read_byte(b)) - throw BER_Decoding_Error("Length field not found"); - field_size = 1; - if((b & 0x80) == 0) - return b; - - field_size += (b & 0x7F); - if(field_size == 1) return find_eoc(ber); - if(field_size > 5) - throw BER_Decoding_Error("Length field is too large"); - - u32bit length = 0; - - for(u32bit j = 0; j != field_size - 1; ++j) - { - if(get_byte(0, length) != 0) - throw BER_Decoding_Error("Field length overflow"); - if(!ber->read_byte(b)) - throw BER_Decoding_Error("Corrupted length field"); - length = (length << 8) | b; - } - return length; - } - -/************************************************* -* BER decode an ASN.1 length field * -*************************************************/ -u32bit decode_length(DataSource* ber) - { - u32bit dummy; - return decode_length(ber, dummy); - } - -/************************************************* -* Find the EOC marker * -*************************************************/ -u32bit find_eoc(DataSource* ber) - { - SecureVector buffer(DEFAULT_BUFFERSIZE), data; - - while(true) - { - const u32bit got = ber->peek(buffer, buffer.size(), data.size()); - if(got == 0) - break; - data.append(buffer, got); - } - - DataSource_Memory source(data); - data.destroy(); - - u32bit length = 0; - while(true) - { - ASN1_Tag type_tag, class_tag; - u32bit tag_size = decode_tag(&source, type_tag, class_tag); - if(type_tag == NO_OBJECT) - break; - - u32bit length_size = 0; - u32bit item_size = decode_length(&source, length_size); - source.discard_next(item_size); - - length += item_size + length_size + tag_size; - - if(type_tag == EOC) - break; - } - return length; - } - -} - -/************************************************* -* Check a type invariant on BER data * -*************************************************/ -void BER_Object::assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) - { - if(this->type_tag != type_tag || this->class_tag != class_tag) - throw BER_Decoding_Error("Tag mismatch when decoding"); - } - -/************************************************* -* Check if more objects are there * -*************************************************/ -bool BER_Decoder::more_items() const - { - if(source->end_of_data() && (pushed.type_tag == NO_OBJECT)) - return false; - return true; - } - -/************************************************* -* Verify that no bytes remain in the source * -*************************************************/ -BER_Decoder& BER_Decoder::verify_end() - { - if(!source->end_of_data() || (pushed.type_tag != NO_OBJECT)) - throw Invalid_State("BER_Decoder::verify_end called, but data remains"); - return (*this); - } - -/************************************************* -* Save all the bytes remaining in the source * -*************************************************/ -BER_Decoder& BER_Decoder::raw_bytes(MemoryRegion& out) - { - out.destroy(); - byte buf; - while(source->read_byte(buf)) - out.append(buf); - return (*this); - } - -/************************************************* -* Discard all the bytes remaining in the source * -*************************************************/ -BER_Decoder& BER_Decoder::discard_remaining() - { - byte buf; - while(source->read_byte(buf)) - ; - return (*this); - } - -/************************************************* -* Return the BER encoding of the next object * -*************************************************/ -BER_Object BER_Decoder::get_next_object() - { - BER_Object next; - - if(pushed.type_tag != NO_OBJECT) - { - next = pushed; - pushed.class_tag = pushed.type_tag = NO_OBJECT; - return next; - } - - decode_tag(source, next.type_tag, next.class_tag); - if(next.type_tag == NO_OBJECT) - return next; - - u32bit length = decode_length(source); - next.value.create(length); - if(source->read(next.value, length) != length) - throw BER_Decoding_Error("Value truncated"); - - if(next.type_tag == EOC && next.class_tag == UNIVERSAL) - return get_next_object(); - - return next; - } - -/************************************************* -* Push a object back into the stream * -*************************************************/ -void BER_Decoder::push_back(const BER_Object& obj) - { - if(pushed.type_tag != NO_OBJECT) - throw Invalid_State("BER_Decoder: Only one push back is allowed"); - pushed = obj; - } - -/************************************************* -* Begin decoding a CONSTRUCTED type * -*************************************************/ -BER_Decoder BER_Decoder::start_cons(ASN1_Tag type_tag, - ASN1_Tag class_tag) - { - BER_Object obj = get_next_object(); - obj.assert_is_a(type_tag, ASN1_Tag(class_tag | CONSTRUCTED)); - - BER_Decoder result(obj.value, obj.value.size()); - result.parent = this; - return result; - } - -/************************************************* -* Finish decoding a CONSTRUCTED type * -*************************************************/ -BER_Decoder& BER_Decoder::end_cons() - { - if(!parent) - throw Invalid_State("BER_Decoder::end_cons called with NULL parent"); - if(!source->end_of_data()) - throw Decoding_Error("BER_Decoder::end_cons called with data left"); - return (*parent); - } - -/************************************************* -* BER_Decoder Constructor * -*************************************************/ -BER_Decoder::BER_Decoder(DataSource& src) - { - source = &src; - owns = false; - pushed.type_tag = pushed.class_tag = NO_OBJECT; - parent = 0; - } - -/************************************************* -* BER_Decoder Constructor * - *************************************************/ -BER_Decoder::BER_Decoder(const byte data[], u32bit length) - { - source = new DataSource_Memory(data, length); - owns = true; - pushed.type_tag = pushed.class_tag = NO_OBJECT; - parent = 0; - } - -/************************************************* -* BER_Decoder Constructor * -*************************************************/ -BER_Decoder::BER_Decoder(const MemoryRegion& data) - { - source = new DataSource_Memory(data); - owns = true; - pushed.type_tag = pushed.class_tag = NO_OBJECT; - parent = 0; - } - -/************************************************* -* BER_Decoder Copy Constructor * -*************************************************/ -BER_Decoder::BER_Decoder(const BER_Decoder& other) - { - source = other.source; - owns = false; - if(other.owns) - { - other.owns = false; - owns = true; - } - pushed.type_tag = pushed.class_tag = NO_OBJECT; - parent = other.parent; - } - -/************************************************* -* BER_Decoder Destructor * -*************************************************/ -BER_Decoder::~BER_Decoder() - { - if(owns) - delete source; - source = 0; - } - -/************************************************* -* Request for an object to decode itself * -*************************************************/ -BER_Decoder& BER_Decoder::decode(ASN1_Object& obj) - { - obj.decode_from(*this); - return (*this); - } - -/************************************************* -* Decode a BER encoded NULL * -*************************************************/ -BER_Decoder& BER_Decoder::decode_null() - { - BER_Object obj = get_next_object(); - obj.assert_is_a(NULL_TAG, UNIVERSAL); - if(obj.value.size()) - throw BER_Decoding_Error("NULL object had nonzero size"); - return (*this); - } - -/************************************************* -* Decode a BER encoded BOOLEAN * -*************************************************/ -BER_Decoder& BER_Decoder::decode(bool& out) - { - return decode(out, BOOLEAN, UNIVERSAL); - } - -/************************************************* -* Decode a small BER encoded INTEGER * -*************************************************/ -BER_Decoder& BER_Decoder::decode(u32bit& out) - { - return decode(out, INTEGER, UNIVERSAL); - } - -/************************************************* -* Decode a BER encoded INTEGER * -*************************************************/ -BER_Decoder& BER_Decoder::decode(BigInt& out) - { - return decode(out, INTEGER, UNIVERSAL); - } - -/************************************************* -* Decode a BER encoded BOOLEAN * -*************************************************/ -BER_Decoder& BER_Decoder::decode(bool& out, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - BER_Object obj = get_next_object(); - obj.assert_is_a(type_tag, class_tag); - - if(obj.value.size() != 1) - throw BER_Decoding_Error("BER boolean value had invalid size"); - - out = (obj.value[0]) ? true : false; - return (*this); - } - -/************************************************* -* Decode a small BER encoded INTEGER * -*************************************************/ -BER_Decoder& BER_Decoder::decode(u32bit& out, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - BigInt integer; - decode(integer, type_tag, class_tag); - out = integer.to_u32bit(); - return (*this); - } - -/************************************************* -* Decode a BER encoded INTEGER * -*************************************************/ -BER_Decoder& BER_Decoder::decode(BigInt& out, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - BER_Object obj = get_next_object(); - obj.assert_is_a(type_tag, class_tag); - - if(obj.value.is_empty()) - out = 0; - else - { - const bool negative = (obj.value[0] & 0x80) ? true : false; - - if(negative) - { - for(u32bit j = obj.value.size(); j > 0; --j) - if(obj.value[j-1]--) - break; - for(u32bit j = 0; j != obj.value.size(); ++j) - obj.value[j] = ~obj.value[j]; - } - - out = BigInt(obj.value, obj.value.size()); - - if(negative) - out.flip_sign(); - } - - return (*this); - } - -/************************************************* -* BER decode a BIT STRING or OCTET STRING * -*************************************************/ -BER_Decoder& BER_Decoder::decode(MemoryRegion& out, ASN1_Tag real_type) - { - return decode(out, real_type, real_type, UNIVERSAL); - } - -/************************************************* -* BER decode a BIT STRING or OCTET STRING * -*************************************************/ -BER_Decoder& BER_Decoder::decode(MemoryRegion& buffer, - ASN1_Tag real_type, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - if(real_type != OCTET_STRING && real_type != BIT_STRING) - throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type); - - BER_Object obj = get_next_object(); - obj.assert_is_a(type_tag, class_tag); - - if(real_type == OCTET_STRING) - buffer = obj.value; - else - { - if(obj.value[0] >= 8) - throw BER_Decoding_Error("Bad number of unused bits in BIT STRING"); - buffer.set(obj.value + 1, obj.value.size() - 1); - } - return (*this); - } - -/************************************************* -* Decode an OPTIONAL string type * -*************************************************/ -BER_Decoder& BER_Decoder::decode_optional_string(MemoryRegion& out, - ASN1_Tag real_type, - u16bit type_no) - { - BER_Object obj = get_next_object(); - - ASN1_Tag type_tag = static_cast(type_no); - - out.clear(); - push_back(obj); - - if(obj.type_tag == type_tag && obj.class_tag == CONTEXT_SPECIFIC) - decode(out, real_type, type_tag, CONTEXT_SPECIFIC); - - return (*this); - } - -} diff --git a/src/codec/base64/base64.cpp b/src/codec/base64/base64.cpp new file mode 100644 index 000000000..0e01d94f3 --- /dev/null +++ b/src/codec/base64/base64.cpp @@ -0,0 +1,225 @@ +/************************************************* +* Base64 Encoder/Decoder Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include + +namespace Botan { + +/************************************************* +* Base64_Encoder Constructor * +*************************************************/ +Base64_Encoder::Base64_Encoder(bool breaks, u32bit length, bool t_n) : + line_length(breaks ? length : 0), trailing_newline(t_n) + { + in.create(48); + out.create(4); + + counter = position = 0; + } + +/************************************************* +* Base64 Encoding Operation * +*************************************************/ +void Base64_Encoder::encode(const byte in[3], byte out[4]) + { + out[0] = BIN_TO_BASE64[((in[0] & 0xFC) >> 2)]; + out[1] = BIN_TO_BASE64[((in[0] & 0x03) << 4) | (in[1] >> 4)]; + out[2] = BIN_TO_BASE64[((in[1] & 0x0F) << 2) | (in[2] >> 6)]; + out[3] = BIN_TO_BASE64[((in[2] & 0x3F) )]; + } + +/************************************************* +* Encode and send a block * +*************************************************/ +void Base64_Encoder::encode_and_send(const byte block[], u32bit length) + { + for(u32bit j = 0; j != length; j += 3) + { + encode(block + j, out); + do_output(out, 4); + } + } + +/************************************************* +* Handle the output * +*************************************************/ +void Base64_Encoder::do_output(const byte input[], u32bit length) + { + if(line_length == 0) + send(input, length); + else + { + u32bit remaining = length, offset = 0; + while(remaining) + { + u32bit sent = std::min(line_length - counter, remaining); + send(input + offset, sent); + counter += sent; + remaining -= sent; + offset += sent; + if(counter == line_length) + { + send('\n'); + counter = 0; + } + } + } + } + +/************************************************* +* Convert some data into Base64 * +*************************************************/ +void Base64_Encoder::write(const byte input[], u32bit length) + { + in.copy(position, input, length); + if(position + length >= in.size()) + { + encode_and_send(in, in.size()); + input += (in.size() - position); + length -= (in.size() - position); + while(length >= in.size()) + { + encode_and_send(input, in.size()); + input += in.size(); + length -= in.size(); + } + in.copy(input, length); + position = 0; + } + position += length; + } + +/************************************************* +* Flush buffers * +*************************************************/ +void Base64_Encoder::end_msg() + { + u32bit start_of_last_block = 3 * (position / 3), + left_over = position % 3; + encode_and_send(in, start_of_last_block); + + if(left_over) + { + SecureBuffer remainder(in + start_of_last_block, left_over); + + encode(remainder, out); + + u32bit empty_bits = 8 * (3 - left_over), index = 4 - 1; + while(empty_bits >= 8) + { + out[index--] = '='; + empty_bits -= 6; + } + + do_output(out, 4); + } + + if(trailing_newline || (counter && line_length)) + send('\n'); + + counter = position = 0; + } + +/************************************************* +* Base64_Decoder Constructor * +*************************************************/ +Base64_Decoder::Base64_Decoder(Decoder_Checking c) : checking(c) + { + in.create(48); + out.create(3); + position = 0; + } + +/************************************************* +* Check if a character is a valid Base64 char * +*************************************************/ +bool Base64_Decoder::is_valid(byte in) + { + return (BASE64_TO_BIN[in] != 0x80); + } + +/************************************************* +* Base64 Decoding Operation * +*************************************************/ +void Base64_Decoder::decode(const byte in[4], byte out[3]) + { + out[0] = ((BASE64_TO_BIN[in[0]] << 2) | (BASE64_TO_BIN[in[1]] >> 4)); + out[1] = ((BASE64_TO_BIN[in[1]] << 4) | (BASE64_TO_BIN[in[2]] >> 2)); + out[2] = ((BASE64_TO_BIN[in[2]] << 6) | (BASE64_TO_BIN[in[3]])); + } + +/************************************************* +* Decode and send a block * +*************************************************/ +void Base64_Decoder::decode_and_send(const byte block[], u32bit length) + { + for(u32bit j = 0; j != length; j += 4) + { + decode(block + j, out); + send(out, 3); + } + } + +/************************************************* +* Handle processing an invalid character * +*************************************************/ +void Base64_Decoder::handle_bad_char(byte c) + { + if(c == '=' || checking == NONE) + return; + + if((checking == IGNORE_WS) && Charset::is_space(c)) + return; + + throw Decoding_Error( + std::string("Base64_Decoder: Invalid base64 character '") + + static_cast(c) + "'" + ); + } + +/************************************************* +* Convert some data from Base64 * +*************************************************/ +void Base64_Decoder::write(const byte input[], u32bit length) + { + for(u32bit j = 0; j != length; ++j) + { + if(is_valid(input[j])) + in[position++] = input[j]; + else + handle_bad_char(input[j]); + + if(position == in.size()) + { + decode_and_send(in, in.size()); + position = 0; + } + } + } + +/************************************************* +* Flush buffers * +*************************************************/ +void Base64_Decoder::end_msg() + { + if(position != 0) + { + u32bit start_of_last_block = 4 * (position / 4), + left_over = position % 4; + decode_and_send(in, start_of_last_block); + + if(left_over) + { + SecureBuffer remainder(in + start_of_last_block, left_over); + decode(remainder, out); + send(out, ((left_over == 1) ? (1) : (left_over - 1))); + } + } + position = 0; + } + +} diff --git a/src/codec/base64/base64.h b/src/codec/base64/base64.h new file mode 100644 index 000000000..0003875a6 --- /dev/null +++ b/src/codec/base64/base64.h @@ -0,0 +1,60 @@ +/************************************************* +* Base64 Encoder/Decoder Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_BASE64_H__ +#define BOTAN_BASE64_H__ + +#include +#include + +namespace Botan { + +/************************************************* +* Base64 Encoder * +*************************************************/ +class BOTAN_DLL Base64_Encoder : public Filter + { + public: + static void encode(const byte[3], byte[4]); + + void write(const byte[], u32bit); + void end_msg(); + Base64_Encoder(bool = false, u32bit = 72, bool = false); + private: + void encode_and_send(const byte[], u32bit); + void do_output(const byte[], u32bit); + static const byte BIN_TO_BASE64[64]; + + const u32bit line_length; + const bool trailing_newline; + SecureVector in, out; + u32bit position, counter; + }; + +/************************************************* +* Base64 Decoder * +*************************************************/ +class BOTAN_DLL Base64_Decoder : public Filter + { + public: + static void decode(const byte[4], byte[3]); + static bool is_valid(byte); + + void write(const byte[], u32bit); + void end_msg(); + Base64_Decoder(Decoder_Checking = NONE); + private: + void decode_and_send(const byte[], u32bit); + void handle_bad_char(byte); + static const byte BASE64_TO_BIN[256]; + + const Decoder_Checking checking; + SecureVector in, out; + u32bit position; + }; + +} + +#endif diff --git a/src/codec/base64/modinfo.txt b/src/codec/base64/modinfo.txt new file mode 100644 index 000000000..4e7b38584 --- /dev/null +++ b/src/codec/base64/modinfo.txt @@ -0,0 +1,10 @@ +realname "Base64 Codec" + +define BASE64_CODEC + +load_on auto + + +base64.cpp +base64.h + diff --git a/src/codec/bzip2/bzip2.cpp b/src/codec/bzip2/bzip2.cpp new file mode 100644 index 000000000..712dacd7d --- /dev/null +++ b/src/codec/bzip2/bzip2.cpp @@ -0,0 +1,271 @@ +/************************************************* +* Bzip Compressor Source File * +* (C) 2001 Peter J Jones * +* 2001-2007 Jack Lloyd * +* 2006 Matt Johnston * +*************************************************/ + +#include +#include +#include +#define BZ_NO_STDIO +#include + +namespace Botan { + +namespace { + +/************************************************* +* Allocation Information for Bzip * +*************************************************/ +class Bzip_Alloc_Info + { + public: + std::map current_allocs; + Allocator* alloc; + + Bzip_Alloc_Info() { alloc = Allocator::get(false); } + }; + +/************************************************* +* Allocation Function for Bzip * +*************************************************/ +void* bzip_malloc(void* info_ptr, int n, int size) + { + Bzip_Alloc_Info* info = static_cast(info_ptr); + void* ptr = info->alloc->allocate(n * size); + info->current_allocs[ptr] = n * size; + return ptr; + } + +/************************************************* +* Allocation Function for Bzip * +*************************************************/ +void bzip_free(void* info_ptr, void* ptr) + { + Bzip_Alloc_Info* info = static_cast(info_ptr); + std::map::const_iterator i = info->current_allocs.find(ptr); + if(i == info->current_allocs.end()) + throw Invalid_Argument("bzip_free: Got pointer not allocated by us"); + info->alloc->deallocate(ptr, i->second); + } + +} + +/************************************************* +* Wrapper Type for Bzip2 Stream * +*************************************************/ +class Bzip_Stream + { + public: + bz_stream stream; + + Bzip_Stream() + { + std::memset(&stream, 0, sizeof(bz_stream)); + stream.bzalloc = bzip_malloc; + stream.bzfree = bzip_free; + stream.opaque = new Bzip_Alloc_Info; + } + ~Bzip_Stream() + { + Bzip_Alloc_Info* info = static_cast(stream.opaque); + delete info; + std::memset(&stream, 0, sizeof(bz_stream)); + } + }; + +/************************************************* +* Bzip_Compression Constructor * +*************************************************/ +Bzip_Compression::Bzip_Compression(u32bit l) : + level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE) + { + bz = 0; + } + +/************************************************* +* Start Compressing with Bzip * +*************************************************/ +void Bzip_Compression::start_msg() + { + clear(); + bz = new Bzip_Stream; + if(BZ2_bzCompressInit(&(bz->stream), level, 0, 0) != BZ_OK) + throw Exception("Bzip_Compression: Memory allocation error"); + } + +/************************************************* +* Compress Input with Bzip * +*************************************************/ +void Bzip_Compression::write(const byte input[], u32bit length) + { + bz->stream.next_in = reinterpret_cast(const_cast(input)); + bz->stream.avail_in = length; + + while(bz->stream.avail_in != 0) + { + bz->stream.next_out = reinterpret_cast(buffer.begin()); + bz->stream.avail_out = buffer.size(); + BZ2_bzCompress(&(bz->stream), BZ_RUN); + send(buffer, buffer.size() - bz->stream.avail_out); + } + } + +/************************************************* +* Finish Compressing with Bzip * +*************************************************/ +void Bzip_Compression::end_msg() + { + bz->stream.next_in = 0; + bz->stream.avail_in = 0; + + int rc = BZ_OK; + while(rc != BZ_STREAM_END) + { + bz->stream.next_out = reinterpret_cast(buffer.begin()); + bz->stream.avail_out = buffer.size(); + rc = BZ2_bzCompress(&(bz->stream), BZ_FINISH); + send(buffer, buffer.size() - bz->stream.avail_out); + } + clear(); + } + +/************************************************* +* Flush the Bzip Compressor * +*************************************************/ +void Bzip_Compression::flush() + { + bz->stream.next_in = 0; + bz->stream.avail_in = 0; + + int rc = BZ_OK; + while(rc != BZ_RUN_OK) + { + bz->stream.next_out = reinterpret_cast(buffer.begin()); + bz->stream.avail_out = buffer.size(); + rc = BZ2_bzCompress(&(bz->stream), BZ_FLUSH); + send(buffer, buffer.size() - bz->stream.avail_out); + } + } + +/************************************************* +* Clean up Compression Context * +*************************************************/ +void Bzip_Compression::clear() + { + if(!bz) return; + BZ2_bzCompressEnd(&(bz->stream)); + delete bz; + bz = 0; + } + +/************************************************* +* Bzip_Decompression Constructor * +*************************************************/ +Bzip_Decompression::Bzip_Decompression(bool s) : + small_mem(s), buffer(DEFAULT_BUFFERSIZE) + { + no_writes = true; + bz = 0; + } + +/************************************************* +* Decompress Input with Bzip * +*************************************************/ +void Bzip_Decompression::write(const byte input_arr[], u32bit length) + { + if(length) no_writes = false; + + char* input = reinterpret_cast(const_cast(input_arr)); + + bz->stream.next_in = input; + bz->stream.avail_in = length; + + while(bz->stream.avail_in != 0) + { + bz->stream.next_out = reinterpret_cast(buffer.begin()); + bz->stream.avail_out = buffer.size(); + + int rc = BZ2_bzDecompress(&(bz->stream)); + + if(rc != BZ_OK && rc != BZ_STREAM_END) + { + clear(); + if(rc == BZ_DATA_ERROR) + throw Decoding_Error("Bzip_Decompression: Data integrity error"); + if(rc == BZ_DATA_ERROR_MAGIC) + throw Decoding_Error("Bzip_Decompression: Invalid input"); + if(rc == BZ_MEM_ERROR) + throw Exception("Bzip_Decompression: Memory allocation error"); + throw Exception("Bzip_Decompression: Unknown decompress error"); + } + + send(buffer, buffer.size() - bz->stream.avail_out); + + if(rc == BZ_STREAM_END) + { + u32bit read_from_block = length - bz->stream.avail_in; + start_msg(); + bz->stream.next_in = input + read_from_block; + bz->stream.avail_in = length - read_from_block; + input += read_from_block; + length -= read_from_block; + } + } + } + +/************************************************* +* Start Decompressing with Bzip * +*************************************************/ +void Bzip_Decompression::start_msg() + { + clear(); + bz = new Bzip_Stream; + + if(BZ2_bzDecompressInit(&(bz->stream), 0, small_mem) != BZ_OK) + throw Exception("Bzip_Decompression: Memory allocation error"); + + no_writes = true; + } + +/************************************************* +* Finish Decompressing with Bzip * +*************************************************/ +void Bzip_Decompression::end_msg() + { + if(no_writes) return; + bz->stream.next_in = 0; + bz->stream.avail_in = 0; + + int rc = BZ_OK; + while(rc != BZ_STREAM_END) + { + bz->stream.next_out = reinterpret_cast(buffer.begin()); + bz->stream.avail_out = buffer.size(); + rc = BZ2_bzDecompress(&(bz->stream)); + + if(rc != BZ_OK && rc != BZ_STREAM_END) + { + clear(); + throw Exception("Bzip_Decompression: Error finalizing decompression"); + } + + send(buffer, buffer.size() - bz->stream.avail_out); + } + + clear(); + } + +/************************************************* +* Clean up Decompression Context * +*************************************************/ +void Bzip_Decompression::clear() + { + if(!bz) return; + BZ2_bzDecompressEnd(&(bz->stream)); + delete bz; + bz = 0; + } + +} diff --git a/src/codec/bzip2/bzip2.h b/src/codec/bzip2/bzip2.h new file mode 100644 index 000000000..1244924ca --- /dev/null +++ b/src/codec/bzip2/bzip2.h @@ -0,0 +1,59 @@ +/************************************************* +* Bzip Compressor Header File * +* (C) 2001 Peter J Jones * +* 2001-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_BZIP2_H__ +#define BOTAN_BZIP2_H__ + +#include + +namespace Botan { + +/************************************************* +* Bzip Compression Filter * +*************************************************/ +class Bzip_Compression : public Filter + { + public: + void write(const byte input[], u32bit length); + void start_msg(); + void end_msg(); + + void flush(); + + Bzip_Compression(u32bit = 9); + ~Bzip_Compression() { clear(); } + private: + void clear(); + + const u32bit level; + SecureVector buffer; + class Bzip_Stream* bz; + }; + +/************************************************* +* Bzip Decompression Filter * +*************************************************/ +class Bzip_Decompression : public Filter + { + public: + void write(const byte input[], u32bit length); + void start_msg(); + void end_msg(); + + Bzip_Decompression(bool = false); + ~Bzip_Decompression() { clear(); } + private: + void clear(); + + const bool small_mem; + SecureVector buffer; + class Bzip_Stream* bz; + bool no_writes; + }; + +} + +#endif diff --git a/src/codec/bzip2/modinfo.txt b/src/codec/bzip2/modinfo.txt new file mode 100644 index 000000000..efedc097f --- /dev/null +++ b/src/codec/bzip2/modinfo.txt @@ -0,0 +1,17 @@ +# This module was written by Peter J. Jones + +realname "Bzip2 Compressor" + +define COMPRESSOR_BZIP2 +modset compression + +load_on request + + +bzip2.h +bzip2.cpp + + + +all -> bz2 + diff --git a/src/codec/hex/hex.cpp b/src/codec/hex/hex.cpp new file mode 100644 index 000000000..afb082f76 --- /dev/null +++ b/src/codec/hex/hex.cpp @@ -0,0 +1,188 @@ +/************************************************* +* Hex Encoder/Decoder Source File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#include +#include +#include +#include + +namespace Botan { + +/************************************************* +* Hex_Encoder Constructor * +*************************************************/ +Hex_Encoder::Hex_Encoder(bool breaks, u32bit length, Case c) : + casing(c), line_length(breaks ? length : 0) + { + in.create(64); + out.create(2*in.size()); + counter = position = 0; + } + +/************************************************* +* Hex_Encoder Constructor * +*************************************************/ +Hex_Encoder::Hex_Encoder(Case c) : casing(c), line_length(0) + { + in.create(64); + out.create(2*in.size()); + counter = position = 0; + } + +/************************************************* +* Hex Encoding Operation * +*************************************************/ +void Hex_Encoder::encode(byte in, byte out[2], Hex_Encoder::Case casing) + { + const byte* BIN_TO_HEX = ((casing == Uppercase) ? BIN_TO_HEX_UPPER : + BIN_TO_HEX_LOWER); + + out[0] = BIN_TO_HEX[((in >> 4) & 0x0F)]; + out[1] = BIN_TO_HEX[((in ) & 0x0F)]; + } + +/************************************************* +* Encode and send a block * +*************************************************/ +void Hex_Encoder::encode_and_send(const byte block[], u32bit length) + { + for(u32bit j = 0; j != length; ++j) + encode(block[j], out + 2*j, casing); + + if(line_length == 0) + send(out, 2*length); + else + { + u32bit remaining = 2*length, offset = 0; + while(remaining) + { + u32bit sent = std::min(line_length - counter, remaining); + send(out + offset, sent); + counter += sent; + remaining -= sent; + offset += sent; + if(counter == line_length) + { + send('\n'); + counter = 0; + } + } + } + } + +/************************************************* +* Convert some data into hex format * +*************************************************/ +void Hex_Encoder::write(const byte input[], u32bit length) + { + in.copy(position, input, length); + if(position + length >= in.size()) + { + encode_and_send(in, in.size()); + input += (in.size() - position); + length -= (in.size() - position); + while(length >= in.size()) + { + encode_and_send(input, in.size()); + input += in.size(); + length -= in.size(); + } + in.copy(input, length); + position = 0; + } + position += length; + } + +/************************************************* +* Flush buffers * +*************************************************/ +void Hex_Encoder::end_msg() + { + encode_and_send(in, position); + if(counter && line_length) + send('\n'); + counter = position = 0; + } + +/************************************************* +* Hex_Decoder Constructor * +*************************************************/ +Hex_Decoder::Hex_Decoder(Decoder_Checking c) : checking(c) + { + in.create(64); + out.create(in.size() / 2); + position = 0; + } + +/************************************************* +* Check if a character is a valid hex char * +*************************************************/ +bool Hex_Decoder::is_valid(byte in) + { + return (HEX_TO_BIN[in] != 0x80); + } + +/************************************************* +* Handle processing an invalid character * +*************************************************/ +void Hex_Decoder::handle_bad_char(byte c) + { + if(checking == NONE) + return; + + if((checking == IGNORE_WS) && Charset::is_space(c)) + return; + + throw Decoding_Error("Hex_Decoder: Invalid hex character: " + + to_string(c)); + } + +/************************************************* +* Hex Decoding Operation * +*************************************************/ +byte Hex_Decoder::decode(const byte hex[2]) + { + return ((HEX_TO_BIN[hex[0]] << 4) | HEX_TO_BIN[hex[1]]); + } + +/************************************************* +* Decode and send a block * +*************************************************/ +void Hex_Decoder::decode_and_send(const byte block[], u32bit length) + { + for(u32bit j = 0; j != length / 2; ++j) + out[j] = decode(block + 2*j); + send(out, length / 2); + } + +/************************************************* +* Convert some data from hex format * +*************************************************/ +void Hex_Decoder::write(const byte input[], u32bit length) + { + for(u32bit j = 0; j != length; ++j) + { + if(is_valid(input[j])) + in[position++] = input[j]; + else + handle_bad_char(input[j]); + if(position == in.size()) + { + decode_and_send(in, in.size()); + position = 0; + } + } + } + +/************************************************* +* Flush buffers * +*************************************************/ +void Hex_Decoder::end_msg() + { + decode_and_send(in, position); + position = 0; + } + +} diff --git a/src/codec/hex/hex.h b/src/codec/hex/hex.h new file mode 100644 index 000000000..0ecddb588 --- /dev/null +++ b/src/codec/hex/hex.h @@ -0,0 +1,64 @@ +/************************************************* +* Hex Encoder/Decoder Header File * +* (C) 1999-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_HEX_H__ +#define BOTAN_HEX_H__ + +#include +#include + +namespace Botan { + +/************************************************* +* Hex Encoder * +*************************************************/ +class BOTAN_DLL Hex_Encoder : public Filter + { + public: + enum Case { Uppercase, Lowercase }; + static void encode(byte, byte[2], Case = Uppercase); + + void write(const byte[], u32bit); + void end_msg(); + + Hex_Encoder(Case); + Hex_Encoder(bool = false, u32bit = 72, Case = Uppercase); + private: + void encode_and_send(const byte[], u32bit); + static const byte BIN_TO_HEX_UPPER[16]; + static const byte BIN_TO_HEX_LOWER[16]; + + const Case casing; + const u32bit line_length; + SecureVector in, out; + u32bit position, counter; + }; + +/************************************************* +* Hex Decoder * +*************************************************/ +class BOTAN_DLL Hex_Decoder : public Filter + { + public: + static byte decode(const byte[2]); + static bool is_valid(byte); + + void write(const byte[], u32bit); + void end_msg(); + + Hex_Decoder(Decoder_Checking = NONE); + private: + void decode_and_send(const byte[], u32bit); + void handle_bad_char(byte); + static const byte HEX_TO_BIN[256]; + + const Decoder_Checking checking; + SecureVector in, out; + u32bit position; + }; + +} + +#endif diff --git a/src/codec/hex/modinfo.txt b/src/codec/hex/modinfo.txt new file mode 100644 index 000000000..e0b07a552 --- /dev/null +++ b/src/codec/hex/modinfo.txt @@ -0,0 +1,10 @@ +realname "Hex Codec" + +define HEX_CODEC + +load_on auto + + +hex.cpp +hex.h + diff --git a/src/codec/zlib/modinfo.txt b/src/codec/zlib/modinfo.txt new file mode 100644 index 000000000..c1f1f998c --- /dev/null +++ b/src/codec/zlib/modinfo.txt @@ -0,0 +1,19 @@ +realname "Zlib Compressor" +#realname "Zlib/Gzip Compressor" + +define COMPRESSOR_ZLIB +#define COMPRESSOR_ZLIB,COMPRESSOR_GZIP + +load_on request +modset compression + + +zlib.h +zlib.cpp +#gzip.h +#gzip.cpp + + + +all -> z + diff --git a/src/codec/zlib/zlib.cpp b/src/codec/zlib/zlib.cpp new file mode 100644 index 000000000..36a9640e3 --- /dev/null +++ b/src/codec/zlib/zlib.cpp @@ -0,0 +1,283 @@ +/************************************************* +* Zlib Compressor Source File * +* (C) 2001 Peter J Jones * +* 2001-2007 Jack Lloyd * +* 2006 Matt Johnston * +*************************************************/ + +#include +#include +#include +#include + +namespace Botan { + +namespace { + +/************************************************* +* Allocation Information for Zlib * +*************************************************/ +class Zlib_Alloc_Info + { + public: + std::map current_allocs; + Allocator* alloc; + + Zlib_Alloc_Info() { alloc = Allocator::get(false); } + }; + +/************************************************* +* Allocation Function for Zlib * +*************************************************/ +void* zlib_malloc(void* info_ptr, unsigned int n, unsigned int size) + { + Zlib_Alloc_Info* info = static_cast(info_ptr); + void* ptr = info->alloc->allocate(n * size); + info->current_allocs[ptr] = n * size; + return ptr; + } + +/************************************************* +* Allocation Function for Zlib * +*************************************************/ +void zlib_free(void* info_ptr, void* ptr) + { + Zlib_Alloc_Info* info = static_cast(info_ptr); + std::map::const_iterator i = info->current_allocs.find(ptr); + if(i == info->current_allocs.end()) + throw Invalid_Argument("zlib_free: Got pointer not allocated by us"); + info->alloc->deallocate(ptr, i->second); + } + +} + +/************************************************* +* Wrapper Type for Zlib z_stream * +*************************************************/ +class Zlib_Stream + { + public: + z_stream stream; + + Zlib_Stream() + { + std::memset(&stream, 0, sizeof(z_stream)); + stream.zalloc = zlib_malloc; + stream.zfree = zlib_free; + stream.opaque = new Zlib_Alloc_Info; + } + ~Zlib_Stream() + { + Zlib_Alloc_Info* info = static_cast(stream.opaque); + delete info; + std::memset(&stream, 0, sizeof(z_stream)); + } + }; + +/************************************************* +* Zlib_Compression Constructor * +*************************************************/ +Zlib_Compression::Zlib_Compression(u32bit l) : + level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE) + { + zlib = 0; + } + +/************************************************* +* Start Compressing with Zlib * +*************************************************/ +void Zlib_Compression::start_msg() + { + clear(); + zlib = new Zlib_Stream; + if(deflateInit(&(zlib->stream), level) != Z_OK) + throw Exception("Zlib_Compression: Memory allocation error"); + } + +/************************************************* +* Compress Input with Zlib * +*************************************************/ +void Zlib_Compression::write(const byte input[], u32bit length) + { + zlib->stream.next_in = static_cast(const_cast(input)); + zlib->stream.avail_in = length; + + while(zlib->stream.avail_in != 0) + { + zlib->stream.next_out = static_cast(buffer.begin()); + zlib->stream.avail_out = buffer.size(); + deflate(&(zlib->stream), Z_NO_FLUSH); + send(buffer.begin(), buffer.size() - zlib->stream.avail_out); + } + } + +/************************************************* +* Finish Compressing with Zlib * +*************************************************/ +void Zlib_Compression::end_msg() + { + zlib->stream.next_in = 0; + zlib->stream.avail_in = 0; + + int rc = Z_OK; + while(rc != Z_STREAM_END) + { + zlib->stream.next_out = reinterpret_cast(buffer.begin()); + zlib->stream.avail_out = buffer.size(); + rc = deflate(&(zlib->stream), Z_FINISH); + send(buffer.begin(), buffer.size() - zlib->stream.avail_out); + } + clear(); + } + +/************************************************* +* Flush the Zlib Compressor * +*************************************************/ +void Zlib_Compression::flush() + { + zlib->stream.next_in = 0; + zlib->stream.avail_in = 0; + + while(true) + { + zlib->stream.avail_out = buffer.size(); + + zlib->stream.next_out = reinterpret_cast(buffer.begin()); + + + deflate(&(zlib->stream), Z_FULL_FLUSH); + send(buffer.begin(), buffer.size() - zlib->stream.avail_out); + if(zlib->stream.avail_out == buffer.size()) break; + } + } + +/************************************************* +* Clean up Compression Context * +*************************************************/ +void Zlib_Compression::clear() + { + if(zlib) + { + deflateEnd(&(zlib->stream)); + delete zlib; + zlib = 0; + } + + buffer.clear(); + } + +/************************************************* +* Zlib_Decompression Constructor * +*************************************************/ +Zlib_Decompression::Zlib_Decompression() : buffer(DEFAULT_BUFFERSIZE) + { + zlib = 0; + no_writes = true; + } + +/************************************************* +* Start Decompressing with Zlib * +*************************************************/ +void Zlib_Decompression::start_msg() + { + clear(); + zlib = new Zlib_Stream; + if(inflateInit(&(zlib->stream)) != Z_OK) + throw Exception("Zlib_Decompression: Memory allocation error"); + } + +/************************************************* +* Decompress Input with Zlib * +*************************************************/ +void Zlib_Decompression::write(const byte input_arr[], u32bit length) + { + if(length) no_writes = false; + + // non-const needed by zlib api :( + Bytef* input = reinterpret_cast(const_cast(input_arr)); + + zlib->stream.next_in = input; + zlib->stream.avail_in = length; + + while(zlib->stream.avail_in != 0) + { + zlib->stream.next_out = reinterpret_cast(buffer.begin()); + zlib->stream.avail_out = buffer.size(); + + int rc = inflate(&(zlib->stream), Z_SYNC_FLUSH); + + if(rc != Z_OK && rc != Z_STREAM_END) + { + clear(); + if(rc == Z_DATA_ERROR) + throw Decoding_Error("Zlib_Decompression: Data integrity error"); + if(rc == Z_NEED_DICT) + throw Decoding_Error("Zlib_Decompression: Need preset dictionary"); + if(rc == Z_MEM_ERROR) + throw Exception("Zlib_Decompression: Memory allocation error"); + throw Exception("Zlib_Decompression: Unknown decompress error"); + } + + send(buffer.begin(), buffer.size() - zlib->stream.avail_out); + + if(rc == Z_STREAM_END) + { + u32bit read_from_block = length - zlib->stream.avail_in; + start_msg(); + + zlib->stream.next_in = input + read_from_block; + zlib->stream.avail_in = length - read_from_block; + + input += read_from_block; + length -= read_from_block; + } + } + } + +/************************************************* +* Finish Decompressing with Zlib * +*************************************************/ +void Zlib_Decompression::end_msg() + { + if(no_writes) return; + zlib->stream.next_in = 0; + zlib->stream.avail_in = 0; + + int rc = Z_OK; + + while(rc != Z_STREAM_END) + { + zlib->stream.next_out = reinterpret_cast(buffer.begin()); + zlib->stream.avail_out = buffer.size(); + rc = inflate(&(zlib->stream), Z_SYNC_FLUSH); + + if(rc != Z_OK && rc != Z_STREAM_END) + { + clear(); + throw Exception("Zlib_Decompression: Error finalizing decompression"); + } + + send(buffer.begin(), buffer.size() - zlib->stream.avail_out); + } + + clear(); + } + +/************************************************* +* Clean up Decompression Context * +*************************************************/ +void Zlib_Decompression::clear() + { + no_writes = true; + + if(zlib) + { + inflateEnd(&(zlib->stream)); + delete zlib; + zlib = 0; + } + + buffer.clear(); + } + +} diff --git a/src/codec/zlib/zlib.h b/src/codec/zlib/zlib.h new file mode 100644 index 000000000..c3baea4ee --- /dev/null +++ b/src/codec/zlib/zlib.h @@ -0,0 +1,56 @@ +/************************************************* +* Zlib Compressor Header File * +* (C) 2001 Peter J Jones * +* 2001-2007 Jack Lloyd * +*************************************************/ + +#ifndef BOTAN_ZLIB_H__ +#define BOTAN_ZLIB_H__ + +#include + +namespace Botan { + +/************************************************* +* Zlib Compression Filter * +*************************************************/ +class Zlib_Compression : public Filter + { + public: + void write(const byte input[], u32bit length); + void start_msg(); + void end_msg(); + + void flush(); + + Zlib_Compression(u32bit = 6); + ~Zlib_Compression() { clear(); } + private: + void clear(); + const u32bit level; + SecureVector buffer; + class Zlib_Stream* zlib; + }; + +/************************************************* +* Zlib Decompression Filter * +*************************************************/ +class Zlib_Decompression : public Filter + { + public: + void write(const byte input[], u32bit length); + void start_msg(); + void end_msg(); + + Zlib_Decompression(); + ~Zlib_Decompression() { clear(); } + private: + void clear(); + SecureVector buffer; + class Zlib_Stream* zlib; + bool no_writes; + }; + +} + +#endif diff --git a/src/compress/bzip2/bzip2.cpp b/src/compress/bzip2/bzip2.cpp deleted file mode 100644 index 712dacd7d..000000000 --- a/src/compress/bzip2/bzip2.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/************************************************* -* Bzip Compressor Source File * -* (C) 2001 Peter J Jones * -* 2001-2007 Jack Lloyd * -* 2006 Matt Johnston * -*************************************************/ - -#include -#include -#include -#define BZ_NO_STDIO -#include - -namespace Botan { - -namespace { - -/************************************************* -* Allocation Information for Bzip * -*************************************************/ -class Bzip_Alloc_Info - { - public: - std::map current_allocs; - Allocator* alloc; - - Bzip_Alloc_Info() { alloc = Allocator::get(false); } - }; - -/************************************************* -* Allocation Function for Bzip * -*************************************************/ -void* bzip_malloc(void* info_ptr, int n, int size) - { - Bzip_Alloc_Info* info = static_cast(info_ptr); - void* ptr = info->alloc->allocate(n * size); - info->current_allocs[ptr] = n * size; - return ptr; - } - -/************************************************* -* Allocation Function for Bzip * -*************************************************/ -void bzip_free(void* info_ptr, void* ptr) - { - Bzip_Alloc_Info* info = static_cast(info_ptr); - std::map::const_iterator i = info->current_allocs.find(ptr); - if(i == info->current_allocs.end()) - throw Invalid_Argument("bzip_free: Got pointer not allocated by us"); - info->alloc->deallocate(ptr, i->second); - } - -} - -/************************************************* -* Wrapper Type for Bzip2 Stream * -*************************************************/ -class Bzip_Stream - { - public: - bz_stream stream; - - Bzip_Stream() - { - std::memset(&stream, 0, sizeof(bz_stream)); - stream.bzalloc = bzip_malloc; - stream.bzfree = bzip_free; - stream.opaque = new Bzip_Alloc_Info; - } - ~Bzip_Stream() - { - Bzip_Alloc_Info* info = static_cast(stream.opaque); - delete info; - std::memset(&stream, 0, sizeof(bz_stream)); - } - }; - -/************************************************* -* Bzip_Compression Constructor * -*************************************************/ -Bzip_Compression::Bzip_Compression(u32bit l) : - level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE) - { - bz = 0; - } - -/************************************************* -* Start Compressing with Bzip * -*************************************************/ -void Bzip_Compression::start_msg() - { - clear(); - bz = new Bzip_Stream; - if(BZ2_bzCompressInit(&(bz->stream), level, 0, 0) != BZ_OK) - throw Exception("Bzip_Compression: Memory allocation error"); - } - -/************************************************* -* Compress Input with Bzip * -*************************************************/ -void Bzip_Compression::write(const byte input[], u32bit length) - { - bz->stream.next_in = reinterpret_cast(const_cast(input)); - bz->stream.avail_in = length; - - while(bz->stream.avail_in != 0) - { - bz->stream.next_out = reinterpret_cast(buffer.begin()); - bz->stream.avail_out = buffer.size(); - BZ2_bzCompress(&(bz->stream), BZ_RUN); - send(buffer, buffer.size() - bz->stream.avail_out); - } - } - -/************************************************* -* Finish Compressing with Bzip * -*************************************************/ -void Bzip_Compression::end_msg() - { - bz->stream.next_in = 0; - bz->stream.avail_in = 0; - - int rc = BZ_OK; - while(rc != BZ_STREAM_END) - { - bz->stream.next_out = reinterpret_cast(buffer.begin()); - bz->stream.avail_out = buffer.size(); - rc = BZ2_bzCompress(&(bz->stream), BZ_FINISH); - send(buffer, buffer.size() - bz->stream.avail_out); - } - clear(); - } - -/************************************************* -* Flush the Bzip Compressor * -*************************************************/ -void Bzip_Compression::flush() - { - bz->stream.next_in = 0; - bz->stream.avail_in = 0; - - int rc = BZ_OK; - while(rc != BZ_RUN_OK) - { - bz->stream.next_out = reinterpret_cast(buffer.begin()); - bz->stream.avail_out = buffer.size(); - rc = BZ2_bzCompress(&(bz->stream), BZ_FLUSH); - send(buffer, buffer.size() - bz->stream.avail_out); - } - } - -/************************************************* -* Clean up Compression Context * -*************************************************/ -void Bzip_Compression::clear() - { - if(!bz) return; - BZ2_bzCompressEnd(&(bz->stream)); - delete bz; - bz = 0; - } - -/************************************************* -* Bzip_Decompression Constructor * -*************************************************/ -Bzip_Decompression::Bzip_Decompression(bool s) : - small_mem(s), buffer(DEFAULT_BUFFERSIZE) - { - no_writes = true; - bz = 0; - } - -/************************************************* -* Decompress Input with Bzip * -*************************************************/ -void Bzip_Decompression::write(const byte input_arr[], u32bit length) - { - if(length) no_writes = false; - - char* input = reinterpret_cast(const_cast(input_arr)); - - bz->stream.next_in = input; - bz->stream.avail_in = length; - - while(bz->stream.avail_in != 0) - { - bz->stream.next_out = reinterpret_cast(buffer.begin()); - bz->stream.avail_out = buffer.size(); - - int rc = BZ2_bzDecompress(&(bz->stream)); - - if(rc != BZ_OK && rc != BZ_STREAM_END) - { - clear(); - if(rc == BZ_DATA_ERROR) - throw Decoding_Error("Bzip_Decompression: Data integrity error"); - if(rc == BZ_DATA_ERROR_MAGIC) - throw Decoding_Error("Bzip_Decompression: Invalid input"); - if(rc == BZ_MEM_ERROR) - throw Exception("Bzip_Decompression: Memory allocation error"); - throw Exception("Bzip_Decompression: Unknown decompress error"); - } - - send(buffer, buffer.size() - bz->stream.avail_out); - - if(rc == BZ_STREAM_END) - { - u32bit read_from_block = length - bz->stream.avail_in; - start_msg(); - bz->stream.next_in = input + read_from_block; - bz->stream.avail_in = length - read_from_block; - input += read_from_block; - length -= read_from_block; - } - } - } - -/************************************************* -* Start Decompressing with Bzip * -*************************************************/ -void Bzip_Decompression::start_msg() - { - clear(); - bz = new Bzip_Stream; - - if(BZ2_bzDecompressInit(&(bz->stream), 0, small_mem) != BZ_OK) - throw Exception("Bzip_Decompression: Memory allocation error"); - - no_writes = true; - } - -/************************************************* -* Finish Decompressing with Bzip * -*************************************************/ -void Bzip_Decompression::end_msg() - { - if(no_writes) return; - bz->stream.next_in = 0; - bz->stream.avail_in = 0; - - int rc = BZ_OK; - while(rc != BZ_STREAM_END) - { - bz->stream.next_out = reinterpret_cast(buffer.begin()); - bz->stream.avail_out = buffer.size(); - rc = BZ2_bzDecompress(&(bz->stream)); - - if(rc != BZ_OK && rc != BZ_STREAM_END) - { - clear(); - throw Exception("Bzip_Decompression: Error finalizing decompression"); - } - - send(buffer, buffer.size() - bz->stream.avail_out); - } - - clear(); - } - -/************************************************* -* Clean up Decompression Context * -*************************************************/ -void Bzip_Decompression::clear() - { - if(!bz) return; - BZ2_bzDecompressEnd(&(bz->stream)); - delete bz; - bz = 0; - } - -} diff --git a/src/compress/bzip2/bzip2.h b/src/compress/bzip2/bzip2.h deleted file mode 100644 index 1244924ca..000000000 --- a/src/compress/bzip2/bzip2.h +++ /dev/null @@ -1,59 +0,0 @@ -/************************************************* -* Bzip Compressor Header File * -* (C) 2001 Peter J Jones * -* 2001-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_BZIP2_H__ -#define BOTAN_BZIP2_H__ - -#include - -namespace Botan { - -/************************************************* -* Bzip Compression Filter * -*************************************************/ -class Bzip_Compression : public Filter - { - public: - void write(const byte input[], u32bit length); - void start_msg(); - void end_msg(); - - void flush(); - - Bzip_Compression(u32bit = 9); - ~Bzip_Compression() { clear(); } - private: - void clear(); - - const u32bit level; - SecureVector buffer; - class Bzip_Stream* bz; - }; - -/************************************************* -* Bzip Decompression Filter * -*************************************************/ -class Bzip_Decompression : public Filter - { - public: - void write(const byte input[], u32bit length); - void start_msg(); - void end_msg(); - - Bzip_Decompression(bool = false); - ~Bzip_Decompression() { clear(); } - private: - void clear(); - - const bool small_mem; - SecureVector buffer; - class Bzip_Stream* bz; - bool no_writes; - }; - -} - -#endif diff --git a/src/compress/bzip2/modinfo.txt b/src/compress/bzip2/modinfo.txt deleted file mode 100644 index efedc097f..000000000 --- a/src/compress/bzip2/modinfo.txt +++ /dev/null @@ -1,17 +0,0 @@ -# This module was written by Peter J. Jones - -realname "Bzip2 Compressor" - -define COMPRESSOR_BZIP2 -modset compression - -load_on request - - -bzip2.h -bzip2.cpp - - - -all -> bz2 - diff --git a/src/compress/zlib/modinfo.txt b/src/compress/zlib/modinfo.txt deleted file mode 100644 index c1f1f998c..000000000 --- a/src/compress/zlib/modinfo.txt +++ /dev/null @@ -1,19 +0,0 @@ -realname "Zlib Compressor" -#realname "Zlib/Gzip Compressor" - -define COMPRESSOR_ZLIB -#define COMPRESSOR_ZLIB,COMPRESSOR_GZIP - -load_on request -modset compression - - -zlib.h -zlib.cpp -#gzip.h -#gzip.cpp - - - -all -> z - diff --git a/src/compress/zlib/zlib.cpp b/src/compress/zlib/zlib.cpp deleted file mode 100644 index 36a9640e3..000000000 --- a/src/compress/zlib/zlib.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/************************************************* -* Zlib Compressor Source File * -* (C) 2001 Peter J Jones * -* 2001-2007 Jack Lloyd * -* 2006 Matt Johnston * -*************************************************/ - -#include -#include -#include -#include - -namespace Botan { - -namespace { - -/************************************************* -* Allocation Information for Zlib * -*************************************************/ -class Zlib_Alloc_Info - { - public: - std::map current_allocs; - Allocator* alloc; - - Zlib_Alloc_Info() { alloc = Allocator::get(false); } - }; - -/************************************************* -* Allocation Function for Zlib * -*************************************************/ -void* zlib_malloc(void* info_ptr, unsigned int n, unsigned int size) - { - Zlib_Alloc_Info* info = static_cast(info_ptr); - void* ptr = info->alloc->allocate(n * size); - info->current_allocs[ptr] = n * size; - return ptr; - } - -/************************************************* -* Allocation Function for Zlib * -*************************************************/ -void zlib_free(void* info_ptr, void* ptr) - { - Zlib_Alloc_Info* info = static_cast(info_ptr); - std::map::const_iterator i = info->current_allocs.find(ptr); - if(i == info->current_allocs.end()) - throw Invalid_Argument("zlib_free: Got pointer not allocated by us"); - info->alloc->deallocate(ptr, i->second); - } - -} - -/************************************************* -* Wrapper Type for Zlib z_stream * -*************************************************/ -class Zlib_Stream - { - public: - z_stream stream; - - Zlib_Stream() - { - std::memset(&stream, 0, sizeof(z_stream)); - stream.zalloc = zlib_malloc; - stream.zfree = zlib_free; - stream.opaque = new Zlib_Alloc_Info; - } - ~Zlib_Stream() - { - Zlib_Alloc_Info* info = static_cast(stream.opaque); - delete info; - std::memset(&stream, 0, sizeof(z_stream)); - } - }; - -/************************************************* -* Zlib_Compression Constructor * -*************************************************/ -Zlib_Compression::Zlib_Compression(u32bit l) : - level((l >= 9) ? 9 : l), buffer(DEFAULT_BUFFERSIZE) - { - zlib = 0; - } - -/************************************************* -* Start Compressing with Zlib * -*************************************************/ -void Zlib_Compression::start_msg() - { - clear(); - zlib = new Zlib_Stream; - if(deflateInit(&(zlib->stream), level) != Z_OK) - throw Exception("Zlib_Compression: Memory allocation error"); - } - -/************************************************* -* Compress Input with Zlib * -*************************************************/ -void Zlib_Compression::write(const byte input[], u32bit length) - { - zlib->stream.next_in = static_cast(const_cast(input)); - zlib->stream.avail_in = length; - - while(zlib->stream.avail_in != 0) - { - zlib->stream.next_out = static_cast(buffer.begin()); - zlib->stream.avail_out = buffer.size(); - deflate(&(zlib->stream), Z_NO_FLUSH); - send(buffer.begin(), buffer.size() - zlib->stream.avail_out); - } - } - -/************************************************* -* Finish Compressing with Zlib * -*************************************************/ -void Zlib_Compression::end_msg() - { - zlib->stream.next_in = 0; - zlib->stream.avail_in = 0; - - int rc = Z_OK; - while(rc != Z_STREAM_END) - { - zlib->stream.next_out = reinterpret_cast(buffer.begin()); - zlib->stream.avail_out = buffer.size(); - rc = deflate(&(zlib->stream), Z_FINISH); - send(buffer.begin(), buffer.size() - zlib->stream.avail_out); - } - clear(); - } - -/************************************************* -* Flush the Zlib Compressor * -*************************************************/ -void Zlib_Compression::flush() - { - zlib->stream.next_in = 0; - zlib->stream.avail_in = 0; - - while(true) - { - zlib->stream.avail_out = buffer.size(); - - zlib->stream.next_out = reinterpret_cast(buffer.begin()); - - - deflate(&(zlib->stream), Z_FULL_FLUSH); - send(buffer.begin(), buffer.size() - zlib->stream.avail_out); - if(zlib->stream.avail_out == buffer.size()) break; - } - } - -/************************************************* -* Clean up Compression Context * -*************************************************/ -void Zlib_Compression::clear() - { - if(zlib) - { - deflateEnd(&(zlib->stream)); - delete zlib; - zlib = 0; - } - - buffer.clear(); - } - -/************************************************* -* Zlib_Decompression Constructor * -*************************************************/ -Zlib_Decompression::Zlib_Decompression() : buffer(DEFAULT_BUFFERSIZE) - { - zlib = 0; - no_writes = true; - } - -/************************************************* -* Start Decompressing with Zlib * -*************************************************/ -void Zlib_Decompression::start_msg() - { - clear(); - zlib = new Zlib_Stream; - if(inflateInit(&(zlib->stream)) != Z_OK) - throw Exception("Zlib_Decompression: Memory allocation error"); - } - -/************************************************* -* Decompress Input with Zlib * -*************************************************/ -void Zlib_Decompression::write(const byte input_arr[], u32bit length) - { - if(length) no_writes = false; - - // non-const needed by zlib api :( - Bytef* input = reinterpret_cast(const_cast(input_arr)); - - zlib->stream.next_in = input; - zlib->stream.avail_in = length; - - while(zlib->stream.avail_in != 0) - { - zlib->stream.next_out = reinterpret_cast(buffer.begin()); - zlib->stream.avail_out = buffer.size(); - - int rc = inflate(&(zlib->stream), Z_SYNC_FLUSH); - - if(rc != Z_OK && rc != Z_STREAM_END) - { - clear(); - if(rc == Z_DATA_ERROR) - throw Decoding_Error("Zlib_Decompression: Data integrity error"); - if(rc == Z_NEED_DICT) - throw Decoding_Error("Zlib_Decompression: Need preset dictionary"); - if(rc == Z_MEM_ERROR) - throw Exception("Zlib_Decompression: Memory allocation error"); - throw Exception("Zlib_Decompression: Unknown decompress error"); - } - - send(buffer.begin(), buffer.size() - zlib->stream.avail_out); - - if(rc == Z_STREAM_END) - { - u32bit read_from_block = length - zlib->stream.avail_in; - start_msg(); - - zlib->stream.next_in = input + read_from_block; - zlib->stream.avail_in = length - read_from_block; - - input += read_from_block; - length -= read_from_block; - } - } - } - -/************************************************* -* Finish Decompressing with Zlib * -*************************************************/ -void Zlib_Decompression::end_msg() - { - if(no_writes) return; - zlib->stream.next_in = 0; - zlib->stream.avail_in = 0; - - int rc = Z_OK; - - while(rc != Z_STREAM_END) - { - zlib->stream.next_out = reinterpret_cast(buffer.begin()); - zlib->stream.avail_out = buffer.size(); - rc = inflate(&(zlib->stream), Z_SYNC_FLUSH); - - if(rc != Z_OK && rc != Z_STREAM_END) - { - clear(); - throw Exception("Zlib_Decompression: Error finalizing decompression"); - } - - send(buffer.begin(), buffer.size() - zlib->stream.avail_out); - } - - clear(); - } - -/************************************************* -* Clean up Decompression Context * -*************************************************/ -void Zlib_Decompression::clear() - { - no_writes = true; - - if(zlib) - { - inflateEnd(&(zlib->stream)); - delete zlib; - zlib = 0; - } - - buffer.clear(); - } - -} diff --git a/src/compress/zlib/zlib.h b/src/compress/zlib/zlib.h deleted file mode 100644 index c3baea4ee..000000000 --- a/src/compress/zlib/zlib.h +++ /dev/null @@ -1,56 +0,0 @@ -/************************************************* -* Zlib Compressor Header File * -* (C) 2001 Peter J Jones * -* 2001-2007 Jack Lloyd * -*************************************************/ - -#ifndef BOTAN_ZLIB_H__ -#define BOTAN_ZLIB_H__ - -#include - -namespace Botan { - -/************************************************* -* Zlib Compression Filter * -*************************************************/ -class Zlib_Compression : public Filter - { - public: - void write(const byte input[], u32bit length); - void start_msg(); - void end_msg(); - - void flush(); - - Zlib_Compression(u32bit = 6); - ~Zlib_Compression() { clear(); } - private: - void clear(); - const u32bit level; - SecureVector buffer; - class Zlib_Stream* zlib; - }; - -/************************************************* -* Zlib Decompression Filter * -*************************************************/ -class Zlib_Decompression : public Filter - { - public: - void write(const byte input[], u32bit length); - void start_msg(); - void end_msg(); - - Zlib_Decompression(); - ~Zlib_Decompression() { clear(); } - private: - void clear(); - SecureVector buffer; - class Zlib_Stream* zlib; - bool no_writes; - }; - -} - -#endif diff --git a/src/der_enc.cpp b/src/der_enc.cpp deleted file mode 100644 index 1ab5ddd4e..000000000 --- a/src/der_enc.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/************************************************* -* DER Encoder Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -namespace Botan { - -namespace { - -/************************************************* -* DER encode an ASN.1 type tag * -*************************************************/ -SecureVector encode_tag(ASN1_Tag type_tag, ASN1_Tag class_tag) - { - if((class_tag | 0xE0) != 0xE0) - throw Encoding_Error("DER_Encoder: Invalid class tag " + - to_string(class_tag)); - - SecureVector encoded_tag; - if(type_tag <= 30) - encoded_tag.append(static_cast(type_tag | class_tag)); - else - { - u32bit blocks = high_bit(type_tag) + 6; - blocks = (blocks - (blocks % 7)) / 7; - - encoded_tag.append(class_tag | 0x1F); - for(u32bit k = 0; k != blocks - 1; ++k) - encoded_tag.append(0x80 | ((type_tag >> 7*(blocks-k-1)) & 0x7F)); - encoded_tag.append(type_tag & 0x7F); - } - - return encoded_tag; - } - -/************************************************* -* DER encode an ASN.1 length field * -*************************************************/ -SecureVector encode_length(u32bit length) - { - SecureVector encoded_length; - if(length <= 127) - encoded_length.append(static_cast(length)); - else - { - const u32bit top_byte = significant_bytes(length); - encoded_length.append(static_cast(0x80 | top_byte)); - for(u32bit j = 4-top_byte; j != 4; ++j) - encoded_length.append(get_byte(j, length)); - } - return encoded_length; - } - -} - -/************************************************* -* Return the encoded SEQUENCE/SET * -*************************************************/ -SecureVector DER_Encoder::DER_Sequence::get_contents() - { - const ASN1_Tag real_class_tag = ASN1_Tag(class_tag | CONSTRUCTED); - - SecureVector encoded_tag = encode_tag(type_tag, real_class_tag); - - if(type_tag == SET) - { - std::sort(set_contents.begin(), set_contents.end()); - for(u32bit j = 0; j != set_contents.size(); ++j) - contents.append(set_contents[j]); - set_contents.clear(); - } - - SecureVector encoded_length = encode_length(contents.size()); - - SecureVector retval; - retval.append(encoded_tag); - retval.append(encoded_length); - retval.append(contents); - contents.destroy(); - return retval; - } - -/************************************************* -* Add an encoded value to the SEQUENCE/SET * -*************************************************/ -void DER_Encoder::DER_Sequence::add_bytes(const byte data[], u32bit length) - { - if(type_tag == SET) - set_contents.push_back(SecureVector(data, length)); - else - contents.append(data, length); - } - -/************************************************* -* Return the type and class taggings * -*************************************************/ -ASN1_Tag DER_Encoder::DER_Sequence::tag_of() const - { - return ASN1_Tag(type_tag | class_tag); - } - -/************************************************* -* DER_Sequence Constructor * -*************************************************/ -DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Tag t1, ASN1_Tag t2) : - type_tag(t1), class_tag(t2) - { - } - -/************************************************* -* Return the encoded contents * -*************************************************/ -SecureVector DER_Encoder::get_contents() - { - if(subsequences.size() != 0) - throw Invalid_State("DER_Encoder: Sequence hasn't been marked done"); - - SecureVector retval; - retval = contents; - contents.destroy(); - return retval; - } - -/************************************************* -* Start a new ASN.1 SEQUENCE/SET/EXPLICIT * -*************************************************/ -DER_Encoder& DER_Encoder::start_cons(ASN1_Tag type_tag, - ASN1_Tag class_tag) - { - subsequences.push_back(DER_Sequence(type_tag, class_tag)); - return (*this); - } - -/************************************************* -* Finish the current ASN.1 SEQUENCE/SET/EXPLICIT * -*************************************************/ -DER_Encoder& DER_Encoder::end_cons() - { - if(subsequences.empty()) - throw Invalid_State("DER_Encoder::end_cons: No such sequence"); - - SecureVector seq = subsequences[subsequences.size()-1].get_contents(); - subsequences.pop_back(); - raw_bytes(seq); - return (*this); - } - -/************************************************* -* Start a new ASN.1 EXPLICIT encoding * -*************************************************/ -DER_Encoder& DER_Encoder::start_explicit(u16bit type_no) - { - ASN1_Tag type_tag = static_cast(type_no); - - if(type_tag == SET) - throw Internal_Error("DER_Encoder.start_explicit(SET); cannot perform"); - - return start_cons(type_tag, CONTEXT_SPECIFIC); - } - -/************************************************* -* Finish the current ASN.1 EXPLICIT encoding * -*************************************************/ -DER_Encoder& DER_Encoder::end_explicit() - { - return end_cons(); - } - -/************************************************* -* Write raw bytes into the stream * -*************************************************/ -DER_Encoder& DER_Encoder::raw_bytes(const MemoryRegion& val) - { - return raw_bytes(val.begin(), val.size()); - } - -/************************************************* -* Write raw bytes into the stream * -*************************************************/ -DER_Encoder& DER_Encoder::raw_bytes(const byte bytes[], u32bit length) - { - if(subsequences.size()) - subsequences[subsequences.size()-1].add_bytes(bytes, length); - else - contents.append(bytes, length); - - return (*this); - } - -/************************************************* -* Encode a NULL object * -*************************************************/ -DER_Encoder& DER_Encoder::encode_null() - { - return add_object(NULL_TAG, UNIVERSAL, 0, 0); - } - -/************************************************* -* DER encode a BOOLEAN * -*************************************************/ -DER_Encoder& DER_Encoder::encode(bool is_true) - { - return encode(is_true, BOOLEAN, UNIVERSAL); - } - -/************************************************* -* DER encode a small INTEGER * -*************************************************/ -DER_Encoder& DER_Encoder::encode(u32bit n) - { - return encode(BigInt(n), INTEGER, UNIVERSAL); - } - -/************************************************* -* DER encode a small INTEGER * -*************************************************/ -DER_Encoder& DER_Encoder::encode(const BigInt& n) - { - return encode(n, INTEGER, UNIVERSAL); - } - -/************************************************* -* DER encode an OCTET STRING or BIT STRING * -*************************************************/ -DER_Encoder& DER_Encoder::encode(const MemoryRegion& bytes, - ASN1_Tag real_type) - { - return encode(bytes.begin(), bytes.size(), - real_type, real_type, UNIVERSAL); - } - -/************************************************* -* Encode this object * -*************************************************/ -DER_Encoder& DER_Encoder::encode(const byte bytes[], u32bit length, - ASN1_Tag real_type) - { - return encode(bytes, length, real_type, real_type, UNIVERSAL); - } - -/************************************************* -* DER encode a BOOLEAN * -*************************************************/ -DER_Encoder& DER_Encoder::encode(bool is_true, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - byte val = is_true ? 0xFF : 0x00; - return add_object(type_tag, class_tag, &val, 1); - } - -/************************************************* -* DER encode a small INTEGER * -*************************************************/ -DER_Encoder& DER_Encoder::encode(u32bit n, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - return encode(BigInt(n), type_tag, class_tag); - } - -/************************************************* -* DER encode an INTEGER * -*************************************************/ -DER_Encoder& DER_Encoder::encode(const BigInt& n, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - if(n == 0) - return add_object(type_tag, class_tag, 0); - - bool extra_zero = (n.bits() % 8 == 0); - SecureVector contents(extra_zero + n.bytes()); - BigInt::encode(contents.begin() + extra_zero, n); - if(n < 0) - { - for(u32bit j = 0; j != contents.size(); ++j) - contents[j] = ~contents[j]; - for(u32bit j = contents.size(); j > 0; --j) - if(++contents[j-1]) - break; - } - - return add_object(type_tag, class_tag, contents); - } - -/************************************************* -* DER encode an OCTET STRING or BIT STRING * -*************************************************/ -DER_Encoder& DER_Encoder::encode(const MemoryRegion& bytes, - ASN1_Tag real_type, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - return encode(bytes.begin(), bytes.size(), - real_type, type_tag, class_tag); - } - -/************************************************* -* DER encode an OCTET STRING or BIT STRING * -*************************************************/ -DER_Encoder& DER_Encoder::encode(const byte bytes[], u32bit length, - ASN1_Tag real_type, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - if(real_type != OCTET_STRING && real_type != BIT_STRING) - throw Invalid_Argument("DER_Encoder: Invalid tag for byte/bit string"); - - if(real_type == BIT_STRING) - { - SecureVector encoded; - encoded.append(0); - encoded.append(bytes, length); - return add_object(type_tag, class_tag, encoded); - } - else - return add_object(type_tag, class_tag, bytes, length); - } - -/************************************************* -* Conditionally write some values to the stream * -*************************************************/ -DER_Encoder& DER_Encoder::encode_if(bool cond, DER_Encoder& codec) - { - if(cond) - return raw_bytes(codec.get_contents()); - return (*this); - } - -/************************************************* -* Request for an object to encode itself * -*************************************************/ -DER_Encoder& DER_Encoder::encode(const ASN1_Object& obj) - { - obj.encode_into(*this); - return (*this); - } - -/************************************************* -* Write the encoding of the byte(s) * -*************************************************/ -DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, - const byte rep[], u32bit length) - { - SecureVector encoded_tag = encode_tag(type_tag, class_tag); - SecureVector encoded_length = encode_length(length); - - SecureVector buffer; - buffer.append(encoded_tag); - buffer.append(encoded_length); - buffer.append(rep, length); - - return raw_bytes(buffer); - } - -/************************************************* -* Write the encoding of the byte(s) * -*************************************************/ -DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, - const MemoryRegion& rep_buf) - { - const byte* rep = rep_buf.begin(); - const u32bit rep_len = rep_buf.size(); - return add_object(type_tag, class_tag, rep, rep_len); - } - -/************************************************* -* Write the encoding of the byte(s) * -*************************************************/ -DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, - const std::string& rep_str) - { - const byte* rep = reinterpret_cast(rep_str.data()); - const u32bit rep_len = rep_str.size(); - return add_object(type_tag, class_tag, rep, rep_len); - } - -/************************************************* -* Write the encoding of the byte * -*************************************************/ -DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, - ASN1_Tag class_tag, byte rep) - { - return add_object(type_tag, class_tag, &rep, 1); - } - -} diff --git a/src/hex.cpp b/src/hex.cpp deleted file mode 100644 index afb082f76..000000000 --- a/src/hex.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/************************************************* -* Hex Encoder/Decoder Source File * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include -#include -#include -#include - -namespace Botan { - -/************************************************* -* Hex_Encoder Constructor * -*************************************************/ -Hex_Encoder::Hex_Encoder(bool breaks, u32bit length, Case c) : - casing(c), line_length(breaks ? length : 0) - { - in.create(64); - out.create(2*in.size()); - counter = position = 0; - } - -/************************************************* -* Hex_Encoder Constructor * -*************************************************/ -Hex_Encoder::Hex_Encoder(Case c) : casing(c), line_length(0) - { - in.create(64); - out.create(2*in.size()); - counter = position = 0; - } - -/************************************************* -* Hex Encoding Operation * -*************************************************/ -void Hex_Encoder::encode(byte in, byte out[2], Hex_Encoder::Case casing) - { - const byte* BIN_TO_HEX = ((casing == Uppercase) ? BIN_TO_HEX_UPPER : - BIN_TO_HEX_LOWER); - - out[0] = BIN_TO_HEX[((in >> 4) & 0x0F)]; - out[1] = BIN_TO_HEX[((in ) & 0x0F)]; - } - -/************************************************* -* Encode and send a block * -*************************************************/ -void Hex_Encoder::encode_and_send(const byte block[], u32bit length) - { - for(u32bit j = 0; j != length; ++j) - encode(block[j], out + 2*j, casing); - - if(line_length == 0) - send(out, 2*length); - else - { - u32bit remaining = 2*length, offset = 0; - while(remaining) - { - u32bit sent = std::min(line_length - counter, remaining); - send(out + offset, sent); - counter += sent; - remaining -= sent; - offset += sent; - if(counter == line_length) - { - send('\n'); - counter = 0; - } - } - } - } - -/************************************************* -* Convert some data into hex format * -*************************************************/ -void Hex_Encoder::write(const byte input[], u32bit length) - { - in.copy(position, input, length); - if(position + length >= in.size()) - { - encode_and_send(in, in.size()); - input += (in.size() - position); - length -= (in.size() - position); - while(length >= in.size()) - { - encode_and_send(input, in.size()); - input += in.size(); - length -= in.size(); - } - in.copy(input, length); - position = 0; - } - position += length; - } - -/************************************************* -* Flush buffers * -*************************************************/ -void Hex_Encoder::end_msg() - { - encode_and_send(in, position); - if(counter && line_length) - send('\n'); - counter = position = 0; - } - -/************************************************* -* Hex_Decoder Constructor * -*************************************************/ -Hex_Decoder::Hex_Decoder(Decoder_Checking c) : checking(c) - { - in.create(64); - out.create(in.size() / 2); - position = 0; - } - -/************************************************* -* Check if a character is a valid hex char * -*************************************************/ -bool Hex_Decoder::is_valid(byte in) - { - return (HEX_TO_BIN[in] != 0x80); - } - -/************************************************* -* Handle processing an invalid character * -*************************************************/ -void Hex_Decoder::handle_bad_char(byte c) - { - if(checking == NONE) - return; - - if((checking == IGNORE_WS) && Charset::is_space(c)) - return; - - throw Decoding_Error("Hex_Decoder: Invalid hex character: " + - to_string(c)); - } - -/************************************************* -* Hex Decoding Operation * -*************************************************/ -byte Hex_Decoder::decode(const byte hex[2]) - { - return ((HEX_TO_BIN[hex[0]] << 4) | HEX_TO_BIN[hex[1]]); - } - -/************************************************* -* Decode and send a block * -*************************************************/ -void Hex_Decoder::decode_and_send(const byte block[], u32bit length) - { - for(u32bit j = 0; j != length / 2; ++j) - out[j] = decode(block + 2*j); - send(out, length / 2); - } - -/************************************************* -* Convert some data from hex format * -*************************************************/ -void Hex_Decoder::write(const byte input[], u32bit length) - { - for(u32bit j = 0; j != length; ++j) - { - if(is_valid(input[j])) - in[position++] = input[j]; - else - handle_bad_char(input[j]); - if(position == in.size()) - { - decode_and_send(in, in.size()); - position = 0; - } - } - } - -/************************************************* -* Flush buffers * -*************************************************/ -void Hex_Decoder::end_msg() - { - decode_and_send(in, position); - position = 0; - } - -} diff --git a/src/pk/dl_algo/modinfo.txt b/src/pk/dl_algo/modinfo.txt new file mode 100644 index 000000000..755ab8682 --- /dev/null +++ b/src/pk/dl_algo/modinfo.txt @@ -0,0 +1,15 @@ +realname "Discrete Logarithm PK Algorithms" + +define DL_PUBLIC_KEY_FAMILY + +load_on auto + + +dl_algo.cpp +dl_algo.h + + + +asn1 +dl_group + diff --git a/src/pk/dl_group/modinfo.txt b/src/pk/dl_group/modinfo.txt new file mode 100644 index 000000000..4d2d6f13c --- /dev/null +++ b/src/pk/dl_group/modinfo.txt @@ -0,0 +1,10 @@ +realname "DL Group" + +load_on auto + +define DL_GROUP + + +dl_group.cpp +dl_group.h + diff --git a/src/pk/dlies/modinfo.txt b/src/pk/dlies/modinfo.txt index 995dbe8a2..163914714 100644 --- a/src/pk/dlies/modinfo.txt +++ b/src/pk/dlies/modinfo.txt @@ -8,3 +8,7 @@ load_on auto dlies.cpp dlies.h + + +asn1 + -- cgit v1.2.3