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