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