summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto
diff options
context:
space:
mode:
authortb <>2023-03-04 21:30:23 +0000
committertb <>2023-03-04 21:30:23 +0000
commitf5af461be23ab6e7a4a998f974edf286d18cac7c (patch)
treed779180f7a5713ad27d6a694abfdddc34dd2ce53 /src/lib/libcrypto
parent73e44beee499b22262049c3d41e658d53f9808ad (diff)
downloadopenbsd-f5af461be23ab6e7a4a998f974edf286d18cac7c.tar.gz
openbsd-f5af461be23ab6e7a4a998f974edf286d18cac7c.tar.bz2
openbsd-f5af461be23ab6e7a4a998f974edf286d18cac7c.zip
Cap the number of iterations in DSA signing
The DSA standard specifies an infinite loop: if either r or s is zero in the signature calculation, a new random number k shall be generated and the whole thing is to be redone. The rationale is that, as the standard puts it, "[i]t is extremely unlikely that r = 0 or s = 0 if signatures are generated properly." The problem is... There is no cheap way to know that the DSA domain parameters we are handed are actually DSA domain parameters, so even if all our calculations are carefully done to do all the checks needed, we cannot know if we generate the signatures properly. For this we would need to do two primality checks as well as various congruences and divisibility properties. Doing this easily leads to DoS, so nobody does it. Unfortunately, it is relatively easy to generate parameters that pass all sorts of sanity checks and will always compute s = 0 since g is nilpotent. Thus, as unlikely as it is, if we are in the mathematical model, in practice it is very possible to ensure that s = 0. Read David Benjamin's glorious commit message for more information https://boringssl-review.googlesource.com/c/boringssl/+/57228 Thanks to Guido Vranken for reporting this issue, also thanks to Hanno Boeck who apparently found and reported similar problems earlier. ok beck jsing
Diffstat (limited to 'src/lib/libcrypto')
-rw-r--r--src/lib/libcrypto/dsa/dsa_ossl.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/lib/libcrypto/dsa/dsa_ossl.c b/src/lib/libcrypto/dsa/dsa_ossl.c
index d32168a48e..ece1026fc9 100644
--- a/src/lib/libcrypto/dsa/dsa_ossl.c
+++ b/src/lib/libcrypto/dsa/dsa_ossl.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: dsa_ossl.c,v 1.49 2023/03/04 21:06:17 tb Exp $ */ 1/* $OpenBSD: dsa_ossl.c,v 1.50 2023/03/04 21:30:23 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 *
@@ -92,6 +92,16 @@ DSA_OpenSSL(void)
92 return &openssl_dsa_meth; 92 return &openssl_dsa_meth;
93} 93}
94 94
95/*
96 * Since DSA parameters are entirely arbitrary and checking them to be
97 * consistent is very expensive, we cannot do so on every sign operation.
98 * Instead, cap the number of retries so we do not loop indefinitely if
99 * the generator of the multiplicative group happens to be nilpotent.
100 * The probability of needing a retry with valid parameters is negligible,
101 * so trying 32 times is amply enough.
102 */
103#define DSA_MAX_SIGN_ITERATIONS 32
104
95static DSA_SIG * 105static DSA_SIG *
96dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) 106dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
97{ 107{
@@ -100,6 +110,7 @@ dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
100 BN_CTX *ctx = NULL; 110 BN_CTX *ctx = NULL;
101 int reason = ERR_R_BN_LIB; 111 int reason = ERR_R_BN_LIB;
102 DSA_SIG *ret = NULL; 112 DSA_SIG *ret = NULL;
113 int attempts = 0;
103 int noredo = 0; 114 int noredo = 0;
104 115
105 if (!dsa_check_key(dsa)) { 116 if (!dsa_check_key(dsa)) {
@@ -187,6 +198,10 @@ dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
187 reason = DSA_R_NEED_NEW_SETUP_VALUES; 198 reason = DSA_R_NEED_NEW_SETUP_VALUES;
188 goto err; 199 goto err;
189 } 200 }
201 if (++attempts > DSA_MAX_SIGN_ITERATIONS) {
202 reason = DSA_R_INVALID_PARAMETERS;
203 goto err;
204 }
190 goto redo; 205 goto redo;
191 } 206 }
192 207