Skip to content

Commit a81246e

Browse files
author
tb
committed
Avoid infinite loop on parsing DSA private keys
DSA private keys with ill-chosen g could cause an infinite loop on deserializing. Add a few sanity checks that ensure that g is according to the FIPS 186-4: check 1 < g < p and g^q == 1 (mod p). This is enough to ascertain that g is a generator of a multiplicative group of order q once we know that q is prime (which is checked a bit later). Issue reported with reproducers by Hanno Boeck. Additional variants and analysis by David Benjamin. ok beck jsing
1 parent 988c9bc commit a81246e

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

src/lib/libcrypto/dsa/dsa_ameth.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* $OpenBSD: dsa_ameth.c,v 1.34 2022/02/24 21:07:03 tb Exp $ */
1+
/* $OpenBSD: dsa_ameth.c,v 1.35 2022/04/07 17:38:24 tb Exp $ */
22
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
33
* project 2006.
44
*/
@@ -479,7 +479,7 @@ old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
479479
{
480480
DSA *dsa;
481481
BN_CTX *ctx = NULL;
482-
BIGNUM *j, *p1, *newp1;
482+
BIGNUM *j, *p1, *newp1, *powg;
483483
int qbits;
484484

485485
if (!(dsa = d2i_DSAPrivateKey(NULL, pder, derlen))) {
@@ -498,6 +498,13 @@ old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
498498
goto err;
499499
}
500500

501+
/* Check that 1 < g < p. */
502+
if (BN_cmp(dsa->g, BN_value_one()) <= 0 ||
503+
BN_cmp(dsa->g, dsa->p) >= 0) {
504+
DSAerror(DSA_R_PARAMETER_ENCODING_ERROR); /* XXX */
505+
goto err;
506+
}
507+
501508
ctx = BN_CTX_new();
502509
if (ctx == NULL)
503510
goto err;
@@ -509,7 +516,8 @@ old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
509516
j = BN_CTX_get(ctx);
510517
p1 = BN_CTX_get(ctx);
511518
newp1 = BN_CTX_get(ctx);
512-
if (j == NULL || p1 == NULL || newp1 == NULL)
519+
powg = BN_CTX_get(ctx);
520+
if (j == NULL || p1 == NULL || newp1 == NULL || powg == NULL)
513521
goto err;
514522
/* p1 = p - 1 */
515523
if (BN_sub(p1, dsa->p, BN_value_one()) == 0)
@@ -525,6 +533,19 @@ old_dsa_priv_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
525533
goto err;
526534
}
527535

536+
/*
537+
* Check that g generates a multiplicative subgroup of order q.
538+
* We only check that g^q == 1, so the order is a divisor of q.
539+
* Once we know that q is prime, this is enough.
540+
*/
541+
542+
if (!BN_mod_exp_ct(powg, dsa->g, dsa->q, dsa->p, ctx))
543+
goto err;
544+
if (BN_cmp(powg, BN_value_one()) != 0) {
545+
DSAerror(DSA_R_PARAMETER_ENCODING_ERROR); /* XXX */
546+
goto err;
547+
}
548+
528549
/*
529550
* Check that q is not a composite number.
530551
*/

0 commit comments

Comments
 (0)