aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/rsa/rsa_eay.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c
index 06f73fc8ff..f325050c1c 100644
--- a/crypto/rsa/rsa_eay.c
+++ b/crypto/rsa/rsa_eay.c
@@ -545,10 +545,19 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
if (rsa->e && rsa->n)
{
if (!meth->bn_mod_exp(&vrfy,r0,rsa->e,rsa->n,ctx,NULL)) goto err;
- if (BN_cmp(I, &vrfy) != 0)
- {
+ /* If 'I' was greater than (or equal to) rsa->n, the operation
+ * will be equivalent to using 'I mod n'. However, the result of
+ * the verify will *always* be less than 'n' so we don't check
+ * for absolute equality, just congruency. */
+ if (!BN_sub(&vrfy, &vrfy, I)) goto err;
+ if (!BN_mod(&vrfy, &vrfy, rsa->n, ctx)) goto err;
+ if (vrfy.neg)
+ if (!BN_add(&vrfy, &vrfy, rsa->n)) goto err;
+ if (!BN_is_zero(&vrfy))
+ /* 'I' and 'vrfy' aren't congruent mod n. Don't leak
+ * miscalculated CRT output, just do a raw (slower)
+ * mod_exp and return that instead. */
if (!meth->bn_mod_exp(r0,I,rsa->d,rsa->n,ctx,NULL)) goto err;
- }
}
ret=1;
err: