aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/asn1_int.h17
-rw-r--r--include/asn1_obj.h66
-rw-r--r--include/asn1_oid.h1
-rw-r--r--include/ber_dec.h108
-rw-r--r--include/crl_ent.h23
-rw-r--r--include/datastor.h6
-rw-r--r--include/der_enc.h49
-rw-r--r--include/x509_ext.h84
-rw-r--r--include/x509_obj.h2
-rw-r--r--include/x509cert.h24
-rw-r--r--src/asn1_alg.cpp36
-rw-r--r--src/asn1_alt.cpp56
-rw-r--r--src/asn1_att.cpp34
-rw-r--r--src/asn1_dn.cpp58
-rw-r--r--src/asn1_ext.cpp40
-rw-r--r--src/asn1_int.cpp20
-rw-r--r--src/asn1_ku.cpp3
-rw-r--r--src/asn1_oid.cpp16
-rw-r--r--src/asn1_str.cpp44
-rw-r--r--src/asn1_tm.cpp11
-rw-r--r--src/ber_code.cpp237
-rw-r--r--src/ber_dec.cpp211
-rw-r--r--src/crl_ent.cpp123
-rw-r--r--src/datastor.cpp13
-rw-r--r--src/der_enc.cpp168
-rw-r--r--src/dl_algo.cpp8
-rw-r--r--src/dl_group.cpp14
-rw-r--r--src/if_algo.cpp45
-rw-r--r--src/libstate.cpp4
-rw-r--r--src/pbes1.cpp25
-rw-r--r--src/pbes2.cpp39
-rw-r--r--src/pkcs10.cpp29
-rw-r--r--src/pkcs8.cpp33
-rw-r--r--src/policy.cpp1
-rw-r--r--src/prf_x942.cpp50
-rw-r--r--src/pubkey.cpp19
-rw-r--r--src/x509_ca.cpp147
-rw-r--r--src/x509_crl.cpp22
-rw-r--r--src/x509_ext.cpp335
-rw-r--r--src/x509_key.cpp19
-rw-r--r--src/x509_obj.cpp72
-rw-r--r--src/x509cert.cpp72
-rw-r--r--src/x509self.cpp29
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()
);