1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
6 * The library is free for all purposes without any express
9 * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
14 @file der_decode_sequence_flexi.c
15 ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis
20 static unsigned long fetch_length(const unsigned char *in, unsigned long inlen)
22 unsigned long x, y, z;
26 /* skip type and read len */
35 /* <128 means literal */
39 x &= 0x7F; /* the lower 7 bits are the length of the length */
42 /* len means len of len! */
43 if (x == 0 || x > 4 || x > inlen) {
50 z = (z<<8) | ((unsigned long)*in);
57 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
59 @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
61 @return CRYPT_OK on success.
63 int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
66 unsigned long err, type, len, totlen, x, y;
69 LTC_ARGCHK(in != NULL);
70 LTC_ARGCHK(inlen != NULL);
71 LTC_ARGCHK(out != NULL);
76 /* scan the input and and get lengths and what not */
78 /* read the type byte */
82 len = fetch_length(in, *inlen);
84 err = CRYPT_INVALID_PACKET;
90 l = XCALLOC(1, sizeof(*l));
96 l->next = XCALLOC(1, sizeof(*l));
97 if (l->next == NULL) {
105 /* now switch on type */
107 case 0x01: /* BOOLEAN */
108 l->type = LTC_ASN1_BOOLEAN;
110 l->data = XCALLOC(1, sizeof(int));
112 if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) {
116 if ((err = der_length_boolean(&len)) != CRYPT_OK) {
121 case 0x02: /* INTEGER */
123 l->type = LTC_ASN1_INTEGER;
125 if ((err = mp_init(&l->data)) != CRYPT_OK) {
130 if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) {
134 /* calc length of object */
135 if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) {
142 l->type = LTC_ASN1_BIT_STRING;
143 l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */
145 if ((l->data = XCALLOC(1, l->size)) == NULL) {
150 if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
154 if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) {
159 case 0x04: /* OCTET */
162 l->type = LTC_ASN1_OCTET_STRING;
165 if ((l->data = XCALLOC(1, l->size)) == NULL) {
170 if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
174 if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) {
179 case 0x05: /* NULL */
181 /* valid NULL is 0x05 0x00 */
182 if (in[0] != 0x05 || in[1] != 0x00) {
183 err = CRYPT_INVALID_PACKET;
187 /* simple to store ;-) */
188 l->type = LTC_ASN1_NULL;
198 l->type = LTC_ASN1_OBJECT_IDENTIFIER;
201 if ((l->data = XCALLOC(len, sizeof(unsigned long))) == NULL) {
206 if ((err = der_decode_object_identifier(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
210 if ((err = der_length_object_identifier(l->data, l->size, &len)) != CRYPT_OK) {
214 /* resize it to save a bunch of mem */
215 if ((realloc_tmp = XREALLOC(l->data, l->size * sizeof(unsigned long))) == NULL) {
216 /* out of heap but this is not an error */
219 l->data = realloc_tmp;
222 case 0x0C: /* UTF8 */
225 l->type = LTC_ASN1_UTF8_STRING;
228 if ((l->data = XCALLOC(sizeof(wchar_t), l->size)) == NULL) {
233 if ((err = der_decode_utf8_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
237 if ((err = der_length_utf8_string(l->data, l->size, &len)) != CRYPT_OK) {
242 case 0x13: /* PRINTABLE */
245 l->type = LTC_ASN1_PRINTABLE_STRING;
248 if ((l->data = XCALLOC(1, l->size)) == NULL) {
253 if ((err = der_decode_printable_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
257 if ((err = der_length_printable_string(l->data, l->size, &len)) != CRYPT_OK) {
265 l->type = LTC_ASN1_IA5_STRING;
268 if ((l->data = XCALLOC(1, l->size)) == NULL) {
273 if ((err = der_decode_ia5_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
277 if ((err = der_length_ia5_string(l->data, l->size, &len)) != CRYPT_OK) {
282 case 0x17: /* UTC TIME */
285 l->type = LTC_ASN1_UTCTIME;
288 if ((l->data = XCALLOC(1, sizeof(ltc_utctime))) == NULL) {
294 if ((err = der_decode_utctime(in, &len, l->data)) != CRYPT_OK) {
298 if ((err = der_length_utctime(l->data, &len)) != CRYPT_OK) {
303 case 0x30: /* SEQUENCE */
307 l->type = (type == 0x30) ? LTC_ASN1_SEQUENCE : LTC_ASN1_SET;
309 /* we have to decode the SEQUENCE header and get it's length */
314 /* read length byte */
315 x = *in++; --(*inlen);
317 /* smallest SEQUENCE/SET header */
320 /* now if it's > 127 the next bytes are the length of the length */
326 /* update sequence header len */
330 /* Sequence elements go as child */
332 if ((err = der_decode_sequence_flexi(in, &len, &(l->child))) != CRYPT_OK) {
339 /* link them up y0 */
340 l->child->parent = l;
344 /* invalid byte ... this is a soft error */
352 /* advance pointers */
360 /* rewind l please */
361 while (l->prev != NULL || l->parent != NULL) {
362 if (l->parent != NULL) {
376 der_sequence_free(l);
384 /* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_flexi.c,v $ */
385 /* $Revision: 1.25 $ */
386 /* $Date: 2006/11/26 02:25:18 $ */