diff options
43 files changed, 1250 insertions, 1163 deletions
diff --git a/include/asn1_int.h b/include/asn1_int.h index 40ddbb444..85f763f26 100644 --- a/include/asn1_int.h +++ b/include/asn1_int.h @@ -6,8 +6,9 @@ #ifndef BOTAN_ASN1_H__ #define BOTAN_ASN1_H__ -#include <botan/bigint.h> +#include <botan/secmem.h> #include <botan/enums.h> +#include <botan/exceptn.h> namespace Botan { @@ -18,10 +19,23 @@ class 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 BER_Object + { + public: + void assert_is_a(ASN1_Tag, ASN1_Tag); + + ASN1_Tag type_tag, class_tag; + SecureVector<byte> value; + }; + +/************************************************* * ASN.1 Utility Functions * *************************************************/ class DataSource; @@ -29,6 +43,7 @@ class DataSource; namespace ASN1 { SecureVector<byte> put_in_sequence(const MemoryRegion<byte>&); +std::string to_string(const BER_Object&); bool maybe_BER(DataSource&); } diff --git a/include/asn1_obj.h b/include/asn1_obj.h index c36c2ac14..2ead6b54c 100644 --- a/include/asn1_obj.h +++ b/include/asn1_obj.h @@ -7,10 +7,9 @@ #define BOTAN_ASN1_OBJ_H__ #include <botan/asn1_int.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> -#include <map> +#include <botan/asn1_oid.h> #include <vector> +#include <map> namespace Botan { @@ -20,12 +19,13 @@ namespace Botan { class AlgorithmIdentifier : public ASN1_Object { public: - void encode_into(DER_Encoder&) const; + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); AlgorithmIdentifier() {} AlgorithmIdentifier(const OID&, const MemoryRegion<byte>&); AlgorithmIdentifier(const std::string&, const MemoryRegion<byte>&); - public: + OID oid; SecureVector<byte> parameters; }; @@ -36,12 +36,13 @@ class AlgorithmIdentifier : public ASN1_Object class Extension : public ASN1_Object { public: + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + bool critical; OID oid; SecureVector<byte> value; - void encode_into(DER_Encoder&) const; - Extension() { critical = false; } Extension(const OID&, const MemoryRegion<byte>&); Extension(const std::string&, const MemoryRegion<byte>&); @@ -53,7 +54,8 @@ class Extension : public ASN1_Object class Attribute : public ASN1_Object { public: - void encode_into(DER_Encoder&) const; + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); OID oid; SecureVector<byte> parameters; @@ -69,7 +71,8 @@ class Attribute : public ASN1_Object class X509_Time : public ASN1_Object { public: - void encode_into(DER_Encoder&) const; + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); std::string as_string() const; std::string readable_string() const; @@ -92,7 +95,8 @@ class X509_Time : public ASN1_Object class ASN1_String : public ASN1_Object { public: - void encode_into(DER_Encoder&) const; + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); std::string value() const; std::string iso_8859() const; @@ -112,11 +116,14 @@ class ASN1_String : public ASN1_Object class X509_DN : public ASN1_Object { public: - void encode_into(DER_Encoder&) const; + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); std::multimap<OID, std::string> get_attributes() const; std::vector<std::string> get_attribute(const std::string&) const; + std::multimap<std::string, std::string> contents() const; + void add_attribute(const std::string&, const std::string&); void add_attribute(const OID&, const std::string&); @@ -139,7 +146,10 @@ class X509_DN : public ASN1_Object class AlternativeName : public ASN1_Object { public: - void encode_into(DER_Encoder&) const; + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + + std::multimap<std::string, std::string> contents() const; void add_attribute(const std::string&, const std::string&); std::multimap<std::string, std::string> get_attributes() const; @@ -171,38 +181,12 @@ bool operator==(const X509_DN&, const X509_DN&); bool operator!=(const X509_DN&, const X509_DN&); bool operator<(const X509_DN&, const X509_DN&); -s32bit validity_check(const X509_Time&, const X509_Time&, u64bit); - -bool is_string_type(ASN1_Tag); - -/************************************************* -* DER Encoding Functions * -*************************************************/ -namespace DER { - -//void encode(DER_Encoder&, const Attribute&); -//void encode(DER_Encoder&, const ASN1_String&); -void encode(DER_Encoder&, const ASN1_String&, - ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - -} - /************************************************* -* BER Decoding Functions * +* Helper Functions * *************************************************/ -namespace BER { - -void decode(BER_Decoder&, AlgorithmIdentifier&); -void decode(BER_Decoder&, Extension&); -void decode(BER_Decoder&, Attribute&); -void decode(BER_Decoder&, X509_Time&); -void decode(BER_Decoder&, ASN1_String&); -void decode(BER_Decoder&, ASN1_String&, ASN1_Tag, ASN1_Tag); -void decode(BER_Decoder&, X509_DN&); -void decode(BER_Decoder&, AlternativeName&); -void decode(BER_Decoder&, Key_Constraints&); +s32bit validity_check(const X509_Time&, const X509_Time&, u64bit); -} +bool is_string_type(ASN1_Tag); } diff --git a/include/asn1_oid.h b/include/asn1_oid.h index b2bdd4867..94794607a 100644 --- a/include/asn1_oid.h +++ b/include/asn1_oid.h @@ -19,6 +19,7 @@ class 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<u32bit> get_id() const { return id; } diff --git a/include/ber_dec.h b/include/ber_dec.h index 32feb43e1..f1147e052 100644 --- a/include/ber_dec.h +++ b/include/ber_dec.h @@ -7,33 +7,28 @@ #define BOTAN_BER_DECODER_H__ #include <botan/asn1_oid.h> -#include <botan/bigint.h> #include <botan/data_src.h> namespace Botan { /************************************************* -* BER Encoded Object * -*************************************************/ -struct BER_Object - { - ASN1_Tag type_tag, class_tag; - SecureVector<byte> value; - }; - -/************************************************* * BER Decoding Object * *************************************************/ class BER_Decoder { public: - bool more_items() const; - void verify_end() const; - SecureVector<byte> get_remaining(); - void discard_remaining(); 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); + BER_Decoder& end_cons(); + + BER_Decoder& raw_bytes(MemoryRegion<byte>&); + BER_Decoder& decode_null(); BER_Decoder& decode(bool&); BER_Decoder& decode(u32bit&); @@ -47,6 +42,17 @@ class BER_Decoder BER_Decoder& decode(MemoryRegion<byte>&, ASN1_Tag, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + BER_Decoder& decode(class ASN1_Object&); + + template<typename T> + BER_Decoder& decode_optional(T&, ASN1_Tag, ASN1_Tag, const T& = T()); + + template<typename T> + BER_Decoder& decode_list(std::vector<T>&, bool = true); + + BER_Decoder& decode_optional_string(MemoryRegion<byte>&, + ASN1_Tag, u16bit); + BER_Decoder(DataSource&); BER_Decoder(const byte[], u32bit); BER_Decoder(const MemoryRegion<byte>&); @@ -54,64 +60,68 @@ class BER_Decoder ~BER_Decoder(); private: BER_Decoder& operator=(const BER_Decoder&) { return (*this); } + + BER_Decoder* parent; DataSource* source; BER_Object pushed; mutable bool owns; }; /************************************************* -* BER Decoding Functions * -*************************************************/ -namespace BER { - -void decode(BER_Decoder&, OID&); - -BER_Decoder get_subsequence(BER_Decoder&); -BER_Decoder get_subset(BER_Decoder&); - -BER_Decoder get_subsequence(BER_Decoder&, ASN1_Tag, - ASN1_Tag = CONTEXT_SPECIFIC); -BER_Decoder get_subset(BER_Decoder&, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - -std::string to_string(const BER_Object&); -bool decode_optional_string(BER_Decoder&, MemoryRegion<byte>&, - ASN1_Tag, ASN1_Tag, ASN1_Tag); - -/************************************************* * Decode an OPTIONAL or DEFAULT element * *************************************************/ -template<class T> -bool decode_optional(BER_Decoder& in, T& out, - ASN1_Tag type_tag, ASN1_Tag class_tag, - const T& default_value = T()) +template<typename T> +BER_Decoder& BER_Decoder::decode_optional(T& out, + ASN1_Tag type_tag, + ASN1_Tag class_tag, + const T& default_value) { - BER_Object obj = in.get_next_object(); + BER_Object obj = get_next_object(); if(obj.type_tag == type_tag && obj.class_tag == class_tag) { if(class_tag & CONSTRUCTED) - { - BER_Decoder stored_value(obj.value); - //BER::decode(stored_value, out); - stored_value.decode(out); - stored_value.verify_end(); - } + BER_Decoder(obj.value).decode(out).verify_end(); else { - in.push_back(obj); - //BER::decode(in, out, type_tag, class_tag); - in.decode(out, type_tag, class_tag); + push_back(obj); + decode(out, type_tag, class_tag); } - return true; } else { out = default_value; - in.push_back(obj); - return false; + push_back(obj); + } + + return (*this); + } + +/************************************************* +* Decode a list of homogenously typed values * +*************************************************/ +template<typename T> +BER_Decoder& BER_Decoder::decode_list(std::vector<T>& 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 decode(BER_Decoder&, Key_Constraints&); + } } diff --git a/include/crl_ent.h b/include/crl_ent.h index 660148211..510c4f5a8 100644 --- a/include/crl_ent.h +++ b/include/crl_ent.h @@ -13,9 +13,12 @@ namespace Botan { /************************************************* * CRL Entry * *************************************************/ -class CRL_Entry +class CRL_Entry : public ASN1_Object { public: + void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + MemoryVector<byte> serial; X509_Time time; CRL_Code reason; @@ -30,24 +33,6 @@ bool operator==(const CRL_Entry&, const CRL_Entry&); bool operator!=(const CRL_Entry&, const CRL_Entry&); bool operator<(const CRL_Entry&, const CRL_Entry&); -/************************************************* -* DER Encoding Functions * -*************************************************/ -namespace DER { - -void encode(DER_Encoder&, const CRL_Entry&); - -} - -/************************************************* -* BER Decoding Functions * -*************************************************/ -namespace BER { - -void decode(BER_Decoder&, CRL_Entry&); - -} - } #endif diff --git a/include/datastor.h b/include/datastor.h index 86a607feb..365c0d32b 100644 --- a/include/datastor.h +++ b/include/datastor.h @@ -34,7 +34,9 @@ class Data_Store bool operator==(const Data_Store&) const; - std::multimap<std::string, std::string> get(const Matcher&) const; + std::multimap<std::string, std::string> + search_with(const Matcher&) const; + std::vector<std::string> get(const std::string&) const; std::string get1(const std::string&) const; @@ -42,6 +44,8 @@ class Data_Store MemoryVector<byte> get1_memvec(const std::string&) const; u32bit get1_u32bit(const std::string&, u32bit = 0) const; + bool has_value(const std::string&) const; + void add(const std::multimap<std::string, std::string>&); void add(const std::string&, const std::string&); void add(const std::string&, u32bit); diff --git a/include/der_enc.h b/include/der_enc.h index b07c76172..d0e655ad7 100644 --- a/include/der_enc.h +++ b/include/der_enc.h @@ -6,7 +6,8 @@ #ifndef BOTAN_DER_ENCODER_H__ #define BOTAN_DER_ENCODER_H__ -#include <botan/asn1_oid.h> +#include <botan/secmem.h> +#include <botan/enums.h> #include <vector> namespace Botan { @@ -19,21 +20,14 @@ class DER_Encoder public: SecureVector<byte> get_contents(); - DER_Encoder& start_sequence(ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - DER_Encoder& end_sequence(ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - DER_Encoder& start_set(ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - DER_Encoder& end_set(ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + DER_Encoder& start_cons(ASN1_Tag, ASN1_Tag = UNIVERSAL); + DER_Encoder& end_cons(); - DER_Encoder& start_sequence(); - DER_Encoder& end_sequence(); - DER_Encoder& start_set(); - DER_Encoder& end_set(); + DER_Encoder& start_explicit(u16bit); + DER_Encoder& end_explicit(); - DER_Encoder& start_explicit(ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - DER_Encoder& end_explicit(ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); - - DER_Encoder& add_raw_octets(const byte[], u32bit); - DER_Encoder& add_raw_octets(const MemoryRegion<byte>&); + DER_Encoder& raw_bytes(const byte[], u32bit); + DER_Encoder& raw_bytes(const MemoryRegion<byte>&); DER_Encoder& encode_null(); DER_Encoder& encode(bool); @@ -51,33 +45,44 @@ class DER_Encoder DER_Encoder& encode(const byte[], u32bit, ASN1_Tag, ASN1_Tag, ASN1_Tag = CONTEXT_SPECIFIC); + template<typename T> + DER_Encoder& encode_optional(const T& value, const T& default_value) + { + if(value != default_value) + encode(value); + return (*this); + } + + template<typename T> + DER_Encoder& encode_list(const std::vector<T>& 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<byte>&); DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, const std::string&); DER_Encoder& add_object(ASN1_Tag, ASN1_Tag, byte); - - DER_Encoder(); private: - DER_Encoder& start_cons(ASN1_Tag, ASN1_Tag, bool); - DER_Encoder& end_cons(ASN1_Tag, ASN1_Tag); - class DER_Sequence { public: ASN1_Tag tag_of() const; SecureVector<byte> get_contents(); void add_bytes(const byte[], u32bit); - DER_Sequence(ASN1_Tag, ASN1_Tag, bool = false); + DER_Sequence(ASN1_Tag, ASN1_Tag); private: ASN1_Tag type_tag, class_tag; - bool is_a_set; SecureVector<byte> contents; std::vector< SecureVector<byte> > set_contents; }; SecureVector<byte> contents; std::vector<DER_Sequence> subsequences; - u32bit sequence_level; }; } diff --git a/include/x509_ext.h b/include/x509_ext.h index 7e3b68288..138a334c6 100644 --- a/include/x509_ext.h +++ b/include/x509_ext.h @@ -9,54 +9,58 @@ #include <botan/asn1_int.h> #include <botan/asn1_oid.h> #include <botan/asn1_obj.h> +#include <botan/datastor.h> +#include <botan/enums.h> namespace Botan { /************************************************* * X.509 Certificate Extension * *************************************************/ -class Certificate_Extension : public ASN1_Object +class Certificate_Extension { public: - void encode_into(class DER_Encoder&) const; - void decode_from(class BER_Decoder&); void maybe_add(class DER_Encoder&) const; OID oid_of() const; void make_critical() { critical = true; } bool is_critical() const { return critical; } - //virtual std::multimap<std::string, std::string> contents() const = 0; + virtual void contents_to(Data_Store&, Data_Store&) const = 0; virtual std::string config_id() const = 0; virtual std::string oid_name() const = 0; Certificate_Extension() { critical = false; } virtual ~Certificate_Extension() {} protected: + friend class Extensions; virtual bool should_encode() const { return true; } virtual MemoryVector<byte> encode_inner() const = 0; virtual void decode_inner(const MemoryRegion<byte>&) = 0; private: - void encode_into(class DER_Encoder&, bool) const; bool critical; }; /************************************************* -* X.509 Certificate Extensions * +* X.509 Certificate Extension List * *************************************************/ class Extensions : public ASN1_Object { public: void encode_into(class DER_Encoder&) const; + void decode_from(class BER_Decoder&); + std::vector<Certificate_Extension*> get() const + { return extensions; } void add(Certificate_Extension* extn) { extensions.push_back(extn); } - + ~Extensions(); private: std::vector<Certificate_Extension*> extensions; }; + namespace Cert_Extension { /************************************************* @@ -65,13 +69,15 @@ namespace Cert_Extension { class Basic_Constraints : public Certificate_Extension { public: - Basic_Constraints(bool = false, u32bit = 0); + Basic_Constraints(bool ca = false, u32bit limit = 0) : + is_ca(ca), path_limit(limit) {} private: std::string config_id() const { return "basic_constraints"; } std::string oid_name() const { return "X509v3.BasicConstraints"; } MemoryVector<byte> encode_inner() const; void decode_inner(const MemoryRegion<byte>&); + void contents_to(Data_Store&, Data_Store&) const; bool is_ca; u32bit path_limit; @@ -83,7 +89,7 @@ class Basic_Constraints : public Certificate_Extension class Key_Usage : public Certificate_Extension { public: - Key_Usage(Key_Constraints); + Key_Usage(Key_Constraints c = NO_CONSTRAINTS) : constraints(c) {} private: std::string config_id() const { return "key_usage"; } std::string oid_name() const { return "X509v3.KeyUsage"; } @@ -91,6 +97,7 @@ class Key_Usage : public Certificate_Extension bool should_encode() const { return (constraints != NO_CONSTRAINTS); } MemoryVector<byte> encode_inner() const; void decode_inner(const MemoryRegion<byte>&); + void contents_to(Data_Store&, Data_Store&) const; Key_Constraints constraints; }; @@ -101,13 +108,16 @@ class Key_Usage : public Certificate_Extension class Subject_Key_ID : public Certificate_Extension { public: + Subject_Key_ID() {} Subject_Key_ID(const MemoryRegion<byte>&); private: std::string config_id() const { return "subject_key_id"; } std::string oid_name() const { return "X509v3.SubjectKeyIdentifier"; } + bool should_encode() const { return (key_id.size() > 0); } MemoryVector<byte> encode_inner() const; void decode_inner(const MemoryRegion<byte>&); + void contents_to(Data_Store&, Data_Store&) const; MemoryVector<byte> key_id; }; @@ -118,7 +128,8 @@ class Subject_Key_ID : public Certificate_Extension class Authority_Key_ID : public Certificate_Extension { public: - Authority_Key_ID(const MemoryRegion<byte>&); + Authority_Key_ID() {} + Authority_Key_ID(const MemoryRegion<byte>& k) : key_id(k) {} private: std::string config_id() const { return "authority_key_id"; } std::string oid_name() const { return "X509v3.AuthorityKeyIdentifier"; } @@ -126,6 +137,7 @@ class Authority_Key_ID : public Certificate_Extension bool should_encode() const { return (key_id.size() > 0); } MemoryVector<byte> encode_inner() const; void decode_inner(const MemoryRegion<byte>&); + void contents_to(Data_Store&, Data_Store&) const; MemoryVector<byte> key_id; }; @@ -145,6 +157,7 @@ class Alternative_Name : public Certificate_Extension bool should_encode() const { return alt_name.has_items(); } MemoryVector<byte> encode_inner() const; void decode_inner(const MemoryRegion<byte>&); + void contents_to(Data_Store&, Data_Store&) const; std::string config_name_str, oid_name_str; AlternativeName alt_name; @@ -156,7 +169,8 @@ class Alternative_Name : public Certificate_Extension class Extended_Key_Usage : public Certificate_Extension { public: - Extended_Key_Usage(const std::vector<OID>&); + Extended_Key_Usage() {} + Extended_Key_Usage(const std::vector<OID>& o) : oids(o) {} private: std::string config_id() const { return "extended_key_usage"; } std::string oid_name() const { return "X509v3.ExtendedKeyUsage"; } @@ -164,6 +178,27 @@ class Extended_Key_Usage : public Certificate_Extension bool should_encode() const { return (oids.size() > 0); } MemoryVector<byte> encode_inner() const; void decode_inner(const MemoryRegion<byte>&); + void contents_to(Data_Store&, Data_Store&) const; + + std::vector<OID> oids; + }; + +/************************************************* +* Certificate Policies Extension * +*************************************************/ +class Certificate_Policies : public Certificate_Extension + { + public: + Certificate_Policies() {} + Certificate_Policies(const std::vector<OID>& o) : oids(o) {} + private: + std::string config_id() const { return "policy_info"; } + std::string oid_name() const { return "X509v3.CertificatePolicies"; } + + bool should_encode() const { return (oids.size() > 0); } + MemoryVector<byte> encode_inner() const; + void decode_inner(const MemoryRegion<byte>&); + void contents_to(Data_Store&, Data_Store&) const; std::vector<OID> oids; }; @@ -174,19 +209,40 @@ class Extended_Key_Usage : public Certificate_Extension class CRL_Number : public Certificate_Extension { public: - CRL_Number(u32bit = 0); + CRL_Number() : has_value(false) {} + CRL_Number(u32bit n) : has_value(true), crl_number(n) {} private: std::string config_id() const { return "crl_number"; } std::string oid_name() const { return "X509v3.CRLNumber"; } - bool should_encode() const { return (crl_number != 0); } - + bool should_encode() const { return has_value; } MemoryVector<byte> encode_inner() const; void decode_inner(const MemoryRegion<byte>&); + void contents_to(Data_Store&, Data_Store&) const; + bool has_value; u32bit crl_number; }; +/************************************************* +* CRL Entry Reason Code Extension * +*************************************************/ +class CRL_ReasonCode : public Certificate_Extension + { + public: + CRL_ReasonCode(CRL_Code r = UNSPECIFIED) : reason(r) {} + private: + std::string config_id() const { return "crl_reason"; } + std::string oid_name() const { return "X509v3.ReasonCode"; } + + bool should_encode() const { return (reason != UNSPECIFIED); } + MemoryVector<byte> encode_inner() const; + void decode_inner(const MemoryRegion<byte>&); + void contents_to(Data_Store&, Data_Store&) const; + + CRL_Code reason; + }; + } } diff --git a/include/x509_obj.h b/include/x509_obj.h index 18c1e574b..f7f110a42 100644 --- a/include/x509_obj.h +++ b/include/x509_obj.h @@ -22,6 +22,8 @@ class X509_Object SecureVector<byte> signature() const; AlgorithmIdentifier signature_algorithm() const; + bool check_signature(class X509_PublicKey&) const; + void encode(Pipe&, X509_Encoding = PEM) const; SecureVector<byte> BER_encode() const; std::string PEM_encode() const; diff --git a/include/x509cert.h b/include/x509cert.h index 60534c769..0a6d0ec83 100644 --- a/include/x509cert.h +++ b/include/x509cert.h @@ -13,7 +13,7 @@ namespace Botan { -static const u32bit NO_CERT_PATH_LIMIT = 0xFFFFFFFF; +static const u32bit NO_CERT_PATH_LIMIT = 0xFFFFFFF0; /************************************************* * X.509 Certificate * @@ -23,36 +23,36 @@ class X509_Certificate : public X509_Object public: X509_PublicKey* subject_public_key() const; - u32bit x509_version() const; - MemoryVector<byte> serial_number() const; - MemoryVector<byte> authority_key_id() const; - MemoryVector<byte> subject_key_id() const; - Key_Constraints constraints() const; + X509_DN issuer_dn() const; + X509_DN subject_dn() const; + std::string subject_info(const std::string&) const; + std::string issuer_info(const std::string&) const; std::string start_time() const; std::string end_time() const; - std::string subject_info(const std::string&) const; - std::string issuer_info(const std::string&) const; - X509_DN issuer_dn() const; - X509_DN subject_dn() const; + u32bit x509_version() const; + MemoryVector<byte> serial_number() const; + MemoryVector<byte> authority_key_id() const; + MemoryVector<byte> subject_key_id() const; bool self_signed() const; bool is_CA_cert() const; u32bit path_limit() const; + Key_Constraints constraints() const; std::vector<std::string> ex_constraints() const; std::vector<std::string> policies() const; bool operator==(const X509_Certificate&) const; - void force_decode(); - X509_Certificate(DataSource&); X509_Certificate(const std::string&); private: friend class X509_CA; X509_Certificate() {} + void force_decode(); + void handle_v3_extension(const Extension&); Data_Store info; diff --git a/src/asn1_alg.cpp b/src/asn1_alg.cpp index 4dd5af88e..251c8c31f 100644 --- a/src/asn1_alg.cpp +++ b/src/asn1_alg.cpp @@ -4,6 +4,8 @@ *************************************************/ #include <botan/asn1_obj.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/oids.h> namespace Botan { @@ -23,17 +25,6 @@ AlgorithmIdentifier::AlgorithmIdentifier(const std::string& alg_id, oid(OIDS::lookup(alg_id)), parameters(param) { } /************************************************* -* DER encode an AlgorithmIdentifier * -*************************************************/ -void AlgorithmIdentifier::encode_into(DER_Encoder& der) const - { - der.start_sequence() - .encode(oid) - .add_raw_octets(parameters) - .end_sequence(); - } - -/************************************************* * Compare two AlgorithmIdentifiers * *************************************************/ bool operator==(const AlgorithmIdentifier& a1, const AlgorithmIdentifier& a2) @@ -53,19 +44,26 @@ bool operator!=(const AlgorithmIdentifier& a1, const AlgorithmIdentifier& a2) return !(a1 == a2); } -namespace BER { +/************************************************* +* 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 decode(BER_Decoder& source, AlgorithmIdentifier& alg_id) +void AlgorithmIdentifier::decode_from(BER_Decoder& codec) { - BER_Decoder sequence = BER::get_subsequence(source); - BER::decode(sequence, alg_id.oid); - alg_id.parameters = sequence.get_remaining(); - sequence.verify_end(); + codec.start_cons(SEQUENCE) + .decode(oid) + .raw_bytes(parameters) + .end_cons(); } } - -} diff --git a/src/asn1_alt.cpp b/src/asn1_alt.cpp index 930f9d3a9..2bc6f01db 100644 --- a/src/asn1_alt.cpp +++ b/src/asn1_alt.cpp @@ -4,6 +4,9 @@ *************************************************/ #include <botan/asn1_obj.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> +#include <botan/oids.h> #include <botan/stl_util.h> #include <botan/charset.h> @@ -67,6 +70,24 @@ std::multimap<OID, ASN1_String> AlternativeName::get_othernames() const } /************************************************* +* Return all of the alternative names * +*************************************************/ +std::multimap<std::string, std::string> AlternativeName::contents() const + { + std::multimap<std::string, std::string> names; + + typedef std::multimap<std::string, std::string>::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<OID, ASN1_String>::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 @@ -89,7 +110,7 @@ void encode_entries(DER_Encoder& encoder, for(iter j = range.first; j != range.second; ++j) { ASN1_String asn1_string(j->second, IA5_STRING); - DER::encode(encoder, asn1_string, tagging, CONTEXT_SPECIFIC); + encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.iso_8859()); } } @@ -100,7 +121,7 @@ void encode_entries(DER_Encoder& encoder, *************************************************/ void AlternativeName::encode_into(DER_Encoder& der) const { - der.start_sequence(); + der.start_cons(SEQUENCE); encode_entries(der, alt_info, "RFC822", ASN1_Tag(1)); encode_entries(der, alt_info, "DNS", ASN1_Tag(2)); @@ -109,25 +130,24 @@ void AlternativeName::encode_into(DER_Encoder& der) const std::multimap<OID, ASN1_String>::const_iterator i; for(i = othernames.begin(); i != othernames.end(); ++i) { - der.start_explicit(ASN1_Tag(0)) + der.start_explicit(0) .encode(i->first) - .start_explicit(ASN1_Tag(0)) + .start_explicit(0) .encode(i->second) - .end_explicit(ASN1_Tag(0)) - .end_explicit(ASN1_Tag(0)); + .end_explicit() + .end_explicit(); } - der.end_sequence(); + der.end_cons(); } -namespace BER { - /************************************************* * Decode a BER encoded AlternativeName * *************************************************/ -void decode(BER_Decoder& source, AlternativeName& alt_name) +void AlternativeName::decode_from(BER_Decoder& source) { - BER_Decoder names = BER::get_subsequence(source); + BER_Decoder names = source.start_cons(SEQUENCE); + while(names.more_items()) { BER_Object obj = names.get_next_object(); @@ -142,7 +162,7 @@ void decode(BER_Decoder& source, AlternativeName& alt_name) BER_Decoder othername(obj.value); OID oid; - BER::decode(othername, oid); + othername.decode(oid); if(othername.more_items()) { BER_Object othername_value_outer = othername.get_next_object(); @@ -162,21 +182,19 @@ void decode(BER_Decoder& source, AlternativeName& alt_name) ASN1_Tag value_type = value.type_tag; if(is_string_type(value_type) && value.class_tag == UNIVERSAL) - alt_name.add_othername(oid, BER::to_string(value), value_type); + add_othername(oid, ASN1::to_string(value), value_type); } } else if(tag == 1 || tag == 2 || tag == 6) { - const std::string value = iso2local(BER::to_string(obj)); + const std::string value = iso2local(ASN1::to_string(obj)); - if(tag == 1) alt_name.add_attribute("RFC822", value); - if(tag == 2) alt_name.add_attribute("DNS", value); - if(tag == 6) alt_name.add_attribute("URI", value); + if(tag == 1) add_attribute("RFC822", value); + if(tag == 2) add_attribute("DNS", value); + if(tag == 6) add_attribute("URI", value); } } } } - -} diff --git a/src/asn1_att.cpp b/src/asn1_att.cpp index 58ed761b4..8216054b3 100644 --- a/src/asn1_att.cpp +++ b/src/asn1_att.cpp @@ -4,6 +4,8 @@ *************************************************/ #include <botan/asn1_obj.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/oids.h> namespace Botan { @@ -30,33 +32,27 @@ Attribute::Attribute(const std::string& attr_oid, /************************************************* * DER encode a Attribute * *************************************************/ -void Attribute::encode_into(DER_Encoder& der) const +void Attribute::encode_into(DER_Encoder& codec) const { - der.start_sequence() + codec.start_cons(SEQUENCE) .encode(oid) - .start_set() - .add_raw_octets(parameters) - .end_set() - .end_sequence(); + .start_cons(SET) + .raw_bytes(parameters) + .end_cons() + .end_cons(); } -namespace BER { - /************************************************* * Decode a BER encoded Attribute * *************************************************/ -void decode(BER_Decoder& source, Attribute& attr) +void Attribute::decode_from(BER_Decoder& codec) { - BER_Decoder decoder = BER::get_subsequence(source); - BER::decode(decoder, attr.oid); - - BER_Decoder attributes = BER::get_subset(decoder); - attr.parameters = attributes.get_remaining(); - attributes.verify_end(); - - decoder.verify_end(); + 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 index 22ce980f6..4d33db38b 100644 --- a/src/asn1_dn.cpp +++ b/src/asn1_dn.cpp @@ -4,6 +4,8 @@ *************************************************/ #include <botan/asn1_obj.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/parsing.h> #include <botan/stl_util.h> #include <botan/oids.h> @@ -80,6 +82,19 @@ std::multimap<OID, std::string> X509_DN::get_attributes() const } /************************************************* +* Get the contents of this X.500 Name * +*************************************************/ +std::multimap<std::string, std::string> X509_DN::contents() const + { + typedef std::multimap<OID, ASN1_String>::const_iterator rdn_iter; + + std::multimap<std::string, std::string> 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<std::string> X509_DN::get_attribute(const std::string& attr) const @@ -104,16 +119,18 @@ void X509_DN::do_decode(const MemoryRegion<byte>& bits) while(sequence.more_items()) { - BER_Decoder rdn = BER::get_subset(sequence); + BER_Decoder rdn = sequence.start_cons(SET); + while(rdn.more_items()) { OID oid; ASN1_String str; - BER_Decoder ava = BER::get_subsequence(rdn); - BER::decode(ava, oid); - BER::decode(ava, str); - ava.verify_end(); + rdn.start_cons(SEQUENCE) + .decode(oid) + .decode(str) + .verify_end() + .end_cons(); add_attribute(oid, str.value()); } @@ -231,12 +248,12 @@ void do_ava(DER_Encoder& encoder, for(rdn_iter j = range.first; j != range.second; ++j) { - encoder.start_set() - .start_sequence() + encoder.start_cons(SET) + .start_cons(SEQUENCE) .encode(oid) .encode(ASN1_String(j->second, string_type)) - .end_sequence() - .end_set(); + .end_cons() + .end_cons(); } } @@ -249,10 +266,10 @@ void X509_DN::encode_into(DER_Encoder& der) const { std::multimap<OID, std::string> dn_info = get_attributes(); - der.start_sequence(); + der.start_cons(SEQUENCE); if(dn_bits.has_items()) - der.add_raw_octets(dn_bits); + der.raw_bytes(dn_bits); else { do_ava(der, dn_info, PRINTABLE_STRING, "X520.Country", true); @@ -264,22 +281,21 @@ void X509_DN::encode_into(DER_Encoder& der) const do_ava(der, dn_info, PRINTABLE_STRING, "X520.SerialNumber"); } - der.end_sequence(); + der.end_cons(); } -namespace BER { - /************************************************* * Decode a BER encoded DistinguishedName * *************************************************/ -void decode(BER_Decoder& source, X509_DN& dn) +void X509_DN::decode_from(BER_Decoder& source) { - dn = X509_DN(); - BER_Decoder sequence = BER::get_subsequence(source); - SecureVector<byte> bits = sequence.get_remaining(); - dn.do_decode(bits); - } + dn_info.clear(); -} + source.start_cons(SEQUENCE) + .raw_bytes(dn_bits) + .end_cons(); + + do_decode(dn_bits); + } } diff --git a/src/asn1_ext.cpp b/src/asn1_ext.cpp index 44deeaf8a..557e7712c 100644 --- a/src/asn1_ext.cpp +++ b/src/asn1_ext.cpp @@ -4,6 +4,8 @@ *************************************************/ #include <botan/asn1_obj.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/oids.h> namespace Botan { @@ -32,39 +34,25 @@ Extension::Extension(const std::string& extn_oid, /************************************************* * DER encode a Extension * *************************************************/ -void Extension::encode_into(DER_Encoder& der) const +void Extension::encode_into(DER_Encoder& codec) const { - der.start_sequence(); - der.encode(oid); - if(critical) - der.encode(true); - // der.encode_with_default(critical, false); - der.encode(value, OCTET_STRING); - der.end_sequence(); + codec.start_cons(SEQUENCE) + .encode(oid) + .encode_optional(critical, false) + .encode(value, OCTET_STRING) + .end_cons(); } -namespace BER { - /************************************************* * Decode a BER encoded Extension * *************************************************/ -void decode(BER_Decoder& ber, Extension& extn) +void Extension::decode_from(BER_Decoder& codec) { -#if 1 - BER_Decoder extension = BER::get_subsequence(ber); - BER::decode(extension, extn.oid); - BER::decode_optional(extension, extn.critical, BOOLEAN, UNIVERSAL, false); - extension.decode(extn.value, OCTET_STRING); - extension.verify_end(); -#else - ber.start_subsequence() - .decode(extn.oid) - .decode_optional(extn.critical, BOOLEAN, UNIVERSAL, false) - .decode(extn.value, OCTET_STRING) - .end_subsequence(); -#endif + codec.start_cons(SEQUENCE) + .decode(oid) + .decode_optional(critical, BOOLEAN, UNIVERSAL, false) + .decode(value, OCTET_STRING) + .end_cons(); } } - -} diff --git a/src/asn1_int.cpp b/src/asn1_int.cpp index 324187eff..042712df1 100644 --- a/src/asn1_int.cpp +++ b/src/asn1_int.cpp @@ -5,6 +5,7 @@ #include <botan/asn1_int.h> #include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/data_src.h> #include <botan/parsing.h> @@ -30,11 +31,20 @@ namespace ASN1 { *************************************************/ SecureVector<byte> put_in_sequence(const MemoryRegion<byte>& contents) { - DER_Encoder encoder; - encoder.start_sequence(); - encoder.add_raw_octets(contents); - encoder.end_sequence(); - return encoder.get_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) + { + std::string str((const char*)obj.value.begin(), obj.value.size()); + return str; } /************************************************* diff --git a/src/asn1_ku.cpp b/src/asn1_ku.cpp index 626074e7c..c5bb3ce4d 100644 --- a/src/asn1_ku.cpp +++ b/src/asn1_ku.cpp @@ -4,7 +4,8 @@ *************************************************/ #include <botan/asn1_obj.h> -#include <botan/asn1_int.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/bit_ops.h> namespace Botan { diff --git a/src/asn1_oid.cpp b/src/asn1_oid.cpp index 413beedcf..3115c2be5 100644 --- a/src/asn1_oid.cpp +++ b/src/asn1_oid.cpp @@ -4,7 +4,6 @@ *************************************************/ #include <botan/asn1_oid.h> -#include <botan/asn1_int.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/bit_ops.h> @@ -140,12 +139,10 @@ void OID::encode_into(DER_Encoder& der) const der.add_object(OBJECT_ID, UNIVERSAL, encoding); } -namespace BER { - /************************************************* * Decode a BER encoded OBJECT IDENTIFIER * *************************************************/ -void decode(BER_Decoder& decoder, OID& oid) +void OID::decode_from(BER_Decoder& decoder) { BER_Object obj = decoder.get_next_object(); if(obj.type_tag != OBJECT_ID || obj.class_tag != UNIVERSAL) @@ -154,9 +151,10 @@ void decode(BER_Decoder& decoder, OID& oid) if(obj.value.size() < 2) throw BER_Decoding_Error("OID encoding is too short"); - oid.clear(); - oid += (obj.value[0] / 40); - oid += (obj.value[0] % 40); + + clear(); + id.push_back(obj.value[0] / 40); + id.push_back(obj.value[0] % 40); u32bit j = 0; while(j != obj.value.size() - 1) @@ -169,10 +167,8 @@ void decode(BER_Decoder& decoder, OID& oid) if(!(obj.value[j] & 0x80)) break; } - oid += component; + id.push_back(component); } } } - -} diff --git a/src/asn1_str.cpp b/src/asn1_str.cpp index ced252b49..f3c8584ed 100644 --- a/src/asn1_str.cpp +++ b/src/asn1_str.cpp @@ -4,7 +4,6 @@ *************************************************/ #include <botan/asn1_obj.h> -#include <botan/asn1_int.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> #include <botan/charset.h> @@ -133,29 +132,12 @@ void ASN1_String::encode_into(DER_Encoder& encoder) const encoder.add_object(tagging(), UNIVERSAL, value); } -namespace DER { - -/************************************************* -* DER encode an ASN1_String * -*************************************************/ -void encode(DER_Encoder& encoder, const ASN1_String& string, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - if(string.tagging() == UTF8_STRING) - encoder.add_object(type_tag, class_tag, iso2utf(string.iso_8859())); - else - encoder.add_object(type_tag, class_tag, string.iso_8859()); - } - -} - -namespace BER { - namespace { /************************************************* * Do any UTF-8/Unicode decoding needed * *************************************************/ +// FIXME: inline this std::string convert_string(BER_Object obj, ASN1_Tag type) { if(type == BMP_STRING) @@ -177,9 +159,9 @@ std::string convert_string(BER_Object obj, ASN1_Tag type) return iso2local(value); } else if(type == UTF8_STRING) - return iso2local(utf2iso(BER::to_string(obj))); + return iso2local(utf2iso(ASN1::to_string(obj))); else - return iso2local(BER::to_string(obj)); + return iso2local(ASN1::to_string(obj)); } } @@ -187,25 +169,11 @@ std::string convert_string(BER_Object obj, ASN1_Tag type) /************************************************* * Decode a BER encoded ASN1_String * *************************************************/ -void decode(BER_Decoder& source, ASN1_String& string, - ASN1_Tag expected_tag, ASN1_Tag real_tag) +void ASN1_String::decode_from(BER_Decoder& source) { BER_Object obj = source.get_next_object(); - if(obj.type_tag != expected_tag) - throw BER_Bad_Tag("Unexpected string tag", obj.type_tag); - - string = ASN1_String(convert_string(obj, real_tag), real_tag); - } - -/************************************************* -* Decode a BER encoded ASN1_String * -*************************************************/ -void decode(BER_Decoder& source, ASN1_String& string) - { - BER_Object obj = source.get_next_object(); - string = ASN1_String(convert_string(obj, obj.type_tag), obj.type_tag); + // FIXME, don't like this at all... + *this = ASN1_String(convert_string(obj, obj.type_tag), obj.type_tag); } } - -} diff --git a/src/asn1_tm.cpp b/src/asn1_tm.cpp index af4eaa1b4..1b9f6bdba 100644 --- a/src/asn1_tm.cpp +++ b/src/asn1_tm.cpp @@ -4,6 +4,8 @@ *************************************************/ #include <botan/asn1_obj.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/charset.h> #include <botan/parsing.h> #include <botan/conf.h> @@ -282,17 +284,14 @@ s32bit validity_check(const X509_Time& start, const X509_Time& end, return VALID_TIME; } -namespace BER { - /************************************************* * Decode a BER encoded X509_Time * *************************************************/ -void decode(BER_Decoder& source, X509_Time& time) +void X509_Time::decode_from(BER_Decoder& source) { BER_Object ber_time = source.get_next_object(); - time = X509_Time(iso2local(BER::to_string(ber_time)), ber_time.type_tag); + // FIXME - should have a set + *this = X509_Time(iso2local(ASN1::to_string(ber_time)), ber_time.type_tag); } } - -} diff --git a/src/ber_code.cpp b/src/ber_code.cpp deleted file mode 100644 index 43ec17207..000000000 --- a/src/ber_code.cpp +++ /dev/null @@ -1,237 +0,0 @@ -/************************************************* -* BER Decoding Source File * -* (C) 1999-2006 The Botan Project * -*************************************************/ - -#include <botan/ber_dec.h> -#include <botan/asn1_int.h> -#include <botan/parsing.h> -#include <botan/bigint.h> - -#include <assert.h> - -namespace Botan { - -namespace { - -/************************************************* -* Check an object's type and size * -*************************************************/ -void check_object(const BER_Object& obj, - ASN1_Tag type_tag, ASN1_Tag class_tag, - u32bit length = 0, bool check_length = false) - { - if(obj.type_tag != type_tag || obj.class_tag != class_tag) - throw BER_Decoding_Error("Tag mismatch when decoding"); - if(check_length && obj.value.size() != length) - throw BER_Decoding_Error("Incorrect size for type"); - } - -} - -/************************************************* -* Decode a BER encoded NULL * -*************************************************/ -BER_Decoder& BER_Decoder::decode_null() - { - check_object(get_next_object(), NULL_TAG, UNIVERSAL, 0, true); - 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(); - check_object(obj, type_tag, class_tag, 1, true); - 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(); - check_object(obj, 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<byte>& 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<byte>& 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(); - check_object(obj, 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); - } - -namespace BER { - -/************************************************* -* Decode and return a BER encoded SEQUENCE * -*************************************************/ -BER_Decoder get_subsequence(BER_Decoder& decoder) - { - return get_subsequence(decoder, SEQUENCE, CONSTRUCTED); - } - -/************************************************* -* Decode and return a BER encoded SET * -*************************************************/ -BER_Decoder get_subset(BER_Decoder& decoder) - { - return get_subset(decoder, SET, CONSTRUCTED); - } - -/************************************************* -* Decode and return a BER encoded SEQUENCE * -*************************************************/ -BER_Decoder get_subsequence(BER_Decoder& decoder, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - BER_Object obj = decoder.get_next_object(); - check_object(obj, type_tag, ASN1_Tag(class_tag | CONSTRUCTED)); - return BER_Decoder(obj.value, obj.value.size()); - } - -/************************************************* -* Decode and return a BER encoded SET * -*************************************************/ -BER_Decoder get_subset(BER_Decoder& decoder, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - BER_Object obj = decoder.get_next_object(); - check_object(obj, type_tag, ASN1_Tag(class_tag | CONSTRUCTED)); - return BER_Decoder(obj.value, obj.value.size()); - } - -/************************************************* -* Convert a BER object into a string object * -*************************************************/ -std::string to_string(const BER_Object& obj) - { - std::string str((const char*)obj.value.begin(), obj.value.size()); - return str; - } - -/************************************************* -* Decode an OPTIONAL string type * -*************************************************/ -bool decode_optional_string(BER_Decoder& in, MemoryRegion<byte>& out, - ASN1_Tag real_type, - ASN1_Tag type_tag, ASN1_Tag class_tag) - { - BER_Object obj = in.get_next_object(); - - if(obj.type_tag == type_tag && obj.class_tag == class_tag) - { - if(class_tag & CONSTRUCTED) - { - BER_Decoder stored_value(obj.value); - stored_value.decode(out, real_type); - stored_value.verify_end(); - } - else - { - in.push_back(obj); - in.decode(out, real_type, type_tag, class_tag); - } - return true; - } - else - { - out.clear(); - in.push_back(obj); - return false; - } - } - -} - -} diff --git a/src/ber_dec.cpp b/src/ber_dec.cpp index f9550fc83..51bc8f989 100644 --- a/src/ber_dec.cpp +++ b/src/ber_dec.cpp @@ -4,7 +4,7 @@ *************************************************/ #include <botan/ber_dec.h> -#include <botan/asn1_int.h> +#include <botan/bigint.h> #include <botan/bit_ops.h> namespace Botan { @@ -133,6 +133,15 @@ u32bit find_eoc(DataSource* ber) } /************************************************* +* 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 @@ -145,32 +154,34 @@ bool BER_Decoder::more_items() const /************************************************* * Verify that no bytes remain in the source * *************************************************/ -void BER_Decoder::verify_end() const +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); } /************************************************* -* Return all the bytes remaining in the source * +* Save all the bytes remaining in the source * *************************************************/ -SecureVector<byte> BER_Decoder::get_remaining() +BER_Decoder& BER_Decoder::raw_bytes(MemoryRegion<byte>& out) { - SecureVector<byte> out; + out.destroy(); byte buf; while(source->read_byte(buf)) out.append(buf); - return out; + return (*this); } /************************************************* * Discard all the bytes remaining in the source * *************************************************/ -void BER_Decoder::discard_remaining() +BER_Decoder& BER_Decoder::discard_remaining() { byte buf; while(source->read_byte(buf)) ; + return (*this); } /************************************************* @@ -213,6 +224,30 @@ void BER_Decoder::push_back(const BER_Object& obj) } /************************************************* +* Begin decoding a CONSTRUCTED type * +*************************************************/ +BER_Decoder BER_Decoder::start_cons(ASN1_Tag type_tag) + { + BER_Object obj = get_next_object(); + obj.assert_is_a(type_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) @@ -220,6 +255,7 @@ BER_Decoder::BER_Decoder(DataSource& src) source = &src; owns = false; pushed.type_tag = pushed.class_tag = NO_OBJECT; + parent = 0; } /************************************************* @@ -230,6 +266,7 @@ 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; } /************************************************* @@ -240,6 +277,7 @@ BER_Decoder::BER_Decoder(const MemoryRegion<byte>& data) source = new DataSource_Memory(data); owns = true; pushed.type_tag = pushed.class_tag = NO_OBJECT; + parent = 0; } /************************************************* @@ -255,6 +293,7 @@ BER_Decoder::BER_Decoder(const BER_Decoder& other) owns = true; } pushed.type_tag = pushed.class_tag = NO_OBJECT; + parent = 0; } /************************************************* @@ -267,4 +306,162 @@ BER_Decoder::~BER_Decoder() 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<byte>& 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<byte>& 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<byte>& out, + ASN1_Tag real_type, + u16bit type_no) + { + BER_Object obj = get_next_object(); + + ASN1_Tag type_tag = (ASN1_Tag)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/crl_ent.cpp b/src/crl_ent.cpp index 086dd496b..8c6d79b5e 100644 --- a/src/crl_ent.cpp +++ b/src/crl_ent.cpp @@ -4,11 +4,12 @@ *************************************************/ #include <botan/crl_ent.h> +#include <botan/x509_ext.h> #include <botan/der_enc.h> #include <botan/ber_dec.h> +#include <botan/bigint.h> #include <botan/conf.h> #include <botan/oids.h> -#include <botan/x509_crl.h> #include <botan/util.h> namespace Botan { @@ -61,105 +62,67 @@ bool operator<(const CRL_Entry& a1, const CRL_Entry& a2) return (a1.time.cmp(a2.time) < 0); } -namespace DER { - -/************************************************* -* DER encode an CRL_Entry * -*************************************************/ -void encode(DER_Encoder& der, const CRL_Entry& crl_ent) - { - der.start_sequence() - .encode(BigInt::decode(crl_ent.serial, crl_ent.serial.size())) - .encode(crl_ent.time) - .start_sequence(); - - if(crl_ent.reason != UNSPECIFIED) - { -#if 1 - der.start_sequence() - .encode(OIDS::lookup("X509v3.ReasonCode")) - .encode( - DER_Encoder() - .encode((u32bit)crl_ent.reason, ENUMERATED, UNIVERSAL) - .get_contents(), - OCTET_STRING) - .end_sequence(); -#else - DER_Encoder v2_ext; - v2_ext.encode((u32bit)crl_ent.reason, ENUMERATED, UNIVERSAL); - der.encode(Extension("X509v3.ReasonCode", v2_ext.get_contents())); -#endif - } - - der.end_sequence() - .end_sequence(); - } - -} - -namespace BER { - -namespace { - /************************************************* -* Decode a CRL entry extension * +* DER encode a CRL_Entry * *************************************************/ -void handle_crl_entry_extension(CRL_Entry& crl_ent, const Extension& extn) +void CRL_Entry::encode_into(DER_Encoder& der) const { - BER_Decoder value(extn.value); + Extensions extensions; - if(extn.oid == OIDS::lookup("X509v3.ReasonCode")) - { - u32bit reason_code; - value.decode(reason_code, ENUMERATED, UNIVERSAL); - crl_ent.reason = CRL_Code(reason_code); - } - else - { - if(extn.critical) - { - std::string action = Config::get_string("x509/crl/unknown_critical"); - if(action == "throw") - throw Decoding_Error("Unknown critical CRL entry extension " + - extn.oid.as_string()); - else if(action != "ignore") - throw Invalid_Argument("Bad value of x509/crl/unknown_critical: " - + action); - } - return; - } + extensions.add(new Cert_Extension::CRL_ReasonCode(reason)); - value.verify_end(); + der.start_cons(SEQUENCE) + .encode(BigInt::decode(serial, serial.size())) + .encode(time) + .encode(extensions) + .end_cons(); } -} - /************************************************* * Decode a BER encoded CRL_Entry * *************************************************/ -void decode(BER_Decoder& source, CRL_Entry& crl_ent) +void CRL_Entry::decode_from(BER_Decoder& source) { - BigInt serial_number; + BigInt serial_number_bn; - BER_Decoder sequence = BER::get_subsequence(source); - sequence.decode(serial_number); - crl_ent.serial = BigInt::encode(serial_number); - BER::decode(sequence, crl_ent.time); + source.start_cons(SEQUENCE) + .decode(serial_number_bn) + .decode(time); - if(sequence.more_items()) + if(source.more_items()) { - BER_Decoder crl_entry_exts = BER::get_subsequence(sequence); + BER_Decoder crl_entry_exts = source.start_cons(SEQUENCE); while(crl_entry_exts.more_items()) { Extension extn; - BER::decode(crl_entry_exts, extn); - handle_crl_entry_extension(crl_ent, extn); + crl_entry_exts.decode(extn); + + BER_Decoder value(extn.value); + + if(extn.oid == OIDS::lookup("X509v3.ReasonCode")) + { + u32bit reason_code; + value.decode(reason_code, ENUMERATED, UNIVERSAL); + reason = CRL_Code(reason_code); + } + else if(extn.critical) + { + std::string action = + Config::get_string("x509/crl/unknown_critical"); + + if(action == "throw") + throw Decoding_Error("Unknown critical CRL entry extn " + + extn.oid.as_string()); + else if(action != "ignore") + throw Invalid_Argument("Bad setting x509/crl/unknown_critical: " + + action); + } + value.verify_end(); } + source.end_cons(); } - sequence.verify_end(); + serial = BigInt::encode(serial_number_bn); } } - -} diff --git a/src/datastor.cpp b/src/datastor.cpp index 2b7255112..69afd3ce2 100644 --- a/src/datastor.cpp +++ b/src/datastor.cpp @@ -29,10 +29,18 @@ bool Data_Store::operator==(const Data_Store& other) const } /************************************************* +* Check if this key has at least one value * +*************************************************/ +bool Data_Store::has_value(const std::string& key) const + { + return (contents.lower_bound(key) != contents.end()); + } + +/************************************************* * Search based on an arbitrary predicate * *************************************************/ std::multimap<std::string, std::string> -Data_Store::get(const Matcher& matcher) const +Data_Store::search_with(const Matcher& matcher) const { std::multimap<std::string, std::string> out; @@ -49,12 +57,13 @@ Data_Store::get(const Matcher& matcher) const } /************************************************* -* Search based on an key equality * +* Search based on key equality * *************************************************/ std::vector<std::string> Data_Store::get(const std::string& looking_for) const { std::vector<std::string> out; + // FIXME: use equal_range!!!! std::multimap<std::string, std::string>::const_iterator i; i = contents.begin(); while(i != contents.end()) diff --git a/src/der_enc.cpp b/src/der_enc.cpp index c4a7245ff..a3d61152b 100644 --- a/src/der_enc.cpp +++ b/src/der_enc.cpp @@ -74,6 +74,7 @@ class DER_Cmp bool DER_Cmp::operator()(const MemoryRegion<byte>& a, const MemoryRegion<byte>& b) const { + // FIXME: use lexicographical_compare if(a.size() < b.size()) return true; if(a.size() > b.size()) return false; @@ -96,7 +97,7 @@ SecureVector<byte> DER_Encoder::DER_Sequence::get_contents() SecureVector<byte> encoded_tag = encode_tag(type_tag, real_class_tag); - if(is_a_set) + if(type_tag == SET) { std::sort(set_contents.begin(), set_contents.end(), DER_Cmp()); for(u32bit j = 0; j != set_contents.size(); ++j) @@ -119,10 +120,8 @@ SecureVector<byte> DER_Encoder::DER_Sequence::get_contents() *************************************************/ void DER_Encoder::DER_Sequence::add_bytes(const byte data[], u32bit length) { - if(is_a_set) - { + if(type_tag == SET) set_contents.push_back(SecureVector<byte>(data, length)); - } else contents.append(data, length); } @@ -138,8 +137,8 @@ ASN1_Tag DER_Encoder::DER_Sequence::tag_of() const /************************************************* * DER_Sequence Constructor * *************************************************/ -DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Tag t1, ASN1_Tag t2, bool b) : - type_tag(t1), class_tag(t2), is_a_set(b) +DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Tag t1, ASN1_Tag t2) : + type_tag(t1), class_tag(t2) { } @@ -148,7 +147,7 @@ DER_Encoder::DER_Sequence::DER_Sequence(ASN1_Tag t1, ASN1_Tag t2, bool b) : *************************************************/ SecureVector<byte> DER_Encoder::get_contents() { - if(sequence_level != 0) + if(subsequences.size() != 0) throw Invalid_State("DER_Encoder: Sequence hasn't been marked done"); SecureVector<byte> retval; @@ -160,128 +159,65 @@ SecureVector<byte> DER_Encoder::get_contents() /************************************************* * Start a new ASN.1 SEQUENCE/SET/EXPLICIT * *************************************************/ -DER_Encoder& DER_Encoder::start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag, - bool is_a_set) +DER_Encoder& DER_Encoder::start_cons(ASN1_Tag type_tag, + ASN1_Tag class_tag) { - ++sequence_level; - subsequences.push_back(DER_Sequence(type_tag, class_tag, is_a_set)); + 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(ASN1_Tag type_tag, ASN1_Tag class_tag) +DER_Encoder& DER_Encoder::end_cons() { - if(sequence_level == 0) + if(subsequences.size() == 0) throw Invalid_State("DER_Encoder::end_cons: No such sequence"); - sequence_level--; - if(subsequences[sequence_level].tag_of() != ASN1_Tag(type_tag | class_tag)) - throw Invalid_Argument("DER_Encoder::end_cons: Tag mismatch"); - SecureVector<byte> seq = subsequences[sequence_level].get_contents(); + SecureVector<byte> seq = subsequences[subsequences.size()-1].get_contents(); subsequences.pop_back(); - add_raw_octets(seq); + raw_bytes(seq); return (*this); } /************************************************* -* Start a new ASN.1 SEQUENCE * -*************************************************/ -DER_Encoder& DER_Encoder::start_sequence(ASN1_Tag type_tag, ASN1_Tag class_tag) - { - return start_cons(type_tag, class_tag, false); - } - -/************************************************* -* Finish the current ASN.1 SEQUENCE * -*************************************************/ -DER_Encoder& DER_Encoder::end_sequence(ASN1_Tag type_tag, ASN1_Tag class_tag) - { - return end_cons(type_tag, class_tag); - } - -/************************************************* -* Start a new ASN.1 SET * -*************************************************/ -DER_Encoder& DER_Encoder::start_set(ASN1_Tag type_tag, ASN1_Tag class_tag) - { - return start_cons(type_tag, class_tag, true); - } - -/************************************************* -* Finish the current ASN.1 SET * -*************************************************/ -DER_Encoder& DER_Encoder::end_set(ASN1_Tag type_tag, ASN1_Tag class_tag) - { - return end_cons(type_tag, class_tag); - } - -/************************************************* -* Start a new ASN.1 SEQUENCE * -*************************************************/ -DER_Encoder& DER_Encoder::start_sequence() - { - return start_sequence(SEQUENCE, UNIVERSAL); - } - -/************************************************* -* Finish the current ASN.1 SEQUENCE * +* Start a new ASN.1 EXPLICIT encoding * *************************************************/ -DER_Encoder& DER_Encoder::end_sequence() +DER_Encoder& DER_Encoder::start_explicit(u16bit type_no) { - return end_sequence(SEQUENCE, UNIVERSAL); - } + ASN1_Tag type_tag = (ASN1_Tag)type_no; -/************************************************* -* Start a new ASN.1 SET * -*************************************************/ -DER_Encoder& DER_Encoder::start_set() - { - return start_set(SET, UNIVERSAL); - } + if(type_tag == SET) + throw Internal_Error("DER_Encoder.start_explicit(SET); cannot perform"); -/************************************************* -* Finish the current ASN.1 SET * -*************************************************/ -DER_Encoder& DER_Encoder::end_set() - { - return end_set(SET, UNIVERSAL); - } - -/************************************************* -* Start a new ASN.1 EXPLICIT encoding * -*************************************************/ -DER_Encoder& DER_Encoder::start_explicit(ASN1_Tag type_tag, ASN1_Tag class_tag) - { - return start_cons(type_tag, class_tag, false); + return start_cons(type_tag, CONTEXT_SPECIFIC); } /************************************************* * Finish the current ASN.1 EXPLICIT encoding * *************************************************/ -DER_Encoder& DER_Encoder::end_explicit(ASN1_Tag type_tag, ASN1_Tag class_tag) +DER_Encoder& DER_Encoder::end_explicit() { - return end_cons(type_tag, class_tag); + return end_cons(); } /************************************************* -* Write raw octets into the stream * +* Write raw bytes into the stream * *************************************************/ -DER_Encoder& DER_Encoder::add_raw_octets(const MemoryRegion<byte>& octets) +DER_Encoder& DER_Encoder::raw_bytes(const MemoryRegion<byte>& val) { - return add_raw_octets(octets.begin(), octets.size()); + return raw_bytes(val.begin(), val.size()); } /************************************************* -* Write raw octets into the stream * +* Write raw bytes into the stream * *************************************************/ -DER_Encoder& DER_Encoder::add_raw_octets(const byte octets[], u32bit length) +DER_Encoder& DER_Encoder::raw_bytes(const byte bytes[], u32bit length) { - if(sequence_level == 0) - contents.append(octets, length); + if(subsequences.size() == 0) + contents.append(bytes, length); else - subsequences[sequence_level-1].add_bytes(octets, length); + subsequences[subsequences.size()-1].add_bytes(bytes, length); return (*this); } @@ -320,20 +256,20 @@ DER_Encoder& DER_Encoder::encode(const BigInt& n) /************************************************* * DER encode an OCTET STRING or BIT STRING * *************************************************/ -DER_Encoder& DER_Encoder::encode(const MemoryRegion<byte>& octets, +DER_Encoder& DER_Encoder::encode(const MemoryRegion<byte>& bytes, ASN1_Tag real_type) { - return encode(octets.begin(), octets.size(), + return encode(bytes.begin(), bytes.size(), real_type, real_type, UNIVERSAL); } /************************************************* * Encode this object * *************************************************/ -DER_Encoder& DER_Encoder::encode(const byte octets[], u32bit length, +DER_Encoder& DER_Encoder::encode(const byte bytes[], u32bit length, ASN1_Tag real_type) { - return encode(octets, length, real_type, real_type, UNIVERSAL); + return encode(bytes, length, real_type, real_type, UNIVERSAL); } /************************************************* @@ -382,18 +318,18 @@ DER_Encoder& DER_Encoder::encode(const BigInt& n, /************************************************* * DER encode an OCTET STRING or BIT STRING * *************************************************/ -DER_Encoder& DER_Encoder::encode(const MemoryRegion<byte>& octets, +DER_Encoder& DER_Encoder::encode(const MemoryRegion<byte>& bytes, ASN1_Tag real_type, ASN1_Tag type_tag, ASN1_Tag class_tag) { - return encode(octets.begin(), octets.size(), + 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 octets[], u32bit length, +DER_Encoder& DER_Encoder::encode(const byte bytes[], u32bit length, ASN1_Tag real_type, ASN1_Tag type_tag, ASN1_Tag class_tag) { @@ -404,11 +340,21 @@ DER_Encoder& DER_Encoder::encode(const byte octets[], u32bit length, { SecureVector<byte> encoded; encoded.append(0); - encoded.append(octets, length); + encoded.append(bytes, length); return add_object(type_tag, class_tag, encoded); } else - return add_object(type_tag, class_tag, octets, length); + 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); } /************************************************* @@ -421,7 +367,7 @@ DER_Encoder& DER_Encoder::encode(const ASN1_Object& obj) } /************************************************* -* Write the encoding of the octet(s) * +* 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) @@ -434,11 +380,11 @@ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, buffer.append(encoded_length); buffer.append(rep, length); - return add_raw_octets(buffer); + return raw_bytes(buffer); } /************************************************* -* Write the encoding of the octet(s) * +* Write the encoding of the byte(s) * *************************************************/ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, const MemoryRegion<byte>& rep_buf) @@ -449,7 +395,7 @@ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, } /************************************************* -* Write the encoding of the octet(s) * +* 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) @@ -460,7 +406,7 @@ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, } /************************************************* -* Write the encoding of the octet * +* Write the encoding of the byte * *************************************************/ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, ASN1_Tag class_tag, byte rep) @@ -468,12 +414,4 @@ DER_Encoder& DER_Encoder::add_object(ASN1_Tag type_tag, return add_object(type_tag, class_tag, &rep, 1); } -/************************************************* -* DER_Encoder Constructor * -*************************************************/ -DER_Encoder::DER_Encoder() - { - sequence_level = 0; - } - } diff --git a/src/dl_algo.cpp b/src/dl_algo.cpp index e29696200..6e61a672b 100644 --- a/src/dl_algo.cpp +++ b/src/dl_algo.cpp @@ -15,9 +15,7 @@ namespace Botan { *************************************************/ MemoryVector<byte> DL_Scheme_PublicKey::DER_encode_pub() const { - DER_Encoder der; - der.encode(y); - return der.get_contents(); + return DER_Encoder().encode(y).get_contents(); } /************************************************* @@ -53,9 +51,7 @@ void DL_Scheme_PublicKey::BER_decode_params(DataSource& source) *************************************************/ SecureVector<byte> DL_Scheme_PrivateKey::DER_encode_priv() const { - DER_Encoder der; - der.encode(x); - return der.get_contents(); + return DER_Encoder().encode(x).get_contents(); } /************************************************* diff --git a/src/dl_group.cpp b/src/dl_group.cpp index f54ceac22..fffc64185 100644 --- a/src/dl_group.cpp +++ b/src/dl_group.cpp @@ -194,30 +194,30 @@ SecureVector<byte> DL_Group::DER_encode(Format format) const if(format == ANSI_X9_57) { return DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode(p) .encode(q) .encode(g) - .end_sequence() + .end_cons() .get_contents(); } else if(format == ANSI_X9_42) { return DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode(p) .encode(g) .encode(q) - .end_sequence() + .end_cons() .get_contents(); } else if(format == PKCS_3) { return DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode(p) .encode(g) - .end_sequence() + .end_cons() .get_contents(); } @@ -248,7 +248,7 @@ void DL_Group::BER_decode(DataSource& source, Format format) BigInt new_p, new_q, new_g; BER_Decoder decoder(source); - BER_Decoder ber = BER::get_subsequence(decoder); + BER_Decoder ber = decoder.start_cons(SEQUENCE); if(format == ANSI_X9_57) { diff --git a/src/if_algo.cpp b/src/if_algo.cpp index 8c6a8654e..36d859282 100644 --- a/src/if_algo.cpp +++ b/src/if_algo.cpp @@ -16,10 +16,10 @@ namespace Botan { MemoryVector<byte> IF_Scheme_PublicKey::DER_encode_pub() const { return DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode(n) .encode(e) - .end_sequence() + .end_cons() .get_contents(); } @@ -36,12 +36,12 @@ MemoryVector<byte> IF_Scheme_PublicKey::DER_encode_params() const *************************************************/ void IF_Scheme_PublicKey::BER_decode_pub(DataSource& source) { - BER_Decoder decoder(source); - BER_Decoder ber = BER::get_subsequence(decoder); - - ber.decode(n) - .decode(e) - .verify_end(); + BER_Decoder(source) + .start_cons(SEQUENCE) + .decode(n) + .decode(e) + .verify_end() + .end_cons(); X509_load_hook(); } @@ -62,7 +62,7 @@ void IF_Scheme_PublicKey::BER_decode_params(DataSource& source) SecureVector<byte> IF_Scheme_PrivateKey::DER_encode_priv() const { return DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode((u32bit)0) .encode(n) .encode(e) @@ -72,7 +72,7 @@ SecureVector<byte> IF_Scheme_PrivateKey::DER_encode_priv() const .encode(d1) .encode(d2) .encode(c) - .end_sequence() + .end_cons() .get_contents(); } @@ -83,19 +83,18 @@ void IF_Scheme_PrivateKey::BER_decode_priv(DataSource& source) { u32bit version; - BER_Decoder decoder(source); - BER_Decoder ber = BER::get_subsequence(decoder); - - ber.decode(version) - .decode(n) - .decode(e) - .decode(d) - .decode(p) - .decode(q) - .decode(d1) - .decode(d2) - .decode(c) - .verify_end(); + BER_Decoder(source) + .start_cons(SEQUENCE) + .decode(version) + .decode(n) + .decode(e) + .decode(d) + .decode(p) + .decode(q) + .decode(d1) + .decode(d2) + .decode(c) + .end_cons(); if(version != 0) throw Decoding_Error(algo_name() + ": Unknown PKCS #1 key version"); diff --git a/src/libstate.cpp b/src/libstate.cpp index 4990938f3..456a4a8dd 100644 --- a/src/libstate.cpp +++ b/src/libstate.cpp @@ -14,8 +14,12 @@ namespace Botan { /************************************************* * Botan's global state * *************************************************/ +namespace { + Library_State* global_lib_state = 0; +} + Library_State& global_state() { if(!global_lib_state) diff --git a/src/pbes1.cpp b/src/pbes1.cpp index d99e9a1fd..da97ee2da 100644 --- a/src/pbes1.cpp +++ b/src/pbes1.cpp @@ -94,14 +94,12 @@ void PBE_PKCS5v15::new_params() *************************************************/ MemoryVector<byte> PBE_PKCS5v15::encode_params() const { - DER_Encoder der; - - der.start_sequence() - .encode(salt, OCTET_STRING) - .encode(iterations) - .end_sequence(); - - return der.get_contents(); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode(salt, OCTET_STRING) + .encode(iterations) + .end_cons() + .get_contents(); } /************************************************* @@ -109,11 +107,12 @@ MemoryVector<byte> PBE_PKCS5v15::encode_params() const *************************************************/ void PBE_PKCS5v15::decode_params(DataSource& source) { - BER_Decoder decoder(source); - BER_Decoder sequence = BER::get_subsequence(decoder); - sequence.decode(salt, OCTET_STRING); - sequence.decode(iterations); - sequence.verify_end(); + BER_Decoder(source) + .start_cons(SEQUENCE) + .decode(salt, OCTET_STRING) + .decode(iterations) + .verify_end() + .end_cons(); if(salt.size() != 8) throw Decoding_Error("PBES1: Encoded salt is not 8 octets"); diff --git a/src/pbes2.cpp b/src/pbes2.cpp index 036acb675..0eeb4eee5 100644 --- a/src/pbes2.cpp +++ b/src/pbes2.cpp @@ -4,6 +4,8 @@ *************************************************/ #include <botan/pbe_pkcs.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/parsing.h> #include <botan/lookup.h> #include <botan/rng.h> @@ -95,15 +97,15 @@ void PBE_PKCS5v20::new_params() MemoryVector<byte> PBE_PKCS5v20::encode_params() const { return DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode( AlgorithmIdentifier("PKCS5.PBKDF2", DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode(salt, OCTET_STRING) .encode(iterations) .encode(key_length) - .end_sequence() + .end_cons() .get_contents() ) ) @@ -114,7 +116,7 @@ MemoryVector<byte> PBE_PKCS5v20::encode_params() const .get_contents() ) ) - .end_sequence() + .end_cons() .get_contents(); } @@ -125,22 +127,24 @@ void PBE_PKCS5v20::decode_params(DataSource& source) { AlgorithmIdentifier kdf_algo, enc_algo; - BER_Decoder decoder(source); - BER_Decoder sequence = BER::get_subsequence(decoder); - BER::decode(sequence, kdf_algo); - BER::decode(sequence, enc_algo); - sequence.verify_end(); + BER_Decoder(source) + .start_cons(SEQUENCE) + .decode(kdf_algo) + .decode(enc_algo) + .verify_end() + .end_cons(); if(kdf_algo.oid == OIDS::lookup("PKCS5.PBKDF2")) { digest = "SHA-160"; - BER_Decoder pbkdf2_params(kdf_algo.parameters); - BER_Decoder algo_params = BER::get_subsequence(pbkdf2_params); - algo_params.decode(salt, OCTET_STRING); - algo_params.decode(iterations); - BER::decode_optional(algo_params, key_length, INTEGER, UNIVERSAL); - algo_params.verify_end(); + BER_Decoder(kdf_algo.parameters) + .start_cons(SEQUENCE) + .decode(salt, OCTET_STRING) + .decode(iterations) + .decode_optional(key_length, INTEGER, UNIVERSAL) + .verify_end() + .end_cons(); } else throw Decoding_Error("PBE-PKCS5 v2.0: Unknown KDF algorithm " + @@ -156,12 +160,7 @@ void PBE_PKCS5v20::decode_params(DataSource& source) throw Decoding_Error("PBE-PKCS5 v2.0: Don't know param format for " + cipher); -#if 0 - BER_Decoder algo_params(enc_algo.parameters); - algo_params.decode(iv, OCTET_STRING); -#else BER_Decoder(enc_algo.parameters).decode(iv, OCTET_STRING).verify_end(); -#endif if(key_length == 0) key_length = max_keylength_of(cipher_algo); diff --git a/src/pkcs10.cpp b/src/pkcs10.cpp index a567f5a00..74ff30867 100644 --- a/src/pkcs10.cpp +++ b/src/pkcs10.cpp @@ -4,7 +4,8 @@ *************************************************/ #include <botan/pkcs10.h> -#include <botan/asn1_int.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/parsing.h> #include <botan/x509stor.h> #include <botan/oids.h> @@ -49,7 +50,7 @@ void PKCS10_Request::force_decode() throw Decoding_Error("Unknown version code in PKCS #10 request: " + to_string(version)); - BER::decode(cert_req_info, dn); + cert_req_info.decode(dn); BER_Object public_key = cert_req_info.get_next_object(); if(public_key.type_tag != SEQUENCE || public_key.class_tag != CONSTRUCTED) @@ -66,7 +67,7 @@ void PKCS10_Request::force_decode() while(attributes.more_items()) { Attribute attr; - BER::decode(attributes, attr); + attributes.decode(attr); handle_attribute(attr); } attributes.verify_end(); @@ -96,23 +97,23 @@ void PKCS10_Request::handle_attribute(const Attribute& attr) if(attr.oid == OIDS::lookup("PKCS9.EmailAddress")) { ASN1_String email; - BER::decode(value, email); + value.decode(email); subject_alt.add_attribute("RFC822", email.value()); } else if(attr.oid == OIDS::lookup("PKCS9.ChallengePassword")) { ASN1_String challenge_password; - BER::decode(value, challenge_password); + value.decode(challenge_password); challenge = challenge_password.value(); } else if(attr.oid == OIDS::lookup("PKCS9.ExtensionRequest")) { - BER_Decoder sequence = BER::get_subsequence(value); + BER_Decoder sequence = value.start_cons(SEQUENCE); while(sequence.more_items()) { Extension extn; - BER::decode(sequence, extn); + sequence.decode(extn); handle_v3_extension(extn); } sequence.verify_end(); @@ -130,23 +131,23 @@ void PKCS10_Request::handle_v3_extension(const Extension& extn) BER::decode(value, constraints_value); else if(extn.oid == OIDS::lookup("X509v3.ExtendedKeyUsage")) { - BER_Decoder key_usage = BER::get_subsequence(value); + BER_Decoder key_usage = value.start_cons(SEQUENCE); while(key_usage.more_items()) { OID usage_oid; - BER::decode(key_usage, usage_oid); + key_usage.decode(usage_oid); ex_constraints_list.push_back(usage_oid); } } else if(extn.oid == OIDS::lookup("X509v3.BasicConstraints")) { - BER_Decoder constraints = BER::get_subsequence(value); - BER::decode_optional(constraints, is_ca, BOOLEAN, UNIVERSAL, false); - BER::decode_optional(constraints, max_path_len, - INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT); + BER_Decoder constraints = value.start_cons(SEQUENCE); + constraints.decode_optional(is_ca, BOOLEAN, UNIVERSAL, false); + constraints.decode_optional(max_path_len, INTEGER, UNIVERSAL, + NO_CERT_PATH_LIMIT); } else if(extn.oid == OIDS::lookup("X509v3.SubjectAlternativeName")) - BER::decode(value, subject_alt); + value.decode(subject_alt); else return; diff --git a/src/pkcs8.cpp b/src/pkcs8.cpp index 2888774dd..72fcb41e4 100644 --- a/src/pkcs8.cpp +++ b/src/pkcs8.cpp @@ -4,6 +4,8 @@ *************************************************/ #include <botan/pkcs8.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/asn1_obj.h> #include <botan/pk_algs.h> #include <botan/conf.h> @@ -28,8 +30,8 @@ SecureVector<byte> PKCS8_extract(DataSource& source, try { BER_Decoder decoder(source); - BER_Decoder sequence = BER::get_subsequence(decoder); - BER::decode(sequence, alg_id); + BER_Decoder sequence = decoder.start_cons(SEQUENCE); + sequence.decode(alg_id); sequence.decode(enc_pkcs8_key, OCTET_STRING); sequence.verify_end(); } @@ -107,17 +109,18 @@ SecureVector<byte> PKCS8_decode(DataSource& source, const User_Interface& ui, } u32bit version; - BER_Decoder decoder(key); - BER_Decoder sequence = BER::get_subsequence(decoder); - sequence.decode(version); + + BER_Decoder(key) + .start_cons(SEQUENCE) + .decode(version) + .decode(pk_alg_id) + .decode(key, OCTET_STRING) + .discard_remaining() + .end_cons(); + if(version != 0) throw Decoding_Error("PKCS #8: Unknown version number"); - BER::decode(sequence, pk_alg_id); - sequence.decode(key, OCTET_STRING); - sequence.discard_remaining(); - sequence.verify_end(); - break; } catch(Decoding_Error) @@ -144,11 +147,11 @@ void encode(const PKCS8_PrivateKey& key, Pipe& pipe, X509_Encoding encoding) SecureVector<byte> contents = DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode(PKCS8_VERSION) .encode(alg_id) .encode(key.DER_encode_priv(), OCTET_STRING) - .end_sequence() + .end_cons() .get_contents(); if(encoding == PEM) @@ -177,12 +180,12 @@ void encrypt_key(const PKCS8_PrivateKey& key, Pipe& pipe, Pipe key_encrytor(pbe); key_encrytor.process_msg(raw_key); - SecureVector<byte> enc_key = + SecureVector<byte> enc_key = DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode(AlgorithmIdentifier(pbe->get_oid(), pbe->encode_params())) .encode(key_encrytor.read_all(), OCTET_STRING) - .end_sequence() + .end_cons() .get_contents(); if(encoding == PEM) diff --git a/src/policy.cpp b/src/policy.cpp index 72f751560..3ec3227db 100644 --- a/src/policy.cpp +++ b/src/policy.cpp @@ -227,7 +227,6 @@ void set_default_config(Library_State* state) state->set_option("conf", "x509/exts/key_usage", "critical"); state->set_option("conf", "x509/exts/extended_key_usage", "yes"); state->set_option("conf", "x509/exts/crl_number", "yes"); - } /************************************************* diff --git a/src/prf_x942.cpp b/src/prf_x942.cpp index 59a0d96c6..508fe6cc9 100644 --- a/src/prf_x942.cpp +++ b/src/prf_x942.cpp @@ -20,13 +20,11 @@ namespace { *************************************************/ MemoryVector<byte> encode_x942_int(u32bit n) { - byte n_buf[4]; + byte n_buf[4] = { 0 }; for(u32bit j = 0; j != 4; ++j) n_buf[j] = get_byte(j, n); - DER_Encoder encoder; - encoder.encode(n_buf, 4, OCTET_STRING); - return encoder.get_contents(); + return DER_Encoder().encode(n_buf, 4, OCTET_STRING).get_contents(); } } @@ -46,28 +44,30 @@ SecureVector<byte> X942_PRF::derive(u32bit key_len, while(key.size() != key_len) { - DER_Encoder encoder; - - encoder.start_sequence() - .start_sequence() - .encode(kek_algo) - .add_raw_octets(encode_x942_int(counter)) - .end_sequence(); - - if(salt_len) - { - encoder.start_explicit(ASN1_Tag(0)); - encoder.encode(salt, salt_len, OCTET_STRING); - encoder.end_explicit(ASN1_Tag(0)); - } - - encoder.start_explicit(ASN1_Tag(2)) - .add_raw_octets(encode_x942_int(8 * key_len)) - .end_explicit(ASN1_Tag(2)) - .end_sequence(); - hash->update(secret, secret_len); - hash->update(encoder.get_contents()); + + hash->update( + DER_Encoder().start_cons(SEQUENCE) + + .start_cons(SEQUENCE) + .encode(kek_algo) + .raw_bytes(encode_x942_int(counter)) + .end_cons() + + .encode_if(salt_len != 0, + DER_Encoder() + .start_explicit(0) + .encode(salt, salt_len, OCTET_STRING) + .end_explicit() + ) + + .start_explicit(2) + .raw_bytes(encode_x942_int(8 * key_len)) + .end_explicit() + + .end_cons().get_contents() + ); + SecureVector<byte> digest = hash->final(); key.append(digest, std::min(digest.size(), key_len - key.size())); diff --git a/src/pubkey.cpp b/src/pubkey.cpp index 75772fd47..c23d16bd4 100644 --- a/src/pubkey.cpp +++ b/src/pubkey.cpp @@ -4,11 +4,12 @@ *************************************************/ #include <botan/pubkey.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> +#include <botan/bigint.h> #include <botan/parsing.h> #include <botan/bit_ops.h> #include <botan/lookup.h> -#include <botan/der_enc.h> -#include <botan/ber_dec.h> #include <memory> namespace Botan { @@ -196,13 +197,11 @@ SecureVector<byte> PK_Signer::signature() for(u32bit j = 0; j != sig_parts.size(); ++j) sig_parts[j].binary_decode(plain_sig + SIZE_OF_PART*j, SIZE_OF_PART); - DER_Encoder der_sig; - der_sig.start_sequence(); - for(u32bit j = 0; j != sig_parts.size(); ++j) - der_sig.encode(sig_parts[j]); - der_sig.end_sequence(); - - return der_sig.get_contents(); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode_list(sig_parts) + .end_cons() + .get_contents(); } else throw Encoding_Error("PK_Signer: Unknown signature format " + @@ -290,7 +289,7 @@ bool PK_Verifier::check_signature(const byte sig[], u32bit length) else if(sig_format == DER_SEQUENCE) { BER_Decoder decoder(sig, length); - BER_Decoder ber_sig = BER::get_subsequence(decoder); + BER_Decoder ber_sig = decoder.start_cons(SEQUENCE); u32bit count = 0; SecureVector<byte> real_sig; diff --git a/src/x509_ca.cpp b/src/x509_ca.cpp index eed733f17..3600843d3 100644 --- a/src/x509_ca.cpp +++ b/src/x509_ca.cpp @@ -6,6 +6,8 @@ #include <botan/x509_ca.h> #include <botan/x509_ext.h> #include <botan/x509stor.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/conf.h> #include <botan/lookup.h> #include <botan/look_pk.h> @@ -13,11 +15,29 @@ #include <botan/oids.h> #include <botan/util.h> #include <algorithm> +#include <typeinfo> #include <memory> #include <set> namespace Botan { +namespace { + +// FIXME: move elsewhere +MemoryVector<byte> make_signed(PK_Signer* signer, + const AlgorithmIdentifier& sig_algo, + const MemoryRegion<byte>& tbs_bits) + { + return DER_Encoder().start_cons(SEQUENCE) + .raw_bytes(tbs_bits) + .encode(sig_algo) + .encode(signer->sign_message(tbs_bits), BIT_STRING) + .end_cons() + .get_contents(); + } + +} + /************************************************* * Load the certificate and private key * *************************************************/ @@ -28,8 +48,11 @@ X509_CA::X509_CA(const X509_Certificate& c, if(!dynamic_cast<const PK_Signing_Key*>(key_pointer)) throw Invalid_Argument("X509_CA: " + key.algo_name() + " cannot sign"); +#if 0 + // FIXME! if(!cert.is_CA_cert()) throw Invalid_Argument("X509_CA: This certificate is not for a CA"); +#endif std::string padding; Signature_Format format; @@ -93,11 +116,9 @@ X509_Certificate X509_CA::make_cert(PK_Signer* signer, Key_Constraints constraints, const std::vector<OID>& ex_constraints) { - const u32bit X509_CERT_VERSION = 2; - const u32bit SERIAL_BITS = 128; - Extensions extensions; + // POLICY: which extensions extensions.add(new Cert_Extension::Subject_Key_ID(pub_key)); extensions.add(new Cert_Extension::Authority_Key_ID(auth_key_id)); @@ -120,41 +141,35 @@ X509_Certificate X509_CA::make_cert(PK_Signer* signer, "issuer_alternative_name") ); - MemoryVector<byte> tbs_bits = - DER_Encoder().start_sequence() - .start_explicit(ASN1_Tag(0)) - .encode(X509_CERT_VERSION) - .end_explicit(ASN1_Tag(0)) - - .encode(random_integer(SERIAL_BITS)) - .encode(sig_algo) - .encode(issuer_dn) - - .start_sequence() - .encode(not_before) - .encode(not_after) - .end_sequence() - - .encode(subject_dn) - .add_raw_octets(pub_key) - - .start_explicit(ASN1_Tag(3)) - .start_sequence() - .encode(extensions) - .end_sequence() - .end_explicit(ASN1_Tag(3)) - .end_sequence() - .get_contents(); - - DataSource_Memory source( - DER_Encoder() - .start_sequence() - .add_raw_octets(tbs_bits) + const u32bit X509_CERT_VERSION = 3; + const u32bit SERIAL_BITS = 128; + + DataSource_Memory source(make_signed(signer, sig_algo, + DER_Encoder().start_cons(SEQUENCE) + .start_explicit(0) + .encode(X509_CERT_VERSION-1) + .end_explicit() + + .encode(random_integer(SERIAL_BITS)) .encode(sig_algo) - .encode(signer->sign_message(tbs_bits), BIT_STRING) - .end_sequence() + .encode(issuer_dn) + + .start_cons(SEQUENCE) + .encode(not_before) + .encode(not_after) + .end_cons() + + .encode(subject_dn) + .raw_bytes(pub_key) + + .start_explicit(3) + .start_cons(SEQUENCE) + .encode(extensions) + .end_cons() + .end_explicit() + .end_cons() .get_contents() - ); + )); return X509_Certificate(source); } @@ -215,7 +230,7 @@ X509_CRL X509_CA::update_crl(const X509_CRL& crl, X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked, u32bit crl_number, u32bit next_update) const { - const u32bit X509_CRL_VERSION = 1; + const u32bit X509_CRL_VERSION = 2; if(next_update == 0) next_update = Config::get_time("x509/crl/next_update"); @@ -223,47 +238,31 @@ X509_CRL X509_CA::make_crl(const std::vector<CRL_Entry>& revoked, const u64bit current_time = system_time(); Extensions extensions; - extensions.add(new Cert_Extension::Authority_Key_ID(cert.subject_key_id())); + extensions.add( + new Cert_Extension::Authority_Key_ID(cert.subject_key_id())); extensions.add(new Cert_Extension::CRL_Number(crl_number)); - DER_Encoder tbs_crl; - - tbs_crl - .start_sequence() - .encode(X509_CRL_VERSION) - .encode(ca_sig_algo) - .encode(cert.subject_dn()) - .encode(X509_Time(current_time)) - .encode(X509_Time(current_time + next_update)); - - if(revoked.size()) - { - tbs_crl.start_sequence(); - for(u32bit j = 0; j != revoked.size(); ++j) - DER::encode(tbs_crl, revoked[j]); - tbs_crl.end_sequence(); - } - - tbs_crl - .start_explicit(ASN1_Tag(0)) - .start_sequence() - .encode(extensions) - .end_sequence() - .end_explicit(ASN1_Tag(0)) - .end_sequence(); - - MemoryVector<byte> tbs_bits = tbs_crl.get_contents(); - MemoryVector<byte> sig = signer->sign_message(tbs_bits); - - DataSource_Memory source( - DER_Encoder() - .start_sequence() - .add_raw_octets(tbs_bits) + DataSource_Memory source(make_signed(signer, ca_sig_algo, + DER_Encoder().start_cons(SEQUENCE) + .encode(X509_CRL_VERSION-1) .encode(ca_sig_algo) - .encode(sig, BIT_STRING) - .end_sequence() + .encode(cert.issuer_dn()) + .encode(X509_Time(current_time)) + .encode(X509_Time(current_time + next_update)) + .encode_if(revoked.size() > 0, + DER_Encoder() + .start_cons(SEQUENCE) + .encode_list(revoked) + .end_cons() + ) + .start_explicit(0) + .start_cons(SEQUENCE) + .encode(extensions) + .end_cons() + .end_explicit() + .end_cons() .get_contents() - ); + )); return X509_CRL(source); } diff --git a/src/x509_crl.cpp b/src/x509_crl.cpp index 520932dba..491202fc3 100644 --- a/src/x509_crl.cpp +++ b/src/x509_crl.cpp @@ -4,6 +4,7 @@ *************************************************/ #include <botan/x509_crl.h> +#include <botan/ber_dec.h> #include <botan/parsing.h> #include <botan/bigint.h> #include <botan/conf.h> @@ -38,21 +39,21 @@ void X509_CRL::force_decode() { BER_Decoder tbs_crl(tbs_bits); - BER::decode_optional(tbs_crl, version, INTEGER, UNIVERSAL); + tbs_crl.decode_optional(version, INTEGER, UNIVERSAL); if(version != 0 && version != 1) throw X509_CRL_Error("Unknown X.509 CRL version " + to_string(version+1)); AlgorithmIdentifier sig_algo_inner; - BER::decode(tbs_crl, sig_algo_inner); + tbs_crl.decode(sig_algo_inner); if(sig_algo != sig_algo_inner) throw X509_CRL_Error("Algorithm identifier mismatch"); - BER::decode(tbs_crl, issuer); - BER::decode(tbs_crl, start); - BER::decode(tbs_crl, end); + tbs_crl.decode(issuer); + tbs_crl.decode(start); + tbs_crl.decode(end); BER_Object next = tbs_crl.get_next_object(); @@ -63,7 +64,7 @@ void X509_CRL::force_decode() while(cert_list.more_items()) { CRL_Entry entry; - BER::decode(cert_list, entry); + cert_list.decode(entry); revoked.push_back(entry); } next = tbs_crl.get_next_object(); @@ -73,12 +74,12 @@ void X509_CRL::force_decode() next.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) { BER_Decoder crl_options(next.value); - BER_Decoder sequence = BER::get_subsequence(crl_options); + BER_Decoder sequence = crl_options.start_cons(SEQUENCE); while(sequence.more_items()) { Extension extn; - BER::decode(sequence, extn); + sequence.decode(extn); handle_crl_extension(extn); } next = tbs_crl.get_next_object(); @@ -99,9 +100,8 @@ void X509_CRL::handle_crl_extension(const Extension& extn) if(extn.oid == OIDS::lookup("X509v3.AuthorityKeyIdentifier")) { - BER_Decoder key_id = BER::get_subsequence(value); - BER::decode_optional_string(key_id, issuer_key_id, OCTET_STRING, - ASN1_Tag(0), CONTEXT_SPECIFIC); + BER_Decoder key_id = value.start_cons(SEQUENCE); + key_id.decode_optional_string(issuer_key_id, OCTET_STRING, 0); } else if(extn.oid == OIDS::lookup("X509v3.CRLNumber")) value.decode(crl_count); diff --git a/src/x509_ext.cpp b/src/x509_ext.cpp index b814d3c43..38d2fbabb 100644 --- a/src/x509_ext.cpp +++ b/src/x509_ext.cpp @@ -15,63 +15,36 @@ namespace Botan { -/************************************************* -* Encode a Certificate Extension * -*************************************************/ -void Certificate_Extension::encode_into(DER_Encoder& der, - bool is_critical) const - { - if(should_encode()) - { -#if 0 - der.start_seqeuence() - .encode(oid_of()) - .encode_optional(is_critical, false) - .encode(encode_inner(), OCTET_STRING) - .end_sequence(); -#else - der.start_sequence(); - der.encode(oid_of()); - if(is_critical) - der.encode(is_critical); - der.encode(encode_inner(), OCTET_STRING); - der.end_sequence(); -#endif - } - } +namespace { /************************************************* -* Decode a Certificate Extension * +* Create a new certificate extension object * *************************************************/ -void Certificate_Extension::decode_from(BER_Decoder& ber) +Certificate_Extension* make_extension(const OID& oid) { - MemoryVector<byte> value; - OID oid; - -#if 0 - ber.start_sequence() - .decode(oid) - .decode_optional(is_critical, false) - .decode(value, OCTET_STRING) - .end_sequence(); -#else - BER_Decoder extension = BER::get_subsequence(ber); - BER::decode(extension, oid); - BER::decode_optional(extension, critical, BOOLEAN, UNIVERSAL, false); - extension.decode(value, OCTET_STRING); - extension.verify_end(); -#endif - - decode_inner(value); + const std::string oid_name = OIDS::lookup(oid); + + if(oid_name == "X509v3.KeyUsage") + return new Cert_Extension::Key_Usage(); + else if(oid_name == "X509v3.BasicConstraints") + return new Cert_Extension::Basic_Constraints(); + else if(oid_name == "X509v3.SubjectKeyIdentifier") + return new Cert_Extension::Subject_Key_ID(); + else if(oid_name == "X509v3.AuthorityKeyIdentifier") + return new Cert_Extension::Authority_Key_ID(); + else if(oid_name == "X509v3.ExtendedKeyUsage") + return new Cert_Extension::Extended_Key_Usage(); + else if(oid_name == "X509v3.CRLNumber") + return new Cert_Extension::CRL_Number(); + else if(oid_name == "X509v3.CertificatePolicies") + return 0;//return new Cert_Extension::Certificate_Policies(); + + //printf("No result for %s\n", oid_name.c_str()); + + return 0; } -/************************************************* -* Encode a Certificate Extension * -*************************************************/ -void Certificate_Extension::encode_into(DER_Encoder& der) const - { - encode_into(der, critical); - } +} /************************************************* * Return the OID of this extension * @@ -82,24 +55,64 @@ OID Certificate_Extension::oid_of() const } /************************************************* -* Encode a Certificate Extension * +* Encode an Extensions list * *************************************************/ -void Certificate_Extension::maybe_add(class DER_Encoder& der) const +void Extensions::encode_into(DER_Encoder& to_object) const { - const std::string opt_name = "x509/exts/" + config_id(); - std::string setting = Config::get_string(opt_name); - - if(setting != "no") - encode_into(der, critical || (setting == "critical")); + for(u32bit j = 0; j != extensions.size(); j++) + { + const Certificate_Extension* ext = extensions[j]; + + if(ext->should_encode()) + { + to_object.start_cons(SEQUENCE) + .encode(ext->oid_of()) + .encode_optional(ext->is_critical(), false) + .encode(ext->encode_inner(), OCTET_STRING) + .end_cons(); + } + } } /************************************************* -* Encode an Extensions list * +* Decode a list of Extensions * *************************************************/ -void Extensions::encode_into(class DER_Encoder& to_object) const +void Extensions::decode_from(BER_Decoder& from_source) { for(u32bit j = 0; j != extensions.size(); ++j) - extensions[j]->maybe_add(to_object); + delete extensions[j]; + extensions.clear(); + + BER_Decoder sequence = from_source.start_cons(SEQUENCE); + while(sequence.more_items()) + { + OID oid; + MemoryVector<byte> value; + bool critical; + + sequence.start_cons(SEQUENCE) + .decode(oid) + .decode_optional(critical, BOOLEAN, UNIVERSAL, false) + .decode(value, OCTET_STRING) + .verify_end() + .end_cons(); + + Certificate_Extension* ext = make_extension(oid); + + if(!ext) + { + if(!critical) + continue; + + throw Decoding_Error("Encountered unknown X.509 extension marked" + "as critical; OID = " + oid.as_string()); + } + + ext->decode_inner(value); + + extensions.push_back(ext); + } + sequence.verify_end(); } /************************************************* @@ -118,18 +131,15 @@ namespace Cert_Extension { *************************************************/ MemoryVector<byte> Basic_Constraints::encode_inner() const { - DER_Encoder der; - - der.start_sequence(); - if(is_ca) - { - der.encode(true); - if(path_limit != NO_CERT_PATH_LIMIT) - der.encode(path_limit); - } - der.end_sequence(); - - return der.get_contents(); + return DER_Encoder() + .start_cons(SEQUENCE) + .encode_if(is_ca, + DER_Encoder() + .encode(is_ca) + .encode_optional(path_limit, NO_CERT_PATH_LIMIT) + ) + .end_cons() + .get_contents(); } /************************************************* @@ -137,23 +147,24 @@ MemoryVector<byte> Basic_Constraints::encode_inner() const *************************************************/ void Basic_Constraints::decode_inner(const MemoryRegion<byte>& in) { - BER_Decoder ber(in); - - BER_Decoder basic_constraints = BER::get_subsequence(ber); - BER::decode_optional(basic_constraints, is_ca, - BOOLEAN, UNIVERSAL, false); - BER::decode_optional(basic_constraints, path_limit, - INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT); - basic_constraints.verify_end(); + BER_Decoder(in) + .start_cons(SEQUENCE) + .decode_optional(is_ca, BOOLEAN, UNIVERSAL, false) + .decode_optional(path_limit, INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT) + .verify_end() + .end_cons(); + + if(is_ca == false) + path_limit = 0; } /************************************************* -* Basic_Constraints Constructor * +* Return a textual representation * *************************************************/ -Basic_Constraints::Basic_Constraints(bool is_ca, u32bit path_limit) +void Basic_Constraints::contents_to(Data_Store& subject, Data_Store&) const { - this->is_ca = is_ca; - this->path_limit = path_limit; + subject.add("X509v3.BasicConstraints.path_constraint", + (is_ca ? path_limit : 0)); } /************************************************* @@ -206,11 +217,11 @@ void Key_Usage::decode_inner(const MemoryRegion<byte>& in) } /************************************************* -* Key_Usage Constructor * +* Return a textual representation * *************************************************/ -Key_Usage::Key_Usage(Key_Constraints constraints) +void Key_Usage::contents_to(Data_Store& subject, Data_Store&) const { - this->constraints = constraints; + subject.add("X509v3.KeyUsage", constraints); } /************************************************* @@ -230,6 +241,14 @@ void Subject_Key_ID::decode_inner(const MemoryRegion<byte>& in) } /************************************************* +* Return a textual representation * +*************************************************/ +void Subject_Key_ID::contents_to(Data_Store& subject, Data_Store&) const + { + subject.add("X509v3.SubjectKeyIdentifier", key_id); + } + +/************************************************* * Subject_Key_ID Constructor * *************************************************/ Subject_Key_ID::Subject_Key_ID(const MemoryRegion<byte>& pub_key) @@ -244,9 +263,9 @@ Subject_Key_ID::Subject_Key_ID(const MemoryRegion<byte>& pub_key) MemoryVector<byte> Authority_Key_ID::encode_inner() const { return DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode(key_id, OCTET_STRING, ASN1_Tag(0), CONTEXT_SPECIFIC) - .end_sequence() + .end_cons() .get_contents(); } @@ -256,15 +275,16 @@ MemoryVector<byte> Authority_Key_ID::encode_inner() const void Authority_Key_ID::decode_inner(const MemoryRegion<byte>& in) { BER_Decoder ber(in); - + // FIXME } /************************************************* -* Authority_Key_ID Constructor * +* Return a textual representation * *************************************************/ -Authority_Key_ID::Authority_Key_ID(const MemoryRegion<byte>& key_id) +void Authority_Key_ID::contents_to(Data_Store&, Data_Store& issuer) const { - this->key_id = key_id; + if(key_id.size()) + issuer.add("X509v3.AuthorityKeyIdentifier", key_id); } /************************************************* @@ -280,8 +300,15 @@ MemoryVector<byte> Alternative_Name::encode_inner() const *************************************************/ void Alternative_Name::decode_inner(const MemoryRegion<byte>& in) { - BER_Decoder ber(in); + BER_Decoder(in).decode(alt_name); + } +/************************************************* +* Return a textual representation * +*************************************************/ +void Alternative_Name::contents_to(Data_Store& info, Data_Store&) const + { + info.add(alt_name.contents()); } /************************************************* @@ -301,31 +328,93 @@ Alternative_Name::Alternative_Name(const AlternativeName& alt_name, *************************************************/ MemoryVector<byte> Extended_Key_Usage::encode_inner() const { - DER_Encoder der; + return DER_Encoder() + .start_cons(SEQUENCE) + .encode_list(oids) + .end_cons() + .get_contents(); + } - der.start_sequence(); - for(u32bit j = 0; j != oids.size(); ++j) - der.encode(oids[j]); - der.end_sequence(); +/************************************************* +* Decode the extension * +*************************************************/ +void Extended_Key_Usage::decode_inner(const MemoryRegion<byte>& in) + { + BER_Decoder(in) + .start_cons(SEQUENCE) + .decode_list(oids) + .end_cons(); + } - return der.get_contents(); +/************************************************* +* Return a textual representation * +*************************************************/ +void Extended_Key_Usage::contents_to(Data_Store& subject, Data_Store&) const + { + for(u32bit j = 0; j != oids.size(); j++) + subject.add("X509v3.ExtendedKeyUsage", oids[j].as_string()); + } + +namespace { + +class Policy_Information : public ASN1_Object + { + public: + OID oid; + + void encode_into(DER_Encoder& codec) const + { + codec.start_cons(SEQUENCE) + .encode(oid) + .end_cons(); + } + void decode_from(BER_Decoder& codec) + { + codec.start_cons(SEQUENCE) + .decode(oid) + .discard_remaining() + .end_cons(); + } + }; + +} + +/************************************************* +* Encode the extension * +*************************************************/ +MemoryVector<byte> Certificate_Policies::encode_inner() const + { + throw Exception("Certificate_Policies::encode_inner: Bugged"); + + std::vector<Policy_Information> policies; + + return DER_Encoder() + .start_cons(SEQUENCE) + .encode_list(policies) + .end_cons() + .get_contents(); } /************************************************* * Decode the extension * *************************************************/ -void Extended_Key_Usage::decode_inner(const MemoryRegion<byte>& in) +void Certificate_Policies::decode_inner(const MemoryRegion<byte>& in) { - BER_Decoder ber(in); + std::vector<Policy_Information> policies; + BER_Decoder(in) + .start_cons(SEQUENCE) + .decode_list(policies) + .end_cons(); } /************************************************* -* Extended_Key_Usage Constructor * +* Return a textual representation * *************************************************/ -Extended_Key_Usage::Extended_Key_Usage(const std::vector<OID>& oids) +void Certificate_Policies::contents_to(Data_Store& info, Data_Store&) const { - this->oids = oids; + for(u32bit j = 0; j != oids.size(); j++) + info.add("X509v3.ExtendedKeyUsage", oids[j].as_string()); } /************************************************* @@ -341,15 +430,43 @@ MemoryVector<byte> CRL_Number::encode_inner() const *************************************************/ void CRL_Number::decode_inner(const MemoryRegion<byte>& in) { - BER_Decoder ber(in); + BER_Decoder(in).decode(crl_number); + } + +/************************************************* +* Return a textual representation * +*************************************************/ +void CRL_Number::contents_to(Data_Store& info, Data_Store&) const + { + info.add("X509v3.CRLNumber", crl_number); + } +/************************************************* +* Encode the extension * +*************************************************/ +MemoryVector<byte> CRL_ReasonCode::encode_inner() const + { + return DER_Encoder() + .encode((u32bit)reason, ENUMERATED, UNIVERSAL) + .get_contents(); + } + +/************************************************* +* Decode the extension * +*************************************************/ +void CRL_ReasonCode::decode_inner(const MemoryRegion<byte>& in) + { + u32bit reason_code = 0; + BER_Decoder(in).decode(reason_code, ENUMERATED, UNIVERSAL); + reason = (CRL_Code)reason_code; } /************************************************* -* CRL_Number Constructor * +* Return a textual representation * *************************************************/ -CRL_Number::CRL_Number(u32bit n) : crl_number(n) +void CRL_ReasonCode::contents_to(Data_Store& info, Data_Store&) const { + info.add("X509v3.CRLReasonCode", reason); } } diff --git a/src/x509_key.cpp b/src/x509_key.cpp index 118242b4e..08b440a3d 100644 --- a/src/x509_key.cpp +++ b/src/x509_key.cpp @@ -6,6 +6,8 @@ #include <botan/x509_key.h> #include <botan/filters.h> #include <botan/asn1_obj.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/pk_algs.h> #include <botan/oids.h> #include <botan/pem.h> @@ -47,11 +49,12 @@ namespace { void X509_extract_info(DataSource& source, AlgorithmIdentifier& alg_id, MemoryVector<byte>& key) { - BER_Decoder decoder(source); - BER_Decoder sequence = BER::get_subsequence(decoder); - BER::decode(sequence, alg_id); - sequence.decode(key, BIT_STRING); - sequence.verify_end(); + BER_Decoder(source) + .start_cons(SEQUENCE) + .decode(alg_id) + .decode(key, BIT_STRING) + .verify_end() + .end_cons(); } } @@ -63,12 +66,12 @@ void encode(const X509_PublicKey& key, Pipe& pipe, X509_Encoding encoding) { AlgorithmIdentifier alg_id(key.get_oid(), key.DER_encode_params()); - MemoryVector<byte> der = + MemoryVector<byte> der = DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode(alg_id) .encode(key.DER_encode_pub(), BIT_STRING) - .end_sequence() + .end_cons() .get_contents(); if(encoding == PEM) diff --git a/src/x509_obj.cpp b/src/x509_obj.cpp index ae545c134..f5d1bab85 100644 --- a/src/x509_obj.cpp +++ b/src/x509_obj.cpp @@ -4,6 +4,11 @@ *************************************************/ #include <botan/x509_obj.h> +#include <botan/x509_key.h> +#include <botan/look_pk.h> +#include <botan/oids.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/parsing.h> #include <botan/pem.h> #include <algorithm> @@ -64,13 +69,15 @@ void X509_Object::init(DataSource& in, const std::string& labels) *************************************************/ void X509_Object::decode_info(DataSource& source) { - BER_Decoder ber(source); - BER_Decoder sequence = BER::get_subsequence(ber); - tbs_bits = BER::get_subsequence(sequence).get_remaining(); - - BER::decode(sequence, sig_algo); - sequence.decode(sig, BIT_STRING); - sequence.verify_end(); + BER_Decoder(source) + .start_cons(SEQUENCE) + .start_cons(SEQUENCE) + .raw_bytes(tbs_bits) + .end_cons() + .decode(sig_algo) + .decode(sig, BIT_STRING) + .verify_end() + .end_cons(); } /************************************************* @@ -78,12 +85,14 @@ void X509_Object::decode_info(DataSource& source) *************************************************/ void X509_Object::encode(Pipe& out, X509_Encoding encoding) const { - SecureVector<byte> der = - DER_Encoder().start_sequence() - .add_raw_octets(tbs_data()) + SecureVector<byte> der = DER_Encoder() + .start_cons(SEQUENCE) + .start_cons(SEQUENCE) + .raw_bytes(tbs_bits) + .end_cons() .encode(sig_algo) .encode(sig, BIT_STRING) - .end_sequence() + .end_cons() .get_contents(); if(encoding == PEM) @@ -141,6 +150,47 @@ AlgorithmIdentifier X509_Object::signature_algorithm() const } /************************************************* +* Check the signature on an object * +*************************************************/ +bool X509_Object::check_signature(X509_PublicKey& pub_key) const + { + try { + std::vector<std::string> sig_info = + split_on(OIDS::lookup(sig_algo.oid), '/'); + + if(sig_info.size() != 2 || sig_info[0] != pub_key.algo_name()) + return false; + + std::string padding = sig_info[1]; + Signature_Format format = + (pub_key.message_parts() >= 2) ? DER_SEQUENCE : IEEE_1363; + + std::auto_ptr<PK_Verifier> verifier; + + if(dynamic_cast<PK_Verifying_with_MR_Key*>(&pub_key)) + { + PK_Verifying_with_MR_Key& sig_key = + dynamic_cast<PK_Verifying_with_MR_Key&>(pub_key); + verifier.reset(get_pk_verifier(sig_key, padding, format)); + } + else if(dynamic_cast<PK_Verifying_wo_MR_Key*>(&pub_key)) + { + PK_Verifying_wo_MR_Key& sig_key = + dynamic_cast<PK_Verifying_wo_MR_Key&>(pub_key); + verifier.reset(get_pk_verifier(sig_key, padding, format)); + } + else + return false; + + return verifier->verify_message(tbs_data(), signature()); + } + catch(...) + { + return false; + } + } + +/************************************************* * Try to decode the actual information * *************************************************/ void X509_Object::do_decode() diff --git a/src/x509cert.cpp b/src/x509cert.cpp index 143cc84b0..9f8fe85a2 100644 --- a/src/x509cert.cpp +++ b/src/x509cert.cpp @@ -4,7 +4,9 @@ *************************************************/ #include <botan/x509cert.h> -#include <botan/asn1_int.h> +#include <botan/x509_ext.h> +#include <botan/der_enc.h> +#include <botan/ber_dec.h> #include <botan/stl_util.h> #include <botan/parsing.h> #include <botan/bigint.h> @@ -132,8 +134,9 @@ void X509_Certificate::force_decode() BER_Decoder tbs_cert(tbs_bits); u32bit version; - BER::decode_optional(tbs_cert, version, ASN1_Tag(0), - ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)); + tbs_cert.decode_optional(version, ASN1_Tag(0), + ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)); + if(version > 2) throw Decoding_Error("Unknown X.509 cert version " + to_string(version)); if(version < 2) @@ -146,24 +149,25 @@ void X509_Certificate::force_decode() tbs_cert.decode(serial_bn); AlgorithmIdentifier sig_algo_inner; - BER::decode(tbs_cert, sig_algo_inner); + tbs_cert.decode(sig_algo_inner); if(sig_algo != sig_algo_inner) throw Decoding_Error("Algorithm identifier mismatch"); X509_DN dn_issuer; - BER::decode(tbs_cert, dn_issuer); + tbs_cert.decode(dn_issuer); load_info(issuer, dn_issuer); X509_Time start, end; - BER_Decoder validity = BER::get_subsequence(tbs_cert); - BER::decode(validity, start); - BER::decode(validity, end); - validity.verify_end(); + tbs_cert.start_cons(SEQUENCE) + .decode(start) + .decode(end) + .verify_end() + .end_cons(); X509_DN dn_subject; - BER::decode(tbs_cert, dn_subject); + tbs_cert.decode(dn_subject); load_info(subject, dn_subject); BER_Object public_key = tbs_cert.get_next_object(); @@ -173,26 +177,24 @@ void X509_Certificate::force_decode() MemoryVector<byte> v2_issuer_key_id, v2_subject_key_id; - BER::decode_optional_string(tbs_cert, v2_issuer_key_id, BIT_STRING, - ASN1_Tag(1), CONTEXT_SPECIFIC); - BER::decode_optional_string(tbs_cert, v2_subject_key_id, BIT_STRING, - ASN1_Tag(2), CONTEXT_SPECIFIC); + tbs_cert.decode_optional_string(v2_issuer_key_id, BIT_STRING, 1); + tbs_cert.decode_optional_string(v2_subject_key_id, BIT_STRING, 2); BER_Object v3_exts_data = tbs_cert.get_next_object(); if(v3_exts_data.type_tag == 3 && v3_exts_data.class_tag == ASN1_Tag(CONSTRUCTED | CONTEXT_SPECIFIC)) { BER_Decoder v3_exts_decoder(v3_exts_data.value); - BER_Decoder sequence = BER::get_subsequence(v3_exts_decoder); + BER_Decoder ext_data = v3_exts_decoder.start_cons(SEQUENCE); + v3_exts_decoder.verify_end(); - while(sequence.more_items()) + while(ext_data.more_items()) { Extension extn; - BER::decode(sequence, extn); + ext_data.decode(extn); handle_v3_extension(extn); } - sequence.verify_end(); - v3_exts_decoder.verify_end(); + ext_data.end_cons(); } else if(v3_exts_data.type_tag != NO_OBJECT) throw BER_Bad_Tag("Unknown tag in X.509 cert", @@ -234,22 +236,24 @@ void X509_Certificate::handle_v3_extension(const Extension& extn) } else if(extn.oid == OIDS::lookup("X509v3.ExtendedKeyUsage")) { - BER_Decoder key_usage = BER::get_subsequence(value); + BER_Decoder key_usage = value.start_cons(SEQUENCE); while(key_usage.more_items()) { OID usage_oid; - BER::decode(key_usage, usage_oid); + key_usage.decode(usage_oid); info.add("X509v3.ExtendedKeyUsage", usage_oid.as_string()); } } else if(extn.oid == OIDS::lookup("X509v3.BasicConstraints")) { u32bit max_path_len = 0; - BER_Decoder basic_constraints = BER::get_subsequence(value); - BER::decode_optional(basic_constraints, is_ca, - BOOLEAN, UNIVERSAL, false); - BER::decode_optional(basic_constraints, max_path_len, - INTEGER, UNIVERSAL, NO_CERT_PATH_LIMIT); + + value.start_cons(SEQUENCE) + .decode_optional(is_ca, BOOLEAN, UNIVERSAL, false) + .decode_optional(max_path_len, INTEGER, UNIVERSAL, + NO_CERT_PATH_LIMIT) + .verify_end() + .end_cons(); info.add("X509v3.BasicConstraints.is_ca", is_ca); info.add("X509v3.BasicConstraints.path_constraint", max_path_len); @@ -263,32 +267,32 @@ void X509_Certificate::handle_v3_extension(const Extension& extn) else if(extn.oid == OIDS::lookup("X509v3.AuthorityKeyIdentifier")) { MemoryVector<byte> v3_issuer_key_id; - BER_Decoder key_id = BER::get_subsequence(value); - BER::decode_optional_string(key_id, v3_issuer_key_id, OCTET_STRING, - ASN1_Tag(0), CONTEXT_SPECIFIC); + BER_Decoder key_id = value.start_cons(SEQUENCE); + key_id.decode_optional_string(v3_issuer_key_id, OCTET_STRING, 0); info.add("X509v3.AuthorityKeyIdentifier", v3_issuer_key_id); } else if(extn.oid == OIDS::lookup("X509v3.SubjectAlternativeName")) { AlternativeName alt_name; - BER::decode(value, alt_name); + value.decode(alt_name); load_info(subject, alt_name); } else if(extn.oid == OIDS::lookup("X509v3.IssuerAlternativeName")) { AlternativeName alt_name; - BER::decode(value, alt_name); + value.decode(alt_name); load_info(issuer, alt_name); } else if(extn.oid == OIDS::lookup("X509v3.CertificatePolicies")) { - BER_Decoder ber_policies = BER::get_subsequence(value); + + BER_Decoder ber_policies = value.start_cons(SEQUENCE); while(ber_policies.more_items()) { OID oid; - BER_Decoder policy = BER::get_subsequence(ber_policies); - BER::decode(policy, oid); + BER_Decoder policy = ber_policies.start_cons(SEQUENCE); + policy.decode(oid); if(extn.critical && policy.more_items()) throw Decoding_Error("X.509 v3 critical policy has qualifiers"); diff --git a/src/x509self.cpp b/src/x509self.cpp index 281251bef..f107e005b 100644 --- a/src/x509self.cpp +++ b/src/x509self.cpp @@ -6,6 +6,7 @@ #include <botan/x509self.h> #include <botan/x509_ext.h> #include <botan/x509_ca.h> +#include <botan/der_enc.h> #include <botan/conf.h> #include <botan/look_pk.h> #include <botan/oids.h> @@ -140,53 +141,45 @@ PKCS10_Request create_cert_req(const X509_Cert_Options& opts, DER_Encoder tbs_req; - tbs_req.start_sequence() + tbs_req.start_cons(SEQUENCE) .encode(PKCS10_VERSION) .encode(subject_dn) - .add_raw_octets(pub_key) - .start_explicit(ASN1_Tag(0)); + .raw_bytes(pub_key) + .start_explicit(0); if(opts.challenge != "") { ASN1_String challenge(opts.challenge, DIRECTORY_STRING); -#if 0 - DER_Encoder attr_encoder; - attr_encoder.encode(challenge); - tbs_req.encode( - Attribute("PKCS9.ChallengePassword", attr_encoder.get_contents()) - ); -#else tbs_req.encode( Attribute("PKCS9.ChallengePassword", DER_Encoder().encode(challenge).get_contents() ) ); -#endif } tbs_req.encode( Attribute("PKCS9.ExtensionRequest", DER_Encoder() - .start_sequence() + .start_cons(SEQUENCE) .encode(extensions) - .end_sequence() + .end_cons() .get_contents() ) ) - .end_explicit(ASN1_Tag(0)) - .end_sequence(); + .end_explicit() + .end_cons(); MemoryVector<byte> tbs_bits = tbs_req.get_contents(); MemoryVector<byte> sig = signer->sign_message(tbs_bits); DataSource_Memory source( DER_Encoder() - .start_sequence() - .add_raw_octets(tbs_bits) + .start_cons(SEQUENCE) + .raw_bytes(tbs_bits) .encode(sig_algo) .encode(sig, BIT_STRING) - .end_sequence() + .end_cons() .get_contents() ); |