1 /**
2 * BER Decoder
3 * 
4 * Copyright:
5 * (C) 1999-2010 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.asn1.ber_dec;
12 
13 import botan.constants;
14 public import botan.asn1.asn1_oid;
15 import botan.filters.data_src;
16 import botan.math.bigint.bigint;
17 import botan.utils.get_byte;
18 import botan.utils.types;
19 
20 public:
21 /**
22 * BER Decoding Object
23 */
24 struct BERDecoder
25 {
26 public:
27     /*
28     * Return the BER encoding of the next object
29     */
30     BERObject getNextObject()
31     {
32         BERObject next;
33         if (m_pushed.type_tag != ASN1Tag.NO_OBJECT)
34         {
35             next = m_pushed.dup;
36             m_pushed.class_tag = m_pushed.type_tag = ASN1Tag.NO_OBJECT;
37             return next.move();
38         }
39         decodeTag(m_source, next.type_tag, next.class_tag);
40 
41         if (next.type_tag == ASN1Tag.NO_OBJECT)
42             return next.move();
43         
44         size_t length = decodeLength(m_source);
45         //logTrace("length: ", length);
46 
47         next.value.resize(length);
48         if (m_source.read(next.value.ptr, length) != length)
49             throw new BERDecodingError("Value truncated");
50         if (next.type_tag == ASN1Tag.EOC && next.class_tag == ASN1Tag.UNIVERSAL)
51             return getNextObject();
52         return next.move();
53     }
54 
55     Vector!ubyte getNextOctetString()
56     {
57         Vector!ubyte out_vec;
58         decode(out_vec, ASN1Tag.OCTET_STRING);
59         return out_vec.move();
60     }
61         
62     /*
63     * Push a object back into the stream
64     */
65     void pushBack()(auto ref BERObject obj)
66     {
67         if (m_pushed.type_tag != ASN1Tag.NO_OBJECT)
68             throw new InvalidState("BERDecoder: Only one push back is allowed");
69         m_pushed = obj.move();
70     }
71 
72     
73     /*
74     * Check if more objects are there
75     */
76     bool moreItems() const
77     {
78         if (m_source.endOfData() && (m_pushed.type_tag == ASN1Tag.NO_OBJECT))
79             return false;
80         return true;
81     }
82 
83     /*
84     * Verify that no bytes remain in the m_source
85     */
86     ref BERDecoder verifyEnd()
87     {
88         if (!m_source.endOfData() || (m_pushed.type_tag != ASN1Tag.NO_OBJECT))
89             throw new InvalidState("verify_end called, but data remains");
90         return this;
91     }
92 
93     /*
94     * Discard all the bytes remaining in the m_source
95     */
96     ref BERDecoder discardRemaining()
97     {
98         ubyte buf;
99         while (m_source.readByte(buf))
100             continue;
101         //logTrace("Discarded");
102         return this;
103     }
104 
105     /*
106     * Begin decoding a ASN1Tag.CONSTRUCTED type
107     */
108     BERDecoder startCons(ASN1Tag type_tag,
109                          ASN1Tag class_tag = ASN1Tag.UNIVERSAL)
110     {
111         BERObject obj = getNextObject();
112         //logTrace("AssertIsA: ", (class_tag | ASN1Tag.CONSTRUCTED));
113         obj.assertIsA(type_tag, class_tag | ASN1Tag.CONSTRUCTED);
114         
115         BERDecoder result = BERDecoder(obj.value.ptr, obj.value.length);
116         result.m_parent = &this;
117         return result.move();
118     }
119 
120     /*
121     * Finish decoding a ASN1Tag.CONSTRUCTED type
122     */
123     ref BERDecoder endCons()
124     {
125         if (!m_parent)
126             throw new InvalidState("endCons called with NULL m_parent");
127         if (!m_source.endOfData())
128             throw new DecodingError("endCons called with data left");
129         return *m_parent;
130     }
131     
132 
133     
134     ref BERDecoder getNext(ref BERObject ber)
135     {
136         ber = getNextObject();
137         return this;
138     }
139         
140     /*
141     * Save all the bytes remaining in the m_source
142     */
143     ref BERDecoder rawBytes(T, ALLOC)(ref Vector!(T, ALLOC) output)
144     {
145         output.clear();
146         ubyte buf;
147         while (m_source.readByte(buf))
148             output.pushBack(buf);
149         return this;
150     }
151 
152     ref BERDecoder rawBytes(T, ALLOC)(ref RefCounted!(Vector!(T, ALLOC), ALLOC) output)
153     {
154         output.clear();
155         ubyte buf;
156         while (m_source.readByte(buf))
157             output.pushBack(buf);
158         return this;
159     }
160 
161     /*
162     * Decode a BER encoded NULL
163     */
164     ref BERDecoder decodeNull()
165     {
166         BERObject obj = getNextObject();
167         obj.assertIsA(ASN1Tag.NULL_TAG, ASN1Tag.UNIVERSAL);
168         if (obj.value.length)
169             throw new BERDecodingError("NULL object had nonzero size");
170         return this;
171     }
172 
173     ref BERDecoder decode(T)(ref T obj)
174     {
175         static if (is(T == class)) {
176             if (!obj)
177                 obj = new T();
178 		} else static if (__traits(compiles, { T t = T(); }())) {
179             if (obj is T.init) obj = T();
180 		}
181         (cast()*obj).decodeFrom(this);
182         return this;
183     }
184     
185     /*
186     * Request for an object to decode itself
187     */
188     ref BERDecoder decode(T)(auto ref T obj, ASN1Tag type, ASN1Tag tag)
189         if (__traits(compiles, { obj.decodeFrom(this); }()))
190     {
191         obj.decodeFrom(this);
192         return this;
193     }
194     
195     /*
196     * Decode a BER encoded BOOLEAN
197     */
198     ref BERDecoder decode(ref bool output)
199     {
200         return decode(output, ASN1Tag.BOOLEAN, ASN1Tag.UNIVERSAL);
201     }
202     
203     /*
204     * Decode a small BER encoded INTEGER
205     */
206     ref BERDecoder decode(ref size_t output)
207     {
208         return decode(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL);
209     }
210     
211     /*
212     * Decode a BER encoded INTEGER
213     */
214     ref BERDecoder decode(ref BigInt output)
215     {
216         return decode(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL);
217     }
218     
219     
220     /*
221     * Decode a BER encoded BOOLEAN
222     */
223     ref BERDecoder decode(ref bool output,
224                           ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
225     {
226         BERObject obj = getNextObject();
227         obj.assertIsA(type_tag, class_tag);
228         
229         if (obj.value.length != 1)
230             throw new BERDecodingError("BER boolean value had invalid size");
231         
232         output = (obj.value[0]) ? true : false;
233         return this;
234     }
235     
236     /*
237     * Decode a small BER encoded INTEGER
238     */
239     ref BERDecoder decode(ref size_t output,
240                           ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
241     {
242         BigInt integer;
243         decode(integer, type_tag, class_tag);
244         
245         if (integer.bits() > 32)
246             throw new BERDecodingError("Decoded integer value larger than expected");
247         
248         output = 0;
249         foreach (size_t i; 0 .. 4)
250             output = (output << 8) | integer.byteAt(3-i);
251         
252         logTrace("decode size_t: ", output);
253 
254         return this;
255     }
256 
257     /*
258     * Decode a BER encoded INTEGER
259     */
260     ref BERDecoder decode(ref BigInt output,
261                           ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
262     {
263         BERObject obj = getNextObject();
264         obj.assertIsA(type_tag, class_tag);
265         
266         if (obj.value.empty) {
267             output = BigInt("0");
268         }
269         else
270         {
271             const bool negative = (obj.value[0] & 0x80) ? true : false;
272             
273             if (negative)
274             {
275                 for (size_t i = obj.value.length; i > 0; --i)
276                     if (obj.value[i-1]--)
277                         break;
278                 foreach (size_t i; 0 .. obj.value.length)
279                     obj.value[i] = ~cast(int)obj.value[i];
280             }
281             output = BigInt(obj.value.ptr, obj.value.length);
282             if (negative)
283                 output.flipSign();
284         }
285         // breaks here
286         logTrace("decode BigInt: ", output.toString());
287         return this;
288     }
289     
290     /*
291     * BER decode a BIT STRING or OCTET STRING
292     */
293     ref BERDecoder decode(ref SecureVector!ubyte output, ASN1Tag real_type)
294     {
295         return decode(output, real_type, real_type, ASN1Tag.UNIVERSAL);
296     }
297     
298     /*
299     * BER decode a BIT STRING or OCTET STRING
300     */
301     ref BERDecoder decode(ref Vector!ubyte output, ASN1Tag real_type)
302     {
303         return decode(output, real_type, real_type, ASN1Tag.UNIVERSAL);
304     }
305     
306     /*
307     * BER decode a BIT STRING or OCTET STRING
308     */
309     ref BERDecoder decode(ref SecureVector!ubyte buffer,
310                           ASN1Tag real_type,
311                           ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
312     {
313         if (real_type != ASN1Tag.OCTET_STRING && real_type != ASN1Tag.BIT_STRING)
314             throw new BERBadTag("Bad tag for {BIT,OCTET} STRING", real_type);
315         
316         BERObject obj = getNextObject();
317         obj.assertIsA(type_tag, class_tag);
318         
319         if (real_type == ASN1Tag.OCTET_STRING)
320             buffer = obj.value.move;
321         else
322         {
323 			if (obj.value.empty())
324 				throw new BERDecodingError("Invalid BIT STRING");
325             if (obj.value[0] >= 8)
326                 throw new BERDecodingError("Bad number of unused bits in BIT STRING");
327             
328             buffer.resize(obj.value.length - 1);
329             copyMem(buffer.ptr, &obj.value[1], obj.value.length - 1);
330         }
331 
332         //logTrace("decode SecureVector: ", buffer[]);
333 
334         return this;
335     }
336     
337     ref BERDecoder decode(ref Vector!ubyte buffer,
338                           ASN1Tag real_type,
339                           ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
340     {
341         if (real_type != ASN1Tag.OCTET_STRING && real_type != ASN1Tag.BIT_STRING)
342             throw new BERBadTag("Bad tag for {BIT,OCTET} STRING", real_type);
343         
344         BERObject obj = getNextObject();
345         obj.assertIsA(type_tag, class_tag);
346         
347         if (real_type == ASN1Tag.OCTET_STRING)
348             buffer = unlock(obj.value);
349         else
350         {
351 			if (obj.value.empty())
352 				throw new BERDecodingError("Invalid BIT STRING");
353             if (obj.value[0] >= 8)
354                 throw new BERDecodingError("Bad number of unused bits in BIT STRING");
355             
356             buffer.resize(obj.value.length - 1);
357             copyMem(buffer.ptr, &obj.value[1], obj.value.length - 1);
358         }
359         //logTrace("decode Vector: ", buffer[]);
360         return this;
361     }
362 
363     /*
364     * Decode a small BER encoded INTEGER
365     */
366     ulong decodeConstrainedInteger(ASN1Tag type_tag,
367                                    ASN1Tag class_tag,
368                                    size_t T_bytes)
369     {
370         if (T_bytes > 8)
371             throw new BERDecodingError("Can't decode small integer over 8 bytes");
372         
373         BigInt integer;
374         decode(integer, type_tag, class_tag);
375         
376         if (integer.bits() > 8*T_bytes)
377             throw new BERDecodingError("Decoded integer value larger than expected");
378         
379         ulong output = 0;
380         foreach (size_t i; 0 .. 8)
381             output = (output << 8) | integer.byteAt(7-i);
382         
383         //logTrace("decode Integer: (64bit) ", output);
384 
385         return output;
386     }
387        
388     ref BERDecoder decodeIntegerType(T)(ref T output)
389     {
390         return decodeIntegerType!T(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL);
391     }
392     
393     ref BERDecoder decodeIntegerType(T)(ref T output,
394                                         ASN1Tag type_tag,
395                                         ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
396     {
397         output = cast(T) decodeConstrainedInteger(type_tag, class_tag, (output).sizeof);
398         return this;
399     }
400 
401     /*
402     * Decode an OPTIONAL or DEFAULT element
403     */
404     ref BERDecoder decodeOptional(T)(auto ref T output,
405                                      ASN1Tag type_tag,
406                                      ASN1Tag class_tag,
407                                      T default_value = T.init)
408     {
409         BERObject obj = getNextObject();
410         
411         if (obj.type_tag == type_tag && obj.class_tag == class_tag)
412         {
413             if ((class_tag & ASN1Tag.CONSTRUCTED) && (class_tag & ASN1Tag.CONTEXT_SPECIFIC))
414                 BERDecoder(obj.value).decode(output).verifyEnd();
415             else
416             {
417                 pushBack(obj);
418                 decode(output, type_tag, class_tag);
419             }
420         }
421         else
422         {
423             static if (__traits(hasMember, T, "isRefCounted")) {
424                 if (default_value is T.init)
425                     output = T();
426                 else output = default_value;
427             }
428             else 
429                 output = default_value;
430             pushBack(obj);
431         }
432 
433         /*
434         static if (__traits(hasMember, T, "toString"))
435             logTrace("decode Optional ", T.stringof, ": ", output.toString());
436         else static if (__traits(compiles, { to!string(output); }()))
437             logTrace("decode Optional ", T.stringof, ": ", output.to!string);
438         else
439             logTrace("decode Optional ", T.stringof);
440         */
441 
442         return this;
443     }
444     
445     /*
446     * Decode an OPTIONAL or DEFAULT element
447     */
448     ref BERDecoder decodeOptionalImplicit(T)(ref T output,
449                                              ASN1Tag type_tag,
450                                              ASN1Tag class_tag,
451                                              ASN1Tag real_type,
452                                              ASN1Tag real_class,
453                                              T default_value = T.init)
454     {
455         BERObject obj = getNextObject();
456         
457         if (obj.type_tag == type_tag && obj.class_tag == class_tag)
458         {
459             obj.type_tag = real_type;
460             obj.class_tag = real_class;
461             pushBack(obj);
462             decode(output, real_type, real_class);
463         }
464         else
465         {
466             output = default_value;
467             pushBack(obj);
468         }
469         /*
470         static if (__traits(hasMember, T, "toString"))
471             logTrace("decode OptionalImplicit ", T.stringof, ": ", output.toString());
472         else
473             logTrace("decode OptionalImplicit ", T.stringof);
474         */
475         return this;
476     }
477     
478 
479     /*
480     * Decode a list of homogenously typed values
481     */
482     ref BERDecoder decodeList(T, Alloc)(auto ref Vector!(T, Alloc) vec,
483                                         ASN1Tag type_tag = ASN1Tag.SEQUENCE,
484                                         ASN1Tag class_tag = ASN1Tag.UNIVERSAL)
485     {
486         BERDecoder list = startCons(type_tag, class_tag);
487         
488         while (list.moreItems())
489         {
490             T value;
491             list.decode(value);
492             //logTrace("Decode List ", T.stringof);
493 
494             vec.pushBack(value);
495         }
496         
497         list.endCons();
498         
499         return this;
500     }
501 
502     /// ditto
503     ref BERDecoder decodeList(T, Alloc)(auto ref RefCounted!(Vector!(T, Alloc), Alloc) vec,
504                                             ASN1Tag type_tag = ASN1Tag.SEQUENCE,
505                                             ASN1Tag class_tag = ASN1Tag.UNIVERSAL)
506     {
507         return decodeList(*vec, type_tag, class_tag); 
508     }
509 
510     ref BERDecoder decodeAndCheck(T)(in T expected,
511                                      in string error_msg)
512     {
513         T actual;
514         decode(actual);
515         
516         if (actual != expected)
517             throw new DecodingError(error_msg ~ " T " ~ T.stringof ~ " : " ~ actual.to!string ~ ", expected: " ~ expected.to!string);
518         
519         static if (__traits(hasMember, T, "toString"))
520             logTrace("decode and check ", T.stringof, ": ", actual.toString());
521         else
522             logTrace("decode and check ", T.stringof);
523 
524         return this;
525     }
526     
527     /*
528         * Decode an OPTIONAL string type
529         */
530     ref BERDecoder decodeOptionalString(Alloc)(ref Vector!( ubyte, Alloc ) output,
531                                                ASN1Tag real_type,
532                                                ushort type_no,
533                                                ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
534     {
535         BERObject obj = getNextObject();
536         ASN1Tag type_tag = cast(ASN1Tag)(type_no);
537         if (obj.type_tag == type_tag && obj.class_tag == class_tag)
538         {
539             if ((class_tag & ASN1Tag.CONSTRUCTED) && (class_tag & ASN1Tag.CONTEXT_SPECIFIC)) {
540                 BERDecoder(obj.value).decode(output, real_type).verifyEnd();
541             }
542             else
543             {
544                 pushBack(obj);
545                 decode(output, real_type, type_tag, class_tag);
546             }
547         }
548         else
549         {
550             output.clear();
551             pushBack(obj);
552         }
553 
554         //logTrace("decode optional string ", output[]);
555 
556         
557         return this;
558     }
559     
560     //BERDecoder operator=(in BERDecoder);
561 
562     ref BERDecoder decodeOctetStringBigint(ref BigInt output)
563     {
564         SecureVector!ubyte out_vec;
565         decode(out_vec, ASN1Tag.OCTET_STRING);
566         output = BigInt.decode(out_vec.ptr, out_vec.length);
567         //logTrace("decode octet string BigInt (32bit): ", output.getSubstring(0,32));
568         return this;
569     }
570 
571     /*
572     * BERDecoder Constructor
573     */
574     this(DataSource src)
575     {
576         m_pushed = BERObject.init;
577         m_source = src;
578         m_owns = false;
579         m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT;
580         m_parent = null;
581     }
582     
583     /*
584     * BERDecoder Constructor
585     */
586     this(const(ubyte)* data, size_t length)
587     {
588         m_pushed = BERObject.init;
589         m_source = cast(DataSource) DataSourceMemory(data, length);
590         m_owns = true;
591         m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT;
592         m_parent = null;
593     }
594     
595     /*
596     * BERDecoder Constructor
597     */
598     this(T, ALLOC)(auto const ref Vector!(T, ALLOC) data)
599     {
600         m_pushed = BERObject.init;
601         m_source = cast(DataSource) DataSourceMemory(data.ptr, data.length);
602         m_owns = true;
603         m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT;
604         m_parent = null;
605     }
606 
607     /// ditto
608     this(T, ALLOC)(auto const ref RefCounted!(Vector!(T, ALLOC), ALLOC) data)
609     {
610         m_pushed = BERObject.init;
611         m_source = cast(DataSource) DataSourceMemory(data.ptr, data.length);
612         m_owns = true;
613         m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT;
614         m_parent = null;
615     }
616 
617     this(ref BERDecoder other, BERObject pushed) {
618         m_parent = other.m_parent;
619         m_source = other.m_source;
620         m_pushed = pushed.move();
621         m_owns = other.m_owns;
622     }
623 
624     @property BERDecoder move() {
625         return BERDecoder(this, m_pushed.move());
626     }
627 
628     @property BERDecoder dup() {
629         return BERDecoder(this, m_pushed.dup());
630     }
631 
632     @disable this(this);
633 private:
634 
635     BERDecoder* m_parent;
636     DataSource m_source;
637     BERObject m_pushed;
638     bool m_owns;
639 }
640 
641 private:
642 /*
643 * BER decode an ASN.1 type tag
644 */
645 size_t decodeTag(DataSource ber, ref ASN1Tag type_tag, ref ASN1Tag class_tag)
646 {
647     ubyte b;
648     if (!ber.readByte(b))
649     {
650         type_tag = ASN1Tag.NO_OBJECT;
651         class_tag = ASN1Tag.NO_OBJECT;
652         return 0;
653     }
654     
655     if ((b & 0x1F) != 0x1F)
656     {
657         type_tag = cast(ASN1Tag)(b & 0x1F);
658         //logTrace("tag: ", type_tag);
659         class_tag = cast(ASN1Tag)(b & 0xE0);
660         return 1;
661     }
662     
663     size_t tag_bytes = 1;
664     class_tag = cast(ASN1Tag)(b & 0xE0);
665     
666     size_t tag_buf = 0;
667     while (true)
668     {
669         if (!ber.readByte(b))
670             throw new BERDecodingError("Long-form tag truncated");
671         if (tag_buf & 0xFF000000)
672             throw new BERDecodingError("Long-form tag overflowed 32 bits");
673         ++tag_bytes;
674         tag_buf = (tag_buf << 7) | (b & 0x7F);
675         if ((b & 0x80) == 0) break;
676     }
677     type_tag = cast(ASN1Tag)(tag_buf);
678     return tag_bytes;
679 }
680 
681 /*
682 * BER decode an ASN.1 length field
683 */
684 size_t decodeLength(DataSource ber, ref size_t field_size)
685 {
686     ubyte b;
687     if (!ber.readByte(b))
688         throw new BERDecodingError("Length field not found");
689     field_size = 1;
690     if ((b & 0x80) == 0)
691         return b;
692     
693     field_size += (b & 0x7F);
694     if (field_size == 1) return findEoc(ber);
695     if (field_size > 5)
696         throw new BERDecodingError("Length field is too large");
697     
698     size_t length = 0;
699     
700     foreach (size_t i; 0 .. (field_size - 1))
701     {
702         if (get_byte(0, length) != 0)
703             throw new BERDecodingError("Field length overflow");
704         if (!ber.readByte(b))
705             throw new BERDecodingError("Corrupted length field");
706         length = (length << 8) | b;
707     }
708     return length;
709 }
710 
711 /*
712 * BER decode an ASN.1 length field
713 */
714 size_t decodeLength(DataSource ber)
715 {
716     size_t dummy;
717     return decodeLength(ber, dummy);
718 }
719 
720 /*
721 * Find the EOC marker
722 */
723 size_t findEoc(DataSource ber)
724 {
725     SecureVector!ubyte buffer = SecureVector!ubyte(DEFAULT_BUFFERSIZE);
726     SecureVector!ubyte data = SecureVector!ubyte();
727     
728     while (true)
729     {
730         const size_t got = ber.peek(buffer.ptr, buffer.length, data.length);
731         if (got == 0)
732             break;
733         
734         data ~= buffer[];
735     }
736 
737     auto source = cast(DataSource) DataSourceMemory(&data);
738     size_t length = 0;
739     while (true)
740     {
741         ASN1Tag type_tag, class_tag;
742         size_t tag_size = decodeTag(source, type_tag, class_tag);
743         if (type_tag == ASN1Tag.NO_OBJECT)
744             break;
745         
746         size_t length_size = 0;
747         size_t item_size = decodeLength(source, length_size);
748         source.discardNext(item_size);
749         
750         length += item_size + length_size + tag_size;
751         
752         if (type_tag == ASN1Tag.EOC && class_tag == ASN1Tag.UNIVERSAL)
753             break;
754     }
755     return length;
756 }
757 
758