/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ /* SPDX-License-Identifier: Unlicense */ #include "tomcrypt_private.h" /** @file der_decode_sequence_multi.c ASN.1 DER, decode a SEQUENCE, Tom St Denis */ #ifdef LTC_DER /** Decode a SEQUENCE type using a VA list @param in Input buffer @param inlen Length of input in octets @param a1 Initialized argument list #1 @param a2 Initialized argument list #2 (copy of #1) @param flags c.f. enum ltc_der_seq @return CRYPT_OK on success */ static int s_der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags) { int err; ltc_asn1_type type; unsigned long size, x; void *data; ltc_asn1_list *list; LTC_ARGCHK(in != NULL); /* get size of output that will be required */ x = 0; for (;;) { type = (ltc_asn1_type)va_arg(a1, int); if (type == LTC_ASN1_EOL) { break; } size = va_arg(a1, unsigned long); data = va_arg(a1, void*); LTC_UNUSED_PARAM(size); LTC_UNUSED_PARAM(data); switch (type) { case LTC_ASN1_BOOLEAN: case LTC_ASN1_INTEGER: case LTC_ASN1_SHORT_INTEGER: case LTC_ASN1_BIT_STRING: case LTC_ASN1_OCTET_STRING: case LTC_ASN1_NULL: case LTC_ASN1_OBJECT_IDENTIFIER: case LTC_ASN1_IA5_STRING: case LTC_ASN1_PRINTABLE_STRING: case LTC_ASN1_UTF8_STRING: case LTC_ASN1_UTCTIME: case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_SEQUENCE: case LTC_ASN1_CHOICE: case LTC_ASN1_RAW_BIT_STRING: case LTC_ASN1_TELETEX_STRING: case LTC_ASN1_GENERALIZEDTIME: ++x; break; case LTC_ASN1_EOL: case LTC_ASN1_CUSTOM_TYPE: return CRYPT_INVALID_ARG; } } /* allocate structure for x elements */ if (x == 0) { return CRYPT_NOP; } list = XCALLOC(x, sizeof(*list)); if (list == NULL) { return CRYPT_MEM; } /* fill in the structure */ x = 0; for (;;) { type = (ltc_asn1_type)va_arg(a2, int); size = va_arg(a2, unsigned long); data = va_arg(a2, void*); if (type == LTC_ASN1_EOL) { break; } switch (type) { case LTC_ASN1_BOOLEAN: case LTC_ASN1_INTEGER: case LTC_ASN1_SHORT_INTEGER: case LTC_ASN1_BIT_STRING: case LTC_ASN1_OCTET_STRING: case LTC_ASN1_NULL: case LTC_ASN1_OBJECT_IDENTIFIER: case LTC_ASN1_IA5_STRING: case LTC_ASN1_PRINTABLE_STRING: case LTC_ASN1_UTF8_STRING: case LTC_ASN1_UTCTIME: case LTC_ASN1_SEQUENCE: case LTC_ASN1_SET: case LTC_ASN1_SETOF: case LTC_ASN1_CHOICE: case LTC_ASN1_RAW_BIT_STRING: case LTC_ASN1_TELETEX_STRING: case LTC_ASN1_GENERALIZEDTIME: LTC_SET_ASN1(list, x++, type, data, size); break; /* coverity[dead_error_line] */ case LTC_ASN1_EOL: case LTC_ASN1_CUSTOM_TYPE: break; } } err = der_decode_sequence_ex(in, inlen, list, x, flags); XFREE(list); return err; } /** Decode a SEQUENCE type using a VA list @param in Input buffer @param inlen Length of input in octets @remark <...> is of the form (int, unsigned long, void*) @return CRYPT_OK on success */ int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...) { va_list a1, a2; int err; LTC_ARGCHK(in != NULL); va_start(a1, inlen); va_start(a2, inlen); err = s_der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED); va_end(a2); va_end(a1); return err; } /** Decode a SEQUENCE type using a VA list @param in Input buffer @param inlen Length of input in octets @param flags c.f. enum ltc_der_seq @remark <...> is of the form (int, unsigned long, void*) @return CRYPT_OK on success */ int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...) { va_list a1, a2; int err; LTC_ARGCHK(in != NULL); va_start(a1, flags); va_start(a2, flags); err = s_der_decode_sequence_va(in, inlen, a1, a2, flags); va_end(a2); va_end(a1); return err; } #endif