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