]> pd.if.org Git - zpackage/blobdiff - 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
diff --git a/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c b/libtomcrypt/src/pk/asn1/der/set/der_encode_setof.c
new file mode 100644 (file)
index 0000000..b837cdd
--- /dev/null
@@ -0,0 +1,161 @@
+/* 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.
+ */
+#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;
+   ptrdiff_t 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 = ptr - 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 = (unsigned long)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
+
+/* ref:         $Format:%D$ */
+/* git commit:  $Format:%H$ */
+/* commit time: $Format:%ai$ */