Home | History | Annotate | Download | only in set
      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_encode_setof.c
     15   ASN.1 DER, Encode SET OF, Tom St Denis
     16 */
     17 
     18 #ifdef LTC_DER
     19 
     20 struct edge {
     21    unsigned char *start;
     22    unsigned long  size;
     23 };
     24 
     25 static int qsort_helper(const void *a, const void *b)
     26 {
     27    struct edge   *A = (struct edge *)a, *B = (struct edge *)b;
     28    int            r;
     29    unsigned long  x;
     30 
     31    /* compare min length */
     32    r = XMEMCMP(A->start, B->start, MIN(A->size, B->size));
     33 
     34    if (r == 0 && A->size != B->size) {
     35       if (A->size > B->size) {
     36          for (x = B->size; x < A->size; x++) {
     37             if (A->start[x]) {
     38                return 1;
     39             }
     40          }
     41       } else {
     42          for (x = A->size; x < B->size; x++) {
     43             if (B->start[x]) {
     44                return -1;
     45             }
     46          }
     47       }
     48    }
     49 
     50    return r;
     51 }
     52 
     53 /**
     54    Encode a SETOF stucture
     55    @param list      The list of items to encode
     56    @param inlen     The number of items in the list
     57    @param out       [out] The destination
     58    @param outlen    [in/out] The size of the output
     59    @return CRYPT_OK on success
     60 */
     61 int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
     62                      unsigned char *out,  unsigned long *outlen)
     63 {
     64    unsigned long  x, y, z, hdrlen;
     65    int            err;
     66    struct edge   *edges;
     67    unsigned char *ptr, *buf;
     68 
     69    /* check that they're all the same type */
     70    for (x = 1; x < inlen; x++) {
     71       if (list[x].type != list[x-1].type) {
     72          return CRYPT_INVALID_ARG;
     73       }
     74    }
     75 
     76    /* alloc buffer to store copy of output */
     77    buf = XCALLOC(1, *outlen);
     78    if (buf == NULL) {
     79       return CRYPT_MEM;
     80    }
     81 
     82    /* encode list */
     83    if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) {
     84        XFREE(buf);
     85        return err;
     86    }
     87 
     88    /* allocate edges */
     89    edges = XCALLOC(inlen, sizeof(*edges));
     90    if (edges == NULL) {
     91       XFREE(buf);
     92       return CRYPT_MEM;
     93    }
     94 
     95    /* skip header */
     96       ptr = buf + 1;
     97 
     98       /* now skip length data */
     99       x = *ptr++;
    100       if (x >= 0x80) {
    101          ptr += (x & 0x7F);
    102       }
    103 
    104       /* get the size of the static header */
    105       hdrlen = ((unsigned long)ptr) - ((unsigned long)buf);
    106 
    107 
    108    /* scan for edges */
    109    x = 0;
    110    while (ptr < (buf + *outlen)) {
    111       /* store start */
    112       edges[x].start = ptr;
    113 
    114       /* skip type */
    115       z = 1;
    116 
    117       /* parse length */
    118       y = ptr[z++];
    119       if (y < 128) {
    120          edges[x].size = y;
    121       } else {
    122          y &= 0x7F;
    123          edges[x].size = 0;
    124          while (y--) {
    125             edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]);
    126          }
    127       }
    128 
    129       /* skip content */
    130       edges[x].size += z;
    131       ptr           += edges[x].size;
    132       ++x;
    133    }
    134 
    135    /* sort based on contents (using edges) */
    136    XQSORT(edges, inlen, sizeof(*edges), &qsort_helper);
    137 
    138    /* copy static header */
    139    XMEMCPY(out, buf, hdrlen);
    140 
    141    /* copy+sort using edges+indecies to output from buffer */
    142    for (y = hdrlen, x = 0; x < inlen; x++) {
    143       XMEMCPY(out+y, edges[x].start, edges[x].size);
    144       y += edges[x].size;
    145    }
    146 
    147 #ifdef LTC_CLEAN_STACK
    148    zeromem(buf, *outlen);
    149 #endif
    150 
    151    /* free buffers */
    152    XFREE(edges);
    153    XFREE(buf);
    154 
    155    return CRYPT_OK;
    156 }
    157 
    158 #endif
    159 
    160 /* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c,v $ */
    161 /* $Revision: 1.11 $ */
    162 /* $Date: 2006/03/31 14:15:35 $ */
    163