• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 24922258954

24 Apr 2026 12:23PM UTC coverage: 89.387% (-0.01%) from 89.401%
24922258954

push

github

web-flow
Merge pull request #5546 from randombit/jack/crldp-fixes

Fix some bugs relating to CRL distribution point handling

106817 of 119500 relevant lines covered (89.39%)

11464956.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.43
/src/lib/asn1/ber_dec.cpp
1
/*
2
* BER Decoder
3
* (C) 1999-2008,2015,2017,2018,2026 Jack Lloyd
4
*
5
* Botan is released under the Simplified BSD License (see license.txt)
6
*/
7

8
#include <botan/ber_dec.h>
9

10
#include <botan/bigint.h>
11
#include <botan/data_src.h>
12
#include <botan/internal/int_utils.h>
13
#include <botan/internal/loadstor.h>
14
#include <memory>
15

16
namespace Botan {
17

18
namespace {
19

20
bool is_constructed(ASN1_Class class_tag) {
7,226,796✔
21
   return (static_cast<uint32_t>(class_tag) & static_cast<uint32_t>(ASN1_Class::Constructed)) != 0;
7,226,796✔
22
}
23

24
/*
25
* BER decode an ASN.1 type tag
26
*/
27
size_t decode_tag(DataSource* ber, ASN1_Type& type_tag, ASN1_Class& class_tag) {
6,876,292✔
28
   auto b = ber->read_byte();
6,876,292✔
29

30
   if(!b) {
6,876,292✔
31
      type_tag = ASN1_Type::NoObject;
46,753✔
32
      class_tag = ASN1_Class::NoObject;
46,753✔
33
      return 0;
46,753✔
34
   }
35

36
   if((*b & 0x1F) != 0x1F) {
6,829,539✔
37
      type_tag = ASN1_Type(*b & 0x1F);
6,828,312✔
38
      class_tag = ASN1_Class(*b & 0xE0);
6,828,312✔
39
      return 1;
6,828,312✔
40
   }
41

42
   size_t tag_bytes = 1;
1,227✔
43
   class_tag = ASN1_Class(*b & 0xE0);
1,227✔
44

45
   uint32_t tag_buf = 0;
1,227✔
46
   while(true) {
2,381✔
47
      b = ber->read_byte();
2,381✔
48
      if(!b) {
2,381✔
49
         throw BER_Decoding_Error("Long-form tag truncated");
69✔
50
      }
51
      if((tag_buf >> 24) != 0) {
2,312✔
52
         throw BER_Decoding_Error("Long-form tag overflowed 32 bits");
5✔
53
      }
54
      // This is required even by BER (see X.690 section 8.1.2.4.2 sentence c).
55
      // Bits 7-1 of the first subsequent octet must not be all zero; this rules
56
      // out both 0x80 (continuation with no data) and 0x00 (a long-form encoding
57
      // of tag value 0, which collides with the EOC marker).
58
      if(tag_bytes == 1 && (*b & 0x7F) == 0) {
2,307✔
59
         throw BER_Decoding_Error("Long form tag with leading zero");
8✔
60
      }
61
      ++tag_bytes;
2,299✔
62
      tag_buf = (tag_buf << 7) | (*b & 0x7F);
2,299✔
63
      if((*b & 0x80) == 0) {
2,299✔
64
         break;
65
      }
66
   }
67
   // Per X.690 8.1.2.2, tag values 0-30 shall be encoded in the short form.
68
   // Long-form encoding is reserved for tag values >= 31 (X.690 8.1.2.3).
69
   // This is unconditional and applies to BER as well as DER.
70
   if(tag_buf <= 30) {
1,145✔
71
      throw BER_Decoding_Error("Long-form tag encoding used for small tag value");
38✔
72
   }
73

74
   if(tag_buf == static_cast<uint32_t>(ASN1_Type::NoObject)) {
1,107✔
75
      throw BER_Decoding_Error("Tag value collides with internal sentinel");
8✔
76
   }
77

78
   // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
79
   type_tag = ASN1_Type(tag_buf);
1,099✔
80
   return tag_bytes;
1,099✔
81
}
82

83
/*
84
* Find the EOC marker by scanning TLVs via peek, without buffering.
85
* Returns the number of bytes before and including the EOC marker.
86
*/
87
size_t find_eoc(DataSource* src, size_t base_offset, size_t allow_indef);
88

89
/*
90
* Result of decoding a BER length field.
91
*
92
* If indefinite is true, indefinite-length encoding was used: content_length
93
* is the number of content bytes (excluding the 2-byte EOC marker) and the
94
* caller must consume the EOC bytes after reading the content.
95
*/
96
class BerDecodedLength {
97
   public:
98
      BerDecodedLength(size_t content_length, size_t field_length) :
6,806,454✔
99
            BerDecodedLength(content_length, field_length, false) {}
6,806,454✔
100

101
      static BerDecodedLength indefinite(size_t content_length, size_t field_length) {
14,011✔
102
         return BerDecodedLength(content_length, field_length, true);
14,011✔
103
      }
104

105
      size_t content_length() const { return m_content_length; }
11,820,577✔
106

107
      // Length plus the EOC bytes if an indefinite length field
108
      size_t total_length() const { return m_indefinite ? m_content_length + 2 : m_content_length; }
6,819,358✔
109

110
      size_t field_length() const { return m_field_length; }
111

112
      bool indefinite_length() const { return m_indefinite; }
5,002,596✔
113

114
   private:
115
      BerDecodedLength(size_t content_length, size_t field_length, bool indefinite) :
6,820,465✔
116
            m_content_length(content_length), m_field_length(field_length), m_indefinite(indefinite) {}
6,820,465✔
117

118
      size_t m_content_length;
119
      size_t m_field_length;
120
      bool m_indefinite;
121
};
122

123
/*
124
* BER decode an ASN.1 length field
125
*/
126
BerDecodedLength decode_length(DataSource* ber, size_t allow_indef, bool der_mode, bool constructed) {
6,829,411✔
127
   uint8_t b = 0;
6,829,411✔
128
   if(ber->read_byte(b) == 0) {
6,829,411✔
129
      throw BER_Decoding_Error("Length field not found");
327✔
130
   }
131
   if((b & 0x80) == 0) {
6,829,084✔
132
      return BerDecodedLength(b, 1);
6,602,875✔
133
   }
134

135
   const size_t num_length_bytes = (b & 0x7F);
226,209✔
136

137
   const size_t field_size = 1 + num_length_bytes;
226,209✔
138
   if(field_size > 5) {
226,209✔
139
      throw BER_Decoding_Error("Length field is too large");
543✔
140
   }
141

142
   if(num_length_bytes == 0) {
225,666✔
143
      if(der_mode) {
21,462✔
144
         throw BER_Decoding_Error("Detected indefinite-length encoding in DER structure");
6,735✔
145
      } else if(!constructed) {
14,727✔
146
         // Indefinite length is only valid for constructed types (X.690 8.1.3.2)
147
         throw BER_Decoding_Error("Indefinite-length encoding used with non-constructed type");
108✔
148
      } else if(allow_indef == 0) {
14,619✔
149
         throw BER_Decoding_Error("Nested EOC markers too deep, rejecting to avoid stack exhaustion");
×
150
      } else {
151
         // find_eoc returns bytes up to and including the EOC marker.
152
         // Return the content length; the caller consumes the EOC separately.
153
         const size_t eoc_len = find_eoc(ber, /*base_offset=*/0, allow_indef - 1);
14,619✔
154
         if(eoc_len < 2) {
14,011✔
155
            throw BER_Decoding_Error("Invalid EOC encoding");
×
156
         }
157
         return BerDecodedLength::indefinite(eoc_len - 2, field_size);
14,011✔
158
      }
159
   }
160

161
   size_t length = 0;
162

163
   for(size_t i = 0; i != num_length_bytes; ++i) {
562,361✔
164
      if(ber->read_byte(b) == 0) {
358,209✔
165
         throw BER_Decoding_Error("Corrupted length field");
52✔
166
      }
167
      if(get_byte<0>(length) != 0) {
358,157✔
168
         throw BER_Decoding_Error("Field length overflow");
×
169
      }
170
      length = (length << 8) | b;
358,157✔
171
   }
172

173
   // DER requires shortest possible length encoding
174
   if(der_mode) {
204,152✔
175
      if(length < 128) {
203,573✔
176
         throw BER_Decoding_Error("Detected non-canonical length encoding in DER structure");
436✔
177
      }
178
      if(num_length_bytes > 1 && length < (size_t(1) << ((num_length_bytes - 1) * 8))) {
203,137✔
179
         throw BER_Decoding_Error("Detected non-canonical length encoding in DER structure");
137✔
180
      }
181
   }
182

183
   return BerDecodedLength(length, field_size);
203,579✔
184
}
185

186
/*
187
* Peek a tag from the source at the given offset without consuming any data.
188
* Returns the number of bytes consumed by the tag, or 0 on EOF.
189
*/
190
size_t peek_tag(DataSource* src, size_t offset, ASN1_Type& type_tag, ASN1_Class& class_tag) {
198,717✔
191
   uint8_t b = 0;
198,717✔
192
   if(src->peek(&b, 1, offset) == 0) {
198,717✔
193
      type_tag = ASN1_Type::NoObject;
225✔
194
      class_tag = ASN1_Class::NoObject;
225✔
195
      return 0;
225✔
196
   }
197

198
   if((b & 0x1F) != 0x1F) {
198,492✔
199
      type_tag = ASN1_Type(b & 0x1F);
197,963✔
200
      class_tag = ASN1_Class(b & 0xE0);
197,963✔
201
      return 1;
197,963✔
202
   }
203

204
   class_tag = ASN1_Class(b & 0xE0);
529✔
205
   size_t tag_bytes = 1;
529✔
206
   uint32_t tag_buf = 0;
529✔
207

208
   while(true) {
867✔
209
      if(src->peek(&b, 1, offset + tag_bytes) == 0) {
867✔
210
         throw BER_Decoding_Error("Long-form tag truncated");
6✔
211
      }
212
      if((tag_buf >> 24) != 0) {
861✔
213
         throw BER_Decoding_Error("Long-form tag overflowed 32 bits");
×
214
      }
215
      // Required even by BER (X.690 section 8.1.2.4.2 sentence c).
216
      // Bits 7-1 of the first subsequent octet must not be all zero; this rules
217
      // out both 0x80 (continuation with no data) and 0x00 (a long-form encoding
218
      // of tag value 0, which collides with the EOC marker).
219
      if(tag_bytes == 1 && (b & 0x7F) == 0) {
861✔
220
         throw BER_Decoding_Error("Long form tag with leading zero");
67✔
221
      }
222
      ++tag_bytes;
794✔
223
      tag_buf = (tag_buf << 7) | (b & 0x7F);
794✔
224
      if((b & 0x80) == 0) {
794✔
225
         break;
226
      }
227
   }
228

229
   // Per X.690 8.1.2.2, tag values 0-30 shall be encoded in the short form.
230
   // Long-form encoding is reserved for tag values >= 31 (X.690 8.1.2.3).
231
   // This is unconditional and applies to BER as well as DER.
232
   if(tag_buf <= 30) {
456✔
233
      throw BER_Decoding_Error("Long-form tag encoding used for small tag value");
10✔
234
   }
235

236
   if(tag_buf == static_cast<uint32_t>(ASN1_Type::NoObject)) {
446✔
237
      throw BER_Decoding_Error("Tag value collides with internal sentinel");
×
238
   }
239

240
   // NOLINTNEXTLINE(clang-analyzer-optin.core.EnumCastOutOfRange)
241
   type_tag = ASN1_Type(tag_buf);
446✔
242
   return tag_bytes;
446✔
243
}
244

245
/*
246
* Peek a length from the source at the given offset without consuming any data.
247
* Returns the decoded length and sets field_size to the number of bytes consumed.
248
* For indefinite-length encoding, recursively scans ahead to find the EOC marker.
249
*/
250
size_t peek_length(DataSource* src, size_t offset, size_t& field_size, size_t allow_indef, bool constructed) {
198,409✔
251
   uint8_t b = 0;
198,409✔
252
   if(src->peek(&b, 1, offset) == 0) {
198,409✔
253
      throw BER_Decoding_Error("Length field not found");
71✔
254
   }
255

256
   field_size = 1;
198,338✔
257
   if((b & 0x80) == 0) {
198,338✔
258
      return b;
145,525✔
259
   }
260

261
   const size_t num_length_bytes = (b & 0x7F);
52,813✔
262
   field_size += num_length_bytes;
52,813✔
263
   if(field_size > 5) {
52,813✔
264
      throw BER_Decoding_Error("Length field is too large");
58✔
265
   }
266

267
   if(num_length_bytes == 0) {
52,755✔
268
      // Indefinite length is only valid for constructed types (X.690 8.1.3.2)
269
      if(!constructed) {
52,062✔
270
         throw BER_Decoding_Error("Indefinite-length encoding used with non-constructed type");
32✔
271
      }
272
      if(allow_indef == 0) {
52,030✔
273
         throw BER_Decoding_Error("Nested EOC markers too deep, rejecting to avoid stack exhaustion");
8✔
274
      }
275
      return find_eoc(src, offset + 1, allow_indef - 1);
52,022✔
276
   }
277

278
   size_t length = 0;
279
   for(size_t i = 0; i < num_length_bytes; ++i) {
1,417✔
280
      if(src->peek(&b, 1, offset + 1 + i) == 0) {
724✔
281
         throw BER_Decoding_Error("Corrupted length field");
×
282
      }
283
      if(get_byte<0>(length) != 0) {
724✔
284
         throw BER_Decoding_Error("Field length overflow");
×
285
      }
286
      length = (length << 8) | b;
724✔
287
   }
288
   return length;
289
}
290

291
/*
292
* Find the EOC marker by scanning TLVs via peek, without buffering.
293
* Returns the number of bytes before and including the EOC marker.
294
*/
295
size_t find_eoc(DataSource* src, size_t base_offset, size_t allow_indef) {
66,641✔
296
   size_t offset = base_offset;
66,641✔
297

298
   while(true) {
330,793✔
299
      ASN1_Type type_tag = ASN1_Type::NoObject;
198,717✔
300
      ASN1_Class class_tag = ASN1_Class::NoObject;
198,717✔
301
      const size_t tag_size = peek_tag(src, offset, type_tag, class_tag);
198,717✔
302
      if(type_tag == ASN1_Type::NoObject) {
198,634✔
303
         throw BER_Decoding_Error("Missing EOC marker in indefinite-length encoding");
225✔
304
      }
305

306
      size_t length_size = 0;
198,409✔
307
      const size_t item_size = peek_length(src, offset + tag_size, length_size, allow_indef, is_constructed(class_tag));
198,409✔
308

309
      if(auto new_offset = checked_add(offset, tag_size, length_size, item_size)) {
394,652✔
310
         offset = new_offset.value();
197,326✔
311
      } else {
312
         throw Decoding_Error("Integer overflow while scanning for EOC");
×
313
      }
314

315
      if(type_tag == ASN1_Type::Eoc && class_tag == ASN1_Class::Universal) {
197,326✔
316
         // Per X.690 8.1.5 the EOC marker is exactly two zero octets
317
         if(length_size != 1 || item_size != 0) {
65,250✔
318
            throw BER_Decoding_Error("EOC marker with non-zero length");
131✔
319
         }
320
         break;
65,119✔
321
      }
322
   }
132,076✔
323

324
   return offset - base_offset;
65,119✔
325
}
326

327
class DataSource_BERObject final : public DataSource {
328
   public:
329
      size_t read(uint8_t out[], size_t length) override {
24,612,699✔
330
         BOTAN_ASSERT_NOMSG(m_offset <= m_obj.length());
24,612,699✔
331
         const size_t got = std::min<size_t>(m_obj.length() - m_offset, length);
24,612,699✔
332
         copy_mem(out, m_obj.bits() + m_offset, got);
24,612,699✔
333
         m_offset += got;
24,612,699✔
334
         return got;
24,612,699✔
335
      }
336

337
      size_t peek(uint8_t out[], size_t length, size_t peek_offset) const override {
4✔
338
         BOTAN_ASSERT_NOMSG(m_offset <= m_obj.length());
4✔
339
         const size_t bytes_left = m_obj.length() - m_offset;
4✔
340

341
         if(peek_offset >= bytes_left) {
4✔
342
            return 0;
343
         }
344

345
         const size_t got = std::min(bytes_left - peek_offset, length);
4✔
346
         copy_mem(out, m_obj.bits() + m_offset + peek_offset, got);
4✔
347
         return got;
4✔
348
      }
349

350
      bool check_available(size_t n) override {
1,155,120✔
351
         BOTAN_ASSERT_NOMSG(m_offset <= m_obj.length());
1,155,120✔
352
         return (n <= (m_obj.length() - m_offset));
1,155,120✔
353
      }
354

355
      bool end_of_data() const override { return get_bytes_read() == m_obj.length(); }
1,028,433✔
356

357
      size_t get_bytes_read() const override { return m_offset; }
1,028,433✔
358

359
      explicit DataSource_BERObject(BER_Object&& obj) : m_obj(std::move(obj)) {}
744,777✔
360

361
   private:
362
      BER_Object m_obj;
363
      size_t m_offset = 0;
364
};
365

366
}  // namespace
367

368
BER_Decoder::~BER_Decoder() = default;
2,225,192✔
369

370
/*
371
* Check if more objects are there
372
*/
373
bool BER_Decoder::more_items() const {
643,106✔
374
   if(m_source->end_of_data() && !m_pushed.is_set()) {
643,106✔
375
      return false;
234,026✔
376
   }
377
   return true;
378
}
379

380
/*
381
* Verify that no bytes remain in the source
382
*/
383
BER_Decoder& BER_Decoder::verify_end() {
219,320✔
384
   return verify_end("BER_Decoder::verify_end called, but data remains");
219,320✔
385
}
386

387
/*
388
* Verify that no bytes remain in the source
389
*/
390
BER_Decoder& BER_Decoder::verify_end(std::string_view err) {
240,662✔
391
   if(!m_source->end_of_data() || m_pushed.is_set()) {
240,662✔
392
      throw Decoding_Error(err);
233✔
393
   }
394
   return (*this);
240,429✔
395
}
396

397
/*
398
* Discard all the bytes remaining in the source
399
*/
400
BER_Decoder& BER_Decoder::discard_remaining() {
19,048✔
401
   uint8_t buf = 0;
19,048✔
402
   while(m_source->read_byte(buf) != 0) {}
155,678✔
403
   return (*this);
19,048✔
404
}
405

406
std::optional<uint8_t> BER_Decoder::read_next_byte() {
20,801,778✔
407
   BOTAN_ASSERT_NOMSG(m_source != nullptr);
20,801,778✔
408
   uint8_t b = 0;
20,801,778✔
409
   if(m_source->read_byte(b) != 0) {
20,801,778✔
410
      return b;
20,623,899✔
411
   } else {
412
      return {};
177,879✔
413
   }
414
}
415

416
const BER_Object& BER_Decoder::peek_next_object() {
17,746✔
417
   if(!m_pushed.is_set()) {
17,746✔
418
      m_pushed = get_next_object();
17,563✔
419
   }
420

421
   return m_pushed;
17,729✔
422
}
423

424
/*
425
* Return the BER encoding of the next object
426
*/
427
BER_Object BER_Decoder::get_next_object() {
2,049,639✔
428
   BER_Object next;
2,049,639✔
429

430
   if(m_pushed.is_set()) {
2,049,639✔
431
      std::swap(next, m_pushed);
174,793✔
432
      return next;
174,793✔
433
   }
434

435
   for(;;) {
11,877,738✔
436
      ASN1_Type type_tag = ASN1_Type::NoObject;
6,876,292✔
437
      ASN1_Class class_tag = ASN1_Class::NoObject;
6,876,292✔
438
      decode_tag(m_source, type_tag, class_tag);
6,876,292✔
439
      next.set_tagging(type_tag, class_tag);
6,876,164✔
440
      if(next.is_set() == false) {  // no more objects
6,876,164✔
441
         return next;
46,753✔
442
      }
443

444
      const size_t allow_indef = m_limits.allow_ber_encoding() ? m_limits.max_nested_indefinite_length() : 0;
6,829,411✔
445
      const bool der_mode = m_limits.require_der_encoding();
6,829,411✔
446
      const auto dl = decode_length(m_source, allow_indef, der_mode, is_constructed(class_tag));
6,829,411✔
447

448
      // Per X.690 8.1.5 the only valid EOC encoding is the two-octet
449
      // sequence 0x00 0x00. Reject any other length encoding on a tag of
450
      // (Eoc, Universal) before we consume the "content" bytes.
451
      if(type_tag == ASN1_Type::Eoc && class_tag == ASN1_Class::Universal &&
6,820,465✔
452
         (dl.content_length() != 0 || dl.indefinite_length())) {
5,003,703✔
453
         throw BER_Decoding_Error("EOC marker with non-zero length");
1,107✔
454
      }
455

456
      if(!m_source->check_available(dl.total_length())) {
13,638,716✔
457
         throw BER_Decoding_Error("Value truncated");
2,484✔
458
      }
459

460
      uint8_t* out = next.mutable_bits(dl.content_length());
6,816,874✔
461
      if(m_source->read(out, dl.content_length()) != dl.content_length()) {
6,816,874✔
462
         throw BER_Decoding_Error("Value truncated");
×
463
      }
464

465
      if(dl.indefinite_length()) {
6,816,874✔
466
         // After reading the data consume the 2-byte EOC
467
         uint8_t eoc[2] = {0xFF, 0xFF};
14,011✔
468
         if(m_source->read(eoc, 2) != 2 || eoc[0] != 0x00 || eoc[1] != 0x00) {
14,011✔
469
            throw BER_Decoding_Error("Missing or malformed EOC marker");
×
470
         }
471
      }
472

473
      if(next.tagging() == static_cast<uint32_t>(ASN1_Type::Eoc)) {
6,816,874✔
474
         if(m_limits.require_der_encoding()) {
5,002,596✔
475
            throw BER_Decoding_Error("Detected EOC marker in DER structure");
1,150✔
476
         }
477
         continue;
5,001,446✔
478
      } else {
479
         break;
480
      }
481
   }
482

483
   return next;
1,814,278✔
484
}
13,815✔
485

486
BER_Object BER_Decoder::get_next_value(size_t sizeofT, ASN1_Type type_tag, ASN1_Class class_tag) {
×
487
   const BER_Object obj = get_next_object();
×
488
   obj.assert_is_a(type_tag, class_tag);
×
489

490
   if(obj.length() != sizeofT) {
×
491
      throw BER_Decoding_Error("Size mismatch. Object value size is " + std::to_string(obj.length()) +
×
492
                               "; Output type size is " + std::to_string(sizeofT));
×
493
   }
494

495
   return obj;
×
496
}
×
497

498
/*
499
* Push a object back into the stream
500
*/
501
void BER_Decoder::push_back(const BER_Object& obj) {
24✔
502
   if(m_pushed.is_set()) {
24✔
503
      throw Invalid_State("BER_Decoder: Only one push back is allowed");
×
504
   }
505
   m_pushed = obj;
24✔
506
}
24✔
507

508
void BER_Decoder::push_back(BER_Object&& obj) {
181,832✔
509
   if(m_pushed.is_set()) {
181,832✔
510
      throw Invalid_State("BER_Decoder: Only one push back is allowed");
×
511
   }
512
   m_pushed = std::move(obj);
181,832✔
513
}
181,832✔
514

515
BER_Decoder BER_Decoder::start_cons(ASN1_Type type_tag, ASN1_Class class_tag) {
754,141✔
516
   BER_Object obj = get_next_object();
754,141✔
517
   obj.assert_is_a(type_tag, class_tag | ASN1_Class::Constructed);
745,631✔
518
   BER_Decoder child(std::move(obj), this);
744,777✔
519
   return child;
744,777✔
520
}
745,631✔
521

522
/*
523
* Finish decoding a CONSTRUCTED type
524
*/
525
BER_Decoder& BER_Decoder::end_cons() {
557,680✔
526
   if(m_parent == nullptr) {
557,680✔
527
      throw Invalid_State("BER_Decoder::end_cons called with null parent");
×
528
   }
529
   if(!m_source->end_of_data()) {
557,680✔
530
      throw Decoding_Error("BER_Decoder::end_cons called with data left");
135✔
531
   }
532
   return (*m_parent);
557,545✔
533
}
534

535
BER_Decoder::BER_Decoder(BER_Object&& obj, BER_Decoder* parent) :
744,777✔
536
      m_limits(parent != nullptr ? parent->limits() : BER_Decoder::Limits::BER()), m_parent(parent) {
744,777✔
537
   m_data_src = std::make_unique<DataSource_BERObject>(std::move(obj));
744,777✔
538
   m_source = m_data_src.get();
744,777✔
539
}
744,777✔
540

541
/*
542
* BER_Decoder Constructor
543
*/
544
BER_Decoder::BER_Decoder(DataSource& src, Limits limits) : m_limits(limits), m_source(&src) {}
48,670✔
545

546
/*
547
* BER_Decoder Constructor
548
 */
549
BER_Decoder::BER_Decoder(std::span<const uint8_t> buf, Limits limits) : m_limits(limits) {
343,395✔
550
   m_data_src = std::make_unique<DataSource_Memory>(buf);
343,395✔
551
   m_source = m_data_src.get();
343,395✔
552
}
343,395✔
553

554
/*
555
* BER_Decoder Copy Constructor
556
*/
557
BER_Decoder::BER_Decoder(const BER_Decoder& other) :
178✔
558
      m_limits(other.m_limits), m_parent(other.m_parent), m_source(other.m_source) {
178✔
559
   // take ownership of other's data source
560
   std::swap(m_data_src, other.m_data_src);
178✔
561
}
178✔
562

563
BER_Decoder::BER_Decoder(BER_Decoder&& other) noexcept = default;
×
564

565
BER_Decoder& BER_Decoder::operator=(BER_Decoder&&) noexcept = default;
×
566

567
/*
568
* Request for an object to decode itself
569
*/
570
BER_Decoder& BER_Decoder::decode(ASN1_Object& obj, ASN1_Type /*unused*/, ASN1_Class /*unused*/) {
741,297✔
571
   obj.decode_from(*this);
741,297✔
572
   return (*this);
735,756✔
573
}
574

575
/*
576
* Decode a BER encoded NULL
577
*/
578
BER_Decoder& BER_Decoder::decode_null() {
111✔
579
   const BER_Object obj = get_next_object();
111✔
580
   obj.assert_is_a(ASN1_Type::Null, ASN1_Class::Universal);
111✔
581
   if(obj.length() > 0) {
111✔
582
      throw BER_Decoding_Error("NULL object had nonzero size");
×
583
   }
584
   return (*this);
111✔
585
}
111✔
586

587
BER_Decoder& BER_Decoder::decode_octet_string_bigint(BigInt& out) {
314✔
588
   secure_vector<uint8_t> out_vec;
314✔
589
   decode(out_vec, ASN1_Type::OctetString);
314✔
590
   out = BigInt::from_bytes(out_vec);
314✔
591
   return (*this);
267✔
592
}
267✔
593

594
/*
595
* Decode a BER encoded BOOLEAN
596
*/
597
BER_Decoder& BER_Decoder::decode(bool& out, ASN1_Type type_tag, ASN1_Class class_tag) {
43,132✔
598
   const BER_Object obj = get_next_object();
43,132✔
599
   obj.assert_is_a(type_tag, class_tag);
43,132✔
600

601
   if(obj.length() != 1) {
43,132✔
602
      throw BER_Decoding_Error("BER boolean value had invalid size");
48✔
603
   }
604

605
   const uint8_t val = obj.bits()[0];
43,084✔
606

607
   // DER requires boolean values to be exactly 0x00 or 0xFF
608
   if(m_limits.require_der_encoding() && val != 0x00 && val != 0xFF) {
43,084✔
609
      throw BER_Decoding_Error("Detected non-canonical boolean encoding in DER structure");
54✔
610
   }
611

612
   out = (val != 0) ? true : false;
43,030✔
613

614
   return (*this);
43,030✔
615
}
43,132✔
616

617
/*
618
* Decode a small BER encoded INTEGER
619
*/
620
BER_Decoder& BER_Decoder::decode(size_t& out, ASN1_Type type_tag, ASN1_Class class_tag) {
41,331✔
621
   BigInt integer;
41,331✔
622
   decode(integer, type_tag, class_tag);
41,331✔
623

624
   if(integer.signum() < 0) {
41,234✔
625
      throw BER_Decoding_Error("Decoded small integer value was negative");
31✔
626
   }
627

628
   if(integer.bits() > 32) {
41,203✔
629
      throw BER_Decoding_Error("Decoded integer value larger than expected");
10✔
630
   }
631

632
   out = 0;
41,193✔
633
   for(size_t i = 0; i != 4; ++i) {
205,965✔
634
      out = (out << 8) | integer.byte_at(3 - i);
164,772✔
635
   }
636

637
   return (*this);
41,193✔
638
}
41,331✔
639

640
/*
641
* Decode a small BER encoded INTEGER
642
*/
643
uint64_t BER_Decoder::decode_constrained_integer(ASN1_Type type_tag, ASN1_Class class_tag, size_t T_bytes) {
3,936✔
644
   if(T_bytes > 8) {
3,936✔
645
      throw BER_Decoding_Error("Can't decode small integer over 8 bytes");
×
646
   }
647

648
   BigInt integer;
3,936✔
649
   decode(integer, type_tag, class_tag);
3,936✔
650

651
   if(integer.is_negative()) {
3,936✔
652
      throw BER_Decoding_Error("Decoded small integer value was negative");
×
653
   }
654

655
   if(integer.bits() > 8 * T_bytes) {
3,936✔
656
      throw BER_Decoding_Error("Decoded integer value larger than expected");
×
657
   }
658

659
   uint64_t out = 0;
660
   for(size_t i = 0; i != 8; ++i) {
35,424✔
661
      out = (out << 8) | integer.byte_at(7 - i);
31,488✔
662
   }
663

664
   return out;
3,936✔
665
}
3,936✔
666

667
/*
668
* Decode a BER encoded INTEGER
669
*/
670
BER_Decoder& BER_Decoder::decode(BigInt& out, ASN1_Type type_tag, ASN1_Class class_tag) {
133,061✔
671
   const BER_Object obj = get_next_object();
133,061✔
672
   obj.assert_is_a(type_tag, class_tag);
132,300✔
673

674
   // DER requires minimal INTEGER encoding (X.690 section 8.3.2)
675
   if(m_limits.require_der_encoding()) {
131,308✔
676
      if(obj.length() == 0) {
125,912✔
677
         throw BER_Decoding_Error("Detected empty INTEGER encoding in DER structure");
82✔
678
      }
679
      if(obj.length() > 1) {
125,830✔
680
         if(obj.bits()[0] == 0x00 && (obj.bits()[1] & 0x80) == 0) {
74,434✔
681
            throw BER_Decoding_Error("Detected non-minimal INTEGER encoding in DER structure");
293✔
682
         }
683
         if(obj.bits()[0] == 0xFF && (obj.bits()[1] & 0x80) != 0) {
74,141✔
684
            throw BER_Decoding_Error("Detected non-minimal INTEGER encoding in DER structure");
39✔
685
         }
686
      }
687
   }
688

689
   if(obj.length() == 0) {
130,894✔
690
      out.clear();
659✔
691
   } else {
692
      const uint8_t first = obj.bits()[0];
130,235✔
693
      const bool negative = (first & 0x80) == 0x80;
130,235✔
694

695
      if(negative) {
130,235✔
696
         secure_vector<uint8_t> vec(obj.bits(), obj.bits() + obj.length());
4,779✔
697
         for(size_t i = obj.length(); i > 0; --i) {
8,465✔
698
            const bool gt0 = (vec[i - 1] > 0);
8,465✔
699
            vec[i - 1] -= 1;
8,465✔
700
            if(gt0) {
8,465✔
701
               break;
702
            }
703
         }
704
         for(size_t i = 0; i != obj.length(); ++i) {
33,985✔
705
            vec[i] = ~vec[i];
29,206✔
706
         }
707
         out._assign_from_bytes(vec);
4,779✔
708
         out.flip_sign();
9,558✔
709
      } else {
4,779✔
710
         out._assign_from_bytes(obj.data());
125,456✔
711
      }
712
   }
713

714
   return (*this);
130,894✔
715
}
132,300✔
716

717
namespace {
718

719
bool is_constructed(const BER_Object& obj) {
198,976✔
720
   return is_constructed(obj.class_tag());
198,976✔
721
}
722

723
template <typename Alloc>
724
void asn1_decode_binary_string(std::vector<uint8_t, Alloc>& buffer,
202,312✔
725
                               const BER_Object& obj,
726
                               ASN1_Type real_type,
727
                               ASN1_Type type_tag,
728
                               ASN1_Class class_tag,
729
                               bool require_der) {
730
   obj.assert_is_a(type_tag, class_tag);
202,312✔
731

732
   // DER requires BIT STRING and OCTET STRING to use primitive encoding
733
   if(require_der && is_constructed(obj)) {
202,219✔
734
      throw BER_Decoding_Error("Detected constructed string encoding in DER structure");
×
735
   }
736

737
   if(real_type == ASN1_Type::OctetString) {
202,219✔
738
      buffer.assign(obj.bits(), obj.bits() + obj.length());
132,343✔
739
   } else {
740
      if(obj.length() == 0) {
69,876✔
741
         throw BER_Decoding_Error("Invalid BIT STRING");
3✔
742
      }
743

744
      const uint8_t unused_bits = obj.bits()[0];
69,873✔
745

746
      if(unused_bits >= 8) {
69,873✔
747
         throw BER_Decoding_Error("Bad number of unused bits in BIT STRING");
24✔
748
      }
749

750
      // Empty BIT STRING with unused bits > 0 ...
751
      if(unused_bits > 0 && obj.length() < 2) {
69,849✔
752
         throw BER_Decoding_Error("Invalid BIT STRING");
6✔
753
      }
754

755
      // DER requires unused bits in BIT STRING to be zero (X.690 section 11.2.2)
756
      if(require_der && unused_bits > 0) {
69,843✔
757
         const uint8_t last_byte = obj.bits()[obj.length() - 1];
489✔
758
         if((last_byte & ((1 << unused_bits) - 1)) != 0) {
489✔
759
            throw BER_Decoding_Error("Detected non-zero padding bits in BIT STRING in DER structure");
124✔
760
         }
761
      }
762

763
      buffer.resize(obj.length() - 1);
69,719✔
764

765
      if(obj.length() > 1) {
69,719✔
766
         copy_mem(buffer.data(), obj.bits() + 1, obj.length() - 1);
68,978✔
767
      }
768
   }
769
}
202,062✔
770

771
}  // namespace
772

773
/*
774
* BER decode a BIT STRING or OCTET STRING
775
*/
776
BER_Decoder& BER_Decoder::decode(secure_vector<uint8_t>& buffer,
11,095✔
777
                                 ASN1_Type real_type,
778
                                 ASN1_Type type_tag,
779
                                 ASN1_Class class_tag) {
780
   if(real_type != ASN1_Type::OctetString && real_type != ASN1_Type::BitString) {
11,095✔
781
      throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", static_cast<uint32_t>(real_type));
×
782
   }
783

784
   asn1_decode_binary_string(
11,043✔
785
      buffer, get_next_object(), real_type, type_tag, class_tag, m_limits.require_der_encoding());
22,138✔
786
   return (*this);
11,040✔
787
}
788

789
BER_Decoder& BER_Decoder::decode(std::vector<uint8_t>& buffer,
193,410✔
790
                                 ASN1_Type real_type,
791
                                 ASN1_Type type_tag,
792
                                 ASN1_Class class_tag) {
793
   if(real_type != ASN1_Type::OctetString && real_type != ASN1_Type::BitString) {
193,410✔
794
      throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", static_cast<uint32_t>(real_type));
1,447✔
795
   }
796

797
   asn1_decode_binary_string(
191,269✔
798
      buffer, get_next_object(), real_type, type_tag, class_tag, m_limits.require_der_encoding());
383,232✔
799
   return (*this);
191,022✔
800
}
801

802
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc