From 0e93a47b7feaee1d3a0f1b14e40f0ead17d8ccd4 Mon Sep 17 00:00:00 2001 From: Christos Zoulas Date: Mon, 7 Nov 2016 15:51:23 +0000 Subject: [PATCH] Fix error checking in the simple case (one digit length) of der magic. (Jonas Wagner) --- src/der.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/der.c b/src/der.c index ee7a7aec..fbb5d838 100644 --- a/src/der.c +++ b/src/der.c @@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: der.c,v 1.9 2016/10/24 15:19:08 christos Exp $") +FILE_RCSID("@(#)$File: der.c,v 1.10 2016/10/24 18:02:17 christos Exp $") #endif #endif @@ -159,31 +159,49 @@ gettag(const uint8_t *c, size_t *p, size_t l) return tag; } +/* + * Read the length of a DER tag from the input. + * + * `c` is the input, `p` is an output parameter that specifies how much of the + * input we consumed, and `l` is the maximum input length. + * + * Returns the length, or DER_BAD if the end of the input is reached or the + * length exceeds the remaining input. + */ static uint32_t getlength(const uint8_t *c, size_t *p, size_t l) { uint8_t digits, i; size_t len; + int is_onebyte_result; if (*p >= l) return DER_BAD; - digits = c[(*p)++]; + /* + * Digits can either be 0b0 followed by the result, or 0b1 + * followed by the number of digits of the result. In either case, + * we verify that we can read so many bytes from the input. + */ + is_onebyte_result = (c[*p] & 0x80) == 0; + digits = c[(*p)++] & 0x7f; + if (*p + digits >= l) + return DER_BAD; - if ((digits & 0x80) == 0) + if (is_onebyte_result) return digits; - digits &= 0x7f; + /* + * Decode len. We've already verified that we're allowed to read + * `digits` bytes. + */ len = 0; - - if (*p + digits >= l) - return DER_BAD; - for (i = 0; i < digits; i++) len = (len << 8) | c[(*p)++]; + if (*p + len >= l) return DER_BAD; - return len; + return len; } static const char * -- 2.49.0