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