1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 
5 
6 /**
7   @file der_decode_custom_type.c
8   ASN.1 DER, decode a Custom type, Steffen Jaeckel
9 */
10 
11 #ifdef LTC_DER
12 
13 /**
14    Decode a Custom type
15    @param in       The DER encoded input
16    @param inlen    The size of the input
17    @param root     The item that defines the custom type to decode
18    @return CRYPT_OK on success
19 */
der_decode_custom_type(const unsigned char * in,unsigned long inlen,ltc_asn1_list * root)20 int der_decode_custom_type(const unsigned char *in, unsigned long  inlen,
21                            ltc_asn1_list *root)
22 {
23    LTC_ARGCHK(root != NULL);
24    return der_decode_custom_type_ex(in, inlen, root, NULL, 0, LTC_DER_SEQ_ORDERED | LTC_DER_SEQ_RELAXED);
25 }
26 
27 /**
28    Extended-decode a Custom type
29 
30       This function is used to decode custom types and sequences/sets
31       For custom types root is used
32       For sequences/sets list and outlen are used
33 
34    @param in       The DER encoded input
35    @param inlen    The size of the input
36    @param root     The item that defines the custom type to decode
37    @param list     The list of items to decode
38    @param outlen   The number of items in the list
39    @param flags    c.f. enum ltc_der_seq
40    @return CRYPT_OK on success
41 */
der_decode_custom_type_ex(const unsigned char * in,unsigned long inlen,ltc_asn1_list * root,ltc_asn1_list * list,unsigned long outlen,unsigned int flags)42 int der_decode_custom_type_ex(const unsigned char *in,   unsigned long  inlen,
43                                     ltc_asn1_list *root,
44                                     ltc_asn1_list *list, unsigned long  outlen,
45                                     unsigned int   flags)
46 {
47    int           err, seq_err, i, ordered;
48    ltc_asn1_type type;
49    ltc_asn1_list ident;
50    unsigned long size, x, y, z, blksize;
51    unsigned char* in_new = NULL;
52    void          *data;
53 
54    LTC_ARGCHK(in   != NULL);
55 
56    /* get blk size */
57    if (inlen < 2) {
58       return CRYPT_INVALID_PACKET;
59    }
60    x = 0;
61 
62    if (root == NULL) {
63       LTC_ARGCHK(list != NULL);
64 
65       /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */
66       if (in[x] != 0x30 && in[x] != 0x31) {
67          return CRYPT_INVALID_PACKET;
68       }
69       ++x;
70    } else {
71       if (root->type != LTC_ASN1_CUSTOM_TYPE) {
72          return CRYPT_INVALID_PACKET;
73       }
74 
75       /* Alloc a copy of the data for primitive handling. */
76       if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
77          in_new = XMALLOC(inlen);
78          if (in_new == NULL) {
79             return CRYPT_MEM;
80          }
81          XMEMCPY(in_new, in, inlen);
82          in = in_new;
83       }
84 
85       y = inlen;
86       if ((err = der_decode_asn1_identifier(in, &y, &ident)) != CRYPT_OK) {
87          goto LBL_ERR;
88       }
89       if ((ident.type != root->type) ||
90             (ident.klass != root->klass) ||
91             (ident.pc != root->pc) ||
92             (ident.tag != root->tag)) {
93          err = CRYPT_INVALID_PACKET;
94          goto LBL_ERR;
95       }
96       x += y;
97 
98       list = root->data;
99       outlen = root->size;
100    }
101 
102    if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE) {
103       if (((unsigned long)root->used >= der_asn1_type_to_identifier_map_sz) ||
104             (der_asn1_type_to_identifier_map[root->used] == -1)) {
105          err = CRYPT_INVALID_PACKET;
106          goto LBL_ERR;
107       }
108 
109       root->type = (ltc_asn1_type)root->used;
110       list = root;
111       outlen = 1;
112 
113       x -= 1;
114       in_new[x] = (unsigned char)der_asn1_type_to_identifier_map[list[0].type];
115       blksize = inlen - x;
116    } else {
117 
118       y = inlen - x;
119       if ((err = der_decode_asn1_length(&in[x], &y, &blksize)) != CRYPT_OK) {
120          goto LBL_ERR;
121       }
122       x += y;
123    }
124 
125    /* would this blksize overflow? */
126    if (blksize > (inlen - x)) {
127       err = CRYPT_INVALID_PACKET;
128       goto LBL_ERR;
129    }
130 
131    /* mark all as unused */
132    for (i = 0; i < (int)outlen; i++) {
133        list[i].used = 0;
134    }
135    ordered = flags & LTC_DER_SEQ_ORDERED;
136 
137    /* ok read data */
138    seq_err  = CRYPT_OK;
139    blksize += x;
140    inlen   -= x;
141    for (i = 0; i < (int)outlen; i++) {
142        z    = 0;
143        type = list[i].type;
144        size = list[i].size;
145        data = list[i].data;
146        if (!ordered && list[i].used == 1) { continue; }
147 
148        if (type == LTC_ASN1_EOL) {
149           break;
150        }
151 
152        if (root != NULL && root->pc == LTC_ASN1_PC_PRIMITIVE && i != 0) {
153           err = CRYPT_PK_ASN1_ERROR;
154           goto LBL_ERR;
155        }
156 
157        switch (type) {
158           case LTC_ASN1_CUSTOM_TYPE:
159           case LTC_ASN1_SET:
160           case LTC_ASN1_SETOF:
161           case LTC_ASN1_SEQUENCE:
162              break;
163           default:
164              /* Verify that all basic types are indeed UNIVERSAL&PRIMITIVE */
165              if (((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT) && (inlen > 0)) {
166                 if (in[x] & 0xE0u) {
167                    err = CRYPT_PK_ASN1_ERROR;
168                    goto LBL_ERR;
169                 }
170              }
171        }
172 
173        switch (type) {
174            case LTC_ASN1_BOOLEAN:
175                z = inlen;
176                if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) {
177                   if (!ordered || list[i].optional) { continue; }
178                   goto LBL_ERR;
179                }
180                if ((err = der_length_boolean(&z)) != CRYPT_OK) {
181                   goto LBL_ERR;
182                }
183                break;
184 
185            case LTC_ASN1_INTEGER:
186                z = inlen;
187                if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) {
188                   if (!ordered || list[i].optional) { continue; }
189                   goto LBL_ERR;
190                }
191                if ((err = der_length_integer(data, &z)) != CRYPT_OK) {
192                   goto LBL_ERR;
193                }
194                break;
195 
196            case LTC_ASN1_SHORT_INTEGER:
197                z = inlen;
198                if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) {
199                   if (!ordered || list[i].optional) { continue; }
200                   goto LBL_ERR;
201                }
202                if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) {
203                   goto LBL_ERR;
204                }
205 
206                break;
207 
208            case LTC_ASN1_BIT_STRING:
209                z = inlen;
210                if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
211                   if (!ordered || list[i].optional) { continue; }
212                   goto LBL_ERR;
213                }
214                list[i].size = size;
215                if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
216                   goto LBL_ERR;
217                }
218                break;
219 
220            case LTC_ASN1_RAW_BIT_STRING:
221                z = inlen;
222                if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) {
223                   if (!ordered || list[i].optional) { continue; }
224                   goto LBL_ERR;
225                }
226                list[i].size = size;
227                if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) {
228                   goto LBL_ERR;
229                }
230                break;
231 
232            case LTC_ASN1_OCTET_STRING:
233                z = inlen;
234                if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) {
235                   if (!ordered || list[i].optional) { continue; }
236                   goto LBL_ERR;
237                }
238                list[i].size = size;
239                if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) {
240                   goto LBL_ERR;
241                }
242                break;
243 
244            case LTC_ASN1_NULL:
245                if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) {
246                   if (!ordered || list[i].optional) { continue; }
247                   err = CRYPT_INVALID_PACKET;
248                   goto LBL_ERR;
249                }
250                z = 2;
251                break;
252 
253            case LTC_ASN1_OBJECT_IDENTIFIER:
254                z = inlen;
255                if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) {
256                   if (!ordered || list[i].optional) { continue; }
257                   goto LBL_ERR;
258                }
259                list[i].size = size;
260                if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) {
261                   goto LBL_ERR;
262                }
263                break;
264 
265            case LTC_ASN1_TELETEX_STRING:
266                z = inlen;
267                if ((err = der_decode_teletex_string(in + x, z, data, &size)) != CRYPT_OK) {
268                   if (!ordered || list[i].optional) { continue; }
269                   goto LBL_ERR;
270                }
271                list[i].size = size;
272                if ((err = der_length_teletex_string(data, size, &z)) != CRYPT_OK) {
273                   goto LBL_ERR;
274                }
275                break;
276 
277            case LTC_ASN1_IA5_STRING:
278                z = inlen;
279                if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) {
280                   if (!ordered || list[i].optional) { continue; }
281                   goto LBL_ERR;
282                }
283                list[i].size = size;
284                if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) {
285                   goto LBL_ERR;
286                }
287                break;
288 
289            case LTC_ASN1_PRINTABLE_STRING:
290                z = inlen;
291                if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) {
292                   if (!ordered || list[i].optional) { continue; }
293                   goto LBL_ERR;
294                }
295                list[i].size = size;
296                if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) {
297                   goto LBL_ERR;
298                }
299                break;
300 
301            case LTC_ASN1_UTF8_STRING:
302                z = inlen;
303                if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) {
304                   if (!ordered || list[i].optional) { continue; }
305                   goto LBL_ERR;
306                }
307                list[i].size = size;
308                if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) {
309                   goto LBL_ERR;
310                }
311                break;
312 
313            case LTC_ASN1_UTCTIME:
314                z = inlen;
315                if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) {
316                   if (!ordered || list[i].optional) { continue; }
317                   goto LBL_ERR;
318                }
319                break;
320 
321            case LTC_ASN1_GENERALIZEDTIME:
322                z = inlen;
323                if ((err = der_decode_generalizedtime(in + x, &z, data)) != CRYPT_OK) {
324                   if (!ordered || list[i].optional) { continue; }
325                   goto LBL_ERR;
326                }
327                break;
328 
329            case LTC_ASN1_SET:
330                z = inlen;
331                if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) {
332                   if (!ordered || list[i].optional) { continue; }
333                   goto LBL_ERR;
334                }
335                if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
336                   goto LBL_ERR;
337                }
338                break;
339 
340            case LTC_ASN1_SETOF:
341            case LTC_ASN1_SEQUENCE:
342                /* detect if we have the right type */
343                if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) {
344                   err = CRYPT_INVALID_PACKET;
345                   goto LBL_ERR;
346                }
347 
348                z = inlen;
349                err = der_decode_sequence_ex(in + x, z, data, size, flags);
350                if (err == CRYPT_INPUT_TOO_LONG) {
351                   seq_err = CRYPT_INPUT_TOO_LONG;
352                   err = CRYPT_OK;
353                }
354                if (err != CRYPT_OK) {
355                   if (!ordered || list[i].optional) { continue; }
356                   goto LBL_ERR;
357                }
358                if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) {
359                   goto LBL_ERR;
360                }
361                break;
362 
363            case LTC_ASN1_CUSTOM_TYPE:
364                z = inlen;
365                err = der_decode_custom_type(in + x, z, &list[i]);
366                if (err == CRYPT_INPUT_TOO_LONG) {
367                   seq_err = CRYPT_INPUT_TOO_LONG;
368                   err = CRYPT_OK;
369                }
370                if (err != CRYPT_OK) {
371                   if (!ordered || list[i].optional) { continue; }
372                   goto LBL_ERR;
373                }
374                if ((err = der_length_custom_type(&list[i], &z, NULL)) != CRYPT_OK) {
375                   goto LBL_ERR;
376                }
377                break;
378 
379            case LTC_ASN1_CHOICE:
380                z = inlen;
381                if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) {
382                   if (!ordered || list[i].optional) { continue; }
383                   goto LBL_ERR;
384                }
385                break;
386 
387            case LTC_ASN1_EOL:
388            default:
389                err = CRYPT_INVALID_ARG;
390                goto LBL_ERR;
391        }
392        x           += z;
393        inlen       -= z;
394        list[i].used = 1;
395        if (!ordered) {
396           /* restart the decoder */
397           i = -1;
398        }
399    }
400 
401    for (i = 0; i < (int)outlen; i++) {
402       if (list[i].used == 0 && list[i].optional == 0) {
403           err = CRYPT_INVALID_PACKET;
404           goto LBL_ERR;
405       }
406    }
407 
408    if (blksize == x && seq_err == CRYPT_OK && inlen == 0) {
409       /* everything decoded and no errors in nested sequences */
410       err = CRYPT_OK;
411    } else if (blksize == x && seq_err == CRYPT_INPUT_TOO_LONG && inlen == 0) {
412       /* a sequence reported too-long input, but now we've decoded everything */
413       err = CRYPT_OK;
414    } else if (blksize != x && ((flags & LTC_DER_SEQ_STRICT) == LTC_DER_SEQ_STRICT)) {
415       err = CRYPT_INVALID_PACKET;
416    } else {
417       err = CRYPT_INPUT_TOO_LONG;
418    }
419 
420 LBL_ERR:
421    if (in_new != NULL) {
422       XFREE(in_new);
423    }
424    return err;
425 }
426 
427 #endif
428