Coverage Report

Created: 2025-07-11 06:15

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