diff options
| author | tb <> | 2022-08-31 13:01:01 +0000 |
|---|---|---|
| committer | tb <> | 2022-08-31 13:01:01 +0000 |
| commit | d1472daedc6c1d5786dbc4b552ac0f1ad19c65d2 (patch) | |
| tree | 8991ebe0360b3e90f90f196c1565ac3ed01531ab /src | |
| parent | 15eca26842e04912050d30a972fcce04e046da8a (diff) | |
| download | openbsd-d1472daedc6c1d5786dbc4b552ac0f1ad19c65d2.tar.gz openbsd-d1472daedc6c1d5786dbc4b552ac0f1ad19c65d2.tar.bz2 openbsd-d1472daedc6c1d5786dbc4b552ac0f1ad19c65d2.zip | |
Rework DSA_size() and ECDSA_size()
DSA_size() and ECDSA_size() have a very special hack. They fudge up an
ASN1_INTEGER with a size which is typically > 100 bytes, backed by a
buffer of size 4. This was "fine", however, since they set buf[0] = 0xff,
where the craziness that was i2c_ASN1_INTEGER() only looks at the first
octet (one may then ask why a buffer of size 4 was necessary...).
This changed with the rewrite of i2c_ASN1_INTEGER(), which doesn't
respect this particular hack and rightly assumes that it is fed an
actual ASN1_INTEGER...
Instead, create an appropriate signature and use i2d to determine its
size.
Fixes an out-of-bounds read flagged by ASAN and oss-fuzz.
ok jsing
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/dsa/dsa_lib.c | 28 | ||||
| -rw-r--r-- | src/lib/libcrypto/ecdsa/ecs_lib.c | 47 |
2 files changed, 32 insertions, 43 deletions
diff --git a/src/lib/libcrypto/dsa/dsa_lib.c b/src/lib/libcrypto/dsa/dsa_lib.c index 949722b734..da95705947 100644 --- a/src/lib/libcrypto/dsa/dsa_lib.c +++ b/src/lib/libcrypto/dsa/dsa_lib.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: dsa_lib.c,v 1.35 2022/06/27 12:28:46 tb Exp $ */ | 1 | /* $OpenBSD: dsa_lib.c,v 1.36 2022/08/31 13:01:01 tb 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 | * |
| @@ -220,23 +220,15 @@ DSA_up_ref(DSA *r) | |||
| 220 | int | 220 | int |
| 221 | DSA_size(const DSA *r) | 221 | DSA_size(const DSA *r) |
| 222 | { | 222 | { |
| 223 | int ret, i; | 223 | DSA_SIG signature; |
| 224 | ASN1_INTEGER bs; | 224 | int ret = 0; |
| 225 | unsigned char buf[4]; /* 4 bytes looks really small. | 225 | |
| 226 | However, i2d_ASN1_INTEGER() will not look | 226 | signature.r = r->q; |
| 227 | beyond the first byte, as long as the second | 227 | signature.s = r->q; |
| 228 | parameter is NULL. */ | 228 | |
| 229 | 229 | if ((ret = i2d_DSA_SIG(&signature, NULL)) < 0) | |
| 230 | i = BN_num_bits(r->q); | 230 | ret = 0; |
| 231 | bs.length = (i + 7) / 8; | 231 | |
| 232 | bs.data = buf; | ||
| 233 | bs.type = V_ASN1_INTEGER; | ||
| 234 | /* If the top bit is set the asn1 encoding is 1 larger. */ | ||
| 235 | buf[0] = 0xff; | ||
| 236 | |||
| 237 | i = i2d_ASN1_INTEGER(&bs, NULL); | ||
| 238 | i += i; /* r and s */ | ||
| 239 | ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE); | ||
| 240 | return ret; | 232 | return ret; |
| 241 | } | 233 | } |
| 242 | 234 | ||
diff --git a/src/lib/libcrypto/ecdsa/ecs_lib.c b/src/lib/libcrypto/ecdsa/ecs_lib.c index c688a95f3b..18eecba704 100644 --- a/src/lib/libcrypto/ecdsa/ecs_lib.c +++ b/src/lib/libcrypto/ecdsa/ecs_lib.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: ecs_lib.c,v 1.13 2018/04/14 07:09:21 tb Exp $ */ | 1 | /* $OpenBSD: ecs_lib.c,v 1.14 2022/08/31 13:01:01 tb Exp $ */ |
| 2 | /* ==================================================================== | 2 | /* ==================================================================== |
| 3 | * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. | 3 | * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. |
| 4 | * | 4 | * |
| @@ -197,36 +197,33 @@ ecdsa_check(EC_KEY *key) | |||
| 197 | int | 197 | int |
| 198 | ECDSA_size(const EC_KEY *r) | 198 | ECDSA_size(const EC_KEY *r) |
| 199 | { | 199 | { |
| 200 | int ret, i; | 200 | BIGNUM *order = NULL; |
| 201 | ASN1_INTEGER bs; | ||
| 202 | BIGNUM *order = NULL; | ||
| 203 | unsigned char buf[4]; | ||
| 204 | const EC_GROUP *group; | 201 | const EC_GROUP *group; |
| 202 | ECDSA_SIG signature; | ||
| 203 | int ret = 0; | ||
| 205 | 204 | ||
| 206 | if (r == NULL) | 205 | if (r == NULL) |
| 207 | return 0; | 206 | goto err; |
| 208 | group = EC_KEY_get0_group(r); | 207 | |
| 209 | if (group == NULL) | 208 | if ((group = EC_KEY_get0_group(r)) == NULL) |
| 210 | return 0; | 209 | goto err; |
| 211 | 210 | ||
| 212 | if ((order = BN_new()) == NULL) | 211 | if ((order = BN_new()) == NULL) |
| 213 | return 0; | 212 | goto err; |
| 214 | if (!EC_GROUP_get_order(group, order, NULL)) { | 213 | |
| 215 | BN_clear_free(order); | 214 | if (!EC_GROUP_get_order(group, order, NULL)) |
| 216 | return 0; | 215 | goto err; |
| 217 | } | 216 | |
| 218 | i = BN_num_bits(order); | 217 | signature.r = order; |
| 219 | bs.length = (i + 7) / 8; | 218 | signature.s = order; |
| 220 | bs.data = buf; | 219 | |
| 221 | bs.type = V_ASN1_INTEGER; | 220 | if ((ret = i2d_ECDSA_SIG(&signature, NULL)) < 0) |
| 222 | /* If the top bit is set the asn1 encoding is 1 larger. */ | 221 | ret = 0; |
| 223 | buf[0] = 0xff; | 222 | |
| 224 | 223 | err: | |
| 225 | i = i2d_ASN1_INTEGER(&bs, NULL); | ||
| 226 | i += i; /* r and s */ | ||
| 227 | ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE); | ||
| 228 | BN_clear_free(order); | 224 | BN_clear_free(order); |
| 229 | return (ret); | 225 | |
| 226 | return ret; | ||
| 230 | } | 227 | } |
| 231 | 228 | ||
| 232 | int | 229 | int |
