version 0.3.33
[fms.git] / libs / libtomcrypt / pk / asn1 / der / set / der_encode_setof.c
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
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 $ */