From 5c5e545d48a581ba7485ef761222ea17d9b9dbbc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niels=20M=C3=B6ller?= <nisse@lysator.liu.se>
Date: Sun, 20 Nov 2005 18:02:26 +0100
Subject: [PATCH] (asn1_der_iterator_init): Initialize length and data.
 (asn1_der_iterator_next): Support for lengths >= 0x80.
 (asn1_der_decode_constructed_last, asn1_der_decode_bitstring)
 (asn1_der_decode_bitstring_last): New functions. (asn1_der_get_bignum): Check
 for non-mininal encodings.

Rev: src/nettle/der-iterator.c:1.2
---
 der-iterator.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 63 insertions(+), 3 deletions(-)

diff --git a/der-iterator.c b/der-iterator.c
index 4a7961c9..f137c446 100644
--- a/der-iterator.c
+++ b/der-iterator.c
@@ -28,6 +28,7 @@
 #endif
 
 #include <assert.h>
+#include <stdlib.h>
 
 #if HAVE_LIBGMP
 #include "bignum.h"
@@ -66,7 +67,7 @@
     _________________
    |_1_|___________k_|
 
-   followed by k additional bytes that gice the length, in network
+   followed by k additional bytes that give the length, in network
    byte order. The length must be encoded using as few bytes as
    possible, and k = 0 is reserved for the "indefinite length form"
    which is not supported.
@@ -92,6 +93,8 @@ asn1_der_iterator_init(struct asn1_der_iterator *iterator,
   iterator->buffer = input;
   iterator->pos = 0;
   iterator->type = 0;
+  iterator->length = 0;
+  iterator->data = NULL;
 }
 
 #define LEFT(i) ((i)->buffer_length - (i)->pos)
@@ -119,8 +122,28 @@ asn1_der_iterator_next(struct asn1_der_iterator *i)
   i->length = NEXT(i);
   if (i->length & 0x80)
     {
-      /* FIXME: Large objects not yet supported. */
-      return ASN1_ITERATOR_ERROR;
+      unsigned k = i->length & 0x7f;
+      unsigned j;
+      const uint8_t *data = i->buffer + i->pos;
+      
+      if (k == 0)
+	/* Indefinite encoding. Not supported. */
+	return ASN1_ITERATOR_ERROR;
+
+      if (LEFT(i) < k)
+	return ASN1_ITERATOR_ERROR;
+
+      if (k > sizeof(unsigned))
+	return ASN1_ITERATOR_ERROR;
+
+      i->pos += k;
+      i->length = data[0];
+      if (i->length == 0
+	  || (k == 1 && i->length < 0x80))
+	return ASN1_ITERATOR_ERROR;
+
+      for (j = 1; j < k; j++)
+	i->length = (i->length << 8) | data[j];
     }
   if (LEFT(i) < i->length)
     return ASN1_ITERATOR_ERROR;
@@ -155,6 +178,37 @@ asn1_der_decode_constructed(struct asn1_der_iterator *i,
   return asn1_der_iterator_first(contents, i->length, i->data);
 }
 
+enum asn1_iterator_result
+asn1_der_decode_constructed_last(struct asn1_der_iterator *i)
+{
+  if (LEFT(i) > 0)
+    return ASN1_ITERATOR_ERROR;
+
+  return asn1_der_decode_constructed(i, i);
+}
+
+/* Decoding a DER object which is wrapped in a bit string. */
+enum asn1_iterator_result
+asn1_der_decode_bitstring(struct asn1_der_iterator *i,
+			  struct asn1_der_iterator *contents)
+{
+  assert(i->type == ASN1_BITSTRING);
+  /* First byte is the number of padding bits, which must be zero. */
+  if (i->length == 0  || i->data[0] != 0)
+    return ASN1_ITERATOR_ERROR;
+
+  return asn1_der_iterator_first(contents, i->length - 1, i->data + 1);
+}
+
+enum asn1_iterator_result
+asn1_der_decode_bitstring_last(struct asn1_der_iterator *i)
+{
+  if (LEFT(i) > 0)
+    return ASN1_ITERATOR_ERROR;
+
+  return asn1_der_decode_bitstring(i, i);
+}
+
 int
 asn1_der_get_uint32(struct asn1_der_iterator *i,
 		    uint32_t *x)
@@ -197,6 +251,12 @@ int
 asn1_der_get_bignum(struct asn1_der_iterator *i,
 		    mpz_t x, unsigned limit)
 {
+  if (i->length > 1
+      && ((i->data[0] == 0 && i->data[1] < 0x80)
+	  || (i->data[0] == 0xff && i->data[1] >= 0x80)))
+    /* Non-minimal number of digits */
+    return 0;
+
   /* Allow some extra here, for leading sign octets. */
   if (limit && (8 * i->length > (16 + limit)))
     return 0;
-- 
GitLab