Coverage Report

Created: 2025-12-31 06:08

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