summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbeck <beck@openbsd.org>2019-03-23 18:48:14 +0000
committerbeck <beck@openbsd.org>2019-03-23 18:48:14 +0000
commitd42c39d7dcd16264d356dbe3a92eaeee6af3d708 (patch)
tree5a7950e76426edec587661639efe07228d46c471
parentRemove useless secure_path(3) calls. (diff)
downloadwireguard-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.c56
-rw-r--r--lib/libcrypto/asn1/tasn_prn.c8
-rw-r--r--lib/libcrypto/bn/bn_lib.c4
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)