-
- if (!BN_mod(r1,I,rsa->q,ctx)) goto err;
- if (!rsa->meth->bn_mod_exp(m1,r1,rsa->dmq1,rsa->q,ctx,
- rsa->method_mod_q)) goto err;
-
- if (!BN_mod(r1,I,rsa->p,ctx)) goto err;
- if (!rsa->meth->bn_mod_exp(r0,r1,rsa->dmp1,rsa->p,ctx,
- rsa->method_mod_p)) goto err;
-
- if (!BN_add(r1,r0,rsa->p)) goto err;
- if (!BN_sub(r0,r1,m1)) goto err;
-
- if (!BN_mul(r1,r0,rsa->iqmp)) goto err;
- if (!BN_mod(r0,r1,rsa->p,ctx)) goto err;
- if (!BN_mul(r1,r0,rsa->q)) goto err;
- if (!BN_add(r0,r1,m1)) goto err;
-
+
+ if (!BN_mod(&r1,I,rsa->q,ctx)) goto err;
+ if (!rsa->meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx,
+ rsa->_method_mod_q)) goto err;
+
+ if (!BN_mod(&r1,I,rsa->p,ctx)) goto err;
+ if (!rsa->meth->bn_mod_exp(r0,&r1,rsa->dmp1,rsa->p,ctx,
+ rsa->_method_mod_p)) goto err;
+
+ if (!BN_sub(r0,r0,&m1)) goto err;
+ /* This will help stop the size of r0 increasing, which does
+ * affect the multiply if it optimised for a power of 2 size */
+ if (r0->neg)
+ if (!BN_add(r0,r0,rsa->p)) goto err;
+
+ if (!BN_mul(&r1,r0,rsa->iqmp,ctx)) goto err;
+ if (!BN_mod(r0,&r1,rsa->p,ctx)) goto err;
+ /* If p < q it is occasionally possible for the correction of
+ * adding 'p' if r0 is negative above to leave the result still
+ * negative. This can break the private key operations: the following
+ * second correction should *always* correct this rare occurrence.
+ * This will *never* happen with OpenSSL generated keys because
+ * they ensure p > q [steve]
+ */
+ if (r0->neg)
+ if (!BN_add(r0,r0,rsa->p)) goto err;
+ if (!BN_mul(&r1,r0,rsa->q,ctx)) goto err;
+ if (!BN_add(r0,&r1,&m1)) goto err;
+
+ if (rsa->e && rsa->n)
+ {
+ if (!rsa->meth->bn_mod_exp(&vrfy,r0,rsa->e,rsa->n,ctx,NULL)) goto err;
+ /* 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 (!rsa->meth->bn_mod_exp(r0,I,rsa->d,rsa->n,ctx,NULL)) goto err;
+ }