Home | History | Annotate | Download | only in choice
      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 
     13 /**
     14   @file der_decode_choice.c
     15   ASN.1 DER, decode a CHOICE, Tom St Denis
     16 */
     17 
     18 #ifdef LTC_DER
     19 
     20 /**
     21    Decode a CHOICE
     22    @param in       The DER encoded input
     23    @param inlen    [in/out] The size of the input and resulting size of read type
     24    @param list     The list of items to decode
     25    @param outlen   The number of items in the list
     26    @return CRYPT_OK on success
     27 */
     28 int der_decode_choice(const unsigned char *in,   unsigned long *inlen,
     29                             ltc_asn1_list *list, unsigned long  outlen)
     30 {
     31    unsigned long size, x, z;
     32    void          *data;
     33 
     34    LTC_ARGCHK(in    != NULL);
     35    LTC_ARGCHK(inlen != NULL);
     36    LTC_ARGCHK(list  != NULL);
     37 
     38    /* get blk size */
     39    if (*inlen < 2) {
     40       return CRYPT_INVALID_PACKET;
     41    }
     42 
     43    /* set all of the "used" flags to zero */
     44    for (x = 0; x < outlen; x++) {
     45        list[x].used = 0;
     46    }
     47 
     48    /* now scan until we have a winner */
     49    for (x = 0; x < outlen; x++) {
     50        size = list[x].size;
     51        data = list[x].data;
     52 
     53        switch (list[x].type) {
     54            case LTC_ASN1_INTEGER:
     55                if (der_decode_integer(in, *inlen, data) == CRYPT_OK) {
     56                   if (der_length_integer(data, &z) == CRYPT_OK) {
     57                       list[x].used = 1;
     58                       *inlen       = z;
     59                       return CRYPT_OK;
     60                   }
     61                }
     62                break;
     63 
     64            case LTC_ASN1_SHORT_INTEGER:
     65                if (der_decode_short_integer(in, *inlen, data) == CRYPT_OK) {
     66                   if (der_length_short_integer(size, &z) == CRYPT_OK) {
     67                       list[x].used = 1;
     68                       *inlen       = z;
     69                       return CRYPT_OK;
     70                   }
     71                }
     72                break;
     73 
     74            case LTC_ASN1_BIT_STRING:
     75                if (der_decode_bit_string(in, *inlen, data, &size) == CRYPT_OK) {
     76                   if (der_length_bit_string(size, &z) == CRYPT_OK) {
     77                      list[x].used = 1;
     78                      list[x].size = size;
     79                      *inlen       = z;
     80                      return CRYPT_OK;
     81                   }
     82                }
     83                break;
     84 
     85            case LTC_ASN1_OCTET_STRING:
     86                if (der_decode_octet_string(in, *inlen, data, &size) == CRYPT_OK) {
     87                   if (der_length_octet_string(size, &z) == CRYPT_OK) {
     88                      list[x].used = 1;
     89                      list[x].size = size;
     90                      *inlen       = z;
     91                      return CRYPT_OK;
     92                   }
     93                }
     94                break;
     95 
     96            case LTC_ASN1_NULL:
     97                if (*inlen == 2 && in[x] == 0x05 && in[x+1] == 0x00) {
     98                   *inlen = 2;
     99                   list[x].used   = 1;
    100                   return CRYPT_OK;
    101                }
    102                break;
    103 
    104            case LTC_ASN1_OBJECT_IDENTIFIER:
    105                if (der_decode_object_identifier(in, *inlen, data, &size) == CRYPT_OK) {
    106                   if (der_length_object_identifier(data, size, &z) == CRYPT_OK) {
    107                      list[x].used = 1;
    108                      list[x].size = size;
    109                      *inlen       = z;
    110                      return CRYPT_OK;
    111                   }
    112                }
    113                break;
    114 
    115            case LTC_ASN1_IA5_STRING:
    116                if (der_decode_ia5_string(in, *inlen, data, &size) == CRYPT_OK) {
    117                   if (der_length_ia5_string(data, size, &z) == CRYPT_OK) {
    118                      list[x].used = 1;
    119                      list[x].size = size;
    120                      *inlen       = z;
    121                      return CRYPT_OK;
    122                   }
    123                }
    124                break;
    125 
    126 
    127            case LTC_ASN1_PRINTABLE_STRING:
    128                if (der_decode_printable_string(in, *inlen, data, &size) == CRYPT_OK) {
    129                   if (der_length_printable_string(data, size, &z) == CRYPT_OK) {
    130                      list[x].used = 1;
    131                      list[x].size = size;
    132                      *inlen       = z;
    133                      return CRYPT_OK;
    134                   }
    135                }
    136                break;
    137 
    138            case LTC_ASN1_UTF8_STRING:
    139                if (der_decode_utf8_string(in, *inlen, data, &size) == CRYPT_OK) {
    140                   if (der_length_utf8_string(data, size, &z) == CRYPT_OK) {
    141                      list[x].used = 1;
    142                      list[x].size = size;
    143                      *inlen       = z;
    144                      return CRYPT_OK;
    145                   }
    146                }
    147                break;
    148 
    149            case LTC_ASN1_UTCTIME:
    150                z = *inlen;
    151                if (der_decode_utctime(in, &z, data) == CRYPT_OK) {
    152                   list[x].used = 1;
    153                   *inlen       = z;
    154                   return CRYPT_OK;
    155                }
    156                break;
    157 
    158            case LTC_ASN1_SET:
    159            case LTC_ASN1_SETOF:
    160            case LTC_ASN1_SEQUENCE:
    161                if (der_decode_sequence(in, *inlen, data, size) == CRYPT_OK) {
    162                   if (der_length_sequence(data, size, &z) == CRYPT_OK) {
    163                      list[x].used = 1;
    164                      *inlen       = z;
    165                      return CRYPT_OK;
    166                   }
    167                }
    168                break;
    169 
    170            default:
    171                return CRYPT_INVALID_ARG;
    172        }
    173    }
    174 
    175    return CRYPT_INVALID_PACKET;
    176 }
    177 
    178 #endif
    179 
    180 /* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/choice/der_decode_choice.c,v $ */
    181 /* $Revision: 1.8 $ */
    182 /* $Date: 2006/12/06 02:23:49 $ */
    183