]> pd.if.org Git - zpackage/blob - libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c
commit files needed for zpm-fetchurl
[zpackage] / libtomcrypt / src / pk / asn1 / der / sequence / der_decode_sequence_flexi.c
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2  *
3  * LibTomCrypt is a library that provides various cryptographic
4  * algorithms in a highly modular and flexible manner.
5  *
6  * The library is free for all purposes without any express
7  * guarantee it works.
8  */
9 #include "tomcrypt.h"
10
11 /**
12   @file der_decode_sequence_flexi.c
13   ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis
14 */
15
16 #ifdef LTC_DER
17
18 static unsigned long _fetch_length(const unsigned char *in, unsigned long inlen, unsigned long *data_offset)
19 {
20    unsigned long x, z;
21
22    *data_offset = 0;
23
24    /* skip type and read len */
25    if (inlen < 2) {
26       return 0xFFFFFFFF;
27    }
28    ++in; ++(*data_offset);
29
30    /* read len */
31    x = *in++; ++(*data_offset);
32
33    /* <128 means literal */
34    if (x < 128) {
35       return x+*data_offset;
36    }
37    x     &= 0x7F; /* the lower 7 bits are the length of the length */
38    inlen -= 2;
39
40    /* len means len of len! */
41    if (x == 0 || x > 4 || x > inlen) {
42       return 0xFFFFFFFF;
43    }
44
45    *data_offset += x;
46    z = 0;
47    while (x--) {
48       z = (z<<8) | ((unsigned long)*in);
49       ++in;
50    }
51    return z+*data_offset;
52 }
53
54 static int _new_element(ltc_asn1_list **l)
55 {
56    /* alloc new link */
57    if (*l == NULL) {
58       *l = XCALLOC(1, sizeof(ltc_asn1_list));
59       if (*l == NULL) {
60          return CRYPT_MEM;
61       }
62    } else {
63       (*l)->next = XCALLOC(1, sizeof(ltc_asn1_list));
64       if ((*l)->next == NULL) {
65          return CRYPT_MEM;
66       }
67       (*l)->next->prev = *l;
68       *l = (*l)->next;
69    }
70    return CRYPT_OK;
71 }
72
73 /**
74    ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
75    @param in      The input buffer
76    @param inlen   [in/out] The length of the input buffer and on output the amount of decoded data
77    @param out     [out] A pointer to the linked list
78    @return CRYPT_OK on success.
79 */
80 int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
81 {
82    ltc_asn1_list *l, *t;
83    unsigned long err, type, len, totlen, data_offset, len_len;
84    void          *realloc_tmp;
85
86    LTC_ARGCHK(in    != NULL);
87    LTC_ARGCHK(inlen != NULL);
88    LTC_ARGCHK(out   != NULL);
89
90    l = NULL;
91    totlen = 0;
92
93    if (*inlen == 0) {
94       /* alloc new link */
95       if ((err = _new_element(&l)) != CRYPT_OK) {
96          goto error;
97       }
98    }
99
100    /* scan the input and and get lengths and what not */
101    while (*inlen) {
102       /* read the type byte */
103       type = *in;
104
105       /* fetch length */
106       len = _fetch_length(in, *inlen, &data_offset);
107       if (len > *inlen) {
108          err = CRYPT_INVALID_PACKET;
109          goto error;
110       }
111
112       /* alloc new link */
113       if ((err = _new_element(&l)) != CRYPT_OK) {
114          goto error;
115       }
116
117       if ((type & 0x20) && (type != 0x30) && (type != 0x31)) {
118          /* constructed, use the 'used' field to store the original identifier */
119          l->used = type;
120          /* treat constructed elements like SETs */
121          type = 0x20;
122       }
123       else if ((type & 0xC0) == 0x80) {
124          /* context-specific, use the 'used' field to store the original identifier */
125          l->used = type;
126          /* context-specific elements are treated as opaque data */
127          type = 0x80;
128       }
129
130      /* now switch on type */
131       switch (type) {
132          case 0x01: /* BOOLEAN */
133             l->type = LTC_ASN1_BOOLEAN;
134             l->size = 1;
135             l->data = XCALLOC(1, sizeof(int));
136
137             if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) {
138                goto error;
139             }
140
141             if ((err = der_length_boolean(&len)) != CRYPT_OK) {
142                goto error;
143             }
144             break;
145
146          case 0x02: /* INTEGER */
147              /* init field */
148              l->type = LTC_ASN1_INTEGER;
149              l->size = 1;
150              if ((err = mp_init(&l->data)) != CRYPT_OK) {
151                  goto error;
152              }
153
154              /* decode field */
155              if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) {
156                  goto error;
157              }
158
159              /* calc length of object */
160              if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) {
161                  goto error;
162              }
163              break;
164
165          case 0x03: /* BIT */
166             /* init field */
167             l->type = LTC_ASN1_BIT_STRING;
168             l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char.  */
169
170             if ((l->data = XCALLOC(1, l->size)) == NULL) {
171                err = CRYPT_MEM;
172                goto error;
173             }
174
175             if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
176                goto error;
177             }
178
179             if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) {
180                goto error;
181             }
182             break;
183
184          case 0x04: /* OCTET */
185
186             /* init field */
187             l->type = LTC_ASN1_OCTET_STRING;
188             l->size = len;
189
190             if ((l->data = XCALLOC(1, l->size)) == NULL) {
191                err = CRYPT_MEM;
192                goto error;
193             }
194
195             if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
196                goto error;
197             }
198
199             if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) {
200                goto error;
201             }
202             break;
203
204          case 0x05: /* NULL */
205
206             /* valid NULL is 0x05 0x00 */
207             if (in[0] != 0x05 || in[1] != 0x00) {
208                err = CRYPT_INVALID_PACKET;
209                goto error;
210             }
211
212             /* simple to store ;-) */
213             l->type = LTC_ASN1_NULL;
214             l->data = NULL;
215             l->size = 0;
216             len     = 2;
217
218             break;
219
220          case 0x06: /* OID */
221
222             /* init field */
223             l->type = LTC_ASN1_OBJECT_IDENTIFIER;
224             l->size = len;
225
226             if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
227                err = CRYPT_MEM;
228                goto error;
229             }
230
231             if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
232                goto error;
233             }
234
235             if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) {
236                goto error;
237             }
238
239             /* resize it to save a bunch of mem */
240             if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) {
241                /* out of heap but this is not an error */
242                break;
243             }
244             l->data = realloc_tmp;
245             break;
246
247          case 0x0C: /* UTF8 */
248
249             /* init field */
250             l->type = LTC_ASN1_UTF8_STRING;
251             l->size = len;
252
253             if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
254                err = CRYPT_MEM;
255                goto error;
256             }
257
258             if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
259                goto error;
260             }
261
262             if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) {
263                goto error;
264             }
265             break;
266
267          case 0x13: /* PRINTABLE */
268
269             /* init field */
270             l->type = LTC_ASN1_PRINTABLE_STRING;
271             l->size = len;
272
273             if ((l->data = XCALLOC(1, l->size)) == NULL) {
274                err = CRYPT_MEM;
275                goto error;
276             }
277
278             if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
279                goto error;
280             }
281
282             if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) {
283                goto error;
284             }
285             break;
286
287          case 0x14: /* TELETEXT */
288
289             /* init field */
290             l->type = LTC_ASN1_TELETEX_STRING;
291             l->size = len;
292
293             if ((l->data = XCALLOC(1, l->size)) == NULL) {
294                err = CRYPT_MEM;
295                goto error;
296             }
297
298             if ((err = der_decode_teletex_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
299                goto error;
300             }
301
302             if ((err = der_length_teletex_string(l->data, l->size, &len)) != CRYPT_OK) {
303                goto error;
304             }
305             break;
306
307          case 0x16: /* IA5 */
308
309             /* init field */
310             l->type = LTC_ASN1_IA5_STRING;
311             l->size = len;
312
313             if ((l->data = XCALLOC(1, l->size)) == NULL) {
314                err = CRYPT_MEM;
315                goto error;
316             }
317
318             if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
319                goto error;
320             }
321
322             if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) {
323                goto error;
324             }
325             break;
326
327          case 0x17: /* UTC TIME */
328
329             /* init field */
330             l->type = LTC_ASN1_UTCTIME;
331             l->size = 1;
332
333             if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
334                err = CRYPT_MEM;
335                goto error;
336             }
337
338             len = *inlen;
339             if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) {
340                goto error;
341             }
342
343             if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) {
344                goto error;
345             }
346             break;
347
348          case 0x18:
349             l->type = LTC_ASN1_GENERALIZEDTIME;
350             l->size = len;
351
352             if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) {
353                err = CRYPT_MEM;
354                goto error;
355             }
356
357             if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) {
358                goto error;
359             }
360
361             if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) {
362                goto error;
363             }
364
365             break;
366
367          case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */
368          case 0x30: /* SEQUENCE */
369          case 0x31: /* SET */
370
371              /* init field */
372              if (type == 0x20) {
373                 l->type = LTC_ASN1_CONSTRUCTED;
374              }
375              else if (type == 0x30) {
376                 l->type = LTC_ASN1_SEQUENCE;
377              }
378              else {
379                 l->type = LTC_ASN1_SET;
380              }
381
382              if ((l->data = XMALLOC(len)) == NULL) {
383                 err = CRYPT_MEM;
384                 goto error;
385              }
386
387              XMEMCPY(l->data, in, len);
388              l->size = len;
389
390
391              /* jump to the start of the data */
392              in     += data_offset;
393              *inlen -= data_offset;
394              len = len - data_offset;
395
396              /* Sequence elements go as child */
397              if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
398                 goto error;
399              }
400
401              /* len update */
402              totlen += data_offset;
403
404              /* the flexi decoder can also do nothing, so make sure a child has been allocated */
405              if (l->child) {
406                 /* link them up y0 */
407                 l->child->parent = l;
408              }
409
410              t = l;
411              len_len = 0;
412              while((t != NULL) && (t->child != NULL)) {
413                 len_len++;
414                 t = t->child;
415              }
416              if (len_len > LTC_DER_MAX_RECURSION) {
417                 err = CRYPT_ERROR;
418                 goto error;
419              }
420
421              break;
422
423          case 0x80: /* Context-specific */
424              l->type = LTC_ASN1_CONTEXT_SPECIFIC;
425
426              if ((l->data = XCALLOC(1, len - data_offset)) == NULL) {
427                 err = CRYPT_MEM;
428                 goto error;
429              }
430
431              XMEMCPY(l->data, in + data_offset, len - data_offset);
432              l->size = len - data_offset;
433
434              break;
435
436          default:
437            /* invalid byte ... this is a soft error */
438            /* remove link */
439            if (l->prev) {
440               l       = l->prev;
441               XFREE(l->next);
442               l->next = NULL;
443            }
444            goto outside;
445       }
446
447       /* advance pointers */
448       totlen  += len;
449       in      += len;
450       *inlen  -= len;
451    }
452
453 outside:
454
455    /* in case we processed anything */
456    if (totlen) {
457       /* rewind l please */
458       while (l->prev != NULL || l->parent != NULL) {
459          if (l->parent != NULL) {
460             l = l->parent;
461          } else {
462             l = l->prev;
463          }
464       }
465    }
466
467    /* return */
468    *out   = l;
469    *inlen = totlen;
470    return CRYPT_OK;
471
472 error:
473    /* free list */
474    der_sequence_free(l);
475
476    return err;
477 }
478
479 #endif
480
481
482 /* ref:         $Format:%D$ */
483 /* git commit:  $Format:%H$ */
484 /* commit time: $Format:%ai$ */