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/lib/libcrypto/dsa/dsa_lib.c | |
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 '')
-rw-r--r-- | src/lib/libcrypto/dsa/dsa_lib.c | 28 |
1 files changed, 10 insertions, 18 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 | ||