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