diff options
author | 2019-03-23 18:48:14 +0000 | |
---|---|---|
committer | 2019-03-23 18:48:14 +0000 | |
commit | d42c39d7dcd16264d356dbe3a92eaeee6af3d708 (patch) | |
tree | 5a7950e76426edec587661639efe07228d46c471 | |
parent | Remove useless secure_path(3) calls. (diff) | |
download | wireguard-openbsd-d42c39d7dcd16264d356dbe3a92eaeee6af3d708.tar.xz wireguard-openbsd-d42c39d7dcd16264d356dbe3a92eaeee6af3d708.zip |
Add range checks to varios ASN1_INTEGER functions to ensure the
sizes used remain a positive integer. Should address issue
13799 from oss-fuzz
ok tb@ jsing@
-rw-r--r-- | lib/libcrypto/asn1/a_int.c | 56 | ||||
-rw-r--r-- | lib/libcrypto/asn1/tasn_prn.c | 8 | ||||
-rw-r--r-- | lib/libcrypto/bn/bn_lib.c | 4 |
3 files changed, 62 insertions, 6 deletions
diff --git a/lib/libcrypto/asn1/a_int.c b/lib/libcrypto/asn1/a_int.c index 95d0f6dbb28..218d0b607bb 100644 --- a/lib/libcrypto/asn1/a_int.c +++ b/lib/libcrypto/asn1/a_int.c @@ -1,4 +1,4 @@ -/* $OpenBSD: a_int.c,v 1.31 2017/01/29 17:49:22 beck Exp $ */ +/* $OpenBSD: a_int.c,v 1.32 2019/03/23 18:48:14 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -59,13 +59,24 @@ #include <stdio.h> #include <string.h> +#include <sys/limits.h> + #include <openssl/asn1.h> #include <openssl/bn.h> #include <openssl/err.h> +static int +ASN1_INTEGER_valid(const ASN1_INTEGER *a) +{ + return (a != NULL && a->length >= 0); +} + ASN1_INTEGER * ASN1_INTEGER_dup(const ASN1_INTEGER *x) { + if (!ASN1_INTEGER_valid(x)) + return NULL; + return ASN1_STRING_dup(x); } @@ -123,8 +134,9 @@ i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) int pad = 0, ret, i, neg; unsigned char *p, *n, pb = 0; - if (a == NULL) - return (0); + if (!ASN1_INTEGER_valid(a)) + return 0; + neg = a->type & V_ASN1_NEG; if (a->length == 0) ret = 1; @@ -201,11 +213,24 @@ c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, long len) } else ret = (*a); + if (!ASN1_INTEGER_valid(ret)) { + /* + * XXX using i for an alert is confusing, + * we should call this al + */ + i = ERR_R_ASN1_LENGTH_MISMATCH; + goto err; + } + p = *pp; pend = p + len; /* We must malloc stuff, even for 0 bytes otherwise it * signifies a missing NULL parameter. */ + if (len < 0 || len > INT_MAX) { + i = ERR_R_ASN1_LENGTH_MISMATCH; + goto err; + } s = malloc(len + 1); if (s == NULL) { i = ERR_R_MALLOC_FAILURE; @@ -294,6 +319,11 @@ d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length) } else ret = (*a); + if (!ASN1_INTEGER_valid(ret)) { + i = ERR_R_ASN1_LENGTH_MISMATCH; + goto err; + } + p = *pp; inf = ASN1_get_object(&p, &len, &tag, &xclass, length); if (inf & 0x80) { @@ -308,6 +338,10 @@ d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length) /* We must malloc stuff, even for 0 bytes otherwise it * signifies a missing NULL parameter. */ + if (len < 0 || len > INT_MAX) { + i = ERR_R_ASN1_LENGTH_MISMATCH; + goto err; + } s = malloc(len + 1); if (s == NULL) { i = ERR_R_MALLOC_FAILURE; @@ -375,6 +409,12 @@ ASN1_INTEGER_set(ASN1_INTEGER *a, long v) return (1); } +/* + * XXX this particular API is a gibbering eidrich horror that makes it + * impossible to determine valid return cases from errors.. "a bit + * ugly" is preserved for posterity, unfortunately this is probably + * unfixable without changing public API + */ long ASN1_INTEGER_get(const ASN1_INTEGER *a) { @@ -389,6 +429,9 @@ ASN1_INTEGER_get(const ASN1_INTEGER *a) else if (i != V_ASN1_INTEGER) return -1; + if (!ASN1_INTEGER_valid(a)) + return -1; /* XXX best effort */ + if (a->length > (int)sizeof(long)) { /* hmm... a bit ugly, return all ones */ return -1; @@ -419,6 +462,10 @@ BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) ASN1error(ERR_R_NESTED_ASN1_ERROR); goto err; } + + if (!ASN1_INTEGER_valid(ret)) + goto err; + if (BN_is_negative(bn)) ret->type = V_ASN1_NEG_INTEGER; else @@ -453,6 +500,9 @@ ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) { BIGNUM *ret; + if (!ASN1_INTEGER_valid(ai)) + return (NULL); + if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) ASN1error(ASN1_R_BN_LIB); else if (ai->type == V_ASN1_NEG_INTEGER) diff --git a/lib/libcrypto/asn1/tasn_prn.c b/lib/libcrypto/asn1/tasn_prn.c index b8f7dd52942..9fbf177ba4c 100644 --- a/lib/libcrypto/asn1/tasn_prn.c +++ b/lib/libcrypto/asn1/tasn_prn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tasn_prn.c,v 1.17 2018/04/25 11:48:21 tb Exp $ */ +/* $OpenBSD: tasn_prn.c,v 1.18 2019/03/23 18:48:14 beck Exp $ */ /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL * project 2000. */ @@ -507,7 +507,12 @@ asn1_primitive_print(BIO *out, ASN1_VALUE **fld, const ASN1_ITEM *it, return 0; if (pf && pf->prim_print) return pf->prim_print(out, fld, it, indent, pctx); + str = (ASN1_STRING *)*fld; + + if (str->length < 0) + return 0; + if (it->itype == ASN1_ITYPE_MSTRING) utype = str->type & ~V_ASN1_NEG; else @@ -516,7 +521,6 @@ asn1_primitive_print(BIO *out, ASN1_VALUE **fld, const ASN1_ITEM *it, ASN1_TYPE *atype = (ASN1_TYPE *)*fld; utype = atype->type; fld = &atype->value.asn1_value; - str = (ASN1_STRING *)*fld; if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE) pname = NULL; else diff --git a/lib/libcrypto/bn/bn_lib.c b/lib/libcrypto/bn/bn_lib.c index 0b79a874134..0025cf52ef1 100644 --- a/lib/libcrypto/bn/bn_lib.c +++ b/lib/libcrypto/bn/bn_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bn_lib.c,v 1.45 2018/07/23 18:14:32 tb Exp $ */ +/* $OpenBSD: bn_lib.c,v 1.46 2019/03/23 18:48:15 beck Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -578,6 +578,8 @@ BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) BN_ULONG l; BIGNUM *bn = NULL; + if (len < 0) + return (NULL); if (ret == NULL) ret = bn = BN_new(); if (ret == NULL) |