diff options
author | lloyd <[email protected]> | 2006-05-19 00:07:25 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2006-05-19 00:07:25 +0000 |
commit | f090e030be53e574fecbe7cf50edfb5fdacb53e1 (patch) | |
tree | 0bff0c249a9dbcb674fcd2491ab17e3d123ef1f9 | |
parent | a0af7b26591f8fb79d1f06fe42548e1eb0c35e90 (diff) |
Syntax changes to the BER and DER APIs to improve readability of code
that uses them. These changes are not backwards compatible, this commit
updates all uses of the APIs within the library.
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() ); |