make RSA blinding thread-safe
This commit is contained in:
parent
6076f21f5e
commit
46b695d850
9
CHANGES
9
CHANGES
@ -14,12 +14,17 @@
|
||||
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.
|
||||
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
|
||||
seeded (in this case, the secret RSA exponent is abused as
|
||||
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]
|
||||
|
||||
*) Fixed a typo bug that would cause ENGINE_set_default() to set an
|
||||
|
@ -248,6 +248,8 @@ typedef struct bn_blinding_st
|
||||
BIGNUM *A;
|
||||
BIGNUM *Ai;
|
||||
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;
|
||||
|
||||
/* Used for montgomery multiplication */
|
||||
|
@ -158,8 +158,8 @@ struct rsa_st
|
||||
#define RSA_FLAG_CACHE_PUBLIC 0x02
|
||||
#define RSA_FLAG_CACHE_PRIVATE 0x04
|
||||
#define RSA_FLAG_BLINDING 0x08
|
||||
#define RSA_FLAG_NO_BLINDING 0x80 /* new with 0.9.7b; the built-in RSA
|
||||
* implementation now uses blinding by
|
||||
#define RSA_FLAG_NO_BLINDING 0x80 /* new with 0.9.6j and 0.9.7b; the built-in
|
||||
* RSA implementation now uses blinding by
|
||||
* default (ignoring RSA_FLAG_BLINDING),
|
||||
* but other engines might not need it
|
||||
*/
|
||||
|
@ -214,6 +214,40 @@ static int rsa_eay_blinding(RSA *rsa, BN_CTX *ctx)
|
||||
err_instr \
|
||||
} 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 */
|
||||
static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
|
||||
unsigned char *to, RSA *rsa, int padding)
|
||||
@ -222,6 +256,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
|
||||
int i,j,k,num=0,r= -1;
|
||||
unsigned char *buf=NULL;
|
||||
BN_CTX *ctx=NULL;
|
||||
int local_blinding = 0;
|
||||
BN_BLINDING *blinding = NULL;
|
||||
|
||||
BN_init(&f);
|
||||
BN_init(&ret);
|
||||
@ -259,9 +295,38 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
|
||||
}
|
||||
|
||||
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 (!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) ||
|
||||
((rsa->p != NULL) &&
|
||||
@ -275,8 +340,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
|
||||
if (!rsa->meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL)) goto err;
|
||||
}
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_BLINDING))
|
||||
if (!BN_BLINDING_invert(&ret,rsa->blinding,ctx)) goto err;
|
||||
if (blinding)
|
||||
if (!BN_BLINDING_invert(&ret, blinding, ctx)) goto err;
|
||||
|
||||
/* put in leading 0 bytes if the number is less than the
|
||||
* length of the modulus */
|
||||
@ -290,6 +355,8 @@ err:
|
||||
if (ctx != NULL) BN_CTX_free(ctx);
|
||||
BN_clear_free(&ret);
|
||||
BN_clear_free(&f);
|
||||
if (local_blinding)
|
||||
BN_BLINDING_free(blinding);
|
||||
if (buf != NULL)
|
||||
{
|
||||
OPENSSL_cleanse(buf,num);
|
||||
@ -306,6 +373,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
|
||||
unsigned char *p;
|
||||
unsigned char *buf=NULL;
|
||||
BN_CTX *ctx=NULL;
|
||||
int local_blinding = 0;
|
||||
BN_BLINDING *blinding = NULL;
|
||||
|
||||
BN_init(&f);
|
||||
BN_init(&ret);
|
||||
@ -338,9 +407,38 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
|
||||
}
|
||||
|
||||
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 (!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 */
|
||||
if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
||||
@ -356,8 +454,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(rsa->flags & RSA_FLAG_NO_BLINDING))
|
||||
if (!BN_BLINDING_invert(&ret,rsa->blinding,ctx)) goto err;
|
||||
if (blinding)
|
||||
if (!BN_BLINDING_invert(&ret, blinding, ctx)) goto err;
|
||||
|
||||
p=buf;
|
||||
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)
|
||||
if (rsa->blinding != NULL)
|
||||
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);
|
||||
A = BN_CTX_get(ctx);
|
||||
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)
|
||||
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;
|
||||
rsa->blinding=BN_BLINDING_new(A,Ai,rsa->n);
|
||||
goto err;
|
||||
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_NO_BLINDING;
|
||||
BN_free(Ai);
|
||||
|
@ -262,7 +262,7 @@ foreach $lib (keys %csrc)
|
||||
} else {
|
||||
push @out,
|
||||
"/* ====================================================================\n",
|
||||
" * Copyright (c) 2001-2002 The OpenSSL Project. All rights reserved.\n",
|
||||
" * Copyright (c) 2001-2003 The OpenSSL Project. All rights reserved.\n",
|
||||
" *\n",
|
||||
" * Redistribution and use in source and binary forms, with or without\n",
|
||||
" * modification, are permitted provided that the following conditions\n",
|
||||
@ -404,7 +404,7 @@ EOF
|
||||
print OUT <<"EOF";
|
||||
/* $cfile */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2002 The OpenSSL Project. All rights reserved.
|
||||
* Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
Loading…
x
Reference in New Issue
Block a user