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