Coverage Report

Created: 2026-09-14 07:14

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