blob: 6c12eb46f64f34716dced58d0741111700b9c185 [file] [log] [blame]
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
*/
#include "tomcrypt.h"
/**
@file der_encode_setof.c
ASN.1 DER, Encode SET OF, Tom St Denis
*/
#ifdef LTC_DER
struct edge {
unsigned char *start;
unsigned long size;
};
static int qsort_helper(const void *a, const void *b)
{
struct edge *A = (struct edge *)a, *B = (struct edge *)b;
int r;
unsigned long x;
/* compare min length */
r = XMEMCMP(A->start, B->start, MIN(A->size, B->size));
if (r == 0 && A->size != B->size) {
if (A->size > B->size) {
for (x = B->size; x < A->size; x++) {
if (A->start[x]) {
return 1;
}
}
} else {
for (x = A->size; x < B->size; x++) {
if (B->start[x]) {
return -1;
}
}
}
}
return r;
}
/**
Encode a SETOF stucture
@param list The list of items to encode
@param inlen The number of items in the list
@param out [out] The destination
@param outlen [in/out] The size of the output
@return CRYPT_OK on success
*/
int der_encode_setof(ltc_asn1_list *list, unsigned long inlen,
unsigned char *out, unsigned long *outlen)
{
unsigned long x, y, z, hdrlen;
int err;
struct edge *edges;
unsigned char *ptr, *buf;
/* check that they're all the same type */
for (x = 1; x < inlen; x++) {
if (list[x].type != list[x-1].type) {
return CRYPT_INVALID_ARG;
}
}
/* alloc buffer to store copy of output */
buf = XCALLOC(1, *outlen);
if (buf == NULL) {
return CRYPT_MEM;
}
/* encode list */
if ((err = der_encode_sequence_ex(list, inlen, buf, outlen, LTC_ASN1_SETOF)) != CRYPT_OK) {
XFREE(buf);
return err;
}
/* allocate edges */
edges = XCALLOC(inlen, sizeof(*edges));
if (edges == NULL) {
XFREE(buf);
return CRYPT_MEM;
}
/* skip header */
ptr = buf + 1;
/* now skip length data */
x = *ptr++;
if (x >= 0x80) {
ptr += (x & 0x7F);
}
/* get the size of the static header */
hdrlen = ((unsigned long)ptr) - ((unsigned long)buf);
/* scan for edges */
x = 0;
while (ptr < (buf + *outlen)) {
/* store start */
edges[x].start = ptr;
/* skip type */
z = 1;
/* parse length */
y = ptr[z++];
if (y < 128) {
edges[x].size = y;
} else {
y &= 0x7F;
edges[x].size = 0;
while (y--) {
edges[x].size = (edges[x].size << 8) | ((unsigned long)ptr[z++]);
}
}
/* skip content */
edges[x].size += z;
ptr += edges[x].size;
++x;
}
/* sort based on contents (using edges) */
XQSORT(edges, inlen, sizeof(*edges), &qsort_helper);
/* copy static header */
XMEMCPY(out, buf, hdrlen);
/* copy+sort using edges+indecies to output from buffer */
for (y = hdrlen, x = 0; x < inlen; x++) {
XMEMCPY(out+y, edges[x].start, edges[x].size);
y += edges[x].size;
}
#ifdef LTC_CLEAN_STACK
zeromem(buf, *outlen);
#endif
/* free buffers */
XFREE(edges);
XFREE(buf);
return CRYPT_OK;
}
#endif
/* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c,v $ */
/* $Revision: 1.11 $ */
/* $Date: 2006/03/31 14:15:35 $ */