This is the part of the ASN1 encoder/decoder library, which is independent of the type of encoding. The classes defined in this file are allocated statically to create the definition of the ASN1 data structures.
The asn1_per or asn1_ber are used together with these definitions to do the actual Basic Encoding Rule (asn1_ber) or Packet Encoding Rules (asn1_per) encoding and decoding.
The asn1_in and asn1_out are abstract classes are used by the actual encoder/decoder to read/write the data. This way the encoder/decoder may be adapted to different data representations. Functions for reading and writing, bits, bit fields, octets and octet fields need to be provided.
void read_object_identifier(byte * in, dword * out);
void write_object_identifier(dword * in, byte * out);
class asn1_out {
public:
virtual void bit(bool v)=0;
virtual void bit_field(dword v, int len)=0;
virtual void octet(byte v)=0;
virtual void octet_field(byte * v, int len)=0;
virtual void align()=0;
virtual void * new_stream(void * stream)=0;
virtual void append(void * stream)=0;
virtual dword length()=0;
virtual void get_reference(void * & buffer, int & offset)=0;
};
Abstract class to write encoded data. Used by the encoder.
class asn1_in {
public:
virtual bool bit()=0;
virtual dword bit_field(int len)=0;
virtual byte octet()=0;
virtual void octet_field(byte * v, int len)=0;
virtual void align()=0;
virtual int left()=0;
virtual void abort()=0;
virtual int get_count()=0;
virtual void set_count(int count)=0;
virtual void skip(int count)=0;
virtual void save()=0;
virtual void restore()=0;
virtual void get_reference(void * & buffer, int & offset)=0;
};
Abstract class to read encoded data. Used by the decoder.
struct asn1_tag {
dword tag;
void * content;
};
class asn1_context {
protected:
int tag_buffer_size;
int tag_index;
struct asn1_tag * tag_buffer;
int content_buffer_size;
int content_index;
byte * content_buffer;
unsigned fix_mask;
bool trace;
public:
asn1_context(struct asn1_tag * tag_buffer, int tag_buffer_size, void * content_buffer, int content_buffer_size, bool trace);
struct asn1_tag * new_tag(word tag);
struct asn1_tag * new_tag(word tag, int size, dword align);
struct asn1_tag * find_tag(word tag);
void set_seq(int num);
dword get_mask();
dword set_mask(dword mask);
bool trace_on() { return trace; };
void set_fix(unsigned fix_mask) { this->fix_mask = fix_mask; };
int get_content_index() { return content_index; };
virtual void read(class asn1 & asn1, class asn1_in & in)=0;
virtual void write(class asn1 & asn1, class asn1_out & out)=0;
int level;
dword seq_of;
dword seq_mask;
};
class to holding the actual decoded data or holding the data to be encoded. See documentation of specific encoder for usage.
class asn1 {
public:
word tag;
word type;
const char * name;
asn1(int & tag, const char * name);
bool is_present(class asn1_context & context);
virtual void fix(unsigned fix_mask) {};
};
For each supported datatype a class is available for the definition, which uses the class asn1 as base class. These classes have type specific put_content and get_content functions. To put data into the coder context or get data from the coder context.
All the classes, which use asn1 as base class have arguments tag and base as first arguments of their constructor. Tag is used to increment a tag variable, so that each data gets a unique tag. The name is used just for creating debug information, when encoding or decoding.
A third argumenet properties, if present, is used for the flag ASN1_EXTENSION, which indicates that the datatype may be extended.
class asn1_null : public asn1 {
public:
asn1_null(int & tag, const char * name);
void put_content(class asn1_context & context);
};
ASN1 NULL datatype. The put_content sets the element as present.
class asn1_boolean : public asn1 {
public:
asn1_boolean(int & tag, const char * name);
bool get_content(class asn1_context & context);
void put_content(class asn1_context & context, bool content);
};
ASN1 BOOLEAN datatype
class asn1_int : public asn1 {
public:
byte count_bits;
asn1_int(int & tag, const char * name, byte count_bits);
dword get_content(class asn1_context & context);
void put_content(class asn1_context & context, dword content);
};
ASN1 INTEGER datatype, assumes positve values
class asn1_ints : public asn1 {
public:
asn1_ints(int & tag, const char * name);
int get_content(class asn1_context & context);
void put_content(class asn1_context & context, int content);
};
ASN1 INTEGER datatype which allows negative values. No restrictions can be defined with this type.
class asn1_inte : public asn1 {
public:
byte count_bits;
dword max;
asn1_inte(int & tag, const char * name, byte count_bits, dword max);
dword get_content(class asn1_context & context);
void put_content(class asn1_context & context, dword content);
};
ASN1 INTEGER datatype, which may be extended. count_bits is the not extended size. max the maximum value.
class asn1_int8 : public asn1 {
public:
asn1_int8(int & tag, const char * name);
dword get_content(class asn1_context & context);
void put_content(class asn1_context & context, dword content);
};
ASN1 INTEGER datatype. Optimization for the common case of an restriction to 8 bits.
class asn1_int16 : public asn1 {
public:
asn1_int16(int & tag, const char * name);
dword get_content(class asn1_context & context);
void put_content(class asn1_context & context, dword content);
};
ASN1 INTEGER datatype. Optimization for the common case of an restriction to 16 bits.
class asn1_bitstring : public asn1 {
public:
word min_length;
word max_length;
byte len_bits;
asn1_bitstring(int & tag, const char * name, int min_length, int max_length, int len_bits);
byte * get_content(class asn1_context & context, int * length);
void put_content(class asn1_context & context, byte * s, int length);
void put_content(class asn1_context & context, class packet * data);
word get_offset(class asn1_context & context, class packet * data);
};
ASN1 BITSTRING datatype.
class asn1_enumerated : public asn1 {
public:
byte properties;
dword count;
byte count_bits;
asn1_enumerated(int & tag, const char * name, byte properties, byte count, byte count_bits);
dword get_content(class asn1_context & context);
void put_content(class asn1_context & context, dword content);
};
ASN1 ENUMERATED datatype
class asn1_octet_array : public asn1 {
public:
word length;
asn1_octet_array(int & tag, const char * name, word length);
byte * get_content(class asn1_context & context);
void put_content(class asn1_context & context, byte * content);
};
ASN1 OCTET ARRAY
class asn1_ia5_string : public asn1 {
public:
word min_length;
word max_length;
byte len_bits;
byte char_bits;
const char * from;
asn1_ia5_string(int & tag, const char * name, int min_length, int max_length, byte len_bits, byte char_bits, const char * from);
byte * get_content(class asn1_context & context, int * length);
void put_content(class asn1_context & context, byte * s, int length);
};
ASN1 IA5 STRING
class asn1_octet_string : public asn1 {
public:
int std_tag;
word min_length;
word max_length;
byte len_bits;
asn1_octet_string(int & tag, const char * name, int min_length, int max_length, int len_bits);
byte * get_content(class asn1_context & context, int * length);
void put_content(class asn1_context & context, byte * s, int length);
void put_content(class asn1_context & context, class packet * data);
};
ASN1 OCTET STRING
class asn1_word_string : public asn1 {
public:
word min_length;
word max_length;
byte len_bits;
asn1_word_string(int & tag, const char * name, int min_length, int max_length, int len_bits);
word * get_content(class asn1_context & context, int * length);
void put_content(class asn1_context & context, word * s, int length);
};
ASN1 WORD STRING
class asn1_object_identifier : public asn1 {
public:
asn1_object_identifier(int & tag, const char * name);
byte * get_content(class asn1_context & context);
void put_content(class asn1_context & context, byte * content);
};
ASN1 OBJECT IDENTIFIER
class asn1_sequence : public asn1 {
public:
byte properties;
byte count;
class asn1 ** table;
byte * flags;
word * tag_table;
byte ext_count;
asn1_sequence(int & tag, const char * name, byte properties, byte count, class asn1 ** table, byte * flags, byte ext_count=0, word * tag_table=0);
bool get_content(class asn1_context & context);
void put_content(class asn1_context & context, bool content);
};
ASN1 SEQUENCE
class asn1_choice : public asn1 {
public:
byte properties;
byte count;
byte count_bits;
class asn1 ** table;
word * tag_table;
byte ext_count;
asn1_choice(int & tag, const char * name, byte properties, byte count, byte count_bits, class asn1 ** table, byte ext_count=0, word * tag_table=0);
dword get_content(class asn1_context & context);
void put_content(class asn1_context & context, dword content);
};
ASN1 CHOICE
class asn1_sequence_of : public asn1 {
public:
byte count_bits;
byte min_length;
class asn1 * seq;
asn1_sequence_of(int & tag, const char * name, byte count_bits, byte min_length, class asn1 * seq);
dword set_mask(class asn1_context & context);
dword get_content(class asn1_context & context);
void put_content(class asn1_context & context, dword content);
};
ASN1 SEQUENCE OF
class asn1_set_of : public asn1 {
public:
byte count_bits;
byte min_length;
class asn1 * seq;
asn1_set_of(int & tag, const char * name, byte count_bits, byte min_length, class asn1 * seq);
dword set_mask(class asn1_context & context);
dword get_content(class asn1_context & context);
void put_content(class asn1_context & context, dword content);
};
ASN1 SET OF
class asn1_numeric_string : public asn1 {
public:
word min_length;
word max_length;
byte len_bits;
asn1_numeric_string(int & tag, const char * name, int min_length, int max_length, int len_bits);
byte * get_content(class asn1_context & context, int * length);
void put_content(class asn1_context & context, byte * s, int length);
void put_content(class asn1_context & context, class packet * data);
};
ASN1 NUMERIC STRING
class asn1_any : public asn1 {
public:
asn1_any(int & tag, const char * name);
bool get_content(class asn1_context & context);
void put_content(class asn1_context & context);
virtual class asn1 * get_actual(class asn1_context & context) {
return 0;
}
};
ASN1 ANY datatype which may hold any asn1 datatype, which means it is encoded containing a length field, because the total length cannot determined by the content