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