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