summaryrefslogtreecommitdiff
path: root/der-iterator.c
diff options
context:
space:
mode:
authorNiels Möller <nisse@lysator.liu.se>2005-11-20 18:02:26 +0100
committerNiels Möller <nisse@lysator.liu.se>2005-11-20 18:02:26 +0100
commit5c5e545d48a581ba7485ef761222ea17d9b9dbbc (patch)
tree6b4074e583616a869e39787ad45222a0c4bd5931 /der-iterator.c
parentceb433facf7b22377744c9d51bc2cc30df9f4c58 (diff)
downloadnettle-5c5e545d48a581ba7485ef761222ea17d9b9dbbc.tar.gz
(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
Diffstat (limited to 'der-iterator.c')
-rw-r--r--der-iterator.c66
1 files 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;