1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2 /* SPDX-License-Identifier: Unlicense */
3 #include "tomcrypt_private.h"
4
5 /**
6 @file der_decode_choice.c
7 ASN.1 DER, decode a CHOICE, Tom St Denis
8 */
9
10 #ifdef LTC_DER
11
12 /**
13 Decode a CHOICE
14 @param in The DER encoded input
15 @param inlen [in/out] The size of the input and resulting size of read type
16 @param list The list of items to decode
17 @param outlen The number of items in the list
18 @return CRYPT_OK on success
19 */
der_decode_choice(const unsigned char * in,unsigned long * inlen,ltc_asn1_list * list,unsigned long outlen)20 int der_decode_choice(const unsigned char *in, unsigned long *inlen,
21 ltc_asn1_list *list, unsigned long outlen)
22 {
23 unsigned long size, x, z;
24 void *data;
25
26 LTC_ARGCHK(in != NULL);
27 LTC_ARGCHK(inlen != NULL);
28 LTC_ARGCHK(list != NULL);
29
30 /* get blk size */
31 if (*inlen < 2) {
32 return CRYPT_INVALID_PACKET;
33 }
34
35 /* set all of the "used" flags to zero */
36 for (x = 0; x < outlen; x++) {
37 list[x].used = 0;
38 }
39
40 /* now scan until we have a winner */
41 for (x = 0; x < outlen; x++) {
42 size = list[x].size;
43 data = list[x].data;
44
45 switch (list[x].type) {
46 case LTC_ASN1_BOOLEAN:
47 if (der_decode_boolean(in, *inlen, data) == CRYPT_OK) {
48 if (der_length_boolean(&z) == CRYPT_OK) {
49 list[x].used = 1;
50 *inlen = z;
51 return CRYPT_OK;
52 }
53 }
54 break;
55
56 case LTC_ASN1_INTEGER:
57 if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {
58 if (der_length_integer(data, &z) == CRYPT_OK) {
59 list[x].used = 1;
60 *inlen = z;
61 return CRYPT_OK;
62 }
63 }
64 break;
65
66 case LTC_ASN1_SHORT_INTEGER:
67 if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) {
68 if (der_length_short_integer(size, &z) == CRYPT_OK) {
69 list[x].used = 1;
70 *inlen = z;
71 return CRYPT_OK;
72 }
73 }
74 break;
75
76 case LTC_ASN1_BIT_STRING:
77 if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
78 if (der_length_bit_string(size, &z) == CRYPT_OK) {
79 list[x].used = 1;
80 list[x].size = size;
81 *inlen = z;
82 return CRYPT_OK;
83 }
84 }
85 break;
86
87 case LTC_ASN1_RAW_BIT_STRING:
88 if (der_decode_raw_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
89 if (der_length_bit_string(size, &z) == CRYPT_OK) {
90 list[x].used = 1;
91 list[x].size = size;
92 *inlen = z;
93 return CRYPT_OK;
94 }
95 }
96 break;
97
98 case LTC_ASN1_OCTET_STRING:
99 if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {
100 if (der_length_octet_string(size, &z) == CRYPT_OK) {
101 list[x].used = 1;
102 list[x].size = size;
103 *inlen = z;
104 return CRYPT_OK;
105 }
106 }
107 break;
108
109 case LTC_ASN1_NULL:
110 if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) {
111 *inlen = 2;
112 list[x].used = 1;
113 return CRYPT_OK;
114 }
115 break;
116
117 case LTC_ASN1_OBJECT_IDENTIFIER:
118 if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) {
119 if (der_length_object_identifier(data, size, &z) == CRYPT_OK) {
120 list[x].used = 1;
121 list[x].size = size;
122 *inlen = z;
123 return CRYPT_OK;
124 }
125 }
126 break;
127
128 case LTC_ASN1_TELETEX_STRING:
129 if (der_decode_teletex_string(in, *inlen, data, &size) == CRYPT_OK) {
130 if (der_length_teletex_string(data, size, &z) == CRYPT_OK) {
131 list[x].used = 1;
132 list[x].size = size;
133 *inlen = z;
134 return CRYPT_OK;
135 }
136 }
137 break;
138
139 case LTC_ASN1_IA5_STRING:
140 if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {
141 if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {
142 list[x].used = 1;
143 list[x].size = size;
144 *inlen = z;
145 return CRYPT_OK;
146 }
147 }
148 break;
149
150 case LTC_ASN1_PRINTABLE_STRING:
151 if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) {
152 if (der_length_printable_string(data, size, &z) == CRYPT_OK) {
153 list[x].used = 1;
154 list[x].size = size;
155 *inlen = z;
156 return CRYPT_OK;
157 }
158 }
159 break;
160
161 case LTC_ASN1_UTF8_STRING:
162 if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) {
163 if (der_length_utf8_string(data, size, &z) == CRYPT_OK) {
164 list[x].used = 1;
165 list[x].size = size;
166 *inlen = z;
167 return CRYPT_OK;
168 }
169 }
170 break;
171
172 case LTC_ASN1_UTCTIME:
173 z = *inlen;
174 if (der_decode_utctime(in, &z, data) == CRYPT_OK) {
175 list[x].used = 1;
176 *inlen = z;
177 return CRYPT_OK;
178 }
179 break;
180
181 case LTC_ASN1_GENERALIZEDTIME:
182 z = *inlen;
183 if (der_decode_generalizedtime(in, &z, data) == CRYPT_OK) {
184 list[x].used = 1;
185 *inlen = z;
186 return CRYPT_OK;
187 }
188 break;
189
190 case LTC_ASN1_SET:
191 case LTC_ASN1_SETOF:
192 case LTC_ASN1_SEQUENCE:
193 if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) {
194 if (der_length_sequence(data, size, &z) == CRYPT_OK) {
195 list[x].used = 1;
196 *inlen = z;
197 return CRYPT_OK;
198 }
199 }
200 break;
201
202 case LTC_ASN1_CUSTOM_TYPE:
203 if (der_decode_custom_type(in, *inlen, &list[x]) == CRYPT_OK) {
204 if (der_length_custom_type(&list[x], &z, NULL) == CRYPT_OK) {
205 list[x].used = 1;
206 *inlen = z;
207 return CRYPT_OK;
208 }
209 }
210 break;
211
212 case LTC_ASN1_CHOICE:
213 case LTC_ASN1_EOL:
214 default:
215 return CRYPT_INVALID_ARG;
216 }
217 }
218
219 return CRYPT_INVALID_PACKET;
220 }
221
222 #endif
223