version 0.3.33
[fms.git] / libs / libtomcrypt / pk / asn1 / der / sequence / der_encode_sequence_ex.c
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, tomstdenis@gmail.com, http://libtomcrypt.com
10  */
11 #include "tomcrypt.h"
12 #include <stdarg.h>
13
14
15 /**
16   @file der_encode_sequence_ex.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    @param type_of   LTC_ASN1_SEQUENCE or LTC_ASN1_SET/LTC_ASN1_SETOF
29    @return CRYPT_OK on success
30 */
31 int der_encode_sequence_ex(ltc_asn1_list *list, unsigned long inlen,
32                            unsigned char *out,  unsigned long *outlen, int type_of) 
33 {
34    int           err, type;
35    unsigned long size, x, y, z, i;
36    void          *data;
37
38    LTC_ARGCHK(list    != NULL);
39    LTC_ARGCHK(out     != NULL);
40    LTC_ARGCHK(outlen  != NULL);
41
42    /* get size of output that will be required */
43    y = 0;
44    for (i = 0; i < inlen; i++) {
45        type = list[i].type;
46        size = list[i].size;
47        data = list[i].data;
48
49        if (type == LTC_ASN1_EOL) { 
50           break;
51        }
52
53        switch (type) {
54             case LTC_ASN1_BOOLEAN:
55                if ((err = der_length_boolean(&x)) != CRYPT_OK) {
56                   goto LBL_ERR;
57                }
58                y += x;
59                break;
60
61            case LTC_ASN1_INTEGER:
62                if ((err = der_length_integer(data, &x)) != CRYPT_OK) {
63                   goto LBL_ERR;
64                }
65                y += x;
66                break;
67
68            case LTC_ASN1_SHORT_INTEGER:
69                if ((err = der_length_short_integer(*((unsigned long*)data), &x)) != CRYPT_OK) {
70                   goto LBL_ERR;
71                }
72                y += x;
73                break;
74
75            case LTC_ASN1_BIT_STRING:
76                if ((err = der_length_bit_string(size, &x)) != CRYPT_OK) {
77                   goto LBL_ERR;
78                }
79                y += x;
80                break;
81
82            case LTC_ASN1_OCTET_STRING:
83                if ((err = der_length_octet_string(size, &x)) != CRYPT_OK) {
84                   goto LBL_ERR;
85                }
86                y += x;
87                break;
88
89            case LTC_ASN1_NULL:
90                y += 2;
91                break;
92
93            case LTC_ASN1_OBJECT_IDENTIFIER:
94                if ((err = der_length_object_identifier(data, size, &x)) != CRYPT_OK) {
95                   goto LBL_ERR;
96                }
97                y += x;
98                break;
99
100            case LTC_ASN1_IA5_STRING:
101                if ((err = der_length_ia5_string(data, size, &x)) != CRYPT_OK) {
102                   goto LBL_ERR;
103                }
104                y += x;
105                break;
106
107            case LTC_ASN1_PRINTABLE_STRING:
108                if ((err = der_length_printable_string(data, size, &x)) != CRYPT_OK) {
109                   goto LBL_ERR;
110                }
111                y += x;
112                break;
113
114            case LTC_ASN1_UTF8_STRING:
115                if ((err = der_length_utf8_string(data, size, &x)) != CRYPT_OK) {
116                   goto LBL_ERR;
117                }
118                y += x;
119                break;
120
121            case LTC_ASN1_UTCTIME:
122                if ((err = der_length_utctime(data, &x)) != CRYPT_OK) {
123                   goto LBL_ERR;
124                }
125                y += x;
126                break;
127
128            case LTC_ASN1_SET:
129            case LTC_ASN1_SETOF:
130            case LTC_ASN1_SEQUENCE:
131                if ((err = der_length_sequence(data, size, &x)) != CRYPT_OK) {
132                   goto LBL_ERR;
133                }
134                y += x;
135                break;
136           
137            default:
138                err = CRYPT_INVALID_ARG;
139                goto LBL_ERR;
140        }
141    }
142
143    /* calc header size */
144    z = y;
145    if (y < 128) {
146       y += 2;
147    } else if (y < 256) {
148       /* 0x30 0x81 LL */
149       y += 3;
150    } else if (y < 65536UL) {
151       /* 0x30 0x82 LL LL */
152       y += 4;
153    } else if (y < 16777216UL) {
154       /* 0x30 0x83 LL LL LL */
155       y += 5;
156    } else {
157       err = CRYPT_INVALID_ARG;
158       goto LBL_ERR;
159    }
160
161    /* too big ? */
162    if (*outlen < y) {
163       *outlen = y;
164       err = CRYPT_BUFFER_OVERFLOW;
165       goto LBL_ERR;
166    }
167
168    /* store header */
169    x = 0;
170    out[x++] = (type_of == LTC_ASN1_SEQUENCE) ? 0x30 : 0x31;
171       
172    if (z < 128) {
173       out[x++] = (unsigned char)z;
174    } else if (z < 256) {
175       out[x++] = 0x81;
176       out[x++] = (unsigned char)z;
177    } else if (z < 65536UL) {
178       out[x++] = 0x82;
179       out[x++] = (unsigned char)((z>>8UL)&255);
180       out[x++] = (unsigned char)(z&255);
181    } else if (z < 16777216UL) {
182       out[x++] = 0x83;
183       out[x++] = (unsigned char)((z>>16UL)&255);
184       out[x++] = (unsigned char)((z>>8UL)&255);
185       out[x++] = (unsigned char)(z&255);
186    }
187
188    /* store data */
189    *outlen -= x;
190    for (i = 0; i < inlen; i++) {
191        type = list[i].type;
192        size = list[i].size;
193        data = list[i].data;
194
195        if (type == LTC_ASN1_EOL) { 
196           break;
197        }
198
199        switch (type) {
200             case LTC_ASN1_BOOLEAN:
201                z = *outlen;
202                if ((err = der_encode_boolean(*((int *)data), out + x, &z)) != CRYPT_OK) {
203                   goto LBL_ERR;
204                }
205                x       += z;
206                *outlen -= z;
207                break;
208           
209            case LTC_ASN1_INTEGER:
210                z = *outlen;
211                if ((err = der_encode_integer(data, out + x, &z)) != CRYPT_OK) {
212                   goto LBL_ERR;
213                }
214                x       += z;
215                *outlen -= z;
216                break;
217
218            case LTC_ASN1_SHORT_INTEGER:
219                z = *outlen;
220                if ((err = der_encode_short_integer(*((unsigned long*)data), out + x, &z)) != CRYPT_OK) {
221                   goto LBL_ERR;
222                }
223                x       += z;
224                *outlen -= z;
225                break;
226
227            case LTC_ASN1_BIT_STRING:
228                z = *outlen;
229                if ((err = der_encode_bit_string(data, size, out + x, &z)) != CRYPT_OK) {
230                   goto LBL_ERR;
231                }
232                x       += z;
233                *outlen -= z;
234                break;
235
236            case LTC_ASN1_OCTET_STRING:
237                z = *outlen;
238                if ((err = der_encode_octet_string(data, size, out + x, &z)) != CRYPT_OK) {
239                   goto LBL_ERR;
240                }
241                x       += z;
242                *outlen -= z;
243                break;
244
245            case LTC_ASN1_NULL:
246                out[x++] = 0x05;
247                out[x++] = 0x00;
248                *outlen -= 2;
249                break;
250
251            case LTC_ASN1_OBJECT_IDENTIFIER:
252                z = *outlen;
253                if ((err = der_encode_object_identifier(data, size, out + x, &z)) != CRYPT_OK) {
254                   goto LBL_ERR;
255                }
256                x       += z;
257                *outlen -= z;
258                break;
259
260            case LTC_ASN1_IA5_STRING:
261                z = *outlen;
262                if ((err = der_encode_ia5_string(data, size, out + x, &z)) != CRYPT_OK) {
263                   goto LBL_ERR;
264                }
265                x       += z;
266                *outlen -= z;
267                break;
268           
269            case LTC_ASN1_PRINTABLE_STRING:
270                z = *outlen;
271                if ((err = der_encode_printable_string(data, size, out + x, &z)) != CRYPT_OK) {
272                   goto LBL_ERR;
273                }
274                x       += z;
275                *outlen -= z;
276                break;
277
278            case LTC_ASN1_UTF8_STRING:
279                z = *outlen;
280                if ((err = der_encode_utf8_string(data, size, out + x, &z)) != CRYPT_OK) {
281                   goto LBL_ERR;
282                }
283                x       += z;
284                *outlen -= z;
285                break;
286
287            case LTC_ASN1_UTCTIME:
288                z = *outlen;
289                if ((err = der_encode_utctime(data, out + x, &z)) != CRYPT_OK) {
290                   goto LBL_ERR;
291                }
292                x       += z;
293                *outlen -= z;
294                break;
295
296            case LTC_ASN1_SET:
297                z = *outlen;
298                if ((err = der_encode_set(data, size, out + x, &z)) != CRYPT_OK) {
299                   goto LBL_ERR;
300                }
301                x       += z;
302                *outlen -= z;
303                break;
304
305            case LTC_ASN1_SETOF:
306                z = *outlen;
307                if ((err = der_encode_setof(data, size, out + x, &z)) != CRYPT_OK) {
308                   goto LBL_ERR;
309                }
310                x       += z;
311                *outlen -= z;
312                break;
313
314            case LTC_ASN1_SEQUENCE:
315                z = *outlen;
316                if ((err = der_encode_sequence_ex(data, size, out + x, &z, type)) != CRYPT_OK) {
317                   goto LBL_ERR;
318                }
319                x       += z;
320                *outlen -= z;
321                break;
322            
323            default:
324                err = CRYPT_INVALID_ARG;
325                goto LBL_ERR;
326        }
327    }
328    *outlen = x;
329    err = CRYPT_OK;   
330
331 LBL_ERR:
332    return err;
333 }
334
335 #endif