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_decode_sequence_ex.c 17 ASN.1 DER, decode a SEQUENCE, Tom St Denis 18*/ 19 20#ifdef LTC_DER 21 22/** 23 Decode a SEQUENCE 24 @param in The DER encoded input 25 @param inlen The size of the input 26 @param list The list of items to decode 27 @param outlen The number of items in the list 28 @param ordered Search an unordeded or ordered list 29 @return CRYPT_OK on success 30*/ 31int der_decode_sequence_ex(const unsigned char *in, unsigned long inlen, 32 ltc_asn1_list *list, unsigned long outlen, int ordered) 33{ 34 int err, type; 35 unsigned long size, x, y, z, i, blksize; 36 void *data; 37 38 LTC_ARGCHK(in != NULL); 39 LTC_ARGCHK(list != NULL); 40 41 /* get blk size */ 42 if (inlen < 2) { 43 return CRYPT_INVALID_PACKET; 44 } 45 46 /* sequence type? We allow 0x30 SEQUENCE and 0x31 SET since fundamentally they're the same structure */ 47 x = 0; 48 if (in[x] != 0x30 && in[x] != 0x31) { 49 return CRYPT_INVALID_PACKET; 50 } 51 ++x; 52 53 if (in[x] < 128) { 54 blksize = in[x++]; 55 } else if (in[x] & 0x80) { 56 if (in[x] < 0x81 || in[x] > 0x83) { 57 return CRYPT_INVALID_PACKET; 58 } 59 y = in[x++] & 0x7F; 60 61 /* would reading the len bytes overrun? */ 62 if (x + y > inlen) { 63 return CRYPT_INVALID_PACKET; 64 } 65 66 /* read len */ 67 blksize = 0; 68 while (y--) { 69 blksize = (blksize << 8) | (unsigned long)in[x++]; 70 } 71 } 72 73 /* would this blksize overflow? */ 74 if (x + blksize > inlen) { 75 return CRYPT_INVALID_PACKET; 76 } 77 78 /* mark all as unused */ 79 for (i = 0; i < outlen; i++) { 80 list[i].used = 0; 81 } 82 83 /* ok read data */ 84 inlen = blksize; 85 for (i = 0; i < outlen; i++) { 86 z = 0; 87 type = list[i].type; 88 size = list[i].size; 89 data = list[i].data; 90 if (!ordered && list[i].used == 1) { continue; } 91 92 if (type == LTC_ASN1_EOL) { 93 break; 94 } 95 96 switch (type) { 97 case LTC_ASN1_BOOLEAN: 98 z = inlen; 99 if ((err = der_decode_boolean(in + x, z, ((int *)data))) != CRYPT_OK) { 100 goto LBL_ERR; 101 } 102 if ((err = der_length_boolean(&z)) != CRYPT_OK) { 103 goto LBL_ERR; 104 } 105 break; 106 107 case LTC_ASN1_INTEGER: 108 z = inlen; 109 if ((err = der_decode_integer(in + x, z, data)) != CRYPT_OK) { 110 if (!ordered) { continue; } 111 goto LBL_ERR; 112 } 113 if ((err = der_length_integer(data, &z)) != CRYPT_OK) { 114 goto LBL_ERR; 115 } 116 break; 117 118 case LTC_ASN1_SHORT_INTEGER: 119 z = inlen; 120 if ((err = der_decode_short_integer(in + x, z, data)) != CRYPT_OK) { 121 if (!ordered) { continue; } 122 goto LBL_ERR; 123 } 124 if ((err = der_length_short_integer(((unsigned long*)data)[0], &z)) != CRYPT_OK) { 125 goto LBL_ERR; 126 } 127 128 break; 129 130 case LTC_ASN1_BIT_STRING: 131 z = inlen; 132 if ((err = der_decode_bit_string(in + x, z, data, &size)) != CRYPT_OK) { 133 if (!ordered) { continue; } 134 goto LBL_ERR; 135 } 136 list[i].size = size; 137 if ((err = der_length_bit_string(size, &z)) != CRYPT_OK) { 138 goto LBL_ERR; 139 } 140 break; 141 142 case LTC_ASN1_OCTET_STRING: 143 z = inlen; 144 if ((err = der_decode_octet_string(in + x, z, data, &size)) != CRYPT_OK) { 145 if (!ordered) { continue; } 146 goto LBL_ERR; 147 } 148 list[i].size = size; 149 if ((err = der_length_octet_string(size, &z)) != CRYPT_OK) { 150 goto LBL_ERR; 151 } 152 break; 153 154 case LTC_ASN1_NULL: 155 if (inlen < 2 || in[x] != 0x05 || in[x+1] != 0x00) { 156 if (!ordered) { continue; } 157 err = CRYPT_INVALID_PACKET; 158 goto LBL_ERR; 159 } 160 z = 2; 161 break; 162 163 case LTC_ASN1_OBJECT_IDENTIFIER: 164 z = inlen; 165 if ((err = der_decode_object_identifier(in + x, z, data, &size)) != CRYPT_OK) { 166 if (!ordered) { continue; } 167 goto LBL_ERR; 168 } 169 list[i].size = size; 170 if ((err = der_length_object_identifier(data, size, &z)) != CRYPT_OK) { 171 goto LBL_ERR; 172 } 173 break; 174 175 case LTC_ASN1_IA5_STRING: 176 z = inlen; 177 if ((err = der_decode_ia5_string(in + x, z, data, &size)) != CRYPT_OK) { 178 if (!ordered) { continue; } 179 goto LBL_ERR; 180 } 181 list[i].size = size; 182 if ((err = der_length_ia5_string(data, size, &z)) != CRYPT_OK) { 183 goto LBL_ERR; 184 } 185 break; 186 187 188 case LTC_ASN1_PRINTABLE_STRING: 189 z = inlen; 190 if ((err = der_decode_printable_string(in + x, z, data, &size)) != CRYPT_OK) { 191 if (!ordered) { continue; } 192 goto LBL_ERR; 193 } 194 list[i].size = size; 195 if ((err = der_length_printable_string(data, size, &z)) != CRYPT_OK) { 196 goto LBL_ERR; 197 } 198 break; 199 200 case LTC_ASN1_UTF8_STRING: 201 z = inlen; 202 if ((err = der_decode_utf8_string(in + x, z, data, &size)) != CRYPT_OK) { 203 if (!ordered) { continue; } 204 goto LBL_ERR; 205 } 206 list[i].size = size; 207 if ((err = der_length_utf8_string(data, size, &z)) != CRYPT_OK) { 208 goto LBL_ERR; 209 } 210 break; 211 212 case LTC_ASN1_UTCTIME: 213 z = inlen; 214 if ((err = der_decode_utctime(in + x, &z, data)) != CRYPT_OK) { 215 if (!ordered) { continue; } 216 goto LBL_ERR; 217 } 218 break; 219 220 case LTC_ASN1_SET: 221 z = inlen; 222 if ((err = der_decode_set(in + x, z, data, size)) != CRYPT_OK) { 223 if (!ordered) { continue; } 224 goto LBL_ERR; 225 } 226 if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { 227 goto LBL_ERR; 228 } 229 break; 230 231 case LTC_ASN1_SETOF: 232 case LTC_ASN1_SEQUENCE: 233 /* detect if we have the right type */ 234 if ((type == LTC_ASN1_SETOF && (in[x] & 0x3F) != 0x31) || (type == LTC_ASN1_SEQUENCE && (in[x] & 0x3F) != 0x30)) { 235 err = CRYPT_INVALID_PACKET; 236 goto LBL_ERR; 237 } 238 239 z = inlen; 240 if ((err = der_decode_sequence(in + x, z, data, size)) != CRYPT_OK) { 241 if (!ordered) { continue; } 242 goto LBL_ERR; 243 } 244 if ((err = der_length_sequence(data, size, &z)) != CRYPT_OK) { 245 goto LBL_ERR; 246 } 247 break; 248 249 250 case LTC_ASN1_CHOICE: 251 z = inlen; 252 if ((err = der_decode_choice(in + x, &z, data, size)) != CRYPT_OK) { 253 if (!ordered) { continue; } 254 goto LBL_ERR; 255 } 256 break; 257 258 default: 259 err = CRYPT_INVALID_ARG; 260 goto LBL_ERR; 261 } 262 x += z; 263 inlen -= z; 264 list[i].used = 1; 265 if (!ordered) { 266 /* restart the decoder */ 267 i = -1; 268 } 269 } 270 271 for (i = 0; i < outlen; i++) { 272 if (list[i].used == 0) { 273 err = CRYPT_INVALID_PACKET; 274 goto LBL_ERR; 275 } 276 } 277 err = CRYPT_OK; 278 279LBL_ERR: 280 return err; 281} 282 283#endif 284 285/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/sequence/der_decode_sequence_ex.c,v $ */ 286/* $Revision: 1.15 $ */ 287/* $Date: 2006/11/26 02:25:18 $ */ 288