Mercurial > dropbear
view libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c @ 1652:d2753238f35f
Added signature for changeset ebcdb893992d
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Wed, 27 Mar 2019 22:15:23 +0800 |
parents | 6dba84798cd5 |
children |
line wrap: on
line source
/* LibTomCrypt, modular cryptographic library -- Tom St Denis * * LibTomCrypt is a library that provides various cryptographic * algorithms in a highly modular and flexible manner. * * The library is free for all purposes without any express * guarantee it works. */ #include "tomcrypt.h" /** @file der_decode_sequence_ex.c ASN.1 DER, decode a SEQUENCE, Tom St Denis */ #ifdef LTC_DER /** Decode a SEQUENCE @param in The DER encoded input @param inlen The size of the input @param list The list of items to decode @param outlen The number of items in the list @param ordered Search an unordeded or ordered list @return CRYPT_OK on success */ int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, ltc_asn1_list *list, unsigned long outlen, int ordered) { int err, i; ltc_asn1_type type; unsigned long size, x, y, z, blksize; void *data; LTC_ARGCHK(in != NULL); LTC_ARGCHK(list != NULL); /* get blk size */ if (inlen < 2) { return CRYPT_INVALID_PACKET; } /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */ x = 0; if (in[x] != 0x30 && in[x] != 0x31) { return CRYPT_INVALID_PACKET; } ++x; /* check if the msb is set, which signals that the * 7 lsb bits represent the number of bytes of the length */ if (in[x] < 128) { blksize = in[x++]; } else { if (in[x] < 0x81 || in[x] > 0x83) { return CRYPT_INVALID_PACKET; } y = in[x++] & 0x7F; /* would reading the len bytes overrun? */ if (x + y > inlen) { return CRYPT_INVALID_PACKET; } /* read len */ blksize = 0; while (y--) { blksize = (blksize << 8) | (unsigned long)in[x++]; } } /* would this blksize overflow? */ if (x + blksize > inlen) { return CRYPT_INVALID_PACKET; } /* mark all as unused */ for (i = 0; i < (int)outlen; i++) { list[i].used = 0; } /* ok read data */ inlen = blksize; for (i = 0; i < (int)outlen; i++) { z = 0; type = list[i].type; size = list[i].size; data = list[i].data; if (!ordered && list[i].used == 1) { continue; } if (type == LTC_ASN1_EOL) { break; } switch (type) { case LTC_ASN1_BOOLEAN: z = inlen; if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) { if (!ordered) { continue; } goto LBL_ERR; } if ((err = der_length_boolean(&z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_INTEGER: z = inlen; if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) { if (!ordered) { continue; } goto LBL_ERR; } if ((err = der_length_integer(data, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_SHORT_INTEGER: z = inlen; if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) { if (!ordered) { continue; } goto LBL_ERR; } if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_BIT_STRING: z = inlen; if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered) { continue; } goto LBL_ERR; } list[i].size = size; if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_RAW_BIT_STRING: z = inlen; if ((err = der_decode_raw_bit_string(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered) { continue; } goto LBL_ERR; } list[i].size = size; if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { goto LBL_ERR; } break; case LTC_ASN1_OCTET_STRING: z = inlen; if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) { if (!ordered) { continue; } goto LBL_ERR; } list[i].size = size;