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