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 (at) 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 336