diff options
author | Christos Zoulas <christos@zoulas.com> | 2016-11-07 15:51:23 +0000 |
---|---|---|
committer | Christos Zoulas <christos@zoulas.com> | 2016-11-07 15:51:23 +0000 |
commit | a6d1be7348c5decb6bdf1d35b75aed8e2652117f (patch) | |
tree | 1b10eddc110407893049ae949343ed09802be0ed | |
parent | 570a8e1083317f7452b9f024898e432bde3c124a (diff) | |
download | file-git-a6d1be7348c5decb6bdf1d35b75aed8e2652117f.tar.gz |
Fix error checking in the simple case (one digit length) of der magic.
(Jonas Wagner)
-rw-r--r-- | src/der.c | 36 |
1 files changed, 27 insertions, 9 deletions
@@ -35,7 +35,7 @@ #include "file.h" #ifndef lint -FILE_RCSID("@(#)$File: der.c,v 1.10 2016/10/24 18:02:17 christos Exp $") +FILE_RCSID("@(#)$File: der.c,v 1.11 2016/11/07 15:51:23 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 * |