comparison src/pk/asn1/der/sequence/der_encode_sequence.c @ 209:39d5d58461d6 libtomcrypt-orig LTC_1.05

Import of libtomcrypt 1.05
author Matt Johnston <matt@ucc.asn.au>
date Wed, 06 Jul 2005 03:53:40 +0000
parents
children
comparison
equal deleted inserted replaced
191:1c15b283127b 209:39d5d58461d6
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, [email protected], http://libtomcrypt.org
10 */
11 #include "tomcrypt.h"
12 #include <stdarg.h>
13
14
15 /**
16 @file der_encode_sequence.c
17 ASN.1 DER, encode a SEQUENCE, Tom St Denis
18 */
19
20 #ifdef LTC_DER
21
22 /**
23 Encode a SEQUENCE
24 @param list The list of items to encode
25 @param inlen The number of items in the list
26 @param out [out] The destination
27 @param outlen [in/out] The size of the output
28 @return CRYPT_OK on success
29 */
30 int der_encode_sequence(ltc_asn1_list *list, unsigned long inlen,
31 unsigned char *out, unsigned long *outlen)
32 {
33 int err, 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;
43 for (i = 0; i < inlen; i++) {
44 type = list[i].type;
45 size = list[i].size;
46 data = list[i].data;
47
48 if (type == LTC_ASN1_EOL) {
49 break;
50 }
51
52 switch (type) {
53 case LTC_ASN1_INTEGER:
54 if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
55 goto LBL_ERR;
56 }
57 y += x;
58 break;
59
60 case LTC_ASN1_SHORT_INTEGER:
61 if ((err = der_length_short_integer(*((unsigned long*)data), &x)) != CRYPT_OK) {
62 goto LBL_ERR;
63 }
64 y += x;
65 break;
66
67 case LTC_ASN1_BIT_STRING:
68 if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
69 goto LBL_ERR;
70 }
71 y += x;
72 break;
73
74 case LTC_ASN1_OCTET_STRING:
75 if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
76 goto LBL_ERR;
77 }
78 y += x;
79 break;
80
81 case LTC_ASN1_NULL:
82 y += 2;
83 break;
84
85 case LTC_ASN1_OBJECT_IDENTIFIER:
86 if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
87 goto LBL_ERR;
88 }
89 y += x;
90 break;
91
92 case LTC_ASN1_IA5_STRING:
93 if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
94 goto LBL_ERR;
95 }
96 y += x;
97 break;
98
99 case LTC_ASN1_PRINTABLE_STRING:
100 if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
101 goto LBL_ERR;
102 }
103 y += x;
104 break;
105
106 case LTC_ASN1_UTCTIME:
107 if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
108 goto LBL_ERR;
109 }
110 y += x;
111 break;
112
113 case LTC_ASN1_SEQUENCE:
114 if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
115 goto LBL_ERR;
116 }
117 y += x;
118 break;
119
120
121 default:
122 err = CRYPT_INVALID_ARG;
123 goto LBL_ERR;
124 }
125 }
126
127 /* calc header size */
128 z = y;
129 if (y < 128) {
130 y += 2;
131 } else if (y < 256) {
132 /* 0x30 0x81 LL */
133 y += 3;
134 } else if (y < 65536UL) {
135 /* 0x30 0x82 LL LL */
136 y += 4;
137 } else if (y < 16777216UL) {
138 /* 0x30 0x83 LL LL LL */
139 y += 5;
140 } else {
141 err = CRYPT_INVALID_ARG;
142 goto LBL_ERR;
143 }
144
145 /* too big ? */
146 if (*outlen < y) {
147 err = CRYPT_BUFFER_OVERFLOW;
148 goto LBL_ERR;
149 }
150
151 /* store header */
152 x = 0;
153 out[x++] = 0x30;
154 if (z < 128) {
155 out[x++] = z;
156 } else if (z < 256) {
157 out[x++] = 0x81;
158 out[x++] = z;
159 } else if (z < 65536UL) {
160 out[x++] = 0x82;
161 out[x++] = (z>>8UL)&255;
162 out[x++] = z&255;
163 } else if (z < 16777216UL) {
164 out[x++] = 0x83;
165 out[x++] = (z>>16UL)&255;
166 out[x++] = (z>>8UL)&255;
167 out[x++] = z&255;
168 }
169
170 /* store data */
171 *outlen -= x;
172 for (i = 0; i < inlen; i++) {
173 type = list[i].type;
174 size = list[i].size;
175 data = list[i].data;
176
177 if (type == LTC_ASN1_EOL) {
178 break;
179 }
180
181 switch (type) {
182 case LTC_ASN1_INTEGER:
183 z = *outlen;
184 if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
185 goto LBL_ERR;
186 }
187 x += z;
188 *outlen -= z;
189 break;
190
191 case LTC_ASN1_SHORT_INTEGER:
192 z = *outlen;
193 if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
194 goto LBL_ERR;
195 }
196 x += z;
197 *outlen -= z;
198 break;
199
200 case LTC_ASN1_BIT_STRING:
201 z = *outlen;
202 if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
203 goto LBL_ERR;
204 }
205 x += z;
206 *outlen -= z;
207 break;
208
209 case LTC_ASN1_OCTET_STRING:
210 z = *outlen;
211 if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
212 goto LBL_ERR;
213 }
214 x += z;
215 *outlen -= z;
216 break;
217
218 case LTC_ASN1_NULL:
219 out[x++] = 0x05;
220 out[x++] = 0x00;
221 *outlen -= 2;
222 break;
223
224 case LTC_ASN1_OBJECT_IDENTIFIER:
225 z = *outlen;
226 if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
227 goto LBL_ERR;
228 }
229 x += z;
230 *outlen -= z;
231 break;
232
233 case LTC_ASN1_IA5_STRING:
234 z = *outlen;
235 if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
236 goto LBL_ERR;
237 }
238 x += z;
239 *outlen -= z;
240 break;
241
242 case LTC_ASN1_PRINTABLE_STRING:
243 z = *outlen;
244 if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
245 goto LBL_ERR;
246 }
247 x += z;
248 *outlen -= z;
249 break;
250
251 case LTC_ASN1_UTCTIME:
252 z = *outlen;
253 if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
254 goto LBL_ERR;
255 }
256 x += z;
257 *outlen -= z;
258 break;
259
260 case LTC_ASN1_SEQUENCE:
261 z = *outlen;
262 if ((err = der_encode_sequence(data, size, out + x, &z)) != CRYPT_OK) {
263 goto LBL_ERR;
264 }
265 x += z;
266 *outlen -= z;
267 break;
268
269 default:
270 err = CRYPT_INVALID_ARG;
271 goto LBL_ERR;
272 }
273 }
274 *outlen = x;
275 err = CRYPT_OK;
276
277 LBL_ERR:
278 return err;
279 }
280
281 #endif