David Brumley <dbrumley@stanford.edu> noted and corrected a case in the
verification step of CRT private key operations in the RSA code - previously no montgomery form was checked or used for 'n', and so it would be generated on the fly each time. As a result, private key operations are now a percent or two faster. Rather than adding this as another repetition of the nearly-identical montgomery "check for first-use" initialisation code blocks, I've taken this chance to create a helper function and macro-wrapper to replace them. PR: 475
This commit is contained in:
@@ -100,6 +100,43 @@ const RSA_METHOD *RSA_PKCS1_SSLeay(void)
|
|||||||
return(&rsa_pkcs1_eay_meth);
|
return(&rsa_pkcs1_eay_meth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Static helper to reduce oodles of code duplication. As a slight
|
||||||
|
* optimisation, the "MONT_HELPER() macro must be used as front-end to this
|
||||||
|
* function, to prevent unnecessary function calls - there is an initial test
|
||||||
|
* that is performed by the macro-generated code. */
|
||||||
|
static int rsa_eay_mont_helper(BN_MONT_CTX **ptr, const BIGNUM *modulus, BN_CTX *ctx)
|
||||||
|
{
|
||||||
|
BN_MONT_CTX *bn_mont_ctx;
|
||||||
|
if((bn_mont_ctx = BN_MONT_CTX_new()) == NULL)
|
||||||
|
return 0;
|
||||||
|
if(!BN_MONT_CTX_set(bn_mont_ctx, modulus, ctx))
|
||||||
|
{
|
||||||
|
BN_MONT_CTX_free(bn_mont_ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (*ptr == NULL) /* other thread may have finished first */
|
||||||
|
{
|
||||||
|
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
|
||||||
|
if (*ptr == NULL) /* check again in the lock to stop races */
|
||||||
|
{
|
||||||
|
*ptr = bn_mont_ctx;
|
||||||
|
bn_mont_ctx = NULL;
|
||||||
|
}
|
||||||
|
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
|
||||||
|
}
|
||||||
|
if (bn_mont_ctx)
|
||||||
|
BN_MONT_CTX_free(bn_mont_ctx);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* Usage example;
|
||||||
|
* MONT_HELPER(rsa, bn_ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
|
||||||
|
*/
|
||||||
|
#define MONT_HELPER(rsa, ctx, m, pre_cond, err_instr) \
|
||||||
|
if((pre_cond) && ((rsa)->_method_mod_##m == NULL) && \
|
||||||
|
!rsa_eay_mont_helper(&((rsa)->_method_mod_##m), \
|
||||||
|
(rsa)->m, (ctx))) \
|
||||||
|
err_instr
|
||||||
|
|
||||||
static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
|
static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
|
||||||
unsigned char *to, RSA *rsa, int padding)
|
unsigned char *to, RSA *rsa, int padding)
|
||||||
{
|
{
|
||||||
@@ -149,29 +186,7 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
|
MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
|
||||||
{
|
|
||||||
BN_MONT_CTX* bn_mont_ctx;
|
|
||||||
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
|
|
||||||
goto err;
|
|
||||||
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
|
|
||||||
{
|
|
||||||
BN_MONT_CTX_free(bn_mont_ctx);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (rsa->_method_mod_n == NULL) /* other thread may have finished first */
|
|
||||||
{
|
|
||||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
|
|
||||||
if (rsa->_method_mod_n == NULL)
|
|
||||||
{
|
|
||||||
rsa->_method_mod_n = bn_mont_ctx;
|
|
||||||
bn_mont_ctx = NULL;
|
|
||||||
}
|
|
||||||
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
|
|
||||||
}
|
|
||||||
if (bn_mont_ctx)
|
|
||||||
BN_MONT_CTX_free(bn_mont_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
|
if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
|
||||||
rsa->_method_mod_n)) goto err;
|
rsa->_method_mod_n)) goto err;
|
||||||
@@ -418,30 +433,7 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do the decrypt */
|
MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err);
|
||||||
if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC))
|
|
||||||
{
|
|
||||||
BN_MONT_CTX* bn_mont_ctx;
|
|
||||||
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
|
|
||||||
goto err;
|
|
||||||
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx))
|
|
||||||
{
|
|
||||||
BN_MONT_CTX_free(bn_mont_ctx);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (rsa->_method_mod_n == NULL) /* other thread may have finished first */
|
|
||||||
{
|
|
||||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
|
|
||||||
if (rsa->_method_mod_n == NULL)
|
|
||||||
{
|
|
||||||
rsa->_method_mod_n = bn_mont_ctx;
|
|
||||||
bn_mont_ctx = NULL;
|
|
||||||
}
|
|
||||||
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
|
|
||||||
}
|
|
||||||
if (bn_mont_ctx)
|
|
||||||
BN_MONT_CTX_free(bn_mont_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
|
if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx,
|
||||||
rsa->_method_mod_n)) goto err;
|
rsa->_method_mod_n)) goto err;
|
||||||
@@ -487,56 +479,9 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
|
|||||||
BN_init(&vrfy);
|
BN_init(&vrfy);
|
||||||
if ((ctx=BN_CTX_new()) == NULL) goto err;
|
if ((ctx=BN_CTX_new()) == NULL) goto err;
|
||||||
|
|
||||||
if (rsa->flags & RSA_FLAG_CACHE_PRIVATE)
|
MONT_HELPER(rsa, ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
|
||||||
{
|
MONT_HELPER(rsa, ctx, q, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
|
||||||
if (rsa->_method_mod_p == NULL)
|
MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err);
|
||||||
{
|
|
||||||
BN_MONT_CTX* bn_mont_ctx;
|
|
||||||
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
|
|
||||||
goto err;
|
|
||||||
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->p,ctx))
|
|
||||||
{
|
|
||||||
BN_MONT_CTX_free(bn_mont_ctx);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (rsa->_method_mod_p == NULL) /* other thread may have finished first */
|
|
||||||
{
|
|
||||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
|
|
||||||
if (rsa->_method_mod_p == NULL)
|
|
||||||
{
|
|
||||||
rsa->_method_mod_p = bn_mont_ctx;
|
|
||||||
bn_mont_ctx = NULL;
|
|
||||||
}
|
|
||||||
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
|
|
||||||
}
|
|
||||||
if (bn_mont_ctx)
|
|
||||||
BN_MONT_CTX_free(bn_mont_ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rsa->_method_mod_q == NULL)
|
|
||||||
{
|
|
||||||
BN_MONT_CTX* bn_mont_ctx;
|
|
||||||
if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL)
|
|
||||||
goto err;
|
|
||||||
if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->q,ctx))
|
|
||||||
{
|
|
||||||
BN_MONT_CTX_free(bn_mont_ctx);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (rsa->_method_mod_q == NULL) /* other thread may have finished first */
|
|
||||||
{
|
|
||||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA);
|
|
||||||
if (rsa->_method_mod_q == NULL)
|
|
||||||
{
|
|
||||||
rsa->_method_mod_q = bn_mont_ctx;
|
|
||||||
bn_mont_ctx = NULL;
|
|
||||||
}
|
|
||||||
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
|
|
||||||
}
|
|
||||||
if (bn_mont_ctx)
|
|
||||||
BN_MONT_CTX_free(bn_mont_ctx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!BN_mod(&r1,I,rsa->q,ctx)) 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,
|
if (!rsa->meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx,
|
||||||
@@ -568,7 +513,7 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
|
|||||||
|
|
||||||
if (rsa->e && rsa->n)
|
if (rsa->e && rsa->n)
|
||||||
{
|
{
|
||||||
if (!rsa->meth->bn_mod_exp(&vrfy,r0,rsa->e,rsa->n,ctx,NULL)) goto err;
|
if (!rsa->meth->bn_mod_exp(&vrfy,r0,rsa->e,rsa->n,ctx,rsa->_method_mod_n)) goto err;
|
||||||
/* If 'I' was greater than (or equal to) rsa->n, the operation
|
/* If 'I' was greater than (or equal to) rsa->n, the operation
|
||||||
* will be equivalent to using 'I mod n'. However, the result of
|
* 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
|
* the verify will *always* be less than 'n' so we don't check
|
||||||
|
|||||||
Reference in New Issue
Block a user