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