Botan 3.12.0
Crypto and TLS for C&
ber_dec.h
Go to the documentation of this file.
1/*
2* BER Decoder
3* (C) 1999-2010,2018 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#ifndef BOTAN_BER_DECODER_H_
9#define BOTAN_BER_DECODER_H_
10
11#include <botan/asn1_obj.h>
12#include <botan/secmem.h>
13#include <cstring>
14#include <memory>
15#include <optional>
16
17namespace Botan {
18
19class BigInt;
20class DataSource;
21
22/**
23* BER Decoding Object
24*/
25class BOTAN_PUBLIC_API(2, 0) BER_Decoder final {
26 public:
27 /**
28 * Controls what encoding rules the decoder accepts.
29 */
30 class BOTAN_PUBLIC_API(3, 12) Limits final {
31 public:
32 /**
33 * Accept only DER encodings
34 */
35 static Limits DER() { return Limits(false, 0); }
36
37 /**
38 * Accept non-canonical BER encodings.
39 *
40 * @param max_nested_indef maximum number of nested indefinite-length encodings accepted
41 */
42 static Limits BER(size_t max_nested_indef = 16) { return Limits(true, max_nested_indef); }
43
44 bool allow_ber_encoding() const { return m_allow_ber; }
45
46 bool require_der_encoding() const { return !allow_ber_encoding(); }
47
48 size_t max_nested_indefinite_length() const { return m_max_nested_indef; }
49
50 bool operator==(const Limits&) const = default;
51
52 private:
53 Limits(bool allow_ber, size_t max_nested_indef) :
54 m_allow_ber(allow_ber), m_max_nested_indef(max_nested_indef) {}
55
56 bool m_allow_ber;
57 size_t m_max_nested_indef;
58 };
59
60 /**
61 * Set up to BER decode the data in buf of length len
62 */
63 BOTAN_DEPRECATED("Use BER_Decoder(span) constructor")
64 BER_Decoder(const uint8_t buf[], size_t len, Limits limits = Limits::BER()) :
65 BER_Decoder(std::span{buf, len}, limits) {}
66
67 /**
68 * Set up to BER decode the data in buf
69 */
70 explicit BER_Decoder(std::span<const uint8_t> buf, Limits limits = Limits::BER());
71
72 /**
73 * Set up to BER decode the data in src
74 */
75 explicit BER_Decoder(DataSource& src, Limits limits = Limits::BER());
76
77 /**
78 * Set up to BER decode the data in obj
79 */
82
83 /**
84 * Set up to BER decode the data in obj
85 * TODO(Botan4) remove this?
86 */
87 BOTAN_FUTURE_EXPLICIT BER_Decoder(BER_Object&& obj) : BER_Decoder(std::move(obj), nullptr) {}
88
89 BER_Decoder(const BER_Decoder& other) = delete;
90 BER_Decoder(BER_Decoder&& other) noexcept;
91
94
95 /**
96 * Returns the limits currently applied to this decoder
97 */
98 Limits limits() const { return m_limits; }
99
100 /**
101 * Get the next object in the data stream.
102 * If EOF, returns an object with type NO_OBJECT.
103 */
104 BER_Object get_next_object();
105
107 ber = get_next_object();
108 return (*this);
109 }
110
111 /**
112 * Peek at the next object without removing it from the stream
113 *
114 * If an object has been pushed, then it returns that object.
115 * Otherwise it reads the next object and pushes it. Thus, a you
116 * call peek_next_object followed by push_back without a
117 * subsequent read, it will fail.
118 */
119 const BER_Object& peek_next_object();
120
121 /**
122 * Push an object back onto the stream. Throws if another
123 * object was previously pushed and has not been subsequently
124 * read out.
125 */
126 void push_back(const BER_Object& obj);
127
128 /**
129 * Push an object back onto the stream. Throws if another
130 * object was previously pushed and has not been subsequently
131 * read out.
132 */
133 void push_back(BER_Object&& obj);
134
135 /**
136 * Return true if there is at least one more item remaining
137 */
138 bool more_items() const;
139
140 /**
141 * Verify the stream is concluded, throws otherwise.
142 * Returns (*this)
143 */
144 BER_Decoder& verify_end();
145
146 /**
147 * Verify the stream is concluded, throws otherwise.
148 * Returns (*this)
149 */
150 BER_Decoder& verify_end(std::string_view err_msg);
151
152 /**
153 * Discard any data that remains unread
154 * Returns (*this)
155 */
156 BER_Decoder& discard_remaining();
157
158 BER_Decoder start_cons(ASN1_Type type_tag, ASN1_Class class_tag);
159
161
163
167
171
172 /**
173 * Finish decoding a constructed data, throws if any data remains.
174 * Returns the parent of *this (ie the object on which start_cons was called).
175 */
176 BER_Decoder& end_cons();
177
178 /**
179 * Get next object and copy value to POD type
180 * Asserts value length is equal to POD type sizeof.
181 * Asserts Type tag and optional Class tag according to parameters.
182 * Copy value to POD type (struct, union, C-style array, std::array, etc.).
183 * @param out POD type reference where to copy object value
184 * @param type_tag ASN1_Type enum to assert type on object read
185 * @param class_tag ASN1_Type enum to assert class on object read (default: CONTEXT_SPECIFIC)
186 * @return this reference
187 */
188 template <typename T>
190 requires std::is_standard_layout_v<T> && std::is_trivial_v<T>
191 {
192 const BER_Object obj = get_next_value(sizeof(T), type_tag, class_tag);
193
194 std::memcpy(reinterpret_cast<uint8_t*>(&out), obj.bits(), obj.length());
195
196 return (*this);
197 }
198
199 /*
200 * Save all the bytes remaining in the source
201 */
202 template <typename Alloc>
203 BER_Decoder& raw_bytes(std::vector<uint8_t, Alloc>& out) {
204 out.clear();
205 for(;;) {
206 if(auto next = this->read_next_byte()) {
207 out.push_back(*next);
208 } else {
209 break;
210 }
211 }
212 return (*this);
213 }
214
215 BER_Decoder& decode_null();
216
217 /**
218 * Decode a BER encoded BOOLEAN
219 */
221
222 /*
223 * Decode a small BER encoded INTEGER
224 */
226
227 /*
228 * Decode a BER encoded INTEGER
229 */
231
232 std::vector<uint8_t> get_next_octet_string() {
233 std::vector<uint8_t> out_vec;
235 return out_vec;
236 }
237
238 /*
239 * BER decode a BIT STRING or OCTET STRING
240 */
241 template <typename Alloc>
242 BER_Decoder& decode(std::vector<uint8_t, Alloc>& out, ASN1_Type real_type) {
243 return decode(out, real_type, real_type, ASN1_Class::Universal);
244 }
245
246 BER_Decoder& decode(bool& v, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
247
248 BER_Decoder& decode(size_t& v, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
249
250 BER_Decoder& decode(BigInt& v, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
251
252 BER_Decoder& decode(std::vector<uint8_t>& v,
253 ASN1_Type real_type,
254 ASN1_Type type_tag,
256
258 ASN1_Type real_type,
259 ASN1_Type type_tag,
261
262 BER_Decoder& decode(ASN1_Object& obj,
264 ASN1_Class class_tag = ASN1_Class::NoObject);
265
266 /**
267 * Decode an integer value which is typed as an octet string
268 */
269 BER_Decoder& decode_octet_string_bigint(BigInt& b);
270
271 uint64_t decode_constrained_integer(ASN1_Type type_tag, ASN1_Class class_tag, size_t T_bytes);
272
273 template <typename T>
277
278 template <typename T>
280 out = static_cast<T>(decode_constrained_integer(type_tag, class_tag, sizeof(out)));
281 return (*this);
282 }
283
284 template <typename T>
285 BER_Decoder& decode_optional(T& out, ASN1_Type type_tag, ASN1_Class class_tag, const T& default_value = T()) {
286 std::optional<T> optval;
287 this->decode_optional(optval, type_tag, class_tag);
288 out = optval ? *optval : default_value;
289 return (*this);
290 }
291
292 template <typename T>
293 BER_Decoder& decode_optional(std::optional<T>& out, ASN1_Type type_tag, ASN1_Class class_tag);
294
295 template <typename T>
296 BER_Decoder& decode_optional_implicit(T& out,
297 ASN1_Type type_tag,
298 ASN1_Class class_tag,
299 ASN1_Type real_type,
300 ASN1_Class real_class,
301 const T& default_value = T());
302
303 template <typename T>
304 BER_Decoder& decode_list(std::vector<T>& out,
307
308 template <typename T>
309 bool decode_optional_list(std::vector<T>& out,
312
313 template <typename T>
314 BER_Decoder& decode_and_check(const T& expected, std::string_view error_msg) {
315 T actual;
316 decode(actual);
317
318 if(actual != expected) {
319 throw Decoding_Error(error_msg);
320 }
321
322 return (*this);
323 }
324
325 /*
326 * Decode an OPTIONAL string type
327 */
328 template <typename Alloc>
329 BER_Decoder& decode_optional_string(std::vector<uint8_t, Alloc>& out,
330 ASN1_Type real_type,
331 uint32_t expected_tag,
334
335 const ASN1_Type type_tag = static_cast<ASN1_Type>(expected_tag);
336
337 if(obj.is_a(type_tag, class_tag)) {
338 if(class_tag == ASN1_Class::ExplicitContextSpecific) {
339 BER_Decoder(obj, m_limits).decode(out, real_type).verify_end();
340 } else {
341 push_back(std::move(obj));
342 decode(out, real_type, type_tag, class_tag);
343 }
344 } else {
345 out.clear();
346 push_back(std::move(obj));
347 }
348
349 return (*this);
350 }
351
352 template <typename Alloc>
353 BER_Decoder& decode_optional_string(std::vector<uint8_t, Alloc>& out,
354 ASN1_Type real_type,
355 ASN1_Type expected_tag,
357 return decode_optional_string(out, real_type, static_cast<uint32_t>(expected_tag), class_tag);
358 }
359
361
362 private:
363 BER_Decoder(BER_Object&& obj, BER_Decoder* parent);
364
365 std::optional<uint8_t> read_next_byte();
366
367 BER_Object get_next_value(size_t sizeofT, ASN1_Type type_tag, ASN1_Class class_tag);
368
369 Limits m_limits;
370 BER_Decoder* m_parent = nullptr;
371 BER_Object m_pushed;
372 // either m_data_src.get() or an unowned pointer
373 DataSource* m_source;
374 std::unique_ptr<DataSource> m_data_src;
375};
376
377/*
378* Decode an OPTIONAL or DEFAULT element
379*/
380template <typename T>
381BER_Decoder& BER_Decoder::decode_optional(std::optional<T>& optval, ASN1_Type type_tag, ASN1_Class class_tag) {
383
384 if(obj.is_a(type_tag, class_tag)) {
385 T out{};
386 if(class_tag == ASN1_Class::ExplicitContextSpecific) {
387 BER_Decoder(obj, m_limits).decode(out).verify_end();
388 } else {
389 this->push_back(std::move(obj));
390 this->decode(out, type_tag, class_tag);
391 }
392 optval = std::move(out);
393 } else {
394 this->push_back(std::move(obj));
395 optval = std::nullopt;
396 }
397
398 return (*this);
399}
400
401/*
402* Decode an OPTIONAL or DEFAULT element
403*/
404template <typename T>
406 ASN1_Type type_tag,
407 ASN1_Class class_tag,
408 ASN1_Type real_type,
409 ASN1_Class real_class,
410 const T& default_value) {
412
413 if(obj.is_a(type_tag, class_tag)) {
414 obj.set_tagging(real_type, real_class);
415 push_back(std::move(obj));
416 decode(out, real_type, real_class);
417 } else {
418 // Not what we wanted, push it back on the stream
419 out = default_value;
420 push_back(std::move(obj));
421 }
422
423 return (*this);
424}
425
426/*
427* Decode a list of homogeneously typed values
428*/
429template <typename T>
430BER_Decoder& BER_Decoder::decode_list(std::vector<T>& vec, ASN1_Type type_tag, ASN1_Class class_tag) {
431 BER_Decoder list = start_cons(type_tag, class_tag);
432
433 while(list.more_items()) {
434 T value;
435 list.decode(value);
436 vec.push_back(std::move(value));
437 }
438
439 list.end_cons();
440
441 return (*this);
442}
443
444/*
445* Decode an optional list of homogeneously typed values
446*/
447template <typename T>
448bool BER_Decoder::decode_optional_list(std::vector<T>& vec, ASN1_Type type_tag, ASN1_Class class_tag) {
449 if(peek_next_object().is_a(type_tag, class_tag)) {
450 decode_list(vec, type_tag, class_tag);
451 return true;
452 }
453
454 return false;
455}
456
457} // namespace Botan
458
459#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:21
#define BOTAN_DEPRECATED(msg)
Definition api.h:73
#define BOTAN_FUTURE_EXPLICIT
Definition api.h:52
bool operator==(const Limits &) const =default
static Limits BER(size_t max_nested_indef=16)
Definition ber_dec.h:42
static Limits DER()
Definition ber_dec.h:35
size_t max_nested_indefinite_length() const
Definition ber_dec.h:48
bool allow_ber_encoding() const
Definition ber_dec.h:44
bool require_der_encoding() const
Definition ber_dec.h:46
BOTAN_FUTURE_EXPLICIT BER_Decoder(BER_Object &&obj)
Definition ber_dec.h:87
BER_Decoder start_set()
Definition ber_dec.h:162
BER_Decoder(BER_Decoder &&other) noexcept
const BER_Object & peek_next_object()
Definition ber_dec.cpp:415
void push_back(const BER_Object &obj)
Definition ber_dec.cpp:500
BER_Object get_next_object()
Definition ber_dec.cpp:426
BER_Decoder & get_next_value(T &out, ASN1_Type type_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition ber_dec.h:189
BER_Decoder & decode(bool &out)
Definition ber_dec.h:220
uint64_t decode_constrained_integer(ASN1_Type type_tag, ASN1_Class class_tag, size_t T_bytes)
Definition ber_dec.cpp:633
bool more_items() const
Definition ber_dec.cpp:371
Limits limits() const
Definition ber_dec.h:98
BER_Decoder & decode(BigInt &out)
Definition ber_dec.h:230
BER_Decoder & decode_optional_string(std::vector< uint8_t, Alloc > &out, ASN1_Type real_type, ASN1_Type expected_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition ber_dec.h:353
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
Definition ber_dec.h:203
BER_Decoder & decode_integer_type(T &out, ASN1_Type type_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition ber_dec.h:279
std::vector< uint8_t > get_next_octet_string()
Definition ber_dec.h:232
BOTAN_FUTURE_EXPLICIT BER_Decoder(const BER_Object &obj, Limits limits=Limits::BER())
Definition ber_dec.h:80
BER_Decoder & decode(std::vector< uint8_t, Alloc > &out, ASN1_Type real_type)
Definition ber_dec.h:242
BER_Decoder start_explicit_context_specific(uint32_t tag)
Definition ber_dec.h:168
BER_Decoder(const uint8_t buf[], size_t len, Limits limits=Limits::BER())
Definition ber_dec.h:64
BER_Decoder & end_cons()
Definition ber_dec.cpp:524
BER_Decoder(const BER_Decoder &other)=delete
BER_Decoder start_cons(ASN1_Type type_tag, ASN1_Class class_tag)
Definition ber_dec.cpp:514
BER_Decoder & decode_list(std::vector< T > &out, ASN1_Type type_tag=ASN1_Type::Sequence, ASN1_Class class_tag=ASN1_Class::Universal)
Definition ber_dec.h:430
BER_Decoder start_sequence()
Definition ber_dec.h:160
BER_Decoder & operator=(BER_Decoder &&) noexcept
BER_Decoder start_context_specific(uint32_t tag)
Definition ber_dec.h:164
BER_Decoder & decode_optional(T &out, ASN1_Type type_tag, ASN1_Class class_tag, const T &default_value=T())
Definition ber_dec.h:285
BER_Decoder & decode_and_check(const T &expected, std::string_view error_msg)
Definition ber_dec.h:314
bool decode_optional_list(std::vector< T > &out, ASN1_Type type_tag=ASN1_Type::Sequence, ASN1_Class class_tag=ASN1_Class::Universal)
Definition ber_dec.h:448
BER_Decoder & decode(size_t &out)
Definition ber_dec.h:225
BER_Decoder & decode_optional_string(std::vector< uint8_t, Alloc > &out, ASN1_Type real_type, uint32_t expected_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition ber_dec.h:329
BER_Decoder & decode_integer_type(T &out)
Definition ber_dec.h:274
BER_Decoder & decode_optional_implicit(T &out, ASN1_Type type_tag, ASN1_Class class_tag, ASN1_Type real_type, ASN1_Class real_class, const T &default_value=T())
Definition ber_dec.h:405
BER_Decoder & operator=(const BER_Decoder &)=delete
BER_Decoder & get_next(BER_Object &ber)
Definition ber_dec.h:106
size_t length() const
Definition asn1_obj.h:152
const uint8_t * bits() const
Definition asn1_obj.h:150
bool is_a(ASN1_Type type_tag, ASN1_Class class_tag) const
Definition asn1_obj.cpp:66
ASN1_Class
Definition asn1_obj.h:28
ASN1_Type
Definition asn1_obj.h:43
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:68