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