diff options
| author | beck <> | 2019-03-23 18:48:15 +0000 |
|---|---|---|
| committer | beck <> | 2019-03-23 18:48:15 +0000 |
| commit | c7b9ffc836ad7a05586d7c83c368d784af9cacda (patch) | |
| tree | 5a672c6d12222c102b5aef132ff6174f5fec66f9 | |
| parent | b45cb195c7a0d58f9ee417f6a2035faec7d3a555 (diff) | |
| download | openbsd-c7b9ffc836ad7a05586d7c83c368d784af9cacda.tar.gz openbsd-c7b9ffc836ad7a05586d7c83c368d784af9cacda.tar.bz2 openbsd-c7b9ffc836ad7a05586d7c83c368d784af9cacda.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@
Diffstat (limited to '')
| -rw-r--r-- | src/lib/libcrypto/asn1/a_int.c | 56 | ||||
| -rw-r--r-- | src/lib/libcrypto/asn1/tasn_prn.c | 8 | ||||
| -rw-r--r-- | src/lib/libcrypto/bn/bn_lib.c | 4 |
3 files changed, 62 insertions, 6 deletions
diff --git a/src/lib/libcrypto/asn1/a_int.c b/src/lib/libcrypto/asn1/a_int.c index 95d0f6dbb2..218d0b607b 100644 --- a/src/lib/libcrypto/asn1/a_int.c +++ b/src/lib/libcrypto/asn1/a_int.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: a_int.c,v 1.31 2017/01/29 17:49:22 beck Exp $ */ | 1 | /* $OpenBSD: a_int.c,v 1.32 2019/03/23 18:48:14 beck Exp $ */ |
| 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| @@ -59,13 +59,24 @@ | |||
| 59 | #include <stdio.h> | 59 | #include <stdio.h> |
| 60 | #include <string.h> | 60 | #include <string.h> |
| 61 | 61 | ||
| 62 | #include <sys/limits.h> | ||
| 63 | |||
| 62 | #include <openssl/asn1.h> | 64 | #include <openssl/asn1.h> |
| 63 | #include <openssl/bn.h> | 65 | #include <openssl/bn.h> |
| 64 | #include <openssl/err.h> | 66 | #include <openssl/err.h> |
| 65 | 67 | ||
| 68 | static int | ||
| 69 | ASN1_INTEGER_valid(const ASN1_INTEGER *a) | ||
| 70 | { | ||
| 71 | return (a != NULL && a->length >= 0); | ||
| 72 | } | ||
| 73 | |||
| 66 | ASN1_INTEGER * | 74 | ASN1_INTEGER * |
| 67 | ASN1_INTEGER_dup(const ASN1_INTEGER *x) | 75 | ASN1_INTEGER_dup(const ASN1_INTEGER *x) |
| 68 | { | 76 | { |
| 77 | if (!ASN1_INTEGER_valid(x)) | ||
| 78 | return NULL; | ||
| 79 | |||
| 69 | return ASN1_STRING_dup(x); | 80 | return ASN1_STRING_dup(x); |
| 70 | } | 81 | } |
| 71 | 82 | ||
| @@ -123,8 +134,9 @@ i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) | |||
| 123 | int pad = 0, ret, i, neg; | 134 | int pad = 0, ret, i, neg; |
| 124 | unsigned char *p, *n, pb = 0; | 135 | unsigned char *p, *n, pb = 0; |
| 125 | 136 | ||
| 126 | if (a == NULL) | 137 | if (!ASN1_INTEGER_valid(a)) |
| 127 | return (0); | 138 | return 0; |
| 139 | |||
| 128 | neg = a->type & V_ASN1_NEG; | 140 | neg = a->type & V_ASN1_NEG; |
| 129 | if (a->length == 0) | 141 | if (a->length == 0) |
| 130 | ret = 1; | 142 | ret = 1; |
| @@ -201,11 +213,24 @@ c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, long len) | |||
| 201 | } else | 213 | } else |
| 202 | ret = (*a); | 214 | ret = (*a); |
| 203 | 215 | ||
| 216 | if (!ASN1_INTEGER_valid(ret)) { | ||
| 217 | /* | ||
| 218 | * XXX using i for an alert is confusing, | ||
| 219 | * we should call this al | ||
| 220 | */ | ||
| 221 | i = ERR_R_ASN1_LENGTH_MISMATCH; | ||
| 222 | goto err; | ||
| 223 | } | ||
| 224 | |||
| 204 | p = *pp; | 225 | p = *pp; |
| 205 | pend = p + len; | 226 | pend = p + len; |
| 206 | 227 | ||
| 207 | /* We must malloc stuff, even for 0 bytes otherwise it | 228 | /* We must malloc stuff, even for 0 bytes otherwise it |
| 208 | * signifies a missing NULL parameter. */ | 229 | * signifies a missing NULL parameter. */ |
| 230 | if (len < 0 || len > INT_MAX) { | ||
| 231 | i = ERR_R_ASN1_LENGTH_MISMATCH; | ||
| 232 | goto err; | ||
| 233 | } | ||
| 209 | s = malloc(len + 1); | 234 | s = malloc(len + 1); |
| 210 | if (s == NULL) { | 235 | if (s == NULL) { |
| 211 | i = ERR_R_MALLOC_FAILURE; | 236 | i = ERR_R_MALLOC_FAILURE; |
| @@ -294,6 +319,11 @@ d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length) | |||
| 294 | } else | 319 | } else |
| 295 | ret = (*a); | 320 | ret = (*a); |
| 296 | 321 | ||
| 322 | if (!ASN1_INTEGER_valid(ret)) { | ||
| 323 | i = ERR_R_ASN1_LENGTH_MISMATCH; | ||
| 324 | goto err; | ||
| 325 | } | ||
| 326 | |||
| 297 | p = *pp; | 327 | p = *pp; |
| 298 | inf = ASN1_get_object(&p, &len, &tag, &xclass, length); | 328 | inf = ASN1_get_object(&p, &len, &tag, &xclass, length); |
| 299 | if (inf & 0x80) { | 329 | if (inf & 0x80) { |
| @@ -308,6 +338,10 @@ d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, long length) | |||
| 308 | 338 | ||
| 309 | /* We must malloc stuff, even for 0 bytes otherwise it | 339 | /* We must malloc stuff, even for 0 bytes otherwise it |
| 310 | * signifies a missing NULL parameter. */ | 340 | * signifies a missing NULL parameter. */ |
| 341 | if (len < 0 || len > INT_MAX) { | ||
| 342 | i = ERR_R_ASN1_LENGTH_MISMATCH; | ||
| 343 | goto err; | ||
| 344 | } | ||
| 311 | s = malloc(len + 1); | 345 | s = malloc(len + 1); |
| 312 | if (s == NULL) { | 346 | if (s == NULL) { |
| 313 | i = ERR_R_MALLOC_FAILURE; | 347 | i = ERR_R_MALLOC_FAILURE; |
| @@ -375,6 +409,12 @@ ASN1_INTEGER_set(ASN1_INTEGER *a, long v) | |||
| 375 | return (1); | 409 | return (1); |
| 376 | } | 410 | } |
| 377 | 411 | ||
| 412 | /* | ||
| 413 | * XXX this particular API is a gibbering eidrich horror that makes it | ||
| 414 | * impossible to determine valid return cases from errors.. "a bit | ||
| 415 | * ugly" is preserved for posterity, unfortunately this is probably | ||
| 416 | * unfixable without changing public API | ||
| 417 | */ | ||
| 378 | long | 418 | long |
| 379 | ASN1_INTEGER_get(const ASN1_INTEGER *a) | 419 | ASN1_INTEGER_get(const ASN1_INTEGER *a) |
| 380 | { | 420 | { |
| @@ -389,6 +429,9 @@ ASN1_INTEGER_get(const ASN1_INTEGER *a) | |||
| 389 | else if (i != V_ASN1_INTEGER) | 429 | else if (i != V_ASN1_INTEGER) |
| 390 | return -1; | 430 | return -1; |
| 391 | 431 | ||
| 432 | if (!ASN1_INTEGER_valid(a)) | ||
| 433 | return -1; /* XXX best effort */ | ||
| 434 | |||
| 392 | if (a->length > (int)sizeof(long)) { | 435 | if (a->length > (int)sizeof(long)) { |
| 393 | /* hmm... a bit ugly, return all ones */ | 436 | /* hmm... a bit ugly, return all ones */ |
| 394 | return -1; | 437 | return -1; |
| @@ -419,6 +462,10 @@ BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) | |||
| 419 | ASN1error(ERR_R_NESTED_ASN1_ERROR); | 462 | ASN1error(ERR_R_NESTED_ASN1_ERROR); |
| 420 | goto err; | 463 | goto err; |
| 421 | } | 464 | } |
| 465 | |||
| 466 | if (!ASN1_INTEGER_valid(ret)) | ||
| 467 | goto err; | ||
| 468 | |||
| 422 | if (BN_is_negative(bn)) | 469 | if (BN_is_negative(bn)) |
| 423 | ret->type = V_ASN1_NEG_INTEGER; | 470 | ret->type = V_ASN1_NEG_INTEGER; |
| 424 | else | 471 | else |
| @@ -453,6 +500,9 @@ ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) | |||
| 453 | { | 500 | { |
| 454 | BIGNUM *ret; | 501 | BIGNUM *ret; |
| 455 | 502 | ||
| 503 | if (!ASN1_INTEGER_valid(ai)) | ||
| 504 | return (NULL); | ||
| 505 | |||
| 456 | if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) | 506 | if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL) |
| 457 | ASN1error(ASN1_R_BN_LIB); | 507 | ASN1error(ASN1_R_BN_LIB); |
| 458 | else if (ai->type == V_ASN1_NEG_INTEGER) | 508 | else if (ai->type == V_ASN1_NEG_INTEGER) |
diff --git a/src/lib/libcrypto/asn1/tasn_prn.c b/src/lib/libcrypto/asn1/tasn_prn.c index b8f7dd5294..9fbf177ba4 100644 --- a/src/lib/libcrypto/asn1/tasn_prn.c +++ b/src/lib/libcrypto/asn1/tasn_prn.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: tasn_prn.c,v 1.17 2018/04/25 11:48:21 tb Exp $ */ | 1 | /* $OpenBSD: tasn_prn.c,v 1.18 2019/03/23 18:48:14 beck Exp $ */ |
| 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
| 3 | * project 2000. | 3 | * project 2000. |
| 4 | */ | 4 | */ |
| @@ -507,7 +507,12 @@ asn1_primitive_print(BIO *out, ASN1_VALUE **fld, const ASN1_ITEM *it, | |||
| 507 | return 0; | 507 | return 0; |
| 508 | if (pf && pf->prim_print) | 508 | if (pf && pf->prim_print) |
| 509 | return pf->prim_print(out, fld, it, indent, pctx); | 509 | return pf->prim_print(out, fld, it, indent, pctx); |
| 510 | |||
| 510 | str = (ASN1_STRING *)*fld; | 511 | str = (ASN1_STRING *)*fld; |
| 512 | |||
| 513 | if (str->length < 0) | ||
| 514 | return 0; | ||
| 515 | |||
| 511 | if (it->itype == ASN1_ITYPE_MSTRING) | 516 | if (it->itype == ASN1_ITYPE_MSTRING) |
| 512 | utype = str->type & ~V_ASN1_NEG; | 517 | utype = str->type & ~V_ASN1_NEG; |
| 513 | else | 518 | else |
| @@ -516,7 +521,6 @@ asn1_primitive_print(BIO *out, ASN1_VALUE **fld, const ASN1_ITEM *it, | |||
| 516 | ASN1_TYPE *atype = (ASN1_TYPE *)*fld; | 521 | ASN1_TYPE *atype = (ASN1_TYPE *)*fld; |
| 517 | utype = atype->type; | 522 | utype = atype->type; |
| 518 | fld = &atype->value.asn1_value; | 523 | fld = &atype->value.asn1_value; |
| 519 | str = (ASN1_STRING *)*fld; | ||
| 520 | if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE) | 524 | if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE) |
| 521 | pname = NULL; | 525 | pname = NULL; |
| 522 | else | 526 | else |
diff --git a/src/lib/libcrypto/bn/bn_lib.c b/src/lib/libcrypto/bn/bn_lib.c index 0b79a87413..0025cf52ef 100644 --- a/src/lib/libcrypto/bn/bn_lib.c +++ b/src/lib/libcrypto/bn/bn_lib.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: bn_lib.c,v 1.45 2018/07/23 18:14:32 tb Exp $ */ | 1 | /* $OpenBSD: bn_lib.c,v 1.46 2019/03/23 18:48:15 beck Exp $ */ |
| 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| @@ -578,6 +578,8 @@ BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) | |||
| 578 | BN_ULONG l; | 578 | BN_ULONG l; |
| 579 | BIGNUM *bn = NULL; | 579 | BIGNUM *bn = NULL; |
| 580 | 580 | ||
| 581 | if (len < 0) | ||
| 582 | return (NULL); | ||
| 581 | if (ret == NULL) | 583 | if (ret == NULL) |
| 582 | ret = bn = BN_new(); | 584 | ret = bn = BN_new(); |
| 583 | if (ret == NULL) | 585 | if (ret == NULL) |
