aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/rsa
diff options
context:
space:
mode:
authorNils Larsch <nils@openssl.org>2005-04-26 22:31:48 +0000
committerNils Larsch <nils@openssl.org>2005-04-26 22:31:48 +0000
commit800e400de5ca30491577301ded618445b48c7911 (patch)
treea6dde859f6c9a77a295aa073d5b37ae422180739 /crypto/rsa
parent05886a6f77e7843c854ed6d0752b6673db45db3c (diff)
downloadopenssl-800e400de5ca30491577301ded618445b48c7911.tar.gz
some updates for the blinding code; summary:
- possibility of re-creation of the blinding parameters after a fixed number of uses (suggested by Bodo) - calculatition of the rsa::e in case it's absent and p and q are present (see bug report #785) - improve the performance when if one rsa structure is shared by more than a thread (see bug report #555) - fix the problem described in bug report #827 - hide the definition ot the BN_BLINDING structure in bn_blind.c
Diffstat (limited to 'crypto/rsa')
-rw-r--r--crypto/rsa/rsa.h4
-rw-r--r--crypto/rsa/rsa_eay.c178
-rw-r--r--crypto/rsa/rsa_err.c2
-rw-r--r--crypto/rsa/rsa_lib.c113
4 files changed, 160 insertions, 137 deletions
diff --git a/crypto/rsa/rsa.h b/crypto/rsa/rsa.h
index 4bfd51a4bb..4e28bbc39c 100644
--- a/crypto/rsa/rsa.h
+++ b/crypto/rsa/rsa.h
@@ -156,6 +156,7 @@ struct rsa_st
* NULL */
char *bignum_data;
BN_BLINDING *blinding;
+ BN_BLINDING *mt_blinding;
};
#define RSA_3 0x3L
@@ -279,6 +280,7 @@ int RSA_verify_ASN1_OCTET_STRING(int type,
int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);
void RSA_blinding_off(RSA *rsa);
+BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx);
int RSA_padding_add_PKCS1_type_1(unsigned char *to,int tlen,
const unsigned char *f,int fl);
@@ -341,6 +343,7 @@ void ERR_load_RSA_strings(void);
#define RSA_F_RSA_PADDING_CHECK_SSLV23 114
#define RSA_F_RSA_PRINT 115
#define RSA_F_RSA_PRINT_FP 116
+#define RSA_F_RSA_SETUP_BLINDING 125
#define RSA_F_RSA_SIGN 117
#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118
#define RSA_F_RSA_VERIFY 119
@@ -367,6 +370,7 @@ void ERR_load_RSA_strings(void);
#define RSA_R_INVALID_MESSAGE_LENGTH 131
#define RSA_R_IQMP_NOT_INVERSE_OF_Q 126
#define RSA_R_KEY_SIZE_TOO_SMALL 120
+#define RSA_R_NO_PUBLIC_EXPONENT 133
#define RSA_R_NULL_BEFORE_BLOCK_MISSING 113
#define RSA_R_N_DOES_NOT_EQUAL_P_Q 127
#define RSA_R_OAEP_DECODING_ERROR 121
diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c
index 3ee753ec86..6bf681f1f9 100644
--- a/crypto/rsa/rsa_eay.c
+++ b/crypto/rsa/rsa_eay.c
@@ -212,64 +212,78 @@ err:
return(r);
}
-static int rsa_eay_blinding(RSA *rsa, BN_CTX *ctx)
- {
- int ret = 1;
- CRYPTO_w_lock(CRYPTO_LOCK_RSA);
- /* Check again inside the lock - the macro's check is racey */
- if(rsa->blinding == NULL)
- ret = RSA_blinding_on(rsa, ctx);
- CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
- return ret;
- }
+static BN_BLINDING *rsa_get_blinding(RSA *rsa, BIGNUM **r, int *local, BN_CTX *ctx)
+{
+ BN_BLINDING *ret;
-#define BLINDING_HELPER(rsa, ctx, err_instr) \
- do { \
- if((!((rsa)->flags & RSA_FLAG_NO_BLINDING)) && \
- ((rsa)->blinding == NULL) && \
- !rsa_eay_blinding(rsa, ctx)) \
- err_instr \
- } while(0)
+ if (rsa->blinding == NULL)
+ {
+ if (rsa->blinding == NULL)
+ {
+ CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+ if (rsa->blinding == NULL)
+ rsa->blinding = RSA_setup_blinding(rsa, ctx);
+ CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+ }
+ }
-static BN_BLINDING *setup_blinding(RSA *rsa, BN_CTX *ctx)
- {
- BIGNUM *A, *Ai;
- BN_BLINDING *ret = NULL;
+ ret = rsa->blinding;
+ if (ret == NULL)
+ return NULL;
- /* added in OpenSSL 0.9.6j and 0.9.7b */
+ if (BN_BLINDING_get_thread_id(ret) != CRYPTO_thread_id())
+ {
+ *local = 0;
+ if (rsa->mt_blinding == NULL)
+ {
+ CRYPTO_w_lock(CRYPTO_LOCK_RSA);
+ if (rsa->mt_blinding == NULL)
+ rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
+ CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
+ }
+ ret = rsa->mt_blinding;
+ }
+ else
+ *local = 1;
- /* 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 */
+ return ret;
+}
- BN_CTX_start(ctx);
- A = BN_CTX_get(ctx);
- if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL)
+static int rsa_blinding_convert(BN_BLINDING *b, int local, BIGNUM *f,
+ BIGNUM *r, BN_CTX *ctx)
+{
+ if (local)
+ return BN_BLINDING_convert_ex(f, NULL, b, ctx);
+ else
{
- /* 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.0);
- if (!BN_pseudo_rand_range(A,rsa->n)) goto err;
- }
+ int ret;
+ CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
+ ret = BN_BLINDING_convert_ex(f, r, b, ctx);
+ CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ return ret;
+ }
+}
+
+static int rsa_blinding_invert(BN_BLINDING *b, int local, BIGNUM *f,
+ BIGNUM *r, BN_CTX *ctx)
+{
+ if (local)
+ return BN_BLINDING_invert_ex(f, NULL, b, ctx);
else
{
- if (!BN_rand_range(A,rsa->n)) goto err;
+ int ret;
+ CRYPTO_r_lock(CRYPTO_LOCK_RSA_BLINDING);
+ ret = BN_BLINDING_invert_ex(f, r, b, ctx);
+ CRYPTO_r_unlock(CRYPTO_LOCK_RSA_BLINDING);
+ return ret;
}
- 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)
{
- BIGNUM *f,*ret;
+ BIGNUM *f, *ret, *br;
int i,j,k,num=0,r= -1;
unsigned char *buf=NULL;
BN_CTX *ctx=NULL;
@@ -278,9 +292,10 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
if ((ctx=BN_CTX_new()) == NULL) goto err;
BN_CTX_start(ctx);
- f = BN_CTX_get(ctx);
+ f = BN_CTX_get(ctx);
+ br = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
- num=BN_num_bytes(rsa->n);
+ num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if(!f || !ret || !buf)
{
@@ -312,17 +327,9 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
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))
{
+ blinding = rsa_get_blinding(rsa, &br, &local_blinding, ctx);
if (blinding == NULL)
{
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
@@ -331,20 +338,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
}
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_blinding_convert(blinding, local_blinding, f, br, ctx))
+ goto err;
if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
((rsa->p != NULL) &&
@@ -361,7 +356,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
}
if (blinding)
- if (!BN_BLINDING_invert(ret, blinding, ctx)) goto err;
+ if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
+ goto err;
/* put in leading 0 bytes if the number is less than the
* length of the modulus */
@@ -377,8 +373,6 @@ err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
- if (local_blinding)
- BN_BLINDING_free(blinding);
if (buf != NULL)
{
OPENSSL_cleanse(buf,num);
@@ -390,7 +384,7 @@ err:
static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
- BIGNUM *f,*ret;
+ BIGNUM *f, *ret, *br;
int j,num=0,r= -1;
unsigned char *p;
unsigned char *buf=NULL;
@@ -400,9 +394,10 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
if((ctx = BN_CTX_new()) == NULL) goto err;
BN_CTX_start(ctx);
- f = BN_CTX_get(ctx);
+ f = BN_CTX_get(ctx);
+ br = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
- num=BN_num_bytes(rsa->n);
+ num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if(!f || !ret || !buf)
{
@@ -427,39 +422,19 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
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))
{
+ blinding = rsa_get_blinding(rsa, &br, &local_blinding, ctx);
if (blinding == NULL)
{
- RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
+ 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_blinding_convert(blinding, local_blinding, f, br, ctx))
+ goto err;
/* do the decrypt */
if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
@@ -478,7 +453,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
}
if (blinding)
- if (!BN_BLINDING_invert(ret, blinding, ctx)) goto err;
+ if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
+ goto err;
p=buf;
j=BN_bn2bin(ret,p); /* j is only used with no-padding mode */
@@ -512,8 +488,6 @@ err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
- if (local_blinding)
- BN_BLINDING_free(blinding);
if (buf != NULL)
{
OPENSSL_cleanse(buf,num);
diff --git a/crypto/rsa/rsa_err.c b/crypto/rsa/rsa_err.c
index 07ef9df0cd..6641e61c7f 100644
--- a/crypto/rsa/rsa_err.c
+++ b/crypto/rsa/rsa_err.c
@@ -91,6 +91,7 @@ static ERR_STRING_DATA RSA_str_functs[]=
{ERR_FUNC(RSA_F_RSA_PADDING_CHECK_SSLV23), "RSA_padding_check_SSLv23"},
{ERR_FUNC(RSA_F_RSA_PRINT), "RSA_print"},
{ERR_FUNC(RSA_F_RSA_PRINT_FP), "RSA_print_fp"},
+{ERR_FUNC(RSA_F_RSA_SETUP_BLINDING), "RSA_setup_blinding"},
{ERR_FUNC(RSA_F_RSA_SIGN), "RSA_sign"},
{ERR_FUNC(RSA_F_RSA_SIGN_ASN1_OCTET_STRING), "RSA_sign_ASN1_OCTET_STRING"},
{ERR_FUNC(RSA_F_RSA_VERIFY), "RSA_verify"},
@@ -120,6 +121,7 @@ static ERR_STRING_DATA RSA_str_reasons[]=
{ERR_REASON(RSA_R_INVALID_MESSAGE_LENGTH),"invalid message length"},
{ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q) ,"iqmp not inverse of q"},
{ERR_REASON(RSA_R_KEY_SIZE_TOO_SMALL) ,"key size too small"},
+{ERR_REASON(RSA_R_NO_PUBLIC_EXPONENT) ,"no public exponent"},
{ERR_REASON(RSA_R_NULL_BEFORE_BLOCK_MISSING),"null before block missing"},
{ERR_REASON(RSA_R_N_DOES_NOT_EQUAL_P_Q) ,"n does not equal p q"},
{ERR_REASON(RSA_R_OAEP_DECODING_ERROR) ,"oaep decoding error"},
diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c
index cba2dd66cd..0447fd5c70 100644
--- a/crypto/rsa/rsa_lib.c
+++ b/crypto/rsa/rsa_lib.c
@@ -179,6 +179,7 @@ RSA *RSA_new_method(ENGINE *engine)
ret->_method_mod_p=NULL;
ret->_method_mod_q=NULL;
ret->blinding=NULL;
+ ret->mt_blinding=NULL;
ret->bignum_data=NULL;
ret->flags=ret->meth->flags;
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data);
@@ -232,6 +233,7 @@ void RSA_free(RSA *r)
if (r->dmq1 != NULL) BN_clear_free(r->dmq1);
if (r->iqmp != NULL) BN_clear_free(r->iqmp);
if (r->blinding != NULL) BN_BLINDING_free(r->blinding);
+ if (r->mt_blinding != NULL) BN_BLINDING_free(r->mt_blinding);
if (r->bignum_data != NULL) OPENSSL_free_locked(r->bignum_data);
OPENSSL_free(r);
}
@@ -314,59 +316,100 @@ void RSA_blinding_off(RSA *rsa)
rsa->flags |= RSA_FLAG_NO_BLINDING;
}
-int RSA_blinding_on(RSA *rsa, BN_CTX *p_ctx)
+int RSA_blinding_on(RSA *rsa, BN_CTX *ctx)
{
- BIGNUM *A,*Ai = NULL;
- BN_CTX *ctx;
int ret=0;
- if (p_ctx == NULL)
+ if (rsa->blinding != NULL)
+ RSA_blinding_off(rsa);
+
+ rsa->blinding = RSA_setup_blinding(rsa, ctx);
+ if (rsa->blinding == NULL)
+ goto err;
+
+ rsa->flags |= RSA_FLAG_BLINDING;
+ rsa->flags &= ~RSA_FLAG_NO_BLINDING;
+ ret=1;
+err:
+ return(ret);
+ }
+
+static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
+ const BIGNUM *q, BN_CTX *ctx)
+{
+ BIGNUM *ret = NULL, *r0, *r1, *r2;
+
+ if (d == NULL || p == NULL || q == NULL)
+ return NULL;
+
+ BN_CTX_start(ctx);
+ r0 = BN_CTX_get(ctx);
+ r1 = BN_CTX_get(ctx);
+ r2 = BN_CTX_get(ctx);
+ if (r2 == NULL)
+ goto err;
+
+ if (!BN_sub(r1, p, BN_value_one())) goto err;
+ if (!BN_sub(r2, q, BN_value_one())) goto err;
+ if (!BN_mul(r0, r1, r2, ctx)) goto err;
+
+ ret = BN_mod_inverse(NULL, d, r0, ctx);
+err:
+ BN_CTX_end(ctx);
+ return ret;
+}
+
+BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx)
+{
+ BIGNUM *e;
+ BN_CTX *ctx;
+ BN_BLINDING *ret = NULL;
+
+ if (in_ctx == NULL)
{
- if ((ctx=BN_CTX_new()) == NULL) goto err;
+ if ((ctx = BN_CTX_new()) == NULL) return 0;
}
else
- ctx=p_ctx;
+ ctx = in_ctx;
- /* XXXXX: Shouldn't this be RSA_blinding_off(rsa)? */
- if (rsa->blinding != NULL)
+ BN_CTX_start(ctx);
+ e = BN_CTX_get(ctx);
+ if (e == NULL)
{
- BN_BLINDING_free(rsa->blinding);
- rsa->blinding = NULL;
+ RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
+ goto err;
}
- /* 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)
+ if (rsa->e == 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.0);
- if (!BN_pseudo_rand_range(A,rsa->n)) goto err;
+ e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
+ if (e == NULL)
+ {
+ RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT);
+ goto err;
+ }
}
else
+ e = rsa->e;
+
+
+ if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL)
{
- if (!BN_rand_range(A,rsa->n)) goto err;
+ /* 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.0);
}
- 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;
- 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;
- ret=1;
+ ret = BN_BLINDING_create_param(NULL, e, rsa->n, ctx,
+ rsa->meth->bn_mod_exp, rsa->_method_mod_n);
+ BN_BLINDING_set_thread_id(ret, CRYPTO_thread_id());
err:
- if (Ai != NULL) BN_free(Ai);
BN_CTX_end(ctx);
- if (ctx != p_ctx) BN_CTX_free(ctx);
- return(ret);
- }
+ if (in_ctx == NULL)
+ BN_CTX_free(ctx);
+
+ return ret;
+}
int RSA_memory_lock(RSA *r)
{