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 | |
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
-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 |