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         }
179         else static if (__traits(compiles, { T t = T(); }())) {
180             if (obj is T.init) obj = T();
181         }
182         //logTrace("Decode obj: ", T.stringof);
183         obj.decodeFrom(this);
184         return this;
185     }
186     
187     /*
188     * Request for an object to decode itself
189     */
190     ref BERDecoder decode(T)(auto ref T obj, ASN1Tag type, ASN1Tag tag)
191         if (__traits(compiles, { obj.decodeFrom(this); }()))
192     {
193         obj.decodeFrom(this);
194         return this;
195     }
196     
197     /*
198     * Decode a BER encoded BOOLEAN
199     */
200     ref BERDecoder decode(ref bool output)
201     {
202         return decode(output, ASN1Tag.BOOLEAN, ASN1Tag.UNIVERSAL);
203     }
204     
205     /*
206     * Decode a small BER encoded INTEGER
207     */
208     ref BERDecoder decode(ref size_t output)
209     {
210         return decode(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL);
211     }
212     
213     /*
214     * Decode a BER encoded INTEGER
215     */
216     ref BERDecoder decode(ref BigInt output)
217     {
218         return decode(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL);
219     }
220     
221     
222     /*
223     * Decode a BER encoded BOOLEAN
224     */
225     ref BERDecoder decode(ref bool output,
226                           ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
227     {
228         BERObject obj = getNextObject();
229         obj.assertIsA(type_tag, class_tag);
230         
231         if (obj.value.length != 1)
232             throw new BERDecodingError("BER boolean value had invalid size");
233         
234         output = (obj.value[0]) ? true : false;
235         return this;
236     }
237     
238     /*
239     * Decode a small BER encoded INTEGER
240     */
241     ref BERDecoder decode(ref size_t output,
242                           ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
243     {
244         BigInt integer;
245         decode(integer, type_tag, class_tag);
246         
247         if (integer.bits() > 32)
248             throw new BERDecodingError("Decoded integer value larger than expected");
249         
250         output = 0;
251         foreach (size_t i; 0 .. 4)
252             output = (output << 8) | integer.byteAt(3-i);
253         
254         logTrace("decode size_t: ", output);
255 
256         return this;
257     }
258 
259     /*
260     * Decode a BER encoded INTEGER
261     */
262     ref BERDecoder decode(ref BigInt output,
263                           ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
264     {
265         BERObject obj = getNextObject();
266         obj.assertIsA(type_tag, class_tag);
267         
268         if (obj.value.empty) {
269             output = BigInt("0");
270         }
271         else
272         {
273             const bool negative = (obj.value[0] & 0x80) ? true : false;
274             
275             if (negative)
276             {
277                 for (size_t i = obj.value.length; i > 0; --i)
278                     if (obj.value[i-1]--)
279                         break;
280                 foreach (size_t i; 0 .. obj.value.length)
281                     obj.value[i] = ~obj.value[i];
282             }
283             output = BigInt(obj.value.ptr, obj.value.length);
284             if (negative)
285                 output.flipSign();
286         }
287         // breaks here
288         logTrace("decode BigInt: ", output.toString());
289         return this;
290     }
291     
292     /*
293     * BER decode a BIT STRING or OCTET STRING
294     */
295     ref BERDecoder decode(ref SecureVector!ubyte output, ASN1Tag real_type)
296     {
297         return decode(output, real_type, real_type, ASN1Tag.UNIVERSAL);
298     }
299     
300     /*
301     * BER decode a BIT STRING or OCTET STRING
302     */
303     ref BERDecoder decode(ref Vector!ubyte output, ASN1Tag real_type)
304     {
305         return decode(output, real_type, real_type, ASN1Tag.UNIVERSAL);
306     }
307     
308     /*
309     * BER decode a BIT STRING or OCTET STRING
310     */
311     ref BERDecoder decode(ref SecureVector!ubyte buffer,
312                           ASN1Tag real_type,
313                           ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
314     {
315         if (real_type != ASN1Tag.OCTET_STRING && real_type != ASN1Tag.BIT_STRING)
316             throw new BERBadTag("Bad tag for {BIT,OCTET} STRING", real_type);
317         
318         BERObject obj = getNextObject();
319         obj.assertIsA(type_tag, class_tag);
320         
321         if (real_type == ASN1Tag.OCTET_STRING)
322             buffer = obj.value.move;
323         else
324         {
325 			if (obj.value.empty())
326 				throw new BERDecodingError("Invalid BIT STRING");
327             if (obj.value[0] >= 8)
328                 throw new BERDecodingError("Bad number of unused bits in BIT STRING");
329             
330             buffer.resize(obj.value.length - 1);
331             copyMem(buffer.ptr, &obj.value[1], obj.value.length - 1);
332         }
333 
334         //logTrace("decode SecureVector: ", buffer[]);
335 
336         return this;
337     }
338     
339     ref BERDecoder decode(ref Vector!ubyte buffer,
340                           ASN1Tag real_type,
341                           ASN1Tag type_tag, ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
342     {
343         if (real_type != ASN1Tag.OCTET_STRING && real_type != ASN1Tag.BIT_STRING)
344             throw new BERBadTag("Bad tag for {BIT,OCTET} STRING", real_type);
345         
346         BERObject obj = getNextObject();
347         obj.assertIsA(type_tag, class_tag);
348         
349         if (real_type == ASN1Tag.OCTET_STRING)
350             buffer = unlock(obj.value);
351         else
352         {
353 			if (obj.value.empty())
354 				throw new BERDecodingError("Invalid BIT STRING");
355             if (obj.value[0] >= 8)
356                 throw new BERDecodingError("Bad number of unused bits in BIT STRING");
357             
358             buffer.resize(obj.value.length - 1);
359             copyMem(buffer.ptr, &obj.value[1], obj.value.length - 1);
360         }
361         //logTrace("decode Vector: ", buffer[]);
362         return this;
363     }
364 
365     /*
366     * Decode a small BER encoded INTEGER
367     */
368     ulong decodeConstrainedInteger(ASN1Tag type_tag,
369                                    ASN1Tag class_tag,
370                                    size_t T_bytes)
371     {
372         if (T_bytes > 8)
373             throw new BERDecodingError("Can't decode small integer over 8 bytes");
374         
375         BigInt integer;
376         decode(integer, type_tag, class_tag);
377         
378         if (integer.bits() > 8*T_bytes)
379             throw new BERDecodingError("Decoded integer value larger than expected");
380         
381         ulong output = 0;
382         foreach (size_t i; 0 .. 8)
383             output = (output << 8) | integer.byteAt(7-i);
384         
385         //logTrace("decode Integer: (64bit) ", output);
386 
387         return output;
388     }
389        
390     ref BERDecoder decodeIntegerType(T)(ref T output)
391     {
392         return decodeIntegerType!T(output, ASN1Tag.INTEGER, ASN1Tag.UNIVERSAL);
393     }
394     
395     ref BERDecoder decodeIntegerType(T)(ref T output,
396                                         ASN1Tag type_tag,
397                                         ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
398     {
399         output = cast(T) decodeConstrainedInteger(type_tag, class_tag, (output).sizeof);
400         return this;
401     }
402 
403     /*
404     * Decode an OPTIONAL or DEFAULT element
405     */
406     ref BERDecoder decodeOptional(T)(auto ref T output,
407                                      ASN1Tag type_tag,
408                                      ASN1Tag class_tag,
409                                      T default_value = T.init)
410     {
411         BERObject obj = getNextObject();
412         
413         if (obj.type_tag == type_tag && obj.class_tag == class_tag)
414         {
415             if ((class_tag & ASN1Tag.CONSTRUCTED) && (class_tag & ASN1Tag.CONTEXT_SPECIFIC))
416                 BERDecoder(obj.value).decode(output).verifyEnd();
417             else
418             {
419                 pushBack(obj);
420                 decode(output, type_tag, class_tag);
421             }
422         }
423         else
424         {
425             static if (__traits(hasMember, T, "isRefCounted")) {
426                 if (default_value is T.init)
427                     output = T();
428                 else output = default_value;
429             }
430             else 
431                 output = default_value;
432             pushBack(obj);
433         }
434 
435         /*
436         static if (__traits(hasMember, T, "toString"))
437             logTrace("decode Optional ", T.stringof, ": ", output.toString());
438         else static if (__traits(compiles, { to!string(output); }()))
439             logTrace("decode Optional ", T.stringof, ": ", output.to!string);
440         else
441             logTrace("decode Optional ", T.stringof);
442         */
443 
444         return this;
445     }
446     
447     /*
448     * Decode an OPTIONAL or DEFAULT element
449     */
450     ref BERDecoder decodeOptionalImplicit(T)(ref T output,
451                                              ASN1Tag type_tag,
452                                              ASN1Tag class_tag,
453                                              ASN1Tag real_type,
454                                              ASN1Tag real_class,
455                                              T default_value = T.init)
456     {
457         BERObject obj = getNextObject();
458         
459         if (obj.type_tag == type_tag && obj.class_tag == class_tag)
460         {
461             obj.type_tag = real_type;
462             obj.class_tag = real_class;
463             pushBack(obj);
464             decode(output, real_type, real_class);
465         }
466         else
467         {
468             output = default_value;
469             pushBack(obj);
470         }
471         /*
472         static if (__traits(hasMember, T, "toString"))
473             logTrace("decode OptionalImplicit ", T.stringof, ": ", output.toString());
474         else
475             logTrace("decode OptionalImplicit ", T.stringof);
476         */
477         return this;
478     }
479     
480 
481     /*
482     * Decode a list of homogenously typed values
483     */
484     ref BERDecoder decodeList(T, Alloc)(auto ref Vector!(T, Alloc) vec,
485                                         ASN1Tag type_tag = ASN1Tag.SEQUENCE,
486                                         ASN1Tag class_tag = ASN1Tag.UNIVERSAL)
487     {
488         BERDecoder list = startCons(type_tag, class_tag);
489         
490         while (list.moreItems())
491         {
492             T value;
493             list.decode(value);
494             //logTrace("Decode List ", T.stringof);
495 
496             vec.pushBack(value);
497         }
498         
499         list.endCons();
500         
501         return this;
502     }
503 
504     /// ditto
505     ref BERDecoder decodeList(T, Alloc)(auto ref RefCounted!(Vector!(T, Alloc), Alloc) vec,
506                                             ASN1Tag type_tag = ASN1Tag.SEQUENCE,
507                                             ASN1Tag class_tag = ASN1Tag.UNIVERSAL)
508     {
509         return decodeList(*vec, type_tag, class_tag); 
510     }
511 
512     ref BERDecoder decodeAndCheck(T)(in T expected,
513                                      in string error_msg)
514     {
515         T actual;
516         decode(actual);
517         
518         if (actual != expected)
519             throw new DecodingError(error_msg ~ " T " ~ T.stringof ~ " : " ~ actual.to!string ~ ", expected: " ~ expected.to!string);
520         
521         static if (__traits(hasMember, T, "toString"))
522             logTrace("decode and check ", T.stringof, ": ", actual.toString());
523         else
524             logTrace("decode and check ", T.stringof);
525 
526         return this;
527     }
528     
529     /*
530         * Decode an OPTIONAL string type
531         */
532     ref BERDecoder decodeOptionalString(Alloc)(ref Vector!( ubyte, Alloc ) output,
533                                                ASN1Tag real_type,
534                                                ushort type_no,
535                                                ASN1Tag class_tag = ASN1Tag.CONTEXT_SPECIFIC)
536     {
537         BERObject obj = getNextObject();
538         ASN1Tag type_tag = cast(ASN1Tag)(type_no);
539         if (obj.type_tag == type_tag && obj.class_tag == class_tag)
540         {
541             if ((class_tag & ASN1Tag.CONSTRUCTED) && (class_tag & ASN1Tag.CONTEXT_SPECIFIC)) {
542                 BERDecoder(obj.value).decode(output, real_type).verifyEnd();
543             }
544             else
545             {
546                 pushBack(obj);
547                 decode(output, real_type, type_tag, class_tag);
548             }
549         }
550         else
551         {
552             output.clear();
553             pushBack(obj);
554         }
555 
556         //logTrace("decode optional string ", output[]);
557 
558         
559         return this;
560     }
561     
562     //BERDecoder operator=(in BERDecoder);
563 
564     ref BERDecoder decodeOctetStringBigint(ref BigInt output)
565     {
566         SecureVector!ubyte out_vec;
567         decode(out_vec, ASN1Tag.OCTET_STRING);
568         output = BigInt.decode(out_vec.ptr, out_vec.length);
569         //logTrace("decode octet string BigInt (32bit): ", output.getSubstring(0,32));
570         return this;
571     }
572 
573     /*
574     * BERDecoder Constructor
575     */
576     this(DataSource src)
577     {
578         m_pushed = BERObject.init;
579         m_source = src;
580         m_owns = false;
581         m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT;
582         m_parent = null;
583     }
584     
585     /*
586     * BERDecoder Constructor
587     */
588     this(const(ubyte)* data, size_t length)
589     {
590         m_pushed = BERObject.init;
591         m_source = cast(DataSource)DataSourceMemory(data, length);
592         m_owns = true;
593         m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT;
594         m_parent = null;
595     }
596     
597     /*
598     * BERDecoder Constructor
599     */
600     this(T, ALLOC)(auto const ref Vector!(T, ALLOC) data)
601     {
602         m_pushed = BERObject.init;
603         m_source = cast(DataSource) DataSourceMemory(data.ptr, data.length);
604         m_owns = true;
605         m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT;
606         m_parent = null;
607     }
608 
609     /// ditto
610     this(T, ALLOC)(auto const ref RefCounted!(Vector!(T, ALLOC), ALLOC) data)
611     {
612         m_pushed = BERObject.init;
613         m_source = cast(DataSource) DataSourceMemory(data.ptr, data.length);
614         m_owns = true;
615         m_pushed.type_tag = m_pushed.class_tag = ASN1Tag.NO_OBJECT;
616         m_parent = null;
617     }
618 
619     this(ref BERDecoder other, BERObject pushed) {
620         m_parent = other.m_parent;
621         m_source = other.m_source;
622         m_pushed = pushed.move();
623         m_owns = other.m_owns;
624     }
625 
626     @property BERDecoder move() {
627         return BERDecoder(this, m_pushed.move());
628     }
629 
630     @property BERDecoder dup() {
631         return BERDecoder(this, m_pushed.dup());
632     }
633 
634     @disable this(this);
635 private:
636 
637     BERDecoder* m_parent;
638     DataSource m_source;
639     BERObject m_pushed;
640     bool m_owns;
641 }
642 
643 private:
644 /*
645 * BER decode an ASN.1 type tag
646 */
647 size_t decodeTag(DataSource ber, ref ASN1Tag type_tag, ref ASN1Tag class_tag)
648 {
649     ubyte b;
650     if (!ber.readByte(b))
651     {
652         type_tag = ASN1Tag.NO_OBJECT;
653         class_tag = ASN1Tag.NO_OBJECT;
654         return 0;
655     }
656     
657     if ((b & 0x1F) != 0x1F)
658     {
659         type_tag = cast(ASN1Tag)(b & 0x1F);
660         //logTrace("tag: ", type_tag);
661         class_tag = cast(ASN1Tag)(b & 0xE0);
662         return 1;
663     }
664     
665     size_t tag_bytes = 1;
666     class_tag = cast(ASN1Tag)(b & 0xE0);
667     
668     size_t tag_buf = 0;
669     while (true)
670     {
671         if (!ber.readByte(b))
672             throw new BERDecodingError("Long-form tag truncated");
673         if (tag_buf & 0xFF000000)
674             throw new BERDecodingError("Long-form tag overflowed 32 bits");
675         ++tag_bytes;
676         tag_buf = (tag_buf << 7) | (b & 0x7F);
677         if ((b & 0x80) == 0) break;
678     }
679     type_tag = cast(ASN1Tag)(tag_buf);
680     return tag_bytes;
681 }
682 
683 /*
684 * BER decode an ASN.1 length field
685 */
686 size_t decodeLength(DataSource ber, ref size_t field_size)
687 {
688     ubyte b;
689     if (!ber.readByte(b))
690         throw new BERDecodingError("Length field not found");
691     field_size = 1;
692     if ((b & 0x80) == 0)
693         return b;
694     
695     field_size += (b & 0x7F);
696     if (field_size == 1) return findEoc(ber);
697     if (field_size > 5)
698         throw new BERDecodingError("Length field is too large");
699     
700     size_t length = 0;
701     
702     foreach (size_t i; 0 .. (field_size - 1))
703     {
704         if (get_byte(0, length) != 0)
705             throw new BERDecodingError("Field length overflow");
706         if (!ber.readByte(b))
707             throw new BERDecodingError("Corrupted length field");
708         length = (length << 8) | b;
709     }
710     return length;
711 }
712 
713 /*
714 * BER decode an ASN.1 length field
715 */
716 size_t decodeLength(DataSource ber)
717 {
718     size_t dummy;
719     return decodeLength(ber, dummy);
720 }
721 
722 /*
723 * Find the EOC marker
724 */
725 size_t findEoc(DataSource ber)
726 {
727     SecureVector!ubyte buffer = SecureVector!ubyte(DEFAULT_BUFFERSIZE);
728     SecureVector!ubyte data = SecureVector!ubyte();
729     
730     while (true)
731     {
732         const size_t got = ber.peek(buffer.ptr, buffer.length, data.length);
733         if (got == 0)
734             break;
735         
736         data ~= buffer[];
737     }
738 
739     auto source = cast(DataSource) DataSourceMemory(&data);
740     size_t length = 0;
741     while (true)
742     {
743         ASN1Tag type_tag, class_tag;
744         size_t tag_size = decodeTag(source, type_tag, class_tag);
745         if (type_tag == ASN1Tag.NO_OBJECT)
746             break;
747         
748         size_t length_size = 0;
749         size_t item_size = decodeLength(source, length_size);
750         source.discardNext(item_size);
751         
752         length += item_size + length_size + tag_size;
753         
754         if (type_tag == ASN1Tag.EOC && class_tag == ASN1Tag.UNIVERSAL)
755             break;
756     }
757     return length;
758 }
759 
760