comparison libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c @ 1471:6dba84798cd5

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