Home | History | Annotate | Download | only in sequence
      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_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 */
     31 int 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 
    279 LBL_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