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