diff libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c @ 382:0cbe8f6dbf9e

propagate from branch 'au.asn.ucc.matt.ltc.dropbear' (head 2af22fb4e878750b88f80f90d439b316d229796f) to branch 'au.asn.ucc.matt.dropbear' (head 02c413252c90e9de8e03d91e9939dde3029f5c0a)
author Matt Johnston <matt@ucc.asn.au>
date Thu, 11 Jan 2007 02:41:05 +0000
parents
children f849a5ca2efc
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c	Thu Jan 11 02:41:05 2007 +0000
@@ -0,0 +1,162 @@
+/* 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, [email protected], 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 $ */