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
12
13 /**
14 @file der_encode_sequence_ex.c
15 ASN.1 DER, encode a SEQUENCE, Tom St Denis
16 */
17
18 #ifdef LTC_DER
19
20 /**
21 Encode a SEQUENCE
22 @param list The list of items to encode
23 @param inlen The number of items in the list
24 @param out [out] The destination
25 @param outlen [in/out] The size of the output
26 @param type_of LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF
27 @return CRYPT_OK on success
28 */
der_encode_sequence_ex(const ltc_asn1_list * list,unsigned long inlen,unsigned char * out,unsigned long * outlen,int type_of)29 int der_encode_sequence_ex(const ltc_asn1_list *list, unsigned long inlen,
30 unsigned char *out, unsigned long *outlen, int type_of)
31 {
32 int err;
33 ltc_asn1_type type;
34 unsigned long size, x, y, z, i;
35 void *data;
36
37 LTC_ARGCHK(list != NULL);
38 LTC_ARGCHK(out != NULL);
39 LTC_ARGCHK(outlen != NULL);
40
41 /* get size of output that will be required */
42 y = 0; z = 0;
43 if ((err = der_length_sequence_ex(list, inlen, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG;
44
45 /* too big ? */
46 if (*outlen < y) {
47 *outlen = y;
48 err = CRYPT_BUFFER_OVERFLOW;
49 goto LBL_ERR;
50 }
51
52 /* store header */
53 x = 0;
54 out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
55
56 y = *outlen - x;
57 if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
58 goto LBL_ERR;
59 }
60 x += y;
61
62 /* store data */
63 *outlen -= x;
64 for (i = 0; i < inlen; i++) {
65 type = list[i].type;
66 size = list[i].size;
67 data = list[i].data;
68
69 if (type == LTC_ASN1_EOL) {
70 break;
71 }
72
73 switch (type) {
74 case LTC_ASN1_BOOLEAN:
75 z = *outlen;
76 if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {
77 goto LBL_ERR;
78 }
79 break;
80
81 case LTC_ASN1_INTEGER:
82 z = *outlen;
83 if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
84 goto LBL_ERR;
85 }
86 break;
87
88 case LTC_ASN1_SHORT_INTEGER:
89 z = *outlen;
90 if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
91 goto LBL_ERR;
92 }
93 break;
94
95 case LTC_ASN1_BIT_STRING:
96 z = *outlen;
97 if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
98 goto LBL_ERR;
99 }
100 break;
101
102 case LTC_ASN1_RAW_BIT_STRING:
103 z = *outlen;
104 if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
105 goto LBL_ERR;
106 }
107 break;
108
109 case LTC_ASN1_OCTET_STRING:
110 z = *outlen;
111 if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
112 goto LBL_ERR;
113 }
114 break;
115
116 case LTC_ASN1_NULL:
117 out[x] = 0x05;
118 out[x+1] = 0x00;
119 z = 2;
120 break;
121
122 case LTC_ASN1_OBJECT_IDENTIFIER:
123 z = *outlen;
124 if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
125 goto LBL_ERR;
126 }
127 break;
128
129 case LTC_ASN1_IA5_STRING:
130 z = *outlen;
131 if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
132 goto LBL_ERR;
133 }
134 break;
135
136 case LTC_ASN1_PRINTABLE_STRING:
137 z = *outlen;
138 if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
139 goto LBL_ERR;
140 }
141 break;
142
143 case LTC_ASN1_UTF8_STRING:
144 z = *outlen;
145 if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {
146 goto LBL_ERR;
147 }
148 break;
149
150 case LTC_ASN1_UTCTIME:
151 z = *outlen;
152 if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
153 goto LBL_ERR;
154 }
155 break;
156
157 case LTC_ASN1_GENERALIZEDTIME:
158 z = *outlen;
159 if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) {
160 goto LBL_ERR;
161 }
162 break;
163
164 case LTC_ASN1_SET:
165 z = *outlen;
166 if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {
167 goto LBL_ERR;
168 }
169 break;
170
171 case LTC_ASN1_SETOF:
172 z = *outlen;
173 if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {
174 goto LBL_ERR;
175 }
176 break;
177
178 case LTC_ASN1_SEQUENCE:
179 z = *outlen;
180 if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {
181 goto LBL_ERR;
182 }
183 break;
184
185 case LTC_ASN1_CUSTOM_TYPE:
186 z = *outlen;
187 if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) {
188 goto LBL_ERR;
189 }
190 break;
191
192 case LTC_ASN1_CHOICE:
193 case LTC_ASN1_EOL:
194 case LTC_ASN1_TELETEX_STRING:
195 default:
196 err = CRYPT_INVALID_ARG;
197 goto LBL_ERR;
198 }
199
200 x += z;
201 *outlen -= z;
202 }
203 *outlen = x;
204 err = CRYPT_OK;
205
206 LBL_ERR:
207 return err;
208 }
209
210 #endif
211
212 /* ref: $Format:%D$ */
213 /* git commit: $Format:%H$ */
214 /* commit time: $Format:%ai$ */
215