提交 5679bcce 编写于 作者: B Bodo Möller

make RSA blinding thread-safe

上级 24692fc5
...@@ -483,12 +483,17 @@ ...@@ -483,12 +483,17 @@
to avoid a timing attack. Applications that don't want it can call to avoid a timing attack. Applications that don't want it can call
RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING. RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING.
They would be ill-advised to do so in most cases. They would be ill-advised to do so in most cases.
[Ben Laurie, Steve Henson, Geoff Thorpe] [Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller]
*) Change RSA blinding code so that it works when the PRNG is not *) Change RSA blinding code so that it works when the PRNG is not
seeded (in this case, the secret RSA exponent is abused as seeded (in this case, the secret RSA exponent is abused as
an unpredictable seed -- if it is not unpredictable, there an unpredictable seed -- if it is not unpredictable, there
is no point in blinding anyway). is no point in blinding anyway). Make RSA blinding thread-safe
by remembering the creator's thread ID in rsa->blinding and
having all other threads use local one-time blinding factors
(this requires more computation than sharing rsa->blinding, but
avoids excessive locking; and if an RSA object is not shared
between threads, blinding will still be very fast).
[Bodo Moeller] [Bodo Moeller]
yet to be integrated into this CVS branch: yet to be integrated into this CVS branch:
......
...@@ -261,6 +261,8 @@ typedef struct bn_blinding_st ...@@ -261,6 +261,8 @@ typedef struct bn_blinding_st
BIGNUM *A; BIGNUM *A;
BIGNUM *Ai; BIGNUM *Ai;
BIGNUM *mod; /* just a reference */ BIGNUM *mod; /* just a reference */
unsigned long thread_id; /* added in OpenSSL 0.9.6j and 0.9.7b;
* used only by crypto/rsa/rsa_eay.c, rsa_lib.c */
} BN_BLINDING; } BN_BLINDING;
/* Used for montgomery multiplication */ /* Used for montgomery multiplication */
......
...@@ -230,6 +230,40 @@ static int rsa_eay_blinding(RSA *rsa, BN_CTX *ctx) ...@@ -230,6 +230,40 @@ static int rsa_eay_blinding(RSA *rsa, BN_CTX *ctx)
err_instr \ err_instr \
} while(0) } while(0)
static BN_BLINDING *setup_blinding(RSA *rsa, BN_CTX *ctx)
{
BIGNUM *A, *Ai;
BN_BLINDING *ret = NULL;
/* added in OpenSSL 0.9.6j and 0.9.7b */
/* NB: similar code appears in RSA_blinding_on (rsa_lib.c);
* this should be placed in a new function of its own, but for reasons
* of binary compatibility can't */
BN_CTX_start(ctx);
A = BN_CTX_get(ctx);
if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL)
{
/* if PRNG is not properly seeded, resort to secret exponent as unpredictable seed */
RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0);
if (!BN_pseudo_rand_range(A,rsa->n)) goto err;
}
else
{
if (!BN_rand_range(A,rsa->n)) goto err;
}
if ((Ai=BN_mod_inverse(NULL,A,rsa->n,ctx)) == NULL) goto err;
if (!rsa->meth->bn_mod_exp(A,A,rsa->e,rsa->n,ctx,rsa->_method_mod_n))
goto err;
ret = BN_BLINDING_new(A,Ai,rsa->n);
BN_free(Ai);
err:
BN_CTX_end(ctx);
return ret;
}
/* signing */ /* signing */
static int RSA_eay_private_encrypt(int flen, const unsigned char *from, static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding) unsigned char *to, RSA *rsa, int padding)
...@@ -238,6 +272,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, ...@@ -238,6 +272,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
int i,j,k,num=0,r= -1; int i,j,k,num=0,r= -1;
unsigned char *buf=NULL; unsigned char *buf=NULL;
BN_CTX *ctx=NULL; BN_CTX *ctx=NULL;
int local_blinding = 0;
BN_BLINDING *blinding = NULL;
BN_init(&f); BN_init(&f);
BN_init(&ret); BN_init(&ret);
...@@ -275,9 +311,38 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, ...@@ -275,9 +311,38 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
} }
BLINDING_HELPER(rsa, ctx, goto err;); BLINDING_HELPER(rsa, ctx, goto err;);
blinding = rsa->blinding;
/* Now unless blinding is disabled, 'blinding' is non-NULL.
* But the BN_BLINDING object may be owned by some other thread
* (we don't want to keep it constant and we don't want to use
* lots of locking to avoid race conditions, so only a single
* thread can use it; other threads have to use local blinding
* factors) */
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) if (!(rsa->flags & RSA_FLAG_NO_BLINDING))
if (!BN_BLINDING_convert(&f,rsa->blinding,ctx)) goto err; {
if (blinding == NULL)
{
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (blinding != NULL)
{
if (blinding->thread_id != CRYPTO_thread_id())
{
/* we need a local one-time blinding factor */
blinding = setup_blinding(rsa, ctx);
if (blinding == NULL)
goto err;
local_blinding = 1;
}
}
if (blinding)
if (!BN_BLINDING_convert(&f, blinding, ctx)) goto err;
if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
((rsa->p != NULL) && ((rsa->p != NULL) &&
...@@ -293,8 +358,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, ...@@ -293,8 +358,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
rsa->_method_mod_n)) goto err; rsa->_method_mod_n)) goto err;
} }
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) if (blinding)
if (!BN_BLINDING_invert(&ret,rsa->blinding,ctx)) goto err; if (!BN_BLINDING_invert(&ret, blinding, ctx)) goto err;
/* put in leading 0 bytes if the number is less than the /* put in leading 0 bytes if the number is less than the
* length of the modulus */ * length of the modulus */
...@@ -308,6 +373,8 @@ err: ...@@ -308,6 +373,8 @@ err:
if (ctx != NULL) BN_CTX_free(ctx); if (ctx != NULL) BN_CTX_free(ctx);
BN_clear_free(&ret); BN_clear_free(&ret);
BN_clear_free(&f); BN_clear_free(&f);
if (local_blinding)
BN_BLINDING_free(blinding);
if (buf != NULL) if (buf != NULL)
{ {
OPENSSL_cleanse(buf,num); OPENSSL_cleanse(buf,num);
...@@ -324,6 +391,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, ...@@ -324,6 +391,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
unsigned char *p; unsigned char *p;
unsigned char *buf=NULL; unsigned char *buf=NULL;
BN_CTX *ctx=NULL; BN_CTX *ctx=NULL;
int local_blinding = 0;
BN_BLINDING *blinding = NULL;
BN_init(&f); BN_init(&f);
BN_init(&ret); BN_init(&ret);
...@@ -356,9 +425,38 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, ...@@ -356,9 +425,38 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
} }
BLINDING_HELPER(rsa, ctx, goto err;); BLINDING_HELPER(rsa, ctx, goto err;);
blinding = rsa->blinding;
/* Now unless blinding is disabled, 'blinding' is non-NULL.
* But the BN_BLINDING object may be owned by some other thread
* (we don't want to keep it constant and we don't want to use
* lots of locking to avoid race conditions, so only a single
* thread can use it; other threads have to use local blinding
* factors) */
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) if (!(rsa->flags & RSA_FLAG_NO_BLINDING))
if (!BN_BLINDING_convert(&f,rsa->blinding,ctx)) goto err; {
if (blinding == NULL)
{
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (blinding != NULL)
{
if (blinding->thread_id != CRYPTO_thread_id())
{
/* we need a local one-time blinding factor */
blinding = setup_blinding(rsa, ctx);
if (blinding == NULL)
goto err;
local_blinding = 1;
}
}
if (blinding)
if (!BN_BLINDING_convert(&f, blinding, ctx)) goto err;
/* do the decrypt */ /* do the decrypt */
if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
...@@ -376,8 +474,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, ...@@ -376,8 +474,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
goto err; goto err;
} }
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) if (blinding)
if (!BN_BLINDING_invert(&ret,rsa->blinding,ctx)) goto err; if (!BN_BLINDING_invert(&ret, blinding, ctx)) goto err;
p=buf; p=buf;
j=BN_bn2bin(&ret,p); /* j is only used with no-padding mode */ j=BN_bn2bin(&ret,p); /* j is only used with no-padding mode */
......
...@@ -329,6 +329,10 @@ int RSA_blinding_on(RSA *rsa, BN_CTX *p_ctx) ...@@ -329,6 +329,10 @@ int RSA_blinding_on(RSA *rsa, BN_CTX *p_ctx)
if (rsa->blinding != NULL) if (rsa->blinding != NULL)
BN_BLINDING_free(rsa->blinding); BN_BLINDING_free(rsa->blinding);
/* NB: similar code appears in setup_blinding (rsa_eay.c);
* this should be placed in a new function of its own, but for reasons
* of binary compatibility can't */
BN_CTX_start(ctx); BN_CTX_start(ctx);
A = BN_CTX_get(ctx); A = BN_CTX_get(ctx);
if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL) if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL)
...@@ -344,8 +348,11 @@ int RSA_blinding_on(RSA *rsa, BN_CTX *p_ctx) ...@@ -344,8 +348,11 @@ int RSA_blinding_on(RSA *rsa, BN_CTX *p_ctx)
if ((Ai=BN_mod_inverse(NULL,A,rsa->n,ctx)) == NULL) goto err; if ((Ai=BN_mod_inverse(NULL,A,rsa->n,ctx)) == NULL) goto err;
if (!rsa->meth->bn_mod_exp(A,A,rsa->e,rsa->n,ctx,rsa->_method_mod_n)) if (!rsa->meth->bn_mod_exp(A,A,rsa->e,rsa->n,ctx,rsa->_method_mod_n))
goto err; goto err;
rsa->blinding=BN_BLINDING_new(A,Ai,rsa->n); if ((rsa->blinding=BN_BLINDING_new(A,Ai,rsa->n)) == NULL) goto err;
/* to make things thread-safe without excessive locking,
* rsa->blinding will be used just by the current thread: */
rsa->blinding->thread_id = CRYPTO_thread_id();
rsa->flags |= RSA_FLAG_BLINDING; rsa->flags |= RSA_FLAG_BLINDING;
rsa->flags &= ~RSA_FLAG_NO_BLINDING; rsa->flags &= ~RSA_FLAG_NO_BLINDING;
BN_free(Ai); BN_free(Ai);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册