aboutsummaryrefslogtreecommitdiffstats
path: root/src/asn1/ber_dec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/asn1/ber_dec.cpp')
-rw-r--r--src/asn1/ber_dec.cpp122
1 files changed, 110 insertions, 12 deletions
diff --git a/src/asn1/ber_dec.cpp b/src/asn1/ber_dec.cpp
index b31c7b903..dbd59988b 100644
--- a/src/asn1/ber_dec.cpp
+++ b/src/asn1/ber_dec.cpp
@@ -99,7 +99,7 @@ size_t decode_length(DataSource* ber)
*/
size_t find_eoc(DataSource* ber)
{
- SecureVector<byte> buffer(DEFAULT_BUFFERSIZE), data;
+ secure_vector<byte> buffer(DEFAULT_BUFFERSIZE), data;
while(true)
{
@@ -141,7 +141,11 @@ size_t find_eoc(DataSource* ber)
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");
+ throw BER_Decoding_Error("Tag mismatch when decoding got " +
+ std::to_string(this->type_tag) + "/" +
+ std::to_string(this->class_tag) + " expected " +
+ std::to_string(type_tag) + "/" +
+ std::to_string(class_tag));
}
/*
@@ -167,7 +171,16 @@ BER_Decoder& BER_Decoder::verify_end()
/*
* Save all the bytes remaining in the source
*/
-BER_Decoder& BER_Decoder::raw_bytes(MemoryRegion<byte>& out)
+BER_Decoder& BER_Decoder::raw_bytes(secure_vector<byte>& out)
+ {
+ out.clear();
+ byte buf;
+ while(source->read_byte(buf))
+ out.push_back(buf);
+ return (*this);
+ }
+
+BER_Decoder& BER_Decoder::raw_bytes(std::vector<byte>& out)
{
out.clear();
byte buf;
@@ -208,7 +221,10 @@ BER_Object BER_Decoder::get_next_object()
size_t length = decode_length(source);
next.value.resize(length);
if(source->read(&next.value[0], length) != length)
+ {
+ abort();
throw BER_Decoding_Error("Value truncated");
+ }
if(next.type_tag == EOC && next.class_tag == UNIVERSAL)
return get_next_object();
@@ -260,7 +276,7 @@ BER_Decoder::BER_Decoder(DataSource& src)
source = &src;
owns = false;
pushed.type_tag = pushed.class_tag = NO_OBJECT;
- parent = 0;
+ parent = nullptr;
}
/*
@@ -271,18 +287,29 @@ BER_Decoder::BER_Decoder(const byte data[], size_t length)
source = new DataSource_Memory(data, length);
owns = true;
pushed.type_tag = pushed.class_tag = NO_OBJECT;
- parent = 0;
+ parent = nullptr;
}
/*
* BER_Decoder Constructor
*/
-BER_Decoder::BER_Decoder(const MemoryRegion<byte>& data)
+BER_Decoder::BER_Decoder(const secure_vector<byte>& data)
{
source = new DataSource_Memory(data);
owns = true;
pushed.type_tag = pushed.class_tag = NO_OBJECT;
- parent = 0;
+ parent = nullptr;
+ }
+
+/*
+* BER_Decoder Constructor
+*/
+BER_Decoder::BER_Decoder(const std::vector<byte>& data)
+ {
+ source = new DataSource_Memory(&data[0], data.size());
+ owns = true;
+ pushed.type_tag = pushed.class_tag = NO_OBJECT;
+ parent = nullptr;
}
/*
@@ -308,7 +335,7 @@ BER_Decoder::~BER_Decoder()
{
if(owns)
delete source;
- source = 0;
+ source = nullptr;
}
/*
@@ -358,7 +385,7 @@ BER_Decoder& BER_Decoder::decode(BigInt& out)
BER_Decoder& BER_Decoder::decode_octet_string_bigint(BigInt& out)
{
- SecureVector<byte> out_vec;
+ secure_vector<byte> out_vec;
decode(out_vec, OCTET_STRING);
out = BigInt::decode(&out_vec[0], out_vec.size());
return (*this);
@@ -400,6 +427,29 @@ BER_Decoder& BER_Decoder::decode(size_t& out,
}
/*
+* Decode a small BER encoded INTEGER
+*/
+u64bit BER_Decoder::decode_constrained_integer(ASN1_Tag type_tag,
+ ASN1_Tag class_tag,
+ size_t T_bytes)
+ {
+ if(T_bytes > 8)
+ throw BER_Decoding_Error("Can't decode small integer over 8 bytes");
+
+ BigInt integer;
+ decode(integer, type_tag, class_tag);
+
+ if(integer.bits() > 8*T_bytes)
+ throw BER_Decoding_Error("Decoded integer value larger than expected");
+
+ u64bit out = 0;
+ for(size_t i = 0; i != 8; ++i)
+ out = (out << 8) | integer.byte_at(7-i);
+
+ return out;
+ }
+
+/*
* Decode a BER encoded INTEGER
*/
BER_Decoder& BER_Decoder::decode(BigInt& out,
@@ -435,7 +485,15 @@ BER_Decoder& BER_Decoder::decode(BigInt& out,
/*
* BER decode a BIT STRING or OCTET STRING
*/
-BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& out, ASN1_Tag real_type)
+BER_Decoder& BER_Decoder::decode(secure_vector<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(std::vector<byte>& out, ASN1_Tag real_type)
{
return decode(out, real_type, real_type, UNIVERSAL);
}
@@ -443,7 +501,7 @@ BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& out, ASN1_Tag real_type)
/*
* BER decode a BIT STRING or OCTET STRING
*/
-BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& buffer,
+BER_Decoder& BER_Decoder::decode(secure_vector<byte>& buffer,
ASN1_Tag real_type,
ASN1_Tag type_tag, ASN1_Tag class_tag)
{
@@ -466,10 +524,50 @@ BER_Decoder& BER_Decoder::decode(MemoryRegion<byte>& buffer,
return (*this);
}
+BER_Decoder& BER_Decoder::decode(std::vector<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 = unlock(obj.value);
+ else
+ {
+ if(obj.value[0] >= 8)
+ throw BER_Decoding_Error("Bad number of unused bits in BIT STRING");
+
+ buffer.resize(obj.value.size() - 1);
+ copy_mem(&buffer[0], &obj.value[1], obj.value.size() - 1);
+ }
+ return (*this);
+ }
+
/*
* Decode an OPTIONAL string type
*/
-BER_Decoder& BER_Decoder::decode_optional_string(MemoryRegion<byte>& out,
+BER_Decoder& BER_Decoder::decode_optional_string(secure_vector<byte>& out,
+ ASN1_Tag real_type,
+ u16bit type_no)
+ {
+ BER_Object obj = get_next_object();
+
+ ASN1_Tag type_tag = static_cast<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);
+ }
+
+BER_Decoder& BER_Decoder::decode_optional_string(std::vector<byte>& out,
ASN1_Tag real_type,
u16bit type_no)
{