Coverage Report

Created: 2025-11-16 06:56

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