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_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