CryptX
view release on metacpan or search on metacpan
src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c view on Meta::CPAN
/* LibTomCrypt, modular cryptographic library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#include "tomcrypt_private.h"
/**
@file der_decode_sequence_flexi.c
ASN.1 DER, decode an array of ASN.1 types with a flexi parser, Tom St Denis
*/
#ifdef LTC_DER
static int s_new_element(ltc_asn1_list **l)
{
/* alloc new link */
if (*l == NULL) {
*l = XCALLOC(1, sizeof(ltc_asn1_list));
if (*l == NULL) {
return CRYPT_MEM;
}
} else {
(*l)->next = XCALLOC(1, sizeof(ltc_asn1_list));
if ((*l)->next == NULL) {
return CRYPT_MEM;
}
(*l)->next->prev = *l;
*l = (*l)->next;
}
return CRYPT_OK;
}
#if defined(LTC_TEST_DBG)
void s_print_err(const char *errstr, ltc_asn1_list *l, int err, unsigned long identifier, unsigned long data_offset, unsigned long len)
{
#if LTC_TEST_DBG <= 1
if (err == CRYPT_OK)
return;
#endif
if (l->type == LTC_ASN1_CUSTOM_TYPE) {
fprintf(stderr, "%s %02lx: hl=%4lu l=%4lu - %s[%s %llu] (%s)\n", errstr, identifier, data_offset, len, der_asn1_class_to_string_map[l->klass], der_asn1_pc_to_string_map[l->pc], l->tag, error_to_string(err));
} else {
fprintf(stderr, "%s %02lx: hl=%4lu l=%4lu - %s (%s)\n", errstr, identifier, data_offset, len, der_asn1_tag_to_string_map[l->tag], error_to_string(err));
}
}
#else
#define s_print_err(errstr, l, err, identifier, data_offset, len) LTC_UNUSED_PARAM(data_offset)
#endif
/**
ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
@param in The input buffer
@param inlen [in/out] The length of the input buffer and on output the amount of decoded data
@param out [out] A pointer to the linked list
@param depth The depth/level of decoding recursion we've already reached
@return CRYPT_OK on success.
*/
static int s_der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out, unsigned long depth)
{
ltc_asn1_list *l;
int err;
unsigned long identifier, len, totlen, data_offset, id_len, len_len;
void *realloc_tmp;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(inlen != NULL);
LTC_ARGCHK(out != NULL);
l = NULL;
totlen = 0;
if (*inlen == 0) {
/* alloc new link */
if ((err = s_new_element(&l)) != CRYPT_OK) {
goto error;
}
}
/* scan the input and and get lengths and what not */
while (*inlen) {
/* alloc new link */
if ((err = s_new_element(&l)) != CRYPT_OK) {
goto error;
}
id_len = *inlen;
if ((err = der_decode_asn1_identifier(in, &id_len, l)) != CRYPT_OK) {
goto error;
}
/* read the type byte */
identifier = *in;
if (l->type != LTC_ASN1_EOL) {
/* fetch length */
len_len = *inlen - id_len;
/* init with dummy values for error cases */
data_offset = 666;
len = 0;
if ((err = der_decode_asn1_length(&in[id_len], &len_len, &len)) != CRYPT_OK) {
s_print_err("E1", l, err, identifier, data_offset, len);
goto error;
} else if (len > (*inlen - id_len - len_len)) {
err = CRYPT_INVALID_PACKET;
s_print_err("E2", l, err, identifier, data_offset, len);
goto error;
}
data_offset = id_len + len_len;
s_print_err("OK", l, err, identifier, data_offset, len);
len += data_offset;
if (l->type == LTC_ASN1_CUSTOM_TYPE) {
/* Custom type, use the 'used' field to store the original identifier */
l->used = identifier;
src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c view on Meta::CPAN
/* Init this so gcc won't complain,
* as this case will only be hit when we
* can't decode the identifier so the
* switch-case should go to default anyway...
*/
data_offset = 0;
len = 0;
}
/* now switch on type */
switch (identifier) {
case 0x01: /* BOOLEAN */
if (l->type != LTC_ASN1_BOOLEAN) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = 1;
l->data = XCALLOC(1, sizeof(int));
if ((err = der_decode_boolean(in, *inlen, l->data)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_boolean(&len)) != CRYPT_OK) {
goto error;
}
break;
case 0x02: /* INTEGER */
if (l->type != LTC_ASN1_INTEGER) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = 1;
if ((err = ltc_mp_init(&l->data)) != CRYPT_OK) {
goto error;
}
/* decode field */
if ((err = der_decode_integer(in, *inlen, l->data)) != CRYPT_OK) {
goto error;
}
/* calc length of object */
if ((err = der_length_integer(l->data, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x03: /* BIT */
if (l->type != LTC_ASN1_BIT_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = len * 8; /* *8 because we store decoded bits one per char and they are encoded 8 per char. */
if ((l->data = XCALLOC(1, l->size)) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_bit_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_bit_string(l->size, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x04: /* OCTET */
if (l->type != LTC_ASN1_OCTET_STRING) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* init field */
l->size = len;
if ((l->data = XCALLOC(1, l->size)) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_octet_string(in, *inlen, l->data, &l->size)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_octet_string(l->size, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x05: /* NULL */
if (l->type != LTC_ASN1_NULL) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* valid NULL is 0x05 0x00 */
if (in[0] != 0x05 || in[1] != 0x00) {
err = CRYPT_INVALID_PACKET;
goto error;
}
/* simple to store ;-) */
l->data = NULL;
l->size = 0;
len = 2;
break;
case 0x06: /* OID */
if (l->type != LTC_ASN1_OBJECT_IDENTIFIER) {
err = CRYPT_PK_ASN1_ERROR;
src/ltc/pk/asn1/der/sequence/der_decode_sequence_flexi.c view on Meta::CPAN
if ((l->data = XCALLOC(1, sizeof(ltc_generalizedtime))) == NULL) {
err = CRYPT_MEM;
goto error;
}
if ((err = der_decode_generalizedtime(in, &len, l->data)) != CRYPT_OK) {
goto error;
}
if ((err = der_length_generalizedtime(l->data, &len)) != CRYPT_OK) {
goto error;
}
break;
case 0x20: /* Any CONSTRUCTED element that is neither SEQUENCE nor SET */
case 0x30: /* SEQUENCE */
case 0x31: /* SET */
/* init field */
if (identifier == 0x20) {
if (l->type != LTC_ASN1_CUSTOM_TYPE) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
}
else if (identifier == 0x30) {
if (l->type != LTC_ASN1_SEQUENCE) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
}
else {
if (l->type != LTC_ASN1_SET) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
}
/* check that we don't go over the recursion limit */
if (depth > LTC_DER_MAX_RECURSION) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
if ((l->data = XMALLOC(len)) == NULL) {
err = CRYPT_MEM;
goto error;
}
XMEMCPY(l->data, in, len);
l->size = len;
/* jump to the start of the data */
in += data_offset;
*inlen -= data_offset;
len -= data_offset;
/* save the decoded ASN.1 len */
len_len = len;
/* Sequence elements go as child */
if ((err = s_der_decode_sequence_flexi(in, &len, &(l->child), depth+1)) != CRYPT_OK) {
goto error;
}
if (len_len != len) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
/* len update */
totlen += data_offset;
/* the flexi decoder can also do nothing, so make sure a child has been allocated */
if (l->child) {
/* link them up y0 */
l->child->parent = l;
}
break;
case 0x80: /* Context-specific */
if (l->type != LTC_ASN1_CUSTOM_TYPE) {
err = CRYPT_PK_ASN1_ERROR;
goto error;
}
if ((l->data = XCALLOC(1, len - data_offset)) == NULL) {
err = CRYPT_MEM;
goto error;
}
XMEMCPY(l->data, in + data_offset, len - data_offset);
l->size = len - data_offset;
break;
default:
/* invalid byte ... this is a soft error */
/* remove link */
if (l->prev) {
l = l->prev;
XFREE(l->next);
l->next = NULL;
}
goto outside;
}
/* advance pointers */
totlen += len;
in += len;
*inlen -= len;
}
outside:
/* in case we processed anything */
if (totlen) {
/* rewind l please */
while (l->prev != NULL || l->parent != NULL) {
if (l->parent != NULL) {
l = l->parent;
} else {
l = l->prev;
}
}
}
/* return */
*out = l;
*inlen = totlen;
return CRYPT_OK;
error:
/* free list */
der_sequence_free(l);
return err;
}
/**
ASN.1 DER Flexi(ble) decoder will decode arbitrary DER packets and create a linked list of the decoded elements.
@param in The input buffer
@param inlen [in/out] The length of the input buffer and on output the amount of decoded data
@param out [out] A pointer to the linked list
@return CRYPT_OK on success.
*/
int der_decode_sequence_flexi(const unsigned char *in, unsigned long *inlen, ltc_asn1_list **out)
{
return s_der_decode_sequence_flexi(in, inlen, out, 0);
}
#endif
( run in 0.632 second using v1.01-cache-2.11-cpan-39bf76dae61 )