Botan 2.19.1
Crypto and TLS for C&
ber_dec.cpp
Go to the documentation of this file.
1/*
2* BER Decoder
3* (C) 1999-2008,2015,2017,2018 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/ber_dec.h>
9#include <botan/bigint.h>
10#include <botan/loadstor.h>
11#include <botan/internal/safeint.h>
12
13namespace Botan {
14
15namespace {
16
17/*
18* This value is somewhat arbitrary. OpenSSL allows up to 128 nested
19* indefinite length sequences. If you increase this, also increase the
20* limit in the test in test_asn1.cpp
21*/
22const size_t ALLOWED_EOC_NESTINGS = 16;
23
24/*
25* BER decode an ASN.1 type tag
26*/
27size_t decode_tag(DataSource* ber, ASN1_Tag& type_tag, ASN1_Tag& class_tag)
28 {
29 uint8_t b;
30 if(!ber->read_byte(b))
31 {
32 class_tag = type_tag = NO_OBJECT;
33 return 0;
34 }
35
36 if((b & 0x1F) != 0x1F)
37 {
38 type_tag = ASN1_Tag(b & 0x1F);
39 class_tag = ASN1_Tag(b & 0xE0);
40 return 1;
41 }
42
43 size_t tag_bytes = 1;
44 class_tag = ASN1_Tag(b & 0xE0);
45
46 size_t tag_buf = 0;
47 while(true)
48 {
49 if(!ber->read_byte(b))
50 throw BER_Decoding_Error("Long-form tag truncated");
51 if(tag_buf & 0xFF000000)
52 throw BER_Decoding_Error("Long-form tag overflowed 32 bits");
53 ++tag_bytes;
54 tag_buf = (tag_buf << 7) | (b & 0x7F);
55 if((b & 0x80) == 0) break;
56 }
57 type_tag = ASN1_Tag(tag_buf);
58 return tag_bytes;
59 }
60
61/*
62* Find the EOC marker
63*/
64size_t find_eoc(DataSource* src, size_t allow_indef);
65
66/*
67* BER decode an ASN.1 length field
68*/
69size_t decode_length(DataSource* ber, size_t& field_size, size_t allow_indef)
70 {
71 uint8_t b;
72 if(!ber->read_byte(b))
73 throw BER_Decoding_Error("Length field not found");
74 field_size = 1;
75 if((b & 0x80) == 0)
76 return b;
77
78 field_size += (b & 0x7F);
79 if(field_size > 5)
80 throw BER_Decoding_Error("Length field is too large");
81
82 if(field_size == 1)
83 {
84 if(allow_indef == 0)
85 {
86 throw BER_Decoding_Error("Nested EOC markers too deep, rejecting to avoid stack exhaustion");
87 }
88 else
89 {
90 return find_eoc(ber, allow_indef - 1);
91 }
92 }
93
94 size_t length = 0;
95
96 for(size_t i = 0; i != field_size - 1; ++i)
97 {
98 if(get_byte(0, length) != 0)
99 throw BER_Decoding_Error("Field length overflow");
100 if(!ber->read_byte(b))
101 throw BER_Decoding_Error("Corrupted length field");
102 length = (length << 8) | b;
103 }
104 return length;
105 }
106
107/*
108* Find the EOC marker
109*/
110size_t find_eoc(DataSource* ber, size_t allow_indef)
111 {
112 secure_vector<uint8_t> buffer(BOTAN_DEFAULT_BUFFER_SIZE), data;
113
114 while(true)
115 {
116 const size_t got = ber->peek(buffer.data(), buffer.size(), data.size());
117 if(got == 0)
118 break;
119
120 data += std::make_pair(buffer.data(), got);
121 }
122
123 DataSource_Memory source(data);
124 data.clear();
125
126 size_t length = 0;
127 while(true)
128 {
129 ASN1_Tag type_tag, class_tag;
130 size_t tag_size = decode_tag(&source, type_tag, class_tag);
131 if(type_tag == NO_OBJECT)
132 break;
133
134 size_t length_size = 0;
135 size_t item_size = decode_length(&source, length_size, allow_indef);
136 source.discard_next(item_size);
137
138 length = BOTAN_CHECKED_ADD(length, item_size);
139 length = BOTAN_CHECKED_ADD(length, tag_size);
140 length = BOTAN_CHECKED_ADD(length, length_size);
141
142 if(type_tag == EOC && class_tag == UNIVERSAL)
143 break;
144 }
145 return length;
146 }
147
148class DataSource_BERObject final : public DataSource
149 {
150 public:
151 size_t read(uint8_t out[], size_t length) override
152 {
153 BOTAN_ASSERT_NOMSG(m_offset <= m_obj.length());
154 const size_t got = std::min<size_t>(m_obj.length() - m_offset, length);
155 copy_mem(out, m_obj.bits() + m_offset, got);
156 m_offset += got;
157 return got;
158 }
159
160 size_t peek(uint8_t out[], size_t length, size_t peek_offset) const override
161 {
162 BOTAN_ASSERT_NOMSG(m_offset <= m_obj.length());
163 const size_t bytes_left = m_obj.length() - m_offset;
164
165 if(peek_offset >= bytes_left)
166 return 0;
167
168 const size_t got = std::min(bytes_left - peek_offset, length);
169 copy_mem(out, m_obj.bits() + peek_offset, got);
170 return got;
171 }
172
173 bool check_available(size_t n) override
174 {
175 BOTAN_ASSERT_NOMSG(m_offset <= m_obj.length());
176 return (n <= (m_obj.length() - m_offset));
177 }
178
179 bool end_of_data() const override
180 {
181 return get_bytes_read() == m_obj.length();
182 }
183
184 size_t get_bytes_read() const override { return m_offset; }
185
186 explicit DataSource_BERObject(BER_Object&& obj) : m_obj(std::move(obj)), m_offset(0) {}
187
188 private:
189 BER_Object m_obj;
190 size_t m_offset;
191 };
192
193}
194
195/*
196* Check if more objects are there
197*/
199 {
200 if(m_source->end_of_data() && !m_pushed.is_set())
201 return false;
202 return true;
203 }
204
205/*
206* Verify that no bytes remain in the source
207*/
209 {
210 return verify_end("BER_Decoder::verify_end called, but data remains");
211 }
212
213/*
214* Verify that no bytes remain in the source
215*/
216BER_Decoder& BER_Decoder::verify_end(const std::string& err)
217 {
218 if(!m_source->end_of_data() || m_pushed.is_set())
219 throw Decoding_Error(err);
220 return (*this);
221 }
222
223/*
224* Discard all the bytes remaining in the source
225*/
227 {
228 uint8_t buf;
229 while(m_source->read_byte(buf))
230 {}
231 return (*this);
232 }
233
234/*
235* Return the BER encoding of the next object
236*/
238 {
239 BER_Object next;
240
241 if(m_pushed.is_set())
242 {
243 std::swap(next, m_pushed);
244 return next;
245 }
246
247 for(;;)
248 {
249 ASN1_Tag type_tag, class_tag;
250 decode_tag(m_source, type_tag, class_tag);
251 next.set_tagging(type_tag, class_tag);
252 if(next.is_set() == false) // no more objects
253 return next;
254
255 size_t field_size;
256 const size_t length = decode_length(m_source, field_size, ALLOWED_EOC_NESTINGS);
257 if(!m_source->check_available(length))
258 throw BER_Decoding_Error("Value truncated");
259
260 uint8_t* out = next.mutable_bits(length);
261 if(m_source->read(out, length) != length)
262 throw BER_Decoding_Error("Value truncated");
263
264 if(next.tagging() == EOC)
265 continue;
266 else
267 break;
268 }
269
270 return next;
271 }
272
273/*
274* Push a object back into the stream
275*/
277 {
278 if(m_pushed.is_set())
279 throw Invalid_State("BER_Decoder: Only one push back is allowed");
280 m_pushed = obj;
281 }
282
284 {
285 if(m_pushed.is_set())
286 throw Invalid_State("BER_Decoder: Only one push back is allowed");
287 m_pushed = std::move(obj);
288 }
289
291 {
293 obj.assert_is_a(type_tag, ASN1_Tag(class_tag | CONSTRUCTED));
294 return BER_Decoder(std::move(obj), this);
295 }
296
297/*
298* Finish decoding a CONSTRUCTED type
299*/
301 {
302 if(!m_parent)
303 throw Invalid_State("BER_Decoder::end_cons called with null parent");
304 if(!m_source->end_of_data())
305 throw Decoding_Error("BER_Decoder::end_cons called with data left");
306 return (*m_parent);
307 }
308
310 {
311 m_data_src.reset(new DataSource_BERObject(std::move(obj)));
312 m_source = m_data_src.get();
313 m_parent = parent;
314 }
315
316/*
317* BER_Decoder Constructor
318*/
320 {
321 m_source = &src;
322 }
323
324/*
325* BER_Decoder Constructor
326 */
327BER_Decoder::BER_Decoder(const uint8_t data[], size_t length)
328 {
329 m_data_src.reset(new DataSource_Memory(data, length));
330 m_source = m_data_src.get();
331 }
332
333/*
334* BER_Decoder Constructor
335*/
337 {
338 m_data_src.reset(new DataSource_Memory(data));
339 m_source = m_data_src.get();
340 }
341
342/*
343* BER_Decoder Constructor
344*/
345BER_Decoder::BER_Decoder(const std::vector<uint8_t>& data)
346 {
347 m_data_src.reset(new DataSource_Memory(data.data(), data.size()));
348 m_source = m_data_src.get();
349 }
350
351/*
352* BER_Decoder Copy Constructor
353*/
355 {
356 m_source = other.m_source;
357
358 // take ownership
359 std::swap(m_data_src, other.m_data_src);
360 m_parent = other.m_parent;
361 }
362
363/*
364* Request for an object to decode itself
365*/
368 {
369 obj.decode_from(*this);
370 return (*this);
371 }
372
373/*
374* Decode a BER encoded NULL
375*/
377 {
380 if(obj.length() > 0)
381 throw BER_Decoding_Error("NULL object had nonzero size");
382 return (*this);
383 }
384
386 {
388 decode(out_vec, OCTET_STRING);
389 out = BigInt::decode(out_vec.data(), out_vec.size());
390 return (*this);
391 }
392
393/*
394* Decode a BER encoded BOOLEAN
395*/
397 ASN1_Tag type_tag, ASN1_Tag class_tag)
398 {
400 obj.assert_is_a(type_tag, class_tag);
401
402 if(obj.length() != 1)
403 throw BER_Decoding_Error("BER boolean value had invalid size");
404
405 out = (obj.bits()[0]) ? true : false;
406 return (*this);
407 }
408
409/*
410* Decode a small BER encoded INTEGER
411*/
413 ASN1_Tag type_tag,
414 ASN1_Tag class_tag)
415 {
416 BigInt integer;
417 decode(integer, type_tag, class_tag);
418
419 if(integer.is_negative())
420 throw BER_Decoding_Error("Decoded small integer value was negative");
421
422 if(integer.bits() > 32)
423 throw BER_Decoding_Error("Decoded integer value larger than expected");
424
425 out = 0;
426 for(size_t i = 0; i != 4; ++i)
427 out = (out << 8) | integer.byte_at(3-i);
428
429 return (*this);
430 }
431
432/*
433* Decode a small BER encoded INTEGER
434*/
436 ASN1_Tag class_tag,
437 size_t T_bytes)
438 {
439 if(T_bytes > 8)
440 throw BER_Decoding_Error("Can't decode small integer over 8 bytes");
441
442 BigInt integer;
443 decode(integer, type_tag, class_tag);
444
445 if(integer.bits() > 8*T_bytes)
446 throw BER_Decoding_Error("Decoded integer value larger than expected");
447
448 uint64_t out = 0;
449 for(size_t i = 0; i != 8; ++i)
450 out = (out << 8) | integer.byte_at(7-i);
451
452 return out;
453 }
454
455/*
456* Decode a BER encoded INTEGER
457*/
459 ASN1_Tag type_tag,
460 ASN1_Tag class_tag)
461 {
463 obj.assert_is_a(type_tag, class_tag);
464
465 if(obj.length() == 0)
466 {
467 out = 0;
468 }
469 else
470 {
471 const bool negative = (obj.bits()[0] & 0x80) ? true : false;
472
473 if(negative)
474 {
475 secure_vector<uint8_t> vec(obj.bits(), obj.bits() + obj.length());
476 for(size_t i = obj.length(); i > 0; --i)
477 if(vec[i-1]--)
478 break;
479 for(size_t i = 0; i != obj.length(); ++i)
480 vec[i] = ~vec[i];
481 out = BigInt(vec.data(), vec.size());
482 out.flip_sign();
483 }
484 else
485 {
486 out = BigInt(obj.bits(), obj.length());
487 }
488 }
489
490 return (*this);
491 }
492
493namespace {
494
495template<typename Alloc>
496void asn1_decode_binary_string(std::vector<uint8_t, Alloc>& buffer,
497 const BER_Object& obj,
498 ASN1_Tag real_type,
499 ASN1_Tag type_tag,
500 ASN1_Tag class_tag)
501 {
502 obj.assert_is_a(type_tag, class_tag);
503
504 if(real_type == OCTET_STRING)
505 {
506 buffer.assign(obj.bits(), obj.bits() + obj.length());
507 }
508 else
509 {
510 if(obj.length() == 0)
511 throw BER_Decoding_Error("Invalid BIT STRING");
512 if(obj.bits()[0] >= 8)
513 throw BER_Decoding_Error("Bad number of unused bits in BIT STRING");
514
515 buffer.resize(obj.length() - 1);
516
517 if(obj.length() > 1)
518 copy_mem(buffer.data(), obj.bits() + 1, obj.length() - 1);
519 }
520 }
521
522}
523
524/*
525* BER decode a BIT STRING or OCTET STRING
526*/
528 ASN1_Tag real_type,
529 ASN1_Tag type_tag, ASN1_Tag class_tag)
530 {
531 if(real_type != OCTET_STRING && real_type != BIT_STRING)
532 throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type);
533
534 asn1_decode_binary_string(buffer, get_next_object(), real_type, type_tag, class_tag);
535 return (*this);
536 }
537
538BER_Decoder& BER_Decoder::decode(std::vector<uint8_t>& buffer,
539 ASN1_Tag real_type,
540 ASN1_Tag type_tag, ASN1_Tag class_tag)
541 {
542 if(real_type != OCTET_STRING && real_type != BIT_STRING)
543 throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type);
544
545 asn1_decode_binary_string(buffer, get_next_object(), real_type, type_tag, class_tag);
546 return (*this);
547 }
548
549}
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:68
virtual void decode_from(BER_Decoder &from)=0
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:290
BER_Decoder(const uint8_t buf[], size_t len)
Definition: ber_dec.cpp:327
void push_back(const BER_Object &obj)
Definition: ber_dec.cpp:276
BER_Object get_next_object()
Definition: ber_dec.cpp:237
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
uint64_t decode_constrained_integer(ASN1_Tag type_tag, ASN1_Tag class_tag, size_t T_bytes)
Definition: ber_dec.cpp:435
bool more_items() const
Definition: ber_dec.cpp:198
BER_Decoder & verify_end()
Definition: ber_dec.cpp:208
BER_Decoder & end_cons()
Definition: ber_dec.cpp:300
BER_Decoder & discard_remaining()
Definition: ber_dec.cpp:226
BER_Decoder & decode_octet_string_bigint(BigInt &b)
Definition: ber_dec.cpp:385
BER_Decoder & decode_null()
Definition: ber_dec.cpp:376
size_t length() const
Definition: asn1_obj.h:121
ASN1_Tag tagging() const
Definition: asn1_obj.h:114
const uint8_t * bits() const
Definition: asn1_obj.h:119
bool is_set() const
Definition: asn1_obj.h:112
void assert_is_a(ASN1_Tag type_tag, ASN1_Tag class_tag, const std::string &descr="object") const
Definition: asn1_obj.cpp:27
static BigInt decode(const uint8_t buf[], size_t length)
Definition: bigint.h:805
void flip_sign()
Definition: bigint.h:554
size_t bits() const
Definition: bigint.cpp:296
uint8_t byte_at(size_t n) const
Definition: bigint.cpp:109
bool is_negative() const
Definition: bigint.h:527
size_t read_byte(uint8_t &out)
Definition: data_src.cpp:23
virtual size_t read(uint8_t out[], size_t length) BOTAN_WARN_UNUSED_RESULT=0
virtual bool check_available(size_t n)=0
virtual bool end_of_data() const =0
int(* final)(unsigned char *, CTX *)
Definition: alg_id.cpp:13
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:133
ASN1_Tag
Definition: asn1_obj.h:25
@ CONSTRUCTED
Definition: asn1_obj.h:30
@ BIT_STRING
Definition: asn1_obj.h:37
@ NO_OBJECT
Definition: asn1_obj.h:58
@ OCTET_STRING
Definition: asn1_obj.h:38
@ NULL_TAG
Definition: asn1_obj.h:39
@ UNIVERSAL
Definition: asn1_obj.h:26
@ EOC
Definition: asn1_obj.h:34
constexpr uint8_t get_byte(size_t byte_num, T input)
Definition: loadstor.h:41
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
Definition: bigint.h:1143
#define BOTAN_CHECKED_ADD(x, y)
Definition: safeint.h:37