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_custom_type.c
15 ASN.1 DER, encode a Custom Type, Steffen Jaeckel
16 */
17
18 #ifdef LTC_DER
19
20 /**
21 Encode a Custom Type
22
23 This function is a bit special compared to the others, as it requires the
24 root-ltc_asn1_list where the type is defined.
25
26 @param root The root of the list of items to encode
27 @param out [out] The destination
28 @param outlen [in/out] The size of the output
29 @return CRYPT_OK on success
30 */
der_encode_custom_type(const ltc_asn1_list * root,unsigned char * out,unsigned long * outlen)31 int der_encode_custom_type(const ltc_asn1_list *root,
32 unsigned char *out, unsigned long *outlen)
33 {
34 int err;
35 ltc_asn1_type type;
36 const ltc_asn1_list *list;
37 unsigned long size, x, y, z, i, inlen, id_len;
38 void *data;
39
40 LTC_ARGCHK(root != NULL);
41 LTC_ARGCHK(out != NULL);
42 LTC_ARGCHK(outlen != NULL);
43
44 /* get size of output that will be required */
45 y = 0; z = 0;
46 if ((err = der_length_custom_type(root, &y, &z)) != CRYPT_OK) return CRYPT_INVALID_ARG;
47
48 /* too big ? */
49 if (*outlen < y) {
50 *outlen = y;
51 err = CRYPT_BUFFER_OVERFLOW;
52 goto LBL_ERR;
53 }
54
55 /* get length of the identifier, so we know the offset where to start writing */
56 if ((err = der_length_asn1_identifier(root, &id_len)) != CRYPT_OK) return CRYPT_INVALID_ARG;
57 x = id_len;
58
59
60 if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
61 list = root;
62 inlen = 1;
63 /* In case it's a PRIMITIVE type we encode directly to the output
64 * but leave space for a potentially longer identifier as it will
65 * simply be replaced afterwards.
66 */
67 x -= 1;
68 } else {
69 list = root->data;
70 inlen = root->size;
71 /* store length, identifier will be added later */
72 y = *outlen - x;
73 if ((err = der_encode_asn1_length(z, &out[x], &y)) != CRYPT_OK) {
74 goto LBL_ERR;
75 }
76 x += y;
77 }
78
79 /* store data */
80 *outlen -= x;
81 for (i = 0; i < inlen; i++) {
82 if (root->pc == LTC_ASN1_PC_PRIMITIVE) {
83 type = (ltc_asn1_type)list[i].used;
84 } else {
85 type = list[i].type;
86 }
87 size = list[i].size;
88 data = list[i].data;
89
90 if (type == LTC_ASN1_EOL) {
91 break;
92 }
93
94 switch (type) {
95 case LTC_ASN1_BOOLEAN:
96 z = *outlen;
97 if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {
98 goto LBL_ERR;
99 }
100 break;
101
102 case LTC_ASN1_INTEGER:
103 z = *outlen;
104 if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
105 goto LBL_ERR;
106 }
107 break;
108
109 case LTC_ASN1_SHORT_INTEGER:
110 z = *outlen;
111 if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
112 goto LBL_ERR;
113 }
114 break;
115
116 case LTC_ASN1_BIT_STRING:
117 z = *outlen;
118 if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
119 goto LBL_ERR;
120 }
121 break;
122
123 case LTC_ASN1_RAW_BIT_STRING:
124 z = *outlen;
125 if ((err = der_encode_raw_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
126 goto LBL_ERR;
127 }
128 break;
129
130 case LTC_ASN1_OCTET_STRING:
131 z = *outlen;
132 if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
133 goto LBL_ERR;
134 }
135 break;
136
137 case LTC_ASN1_NULL:
138 out[x] = 0x05;
139 out[x+1] = 0x00;
140 z = 2;
141 break;
142
143 case LTC_ASN1_OBJECT_IDENTIFIER:
144 z = *outlen;
145 if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
146 goto LBL_ERR;
147 }
148 break;
149
150 case LTC_ASN1_IA5_STRING:
151 z = *outlen;
152 if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
153 goto LBL_ERR;
154 }
155 break;
156
157 case LTC_ASN1_PRINTABLE_STRING:
158 z = *outlen;
159 if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
160 goto LBL_ERR;
161 }
162 break;
163
164 case LTC_ASN1_UTF8_STRING:
165 z = *outlen;
166 if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {
167 goto LBL_ERR;
168 }
169 break;
170
171 case LTC_ASN1_UTCTIME:
172 z = *outlen;
173 if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
174 goto LBL_ERR;
175 }
176 break;
177
178 case LTC_ASN1_GENERALIZEDTIME:
179 z = *outlen;
180 if ((err = der_encode_generalizedtime(data, out + x, &z)) != CRYPT_OK) {
181 goto LBL_ERR;
182 }
183 break;
184
185 case LTC_ASN1_SET:
186 z = *outlen;
187 if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {
188 goto LBL_ERR;
189 }
190 break;
191
192 case LTC_ASN1_SETOF:
193 z = *outlen;
194 if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {
195 goto LBL_ERR;
196 }
197 break;
198
199 case LTC_ASN1_SEQUENCE:
200 z = *outlen;
201 if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {
202 goto LBL_ERR;
203 }
204 break;
205
206 case LTC_ASN1_CUSTOM_TYPE:
207 z = *outlen;
208 if ((err = der_encode_custom_type(&list[i], out + x, &z)) != CRYPT_OK) {
209 goto LBL_ERR;
210 }
211 break;
212
213 case LTC_ASN1_CHOICE:
214 case LTC_ASN1_EOL:
215 case LTC_ASN1_TELETEX_STRING:
216 default:
217 err = CRYPT_INVALID_ARG;
218 goto LBL_ERR;
219 }
220
221
222 x += z;
223 *outlen -= z;
224 }
225
226 if ((err = der_encode_asn1_identifier(root, out, &id_len)) != CRYPT_OK) {
227 goto LBL_ERR;
228 }
229 *outlen = x;
230 err = CRYPT_OK;
231
232 LBL_ERR:
233 return err;
234 }
235
236 #endif
237
238 /* ref: $Format:%D$ */
239 /* git commit: $Format:%H$ */
240 /* commit time: $Format:%ai$ */
241