Botan  2.7.0
Crypto and TLS for C++11
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 
14 namespace Botan {
15 
16 class BigInt;
17 
18 /**
19 * BER Decoding Object
20 */
21 class BOTAN_PUBLIC_API(2,0) BER_Decoder final
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 
58  BER_Decoder& operator=(const BER_Decoder&) = delete;
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_pod<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>
277  BER_Decoder& decode_and_check(const T& expected,
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 */
336 template<typename T>
338  ASN1_Tag type_tag,
339  ASN1_Tag class_tag,
340  const T& default_value)
341  {
342  BER_Object obj = get_next_object();
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 */
368 template<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  {
377  BER_Object obj = get_next_object();
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 */
397 template<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(BER_Object &&obj)
Definition: ber_dec.h:53
BER_Decoder & decode_integer_type(T &out)
Definition: ber_dec.h:242
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
std::vector< uint8_t > get_next_octet_string()
Definition: ber_dec.h:191
bool is_a(ASN1_Tag type_tag, ASN1_Tag class_tag) const
Definition: asn1_obj.cpp:71
#define BOTAN_PUBLIC_API(maj, min)
Definition: compiler.h:27
BER_Decoder & decode(BigInt &out)
Definition: ber_dec.h:186
void assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag, const std::string &descr="object") const
Definition: asn1_obj.cpp:27
Definition: bigint.h:796
void push_back(const BER_Object &obj)
Definition: ber_dec.cpp:276
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
ASN1_Tag
Definition: asn1_obj.h:22
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
Definition: ber_dec.h:156
BER_Decoder(const BER_Object &obj)
Definition: ber_dec.h:47
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
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 & end_cons()
Definition: ber_dec.cpp:300
BER_Decoder(const uint8_t buf[], size_t len)
Definition: ber_dec.cpp:327
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
Definition: pem.cpp:68
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:290
size_t length() const
Definition: asn1_obj.h:120
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
Definition: alg_id.cpp:13
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, ASN1_Tag type_tag, ASN1_Tag class_tag=CONTEXT_SPECIFIC)
Definition: ber_dec.h:248
BER_Object get_next_object()
Definition: ber_dec.cpp:237
const uint8_t * bits() const
Definition: asn1_obj.h:118
BER_Decoder & get_next(BER_Object &ber)
Definition: ber_dec.h:66
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(size_t &out)
Definition: ber_dec.h:178
BER_Decoder & verify_end()
Definition: ber_dec.cpp:208
fe T
Definition: ge.cpp:37
BER_Decoder & decode_list(std::vector< T > &out, ASN1_Tag type_tag=SEQUENCE, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.h:398
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
bool more_items() const
Definition: ber_dec.cpp:198
BER_Decoder & decode(std::vector< uint8_t, Alloc > &out, ASN1_Tag real_type)
Definition: ber_dec.h:202