8#include <botan/ber_dec.h>
10#include <botan/bigint.h>
11#include <botan/data_src.h>
12#include <botan/internal/int_utils.h>
13#include <botan/internal/loadstor.h>
25const size_t ALLOWED_EOC_NESTINGS = 16;
31 auto b = ber->read_byte();
39 if((*b & 0x1F) != 0x1F) {
54 if((tag_buf >> 24) != 0) {
58 if(tag_bytes == 0 && b == 0x80) {
62 tag_buf = (tag_buf << 7) | (*b & 0x7F);
63 if((*b & 0x80) == 0) {
74size_t find_eoc(
DataSource* src,
size_t allow_indef);
79size_t decode_length(
DataSource* ber,
size_t& field_size,
size_t allow_indef) {
81 if(ber->read_byte(b) == 0) {
89 field_size += (b & 0x7F);
95 if(allow_indef == 0) {
96 throw BER_Decoding_Error(
"Nested EOC markers too deep, rejecting to avoid stack exhaustion");
98 return find_eoc(ber, allow_indef - 1);
104 for(
size_t i = 0; i != field_size - 1; ++i) {
108 if(ber->read_byte(b) == 0) {
111 length = (length << 8) | b;
119size_t find_eoc(
DataSource* ber,
size_t allow_indef) {
124 const size_t got = ber->peek(buffer.data(), buffer.size(), data.size());
129 data += std::make_pair(buffer.data(), got);
139 const size_t tag_size = decode_tag(&source, type_tag, class_tag);
144 size_t length_size = 0;
145 const size_t item_size = decode_length(&source, length_size, allow_indef);
146 source.discard_next(item_size);
148 if(
auto new_len =
checked_add(length, item_size, tag_size, length_size)) {
149 length = new_len.value();
161class DataSource_BERObject final :
public DataSource {
163 size_t read(uint8_t out[],
size_t length)
override {
165 const size_t got = std::min<size_t>(m_obj.length() - m_offset, length);
166 copy_mem(out, m_obj.bits() + m_offset, got);
171 size_t peek(uint8_t out[],
size_t length,
size_t peek_offset)
const override {
173 const size_t bytes_left = m_obj.length() - m_offset;
175 if(peek_offset >= bytes_left) {
179 const size_t got = std::min(bytes_left - peek_offset, length);
180 copy_mem(out, m_obj.bits() + m_offset + peek_offset, got);
184 bool check_available(
size_t n)
override {
186 return (n <= (m_obj.length() - m_offset));
189 bool end_of_data()
const override {
return get_bytes_read() == m_obj.length(); }
191 size_t get_bytes_read()
const override {
return m_offset; }
193 explicit DataSource_BERObject(BER_Object&& obj) : m_obj(std::move(obj)) {}
208 if(m_source->end_of_data() && !m_pushed.is_set()) {
218 return verify_end(
"BER_Decoder::verify_end called, but data remains");
225 if(!m_source->end_of_data() || m_pushed.is_set()) {
236 while(m_source->read_byte(buf) != 0) {}
240std::optional<uint8_t> BER_Decoder::read_next_byte() {
251 if(!m_pushed.is_set()) {
264 if(m_pushed.is_set()) {
265 std::swap(next, m_pushed);
272 decode_tag(m_source, type_tag, class_tag);
273 next.set_tagging(type_tag, class_tag);
274 if(next.
is_set() ==
false) {
278 size_t field_size = 0;
279 const size_t length = decode_length(m_source, field_size, ALLOWED_EOC_NESTINGS);
280 if(!m_source->check_available(length)) {
284 uint8_t* out = next.mutable_bits(length);
285 if(m_source->read(out, length) != length) {
303 if(obj.
length() != sizeofT) {
305 "; Output type size is " + std::to_string(sizeofT));
315 if(m_pushed.is_set()) {
316 throw Invalid_State(
"BER_Decoder: Only one push back is allowed");
322 if(m_pushed.is_set()) {
323 throw Invalid_State(
"BER_Decoder: Only one push back is allowed");
325 m_pushed = std::move(obj);
338 if(m_parent ==
nullptr) {
339 throw Invalid_State(
"BER_Decoder::end_cons called with null parent");
341 if(!m_source->end_of_data()) {
342 throw Decoding_Error(
"BER_Decoder::end_cons called with data left");
348 m_data_src = std::make_unique<DataSource_BERObject>(std::move(obj));
349 m_source = m_data_src.get();
361 m_data_src = std::make_unique<DataSource_Memory>(data, length);
362 m_source = m_data_src.get();
369 m_data_src = std::make_unique<DataSource_Memory>(data);
370 m_source = m_data_src.get();
377 m_data_src = std::make_unique<DataSource_Memory>(data.data(), data.size());
378 m_source = m_data_src.get();
386 std::swap(m_data_src, other.m_data_src);
397 obj.decode_from(*
this);
431 const uint8_t val = obj.
bits()[0];
434 out = (val != 0) ?
true :
false;
444 decode(integer, type_tag, class_tag);
450 if(integer.
bits() > 32) {
455 for(
size_t i = 0; i != 4; ++i) {
456 out = (out << 8) | integer.
byte_at(3 - i);
471 decode(integer, type_tag, class_tag);
473 if(integer.
bits() > 8 * T_bytes) {
478 for(
size_t i = 0; i != 8; ++i) {
479 out = (out << 8) | integer.
byte_at(7 - i);
495 const uint8_t first = obj.
bits()[0];
496 const bool negative = (first & 0x80) == 0x80;
500 for(
size_t i = obj.
length(); i > 0; --i) {
501 const bool gt0 = (vec[i - 1] > 0);
507 for(
size_t i = 0; i != obj.
length(); ++i) {
522template <
typename Alloc>
523void asn1_decode_binary_string(std::vector<uint8_t, Alloc>& buffer,
534 throw BER_Decoding_Error(
"Invalid BIT STRING");
536 if(obj.
bits()[0] >= 8) {
540 buffer.resize(obj.
length() - 1);
558 throw BER_Bad_Tag(
"Bad tag for {BIT,OCTET} STRING",
static_cast<uint32_t
>(real_type));
561 asn1_decode_binary_string(buffer,
get_next_object(), real_type, type_tag, class_tag);
570 throw BER_Bad_Tag(
"Bad tag for {BIT,OCTET} STRING",
static_cast<uint32_t
>(real_type));
573 asn1_decode_binary_string(buffer,
get_next_object(), real_type, type_tag, class_tag);
#define BOTAN_ASSERT_NOMSG(expr)
BER_Decoder(const uint8_t buf[], size_t len)
const BER_Object & peek_next_object()
void push_back(const BER_Object &obj)
BER_Object get_next_object()
BER_Decoder & get_next_value(T &out, ASN1_Type type_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
BER_Decoder & decode(bool &out)
uint64_t decode_constrained_integer(ASN1_Type type_tag, ASN1_Class class_tag, size_t T_bytes)
BER_Decoder & verify_end()
BER_Decoder start_cons(ASN1_Type type_tag, ASN1_Class class_tag)
BER_Decoder & discard_remaining()
BER_Decoder & decode_octet_string_bigint(BigInt &b)
BER_Decoder & decode_null()
BER_Decoder & operator=(const BER_Decoder &)=delete
const uint8_t * bits() const
void assert_is_a(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view descr="object") const
std::span< const uint8_t > data() const
static BigInt from_bytes(std::span< const uint8_t > bytes)
uint8_t byte_at(size_t n) const
void _assign_from_bytes(std::span< const uint8_t > bytes)
size_t read_byte(uint8_t &out)
constexpr uint8_t get_byte(T input)
constexpr std::optional< T > checked_add(T a, T b)
constexpr void copy_mem(T *out, const T *in, size_t n)
std::vector< T, secure_allocator< T > > secure_vector
constexpr size_t DefaultBufferSize