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