summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortb <>2022-08-31 13:01:01 +0000
committertb <>2022-08-31 13:01:01 +0000
commitd1472daedc6c1d5786dbc4b552ac0f1ad19c65d2 (patch)
tree8991ebe0360b3e90f90f196c1565ac3ed01531ab /src
parent15eca26842e04912050d30a972fcce04e046da8a (diff)
downloadopenbsd-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.c28
-rw-r--r--src/lib/libcrypto/ecdsa/ecs_lib.c47
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)
220int 220int
221DSA_size(const DSA *r) 221DSA_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)
197int 197int
198ECDSA_size(const EC_KEY *r) 198ECDSA_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
232int 229int