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