/src/botan/src/lib/asn1/ber_dec.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
13 | | namespace Botan { |
14 | | |
15 | | namespace { |
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 | | */ |
22 | | const size_t ALLOWED_EOC_NESTINGS = 16; |
23 | | |
24 | | /* |
25 | | * BER decode an ASN.1 type tag |
26 | | */ |
27 | | size_t decode_tag(DataSource* ber, ASN1_Tag& type_tag, ASN1_Tag& class_tag) |
28 | 2.33M | { |
29 | 2.33M | uint8_t b; |
30 | 2.33M | if(!ber->read_byte(b)) |
31 | 176k | { |
32 | 176k | class_tag = type_tag = NO_OBJECT; |
33 | 176k | return 0; |
34 | 176k | } |
35 | 2.15M | |
36 | 2.15M | if((b & 0x1F) != 0x1F) |
37 | 2.12M | { |
38 | 2.12M | type_tag = ASN1_Tag(b & 0x1F); |
39 | 2.12M | class_tag = ASN1_Tag(b & 0xE0); |
40 | 2.12M | return 1; |
41 | 2.12M | } |
42 | 31.8k | |
43 | 31.8k | size_t tag_bytes = 1; |
44 | 31.8k | class_tag = ASN1_Tag(b & 0xE0); |
45 | 31.8k | |
46 | 31.8k | size_t tag_buf = 0; |
47 | 52.4k | while(true) |
48 | 52.4k | { |
49 | 52.4k | if(!ber->read_byte(b)) |
50 | 647 | throw BER_Decoding_Error("Long-form tag truncated"); |
51 | 51.8k | if(tag_buf & 0xFF000000) |
52 | 354 | throw BER_Decoding_Error("Long-form tag overflowed 32 bits"); |
53 | 51.4k | ++tag_bytes; |
54 | 51.4k | tag_buf = (tag_buf << 7) | (b & 0x7F); |
55 | 51.4k | if((b & 0x80) == 0) break; |
56 | 51.4k | } |
57 | 31.8k | type_tag = ASN1_Tag(tag_buf); |
58 | 30.8k | return tag_bytes; |
59 | 31.8k | } |
60 | | |
61 | | /* |
62 | | * Find the EOC marker |
63 | | */ |
64 | | size_t find_eoc(DataSource* src, size_t allow_indef); |
65 | | |
66 | | /* |
67 | | * BER decode an ASN.1 length field |
68 | | */ |
69 | | size_t decode_length(DataSource* ber, size_t& field_size, size_t allow_indef) |
70 | 2.15M | { |
71 | 2.15M | uint8_t b; |
72 | 2.15M | if(!ber->read_byte(b)) |
73 | 2.07k | throw BER_Decoding_Error("Length field not found"); |
74 | 2.15M | field_size = 1; |
75 | 2.15M | if((b & 0x80) == 0) |
76 | 1.83M | return b; |
77 | 319k | |
78 | 319k | field_size += (b & 0x7F); |
79 | 319k | if(field_size > 5) |
80 | 2.67k | throw BER_Decoding_Error("Length field is too large"); |
81 | 316k | |
82 | 316k | if(field_size == 1) |
83 | 194k | { |
84 | 194k | if(allow_indef == 0) |
85 | 236 | { |
86 | 236 | throw BER_Decoding_Error("Nested EOC markers too deep, rejecting to avoid stack exhaustion"); |
87 | 236 | } |
88 | 194k | else |
89 | 194k | { |
90 | 194k | return find_eoc(ber, allow_indef - 1); |
91 | 194k | } |
92 | 122k | } |
93 | 122k | |
94 | 122k | size_t length = 0; |
95 | 122k | |
96 | 340k | for(size_t i = 0; i != field_size - 1; ++i) |
97 | 219k | { |
98 | 219k | if(get_byte(0, length) != 0) |
99 | 0 | throw BER_Decoding_Error("Field length overflow"); |
100 | 219k | if(!ber->read_byte(b)) |
101 | 435 | throw BER_Decoding_Error("Corrupted length field"); |
102 | 218k | length = (length << 8) | b; |
103 | 218k | } |
104 | 122k | return length; |
105 | 122k | } |
106 | | |
107 | | /* |
108 | | * Find the EOC marker |
109 | | */ |
110 | | size_t find_eoc(DataSource* ber, size_t allow_indef) |
111 | 194k | { |
112 | 194k | secure_vector<uint8_t> buffer(BOTAN_DEFAULT_BUFFER_SIZE), data; |
113 | 194k | |
114 | 427k | while(true) |
115 | 427k | { |
116 | 427k | const size_t got = ber->peek(buffer.data(), buffer.size(), data.size()); |
117 | 427k | if(got == 0) |
118 | 194k | break; |
119 | 233k | |
120 | 233k | data += std::make_pair(buffer.data(), got); |
121 | 233k | } |
122 | 194k | |
123 | 194k | DataSource_Memory source(data); |
124 | 194k | data.clear(); |
125 | 194k | |
126 | 194k | size_t length = 0; |
127 | 909k | while(true) |
128 | 903k | { |
129 | 903k | ASN1_Tag type_tag, class_tag; |
130 | 903k | size_t tag_size = decode_tag(&source, type_tag, class_tag); |
131 | 903k | if(type_tag == NO_OBJECT) |
132 | 131k | break; |
133 | 772k | |
134 | 772k | size_t length_size = 0; |
135 | 772k | size_t item_size = decode_length(&source, length_size, allow_indef); |
136 | 772k | source.discard_next(item_size); |
137 | 772k | |
138 | 772k | length = BOTAN_CHECKED_ADD(length, item_size); |
139 | 772k | length = BOTAN_CHECKED_ADD(length, tag_size); |
140 | 772k | length = BOTAN_CHECKED_ADD(length, length_size); |
141 | 772k | |
142 | 772k | if(type_tag == EOC && class_tag == UNIVERSAL) |
143 | 57.4k | break; |
144 | 772k | } |
145 | 194k | return length; |
146 | 194k | } |
147 | | |
148 | | class DataSource_BERObject final : public DataSource |
149 | | { |
150 | | public: |
151 | | size_t read(uint8_t out[], size_t length) override |
152 | 14.7M | { |
153 | 14.7M | BOTAN_ASSERT_NOMSG(m_offset <= m_obj.length()); |
154 | 14.7M | const size_t got = std::min<size_t>(m_obj.length() - m_offset, length); |
155 | 14.7M | copy_mem(out, m_obj.bits() + m_offset, got); |
156 | 14.7M | m_offset += got; |
157 | 14.7M | return got; |
158 | 14.7M | } |
159 | | |
160 | | size_t peek(uint8_t out[], size_t length, size_t peek_offset) const override |
161 | 43.9k | { |
162 | 43.9k | BOTAN_ASSERT_NOMSG(m_offset <= m_obj.length()); |
163 | 43.9k | const size_t bytes_left = m_obj.length() - m_offset; |
164 | 43.9k | |
165 | 43.9k | if(peek_offset >= bytes_left) |
166 | 21.1k | return 0; |
167 | 22.7k | |
168 | 22.7k | const size_t got = std::min(bytes_left - peek_offset, length); |
169 | 22.7k | copy_mem(out, m_obj.bits() + peek_offset, got); |
170 | 22.7k | return got; |
171 | 22.7k | } |
172 | | |
173 | | bool check_available(size_t n) override |
174 | 869k | { |
175 | 869k | BOTAN_ASSERT_NOMSG(m_offset <= m_obj.length()); |
176 | 869k | return (n <= (m_obj.length() - m_offset)); |
177 | 869k | } |
178 | | |
179 | | bool end_of_data() const override |
180 | 849k | { |
181 | 849k | return get_bytes_read() == m_obj.length(); |
182 | 849k | } |
183 | | |
184 | 849k | size_t get_bytes_read() const override { return m_offset; } |
185 | | |
186 | 527k | 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 | | */ |
198 | | bool BER_Decoder::more_items() const |
199 | 518k | { |
200 | 518k | if(m_source->end_of_data() && !m_pushed.is_set()) |
201 | 172k | return false; |
202 | 345k | return true; |
203 | 345k | } |
204 | | |
205 | | /* |
206 | | * Verify that no bytes remain in the source |
207 | | */ |
208 | | BER_Decoder& BER_Decoder::verify_end() |
209 | 26.5k | { |
210 | 26.5k | return verify_end("BER_Decoder::verify_end called, but data remains"); |
211 | 26.5k | } |
212 | | |
213 | | /* |
214 | | * Verify that no bytes remain in the source |
215 | | */ |
216 | | BER_Decoder& BER_Decoder::verify_end(const std::string& err) |
217 | 151k | { |
218 | 151k | if(!m_source->end_of_data() || m_pushed.is_set()) |
219 | 269 | throw Decoding_Error(err); |
220 | 151k | return (*this); |
221 | 151k | } |
222 | | |
223 | | /* |
224 | | * Discard all the bytes remaining in the source |
225 | | */ |
226 | | BER_Decoder& BER_Decoder::discard_remaining() |
227 | 16.1k | { |
228 | 16.1k | uint8_t buf; |
229 | 2.52M | while(m_source->read_byte(buf)) |
230 | 2.50M | {} |
231 | 16.1k | return (*this); |
232 | 16.1k | } |
233 | | |
234 | | /* |
235 | | * Return the BER encoding of the next object |
236 | | */ |
237 | | BER_Object BER_Decoder::get_next_object() |
238 | 1.40M | { |
239 | 1.40M | BER_Object next; |
240 | 1.40M | |
241 | 1.40M | if(m_pushed.is_set()) |
242 | 70.5k | { |
243 | 70.5k | std::swap(next, m_pushed); |
244 | 70.5k | return next; |
245 | 70.5k | } |
246 | 1.33M | |
247 | 1.33M | for(;;) |
248 | 1.42M | { |
249 | 1.42M | ASN1_Tag type_tag, class_tag; |
250 | 1.42M | decode_tag(m_source, type_tag, class_tag); |
251 | 1.42M | next.set_tagging(type_tag, class_tag); |
252 | 1.42M | if(next.is_set() == false) // no more objects |
253 | 45.7k | return next; |
254 | 1.38M | |
255 | 1.38M | size_t field_size; |
256 | 1.38M | const size_t length = decode_length(m_source, field_size, ALLOWED_EOC_NESTINGS); |
257 | 1.38M | if(!m_source->check_available(length)) |
258 | 5.09k | throw BER_Decoding_Error("Value truncated"); |
259 | 1.37M | |
260 | 1.37M | uint8_t* out = next.mutable_bits(length); |
261 | 1.37M | if(m_source->read(out, length) != length) |
262 | 0 | throw BER_Decoding_Error("Value truncated"); |
263 | 1.37M | |
264 | 1.37M | if(next.tagging() == EOC) |
265 | 94.0k | continue; |
266 | 1.28M | else |
267 | 1.28M | break; |
268 | 1.37M | } |
269 | 1.33M | |
270 | 1.33M | return next; |
271 | 1.33M | } |
272 | | |
273 | | /* |
274 | | * Push a object back into the stream |
275 | | */ |
276 | | void BER_Decoder::push_back(const BER_Object& obj) |
277 | 5.79k | { |
278 | 5.79k | if(m_pushed.is_set()) |
279 | 0 | throw Invalid_State("BER_Decoder: Only one push back is allowed"); |
280 | 5.79k | m_pushed = obj; |
281 | 5.79k | } |
282 | | |
283 | | void BER_Decoder::push_back(BER_Object&& obj) |
284 | 89.2k | { |
285 | 89.2k | if(m_pushed.is_set()) |
286 | 0 | throw Invalid_State("BER_Decoder: Only one push back is allowed"); |
287 | 89.2k | m_pushed = std::move(obj); |
288 | 89.2k | } |
289 | | |
290 | | BER_Decoder BER_Decoder::start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag) |
291 | 530k | { |
292 | 530k | BER_Object obj = get_next_object(); |
293 | 530k | obj.assert_is_a(type_tag, ASN1_Tag(class_tag | CONSTRUCTED)); |
294 | 530k | return BER_Decoder(std::move(obj), this); |
295 | 530k | } |
296 | | |
297 | | /* |
298 | | * Finish decoding a CONSTRUCTED type |
299 | | */ |
300 | | BER_Decoder& BER_Decoder::end_cons() |
301 | 357k | { |
302 | 357k | if(!m_parent) |
303 | 0 | throw Invalid_State("BER_Decoder::end_cons called with null parent"); |
304 | 357k | if(!m_source->end_of_data()) |
305 | 639 | throw Decoding_Error("BER_Decoder::end_cons called with data left"); |
306 | 357k | return (*m_parent); |
307 | 357k | } |
308 | | |
309 | | BER_Decoder::BER_Decoder(BER_Object&& obj, BER_Decoder* parent) |
310 | 527k | { |
311 | 527k | m_data_src.reset(new DataSource_BERObject(std::move(obj))); |
312 | 527k | m_source = m_data_src.get(); |
313 | 527k | m_parent = parent; |
314 | 527k | } |
315 | | |
316 | | /* |
317 | | * BER_Decoder Constructor |
318 | | */ |
319 | | BER_Decoder::BER_Decoder(DataSource& src) |
320 | 29.7k | { |
321 | 29.7k | m_source = &src; |
322 | 29.7k | } |
323 | | |
324 | | /* |
325 | | * BER_Decoder Constructor |
326 | | */ |
327 | | BER_Decoder::BER_Decoder(const uint8_t data[], size_t length) |
328 | 48.6k | { |
329 | 48.6k | m_data_src.reset(new DataSource_Memory(data, length)); |
330 | 48.6k | m_source = m_data_src.get(); |
331 | 48.6k | } |
332 | | |
333 | | /* |
334 | | * BER_Decoder Constructor |
335 | | */ |
336 | | BER_Decoder::BER_Decoder(const secure_vector<uint8_t>& data) |
337 | 4.46k | { |
338 | 4.46k | m_data_src.reset(new DataSource_Memory(data)); |
339 | 4.46k | m_source = m_data_src.get(); |
340 | 4.46k | } |
341 | | |
342 | | /* |
343 | | * BER_Decoder Constructor |
344 | | */ |
345 | | BER_Decoder::BER_Decoder(const std::vector<uint8_t>& data) |
346 | 190k | { |
347 | 190k | m_data_src.reset(new DataSource_Memory(data.data(), data.size())); |
348 | 190k | m_source = m_data_src.get(); |
349 | 190k | } |
350 | | |
351 | | /* |
352 | | * BER_Decoder Copy Constructor |
353 | | */ |
354 | | BER_Decoder::BER_Decoder(const BER_Decoder& other) |
355 | 0 | { |
356 | 0 | m_source = other.m_source; |
357 | 0 |
|
358 | 0 | // take ownership |
359 | 0 | std::swap(m_data_src, other.m_data_src); |
360 | 0 | m_parent = other.m_parent; |
361 | 0 | } |
362 | | |
363 | | /* |
364 | | * Request for an object to decode itself |
365 | | */ |
366 | | BER_Decoder& BER_Decoder::decode(ASN1_Object& obj, |
367 | | ASN1_Tag, ASN1_Tag) |
368 | 566k | { |
369 | 566k | obj.decode_from(*this); |
370 | 566k | return (*this); |
371 | 566k | } |
372 | | |
373 | | /* |
374 | | * Decode a BER encoded NULL |
375 | | */ |
376 | | BER_Decoder& BER_Decoder::decode_null() |
377 | 0 | { |
378 | 0 | BER_Object obj = get_next_object(); |
379 | 0 | obj.assert_is_a(NULL_TAG, UNIVERSAL); |
380 | 0 | if(obj.length() > 0) |
381 | 0 | throw BER_Decoding_Error("NULL object had nonzero size"); |
382 | 0 | return (*this); |
383 | 0 | } |
384 | | |
385 | | BER_Decoder& BER_Decoder::decode_octet_string_bigint(BigInt& out) |
386 | 1.76k | { |
387 | 1.76k | secure_vector<uint8_t> out_vec; |
388 | 1.76k | decode(out_vec, OCTET_STRING); |
389 | 1.76k | out = BigInt::decode(out_vec.data(), out_vec.size()); |
390 | 1.76k | return (*this); |
391 | 1.76k | } |
392 | | |
393 | | /* |
394 | | * Decode a BER encoded BOOLEAN |
395 | | */ |
396 | | BER_Decoder& BER_Decoder::decode(bool& out, |
397 | | ASN1_Tag type_tag, ASN1_Tag class_tag) |
398 | 4.96k | { |
399 | 4.96k | BER_Object obj = get_next_object(); |
400 | 4.96k | obj.assert_is_a(type_tag, class_tag); |
401 | 4.96k | |
402 | 4.96k | if(obj.length() != 1) |
403 | 314 | throw BER_Decoding_Error("BER boolean value had invalid size"); |
404 | 4.65k | |
405 | 4.65k | out = (obj.bits()[0]) ? true : false; |
406 | 4.65k | return (*this); |
407 | 4.65k | } |
408 | | |
409 | | /* |
410 | | * Decode a small BER encoded INTEGER |
411 | | */ |
412 | | BER_Decoder& BER_Decoder::decode(size_t& out, |
413 | | ASN1_Tag type_tag, |
414 | | ASN1_Tag class_tag) |
415 | 19.6k | { |
416 | 19.6k | BigInt integer; |
417 | 19.6k | decode(integer, type_tag, class_tag); |
418 | 19.6k | |
419 | 19.6k | if(integer.is_negative()) |
420 | 292 | throw BER_Decoding_Error("Decoded small integer value was negative"); |
421 | 19.4k | |
422 | 19.4k | if(integer.bits() > 32) |
423 | 217 | throw BER_Decoding_Error("Decoded integer value larger than expected"); |
424 | 19.1k | |
425 | 19.1k | out = 0; |
426 | 86.8k | for(size_t i = 0; i != 4; ++i) |
427 | 67.6k | out = (out << 8) | integer.byte_at(3-i); |
428 | 19.1k | |
429 | 19.1k | return (*this); |
430 | 19.1k | } |
431 | | |
432 | | /* |
433 | | * Decode a small BER encoded INTEGER |
434 | | */ |
435 | | uint64_t BER_Decoder::decode_constrained_integer(ASN1_Tag type_tag, |
436 | | ASN1_Tag class_tag, |
437 | | size_t T_bytes) |
438 | 0 | { |
439 | 0 | if(T_bytes > 8) |
440 | 0 | throw BER_Decoding_Error("Can't decode small integer over 8 bytes"); |
441 | 0 | |
442 | 0 | BigInt integer; |
443 | 0 | decode(integer, type_tag, class_tag); |
444 | 0 |
|
445 | 0 | if(integer.bits() > 8*T_bytes) |
446 | 0 | throw BER_Decoding_Error("Decoded integer value larger than expected"); |
447 | 0 | |
448 | 0 | uint64_t out = 0; |
449 | 0 | for(size_t i = 0; i != 8; ++i) |
450 | 0 | out = (out << 8) | integer.byte_at(7-i); |
451 | 0 |
|
452 | 0 | return out; |
453 | 0 | } |
454 | | |
455 | | /* |
456 | | * Decode a BER encoded INTEGER |
457 | | */ |
458 | | BER_Decoder& BER_Decoder::decode(BigInt& out, |
459 | | ASN1_Tag type_tag, |
460 | | ASN1_Tag class_tag) |
461 | 68.7k | { |
462 | 68.7k | BER_Object obj = get_next_object(); |
463 | 68.7k | obj.assert_is_a(type_tag, class_tag); |
464 | 68.7k | |
465 | 68.7k | if(obj.length() == 0) |
466 | 7.83k | { |
467 | 7.83k | out = 0; |
468 | 7.83k | } |
469 | 60.8k | else |
470 | 60.8k | { |
471 | 60.8k | const bool negative = (obj.bits()[0] & 0x80) ? true : false; |
472 | 60.8k | |
473 | 60.8k | if(negative) |
474 | 3.94k | { |
475 | 3.94k | secure_vector<uint8_t> vec(obj.bits(), obj.bits() + obj.length()); |
476 | 8.17k | for(size_t i = obj.length(); i > 0; --i) |
477 | 8.17k | if(vec[i-1]--) |
478 | 3.94k | break; |
479 | 243k | for(size_t i = 0; i != obj.length(); ++i) |
480 | 239k | vec[i] = ~vec[i]; |
481 | 3.94k | out = BigInt(vec.data(), vec.size()); |
482 | 3.94k | out.flip_sign(); |
483 | 3.94k | } |
484 | 56.9k | else |
485 | 56.9k | { |
486 | 56.9k | out = BigInt(obj.bits(), obj.length()); |
487 | 56.9k | } |
488 | 60.8k | } |
489 | 68.7k | |
490 | 68.7k | return (*this); |
491 | 68.7k | } |
492 | | |
493 | | namespace { |
494 | | |
495 | | template<typename Alloc> |
496 | | void 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 | 108k | { |
502 | 108k | obj.assert_is_a(type_tag, class_tag); |
503 | 108k | |
504 | 108k | if(real_type == OCTET_STRING) |
505 | 60.0k | { |
506 | 60.0k | buffer.assign(obj.bits(), obj.bits() + obj.length()); |
507 | 60.0k | } |
508 | 48.7k | else |
509 | 48.7k | { |
510 | 48.7k | if(obj.length() == 0) |
511 | 390 | throw BER_Decoding_Error("Invalid BIT STRING"); |
512 | 48.3k | if(obj.bits()[0] >= 8) |
513 | 257 | throw BER_Decoding_Error("Bad number of unused bits in BIT STRING"); |
514 | 48.1k | |
515 | 48.1k | buffer.resize(obj.length() - 1); |
516 | 48.1k | |
517 | 48.1k | if(obj.length() > 1) |
518 | 40.7k | copy_mem(buffer.data(), obj.bits() + 1, obj.length() - 1); |
519 | 48.1k | } |
520 | 108k | } ber_dec.cpp:void Botan::(anonymous namespace)::asn1_decode_binary_string<Botan::secure_allocator<unsigned char> >(std::__1::vector<unsigned char, Botan::secure_allocator<unsigned char> >&, Botan::BER_Object const&, Botan::ASN1_Tag, Botan::ASN1_Tag, Botan::ASN1_Tag) Line | Count | Source | 501 | 4.67k | { | 502 | 4.67k | obj.assert_is_a(type_tag, class_tag); | 503 | 4.67k | | 504 | 4.67k | if(real_type == OCTET_STRING) | 505 | 3.80k | { | 506 | 3.80k | buffer.assign(obj.bits(), obj.bits() + obj.length()); | 507 | 3.80k | } | 508 | 864 | else | 509 | 864 | { | 510 | 864 | if(obj.length() == 0) | 511 | 1 | throw BER_Decoding_Error("Invalid BIT STRING"); | 512 | 863 | if(obj.bits()[0] >= 8) | 513 | 6 | throw BER_Decoding_Error("Bad number of unused bits in BIT STRING"); | 514 | 857 | | 515 | 857 | buffer.resize(obj.length() - 1); | 516 | 857 | | 517 | 857 | if(obj.length() > 1) | 518 | 706 | copy_mem(buffer.data(), obj.bits() + 1, obj.length() - 1); | 519 | 857 | } | 520 | 4.67k | } |
ber_dec.cpp:void Botan::(anonymous namespace)::asn1_decode_binary_string<std::__1::allocator<unsigned char> >(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, Botan::BER_Object const&, Botan::ASN1_Tag, Botan::ASN1_Tag, Botan::ASN1_Tag) Line | Count | Source | 501 | 104k | { | 502 | 104k | obj.assert_is_a(type_tag, class_tag); | 503 | 104k | | 504 | 104k | if(real_type == OCTET_STRING) | 505 | 56.2k | { | 506 | 56.2k | buffer.assign(obj.bits(), obj.bits() + obj.length()); | 507 | 56.2k | } | 508 | 47.8k | else | 509 | 47.8k | { | 510 | 47.8k | if(obj.length() == 0) | 511 | 389 | throw BER_Decoding_Error("Invalid BIT STRING"); | 512 | 47.5k | if(obj.bits()[0] >= 8) | 513 | 251 | throw BER_Decoding_Error("Bad number of unused bits in BIT STRING"); | 514 | 47.2k | | 515 | 47.2k | buffer.resize(obj.length() - 1); | 516 | 47.2k | | 517 | 47.2k | if(obj.length() > 1) | 518 | 40.0k | copy_mem(buffer.data(), obj.bits() + 1, obj.length() - 1); | 519 | 47.2k | } | 520 | 104k | } |
|
521 | | |
522 | | } |
523 | | |
524 | | /* |
525 | | * BER decode a BIT STRING or OCTET STRING |
526 | | */ |
527 | | BER_Decoder& BER_Decoder::decode(secure_vector<uint8_t>& buffer, |
528 | | ASN1_Tag real_type, |
529 | | ASN1_Tag type_tag, ASN1_Tag class_tag) |
530 | 4.67k | { |
531 | 4.67k | if(real_type != OCTET_STRING && real_type != BIT_STRING) |
532 | 0 | throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type); |
533 | 4.67k | |
534 | 4.67k | asn1_decode_binary_string(buffer, get_next_object(), real_type, type_tag, class_tag); |
535 | 4.67k | return (*this); |
536 | 4.67k | } |
537 | | |
538 | | BER_Decoder& BER_Decoder::decode(std::vector<uint8_t>& buffer, |
539 | | ASN1_Tag real_type, |
540 | | ASN1_Tag type_tag, ASN1_Tag class_tag) |
541 | 105k | { |
542 | 105k | if(real_type != OCTET_STRING && real_type != BIT_STRING) |
543 | 1.37k | throw BER_Bad_Tag("Bad tag for {BIT,OCTET} STRING", real_type); |
544 | 104k | |
545 | 104k | asn1_decode_binary_string(buffer, get_next_object(), real_type, type_tag, class_tag); |
546 | 104k | return (*this); |
547 | 104k | } |
548 | | |
549 | | } |