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