1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4 #include <stdarg.h>
5 
6 
7 /**
8   @file der_decode_sequence_multi.c
9   ASN.1 DER, decode a SEQUENCE, Tom St Denis
10 */
11 
12 #ifdef LTC_DER
13 
14 /**
15   Decode a SEQUENCE type using a VA list
16   @param in    Input buffer
17   @param inlen Length of input in octets
18   @param a1    Initialized argument list #1
19   @param a2    Initialized argument list #2 (copy of #1)
20   @param flags    c.f. enum ltc_der_seq
21   @return CRYPT_OK on success
22 */
s_der_decode_sequence_va(const unsigned char * in,unsigned long inlen,va_list a1,va_list a2,unsigned int flags)23 static int s_der_decode_sequence_va(const unsigned char *in, unsigned long inlen, va_list a1, va_list a2, unsigned int flags)
24 {
25    int           err;
26    ltc_asn1_type type;
27    unsigned long size, x;
28    void          *data;
29    ltc_asn1_list *list;
30 
31    LTC_ARGCHK(in    != NULL);
32 
33    /* get size of output that will be required */
34    x = 0;
35    for (;;) {
36        type = (ltc_asn1_type)va_arg(a1, int);
37 
38        if (type == LTC_ASN1_EOL) {
39           break;
40        }
41 
42        size = va_arg(a1, unsigned long);
43        data = va_arg(a1, void*);
44        LTC_UNUSED_PARAM(size);
45        LTC_UNUSED_PARAM(data);
46 
47        switch (type) {
48            case LTC_ASN1_BOOLEAN:
49            case LTC_ASN1_INTEGER:
50            case LTC_ASN1_SHORT_INTEGER:
51            case LTC_ASN1_BIT_STRING:
52            case LTC_ASN1_OCTET_STRING:
53            case LTC_ASN1_NULL:
54            case LTC_ASN1_OBJECT_IDENTIFIER:
55            case LTC_ASN1_IA5_STRING:
56            case LTC_ASN1_PRINTABLE_STRING:
57            case LTC_ASN1_UTF8_STRING:
58            case LTC_ASN1_UTCTIME:
59            case LTC_ASN1_SET:
60            case LTC_ASN1_SETOF:
61            case LTC_ASN1_SEQUENCE:
62            case LTC_ASN1_CHOICE:
63            case LTC_ASN1_RAW_BIT_STRING:
64            case LTC_ASN1_TELETEX_STRING:
65            case LTC_ASN1_GENERALIZEDTIME:
66                 ++x;
67                 break;
68 
69            case LTC_ASN1_EOL:
70            case LTC_ASN1_CUSTOM_TYPE:
71            default:
72                return CRYPT_INVALID_ARG;
73        }
74    }
75 
76    /* allocate structure for x elements */
77    if (x == 0) {
78       return CRYPT_NOP;
79    }
80 
81    list = XCALLOC(sizeof(*list), x);
82    if (list == NULL) {
83       return CRYPT_MEM;
84    }
85 
86    /* fill in the structure */
87    x = 0;
88    for (;;) {
89        type = (ltc_asn1_type)va_arg(a2, int);
90        size = va_arg(a2, unsigned long);
91        data = va_arg(a2, void*);
92 
93        if (type == LTC_ASN1_EOL) {
94           break;
95        }
96 
97        switch (type) {
98            case LTC_ASN1_BOOLEAN:
99            case LTC_ASN1_INTEGER:
100            case LTC_ASN1_SHORT_INTEGER:
101            case LTC_ASN1_BIT_STRING:
102            case LTC_ASN1_OCTET_STRING:
103            case LTC_ASN1_NULL:
104            case LTC_ASN1_OBJECT_IDENTIFIER:
105            case LTC_ASN1_IA5_STRING:
106            case LTC_ASN1_PRINTABLE_STRING:
107            case LTC_ASN1_UTF8_STRING:
108            case LTC_ASN1_UTCTIME:
109            case LTC_ASN1_SEQUENCE:
110            case LTC_ASN1_SET:
111            case LTC_ASN1_SETOF:
112            case LTC_ASN1_CHOICE:
113            case LTC_ASN1_RAW_BIT_STRING:
114            case LTC_ASN1_TELETEX_STRING:
115            case LTC_ASN1_GENERALIZEDTIME:
116                 LTC_SET_ASN1(list, x++, type, data, size);
117                 break;
118            /* coverity[dead_error_line] */
119            case LTC_ASN1_EOL:
120            case LTC_ASN1_CUSTOM_TYPE:
121            default:
122                 break;
123        }
124    }
125 
126    err = der_decode_sequence_ex(in, inlen, list, x, flags);
127    XFREE(list);
128    return err;
129 }
130 
131 /**
132   Decode a SEQUENCE type using a VA list
133   @param in    Input buffer
134   @param inlen Length of input in octets
135   @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
136   @return CRYPT_OK on success
137 */
der_decode_sequence_multi(const unsigned char * in,unsigned long inlen,...)138 int der_decode_sequence_multi(const unsigned char *in, unsigned long inlen, ...)
139 {
140    va_list       a1, a2;
141    int err;
142 
143    LTC_ARGCHK(in    != NULL);
144 
145    va_start(a1, inlen);
146    va_start(a2, inlen);
147 
148    err = s_der_decode_sequence_va(in, inlen, a1, a2, LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_RELAXED);
149 
150    va_end(a2);
151    va_end(a1);
152 
153    return err;
154 }
155 
156 /**
157   Decode a SEQUENCE type using a VA list
158   @param in    Input buffer
159   @param inlen Length of input in octets
160   @param flags c.f. enum ltc_der_seq
161   @remark <...> is of the form <type, size, data> (int, unsigned long, void*)
162   @return CRYPT_OK on success
163 */
der_decode_sequence_multi_ex(const unsigned char * in,unsigned long inlen,unsigned int flags,...)164 int der_decode_sequence_multi_ex(const unsigned char *in, unsigned long inlen, unsigned int flags, ...)
165 {
166    va_list       a1, a2;
167    int err;
168 
169    LTC_ARGCHK(in    != NULL);
170 
171    va_start(a1, flags);
172    va_start(a2, flags);
173 
174    err = s_der_decode_sequence_va(in, inlen, a1, a2, flags);
175 
176    va_end(a2);
177    va_end(a1);
178 
179    return err;
180 }
181 
182 #endif
183 
184