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