Botan 3.8.1
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/data_src.h>
13
14namespace Botan {
15
16class BigInt;
17
18/**
19* BER Decoding Object
20*/
21class BOTAN_PUBLIC_API(2, 0) BER_Decoder final {
22 public:
23 /**
24 * Set up to BER decode the data in buf of length len
25 */
26 BER_Decoder(const uint8_t buf[], size_t len);
27
28 /**
29 * Set up to BER decode the data in buf of length len
30 */
31 BER_Decoder(std::span<const uint8_t> buf) : BER_Decoder(buf.data(), buf.size()) {}
32
33 /**
34 * Set up to BER decode the data in vec
35 */
36 explicit BER_Decoder(const secure_vector<uint8_t>& vec);
37
38 /**
39 * Set up to BER decode the data in vec
40 */
41 explicit BER_Decoder(const std::vector<uint8_t>& vec);
42
43 /**
44 * Set up to BER decode the data in src
45 */
46 explicit BER_Decoder(DataSource& src);
47
48 /**
49 * Set up to BER decode the data in obj
50 */
51 BER_Decoder(const BER_Object& obj) : BER_Decoder(obj.bits(), obj.length()) {}
52
53 /**
54 * Set up to BER decode the data in obj
55 */
56 BER_Decoder(BER_Object&& obj) : BER_Decoder(std::move(obj), nullptr) {}
57
58 BER_Decoder(const BER_Decoder& other);
59
61
62 /**
63 * Get the next object in the data stream.
64 * If EOF, returns an object with type NO_OBJECT.
65 */
67
69 ber = get_next_object();
70 return (*this);
71 }
72
73 /**
74 * Peek at the next object without removing it from the stream
75 *
76 * If an object has been pushed, then it returns that object.
77 * Otherwise it reads the next object and pushes it. Thus, a you
78 * call peek_next_object followed by push_back without a
79 * subsequent read, it will fail.
80 */
81 const BER_Object& peek_next_object();
82
83 /**
84 * Push an object back onto the stream. Throws if another
85 * object was previously pushed and has not been subsequently
86 * read out.
87 */
88 void push_back(const BER_Object& obj);
89
90 /**
91 * Push an object back onto the stream. Throws if another
92 * object was previously pushed and has not been subsequently
93 * read out.
94 */
95 void push_back(BER_Object&& obj);
96
97 /**
98 * Return true if there is at least one more item remaining
99 */
100 bool more_items() const;
101
102 /**
103 * Verify the stream is concluded, throws otherwise.
104 * Returns (*this)
105 */
106 BER_Decoder& verify_end();
107
108 /**
109 * Verify the stream is concluded, throws otherwise.
110 * Returns (*this)
111 */
112 BER_Decoder& verify_end(std::string_view err_msg);
113
114 /**
115 * Discard any data that remains unread
116 * Returns (*this)
117 */
118 BER_Decoder& discard_remaining();
119
120 BER_Decoder start_cons(ASN1_Type type_tag, ASN1_Class class_tag);
121
123
125
129
133
134 /**
135 * Finish decoding a constructed data, throws if any data remains.
136 * Returns the parent of *this (ie the object on which start_cons was called).
137 */
138 BER_Decoder& end_cons();
139
140 /**
141 * Get next object and copy value to POD type
142 * Asserts value length is equal to POD type sizeof.
143 * Asserts Type tag and optional Class tag according to parameters.
144 * Copy value to POD type (struct, union, C-style array, std::array, etc.).
145 * @param out POD type reference where to copy object value
146 * @param type_tag ASN1_Type enum to assert type on object read
147 * @param class_tag ASN1_Type enum to assert class on object read (default: CONTEXT_SPECIFIC)
148 * @return this reference
149 */
150 template <typename T>
152 requires std::is_standard_layout<T>::value && std::is_trivial<T>::value
153 {
155 obj.assert_is_a(type_tag, class_tag);
156
157 if(obj.length() != sizeof(T)) {
158 throw BER_Decoding_Error("Size mismatch. Object value size is " + std::to_string(obj.length()) +
159 "; Output type size is " + std::to_string(sizeof(T)));
160 }
161
162 std::memcpy(reinterpret_cast<uint8_t*>(&out), obj.bits(), obj.length());
163
164 return (*this);
165 }
166
167 /*
168 * Save all the bytes remaining in the source
169 */
170 template <typename Alloc>
171 BER_Decoder& raw_bytes(std::vector<uint8_t, Alloc>& out) {
172 out.clear();
173 uint8_t buf;
174 while(m_source->read_byte(buf)) {
175 out.push_back(buf);
176 }
177 return (*this);
178 }
179
180 BER_Decoder& decode_null();
181
182 /**
183 * Decode a BER encoded BOOLEAN
184 */
186
187 /*
188 * Decode a small BER encoded INTEGER
189 */
191
192 /*
193 * Decode a BER encoded INTEGER
194 */
196
197 std::vector<uint8_t> get_next_octet_string() {
198 std::vector<uint8_t> out_vec;
200 return out_vec;
201 }
202
203 /*
204 * BER decode a BIT STRING or OCTET STRING
205 */
206 template <typename Alloc>
207 BER_Decoder& decode(std::vector<uint8_t, Alloc>& out, ASN1_Type real_type) {
208 return decode(out, real_type, real_type, ASN1_Class::Universal);
209 }
210
211 BER_Decoder& decode(bool& v, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
212
213 BER_Decoder& decode(size_t& v, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
214
215 BER_Decoder& decode(BigInt& v, ASN1_Type type_tag, ASN1_Class class_tag = ASN1_Class::ContextSpecific);
216
217 BER_Decoder& decode(std::vector<uint8_t>& v,
218 ASN1_Type real_type,
219 ASN1_Type type_tag,
221
223 ASN1_Type real_type,
224 ASN1_Type type_tag,
226
227 BER_Decoder& decode(ASN1_Object& obj,
229 ASN1_Class class_tag = ASN1_Class::NoObject);
230
231 /**
232 * Decode an integer value which is typed as an octet string
233 */
234 BER_Decoder& decode_octet_string_bigint(BigInt& b);
235
236 uint64_t decode_constrained_integer(ASN1_Type type_tag, ASN1_Class class_tag, size_t T_bytes);
237
238 template <typename T>
242
243 template <typename T>
245 out = static_cast<T>(decode_constrained_integer(type_tag, class_tag, sizeof(out)));
246 return (*this);
247 }
248
249 template <typename T>
250 BER_Decoder& decode_optional(T& out, ASN1_Type type_tag, ASN1_Class class_tag, const T& default_value = T());
251
252 template <typename T>
253 BER_Decoder& decode_optional_implicit(T& out,
254 ASN1_Type type_tag,
255 ASN1_Class class_tag,
256 ASN1_Type real_type,
257 ASN1_Class real_class,
258 const T& default_value = T());
259
260 template <typename T>
261 BER_Decoder& decode_list(std::vector<T>& out,
264
265 template <typename T>
266 bool decode_optional_list(std::vector<T>& out,
269
270 template <typename T>
271 BER_Decoder& decode_and_check(const T& expected, std::string_view error_msg) {
272 T actual;
273 decode(actual);
274
275 if(actual != expected) {
276 throw Decoding_Error(error_msg);
277 }
278
279 return (*this);
280 }
281
282 /*
283 * Decode an OPTIONAL string type
284 */
285 template <typename Alloc>
286 BER_Decoder& decode_optional_string(std::vector<uint8_t, Alloc>& out,
287 ASN1_Type real_type,
288 uint32_t expected_tag,
291
292 ASN1_Type type_tag = static_cast<ASN1_Type>(expected_tag);
293
294 if(obj.is_a(type_tag, class_tag)) {
295 if(class_tag == ASN1_Class::ExplicitContextSpecific) {
296 BER_Decoder(std::move(obj)).decode(out, real_type).verify_end();
297 } else {
298 push_back(std::move(obj));
299 decode(out, real_type, type_tag, class_tag);
300 }
301 } else {
302 out.clear();
303 push_back(std::move(obj));
304 }
305
306 return (*this);
307 }
308
309 template <typename Alloc>
310 BER_Decoder& decode_optional_string(std::vector<uint8_t, Alloc>& out,
311 ASN1_Type real_type,
312 ASN1_Type expected_tag,
314 return decode_optional_string(out, real_type, static_cast<uint32_t>(expected_tag), class_tag);
315 }
316
317 private:
318 BER_Decoder(BER_Object&& obj, BER_Decoder* parent);
319
320 BER_Decoder* m_parent = nullptr;
321 BER_Object m_pushed;
322 // either m_data_src.get() or an unowned pointer
323 DataSource* m_source;
324 mutable std::unique_ptr<DataSource> m_data_src;
325};
326
327/*
328* Decode an OPTIONAL or DEFAULT element
329*/
330template <typename T>
331BER_Decoder& BER_Decoder::decode_optional(T& out, ASN1_Type type_tag, ASN1_Class class_tag, const T& default_value) {
333
334 if(obj.is_a(type_tag, class_tag)) {
335 if(class_tag == ASN1_Class::ExplicitContextSpecific) {
336 BER_Decoder(std::move(obj)).decode(out).verify_end();
337 } else {
338 push_back(std::move(obj));
339 decode(out, type_tag, class_tag);
340 }
341 } else {
342 out = default_value;
343 push_back(std::move(obj));
344 }
345
346 return (*this);
347}
348
349/*
350* Decode an OPTIONAL or DEFAULT element
351*/
352template <typename T>
354 ASN1_Type type_tag,
355 ASN1_Class class_tag,
356 ASN1_Type real_type,
357 ASN1_Class real_class,
358 const T& default_value) {
360
361 if(obj.is_a(type_tag, class_tag)) {
362 obj.set_tagging(real_type, real_class);
363 push_back(std::move(obj));
364 decode(out, real_type, real_class);
365 } else {
366 // Not what we wanted, push it back on the stream
367 out = default_value;
368 push_back(std::move(obj));
369 }
370
371 return (*this);
372}
373
374/*
375* Decode a list of homogenously typed values
376*/
377template <typename T>
378BER_Decoder& BER_Decoder::decode_list(std::vector<T>& vec, ASN1_Type type_tag, ASN1_Class class_tag) {
379 BER_Decoder list = start_cons(type_tag, class_tag);
380
381 while(list.more_items()) {
382 T value;
383 list.decode(value);
384 vec.push_back(std::move(value));
385 }
386
387 list.end_cons();
388
389 return (*this);
390}
391
392/*
393* Decode an optional list of homogenously typed values
394*/
395template <typename T>
396bool BER_Decoder::decode_optional_list(std::vector<T>& vec, ASN1_Type type_tag, ASN1_Class class_tag) {
397 if(peek_next_object().is_a(type_tag, class_tag)) {
398 decode_list(vec, type_tag, class_tag);
399 return true;
400 }
401
402 return false;
403}
404
405} // namespace Botan
406
407#endif
#define BOTAN_PUBLIC_API(maj, min)
Definition api.h:19
BER_Decoder start_set()
Definition ber_dec.h:124
BER_Decoder & get_next_value(T &out, ASN1_Type type_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition ber_dec.h:151
BER_Decoder(const uint8_t buf[], size_t len)
Definition ber_dec.cpp:335
const BER_Object & peek_next_object()
Definition ber_dec.cpp:234
void push_back(const BER_Object &obj)
Definition ber_dec.cpp:286
BER_Object get_next_object()
Definition ber_dec.cpp:245
BER_Decoder & decode(bool &out)
Definition ber_dec.h:185
uint64_t decode_constrained_integer(ASN1_Type type_tag, ASN1_Class class_tag, size_t T_bytes)
Definition ber_dec.cpp:435
bool more_items() const
Definition ber_dec.cpp:201
BER_Decoder & decode(BigInt &out)
Definition ber_dec.h:195
BER_Decoder(BER_Object &&obj)
Definition ber_dec.h:56
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:310
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
Definition ber_dec.h:171
BER_Decoder & decode_integer_type(T &out, ASN1_Type type_tag, ASN1_Class class_tag=ASN1_Class::ContextSpecific)
Definition ber_dec.h:244
std::vector< uint8_t > get_next_octet_string()
Definition ber_dec.h:197
BER_Decoder & decode(std::vector< uint8_t, Alloc > &out, ASN1_Type real_type)
Definition ber_dec.h:207
BER_Decoder start_explicit_context_specific(uint32_t tag)
Definition ber_dec.h:130
BER_Decoder & end_cons()
Definition ber_dec.cpp:309
BER_Decoder(std::span< const uint8_t > buf)
Definition ber_dec.h:31
BER_Decoder start_cons(ASN1_Type type_tag, ASN1_Class class_tag)
Definition ber_dec.cpp:300
BER_Decoder(const BER_Object &obj)
Definition ber_dec.h:51
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:378
BER_Decoder start_sequence()
Definition ber_dec.h:122
BER_Decoder start_context_specific(uint32_t tag)
Definition ber_dec.h:126
BER_Decoder & decode_optional(T &out, ASN1_Type type_tag, ASN1_Class class_tag, const T &default_value=T())
Definition ber_dec.h:331
BER_Decoder & decode_and_check(const T &expected, std::string_view error_msg)
Definition ber_dec.h:271
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:396
BER_Decoder & decode(size_t &out)
Definition ber_dec.h:190
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:286
BER_Decoder & decode_integer_type(T &out)
Definition ber_dec.h:239
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:353
BER_Decoder & operator=(const BER_Decoder &)=delete
BER_Decoder & get_next(BER_Object &ber)
Definition ber_dec.h:68
size_t length() const
Definition asn1_obj.h:153
const uint8_t * bits() const
Definition asn1_obj.h:151
bool is_a(ASN1_Type type_tag, ASN1_Class class_tag) const
Definition asn1_obj.cpp:61
void assert_is_a(ASN1_Type type_tag, ASN1_Class class_tag, std::string_view descr="object") const
Definition asn1_obj.cpp:29
ASN1_Class
Definition asn1_obj.h:29
ASN1_Type
Definition asn1_obj.h:44
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:65