提交 800e400d 编写于 作者: N Nils Larsch

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
上级 05886a6f
......@@ -4,6 +4,18 @@
Changes between 0.9.7g and 0.9.8 [xx XXX xxxx]
*) Add new functionality to the bn blinding code:
- automatic re-creation of the BN_BLINDING parameters after
a fixed number of uses (currently 32)
- add new function for parameter creation
- introduce flags to control the update behaviour of the
BN_BLINDING parameters
- hide BN_BLINDING structure
Add a second BN_BLINDING slot to the RSA structure to improve
performance when a single RSA object is shared among several
threads.
[Nils Larsch]
*) Add support for DTLS.
[Nagendra Modadugu <nagendra@cs.stanford.edu> and Ben Laurie]
......
......@@ -274,16 +274,6 @@ struct bignum_st
int flags;
};
struct bn_blinding_st
{
int init;
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 */
};
/* Used for montgomery multiplication */
struct bn_mont_ctx_st
{
......@@ -521,11 +511,26 @@ void BN_MONT_CTX_free(BN_MONT_CTX *mont);
int BN_MONT_CTX_set(BN_MONT_CTX *mont,const BIGNUM *mod,BN_CTX *ctx);
BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from);
BN_BLINDING *BN_BLINDING_new(BIGNUM *A,BIGNUM *Ai,BIGNUM *mod);
/* BN_BLINDING flags */
#define BN_BLINDING_NO_UPDATE 0x00000001
#define BN_BLINDING_NO_RECREATE 0x00000002
BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod);
void BN_BLINDING_free(BN_BLINDING *b);
int BN_BLINDING_update(BN_BLINDING *b,BN_CTX *ctx);
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *r, BN_CTX *ctx);
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *);
void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long);
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx),
BN_MONT_CTX *m_ctx);
#ifndef OPENSSL_NO_DEPRECATED
void BN_set_params(int mul,int high,int low,int mont);
......@@ -727,6 +732,7 @@ void ERR_load_BN_strings(void);
/* Function codes. */
#define BN_F_BNRAND 114
#define BN_F_BN_BLINDING_CONVERT 100
#define BN_F_BN_BLINDING_CREATE_PARAM 133
#define BN_F_BN_BLINDING_INVERT 101
#define BN_F_BN_BLINDING_NEW 102
#define BN_F_BN_BLINDING_UPDATE 103
......
/* crypto/bn/bn_blind.c */
/* ====================================================================
* Copyright (c) 1998-2005 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
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
......@@ -60,11 +113,28 @@
#include "cryptlib.h"
#include "bn_lcl.h"
BN_BLINDING *BN_BLINDING_new(BIGNUM *A, BIGNUM *Ai, BIGNUM *mod)
#define BN_BLINDING_COUNTER 32
struct bn_blinding_st
{
BIGNUM *A;
BIGNUM *Ai;
BIGNUM *e;
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 */
unsigned int counter;
unsigned long flags;
BN_MONT_CTX *m_ctx;
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx,
BN_MONT_CTX *m_ctx);
};
BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
{
BN_BLINDING *ret=NULL;
bn_check_top(Ai);
bn_check_top(mod);
if ((ret=(BN_BLINDING *)OPENSSL_malloc(sizeof(BN_BLINDING))) == NULL)
......@@ -73,11 +143,16 @@ BN_BLINDING *BN_BLINDING_new(BIGNUM *A, BIGNUM *Ai, BIGNUM *mod)
return(NULL);
}
memset(ret,0,sizeof(BN_BLINDING));
if ((ret->A=BN_new()) == NULL) goto err;
if ((ret->Ai=BN_new()) == NULL) goto err;
if (!BN_copy(ret->A,A)) goto err;
if (!BN_copy(ret->Ai,Ai)) goto err;
ret->mod=mod;
if (A != NULL)
{
if ((ret->A = BN_dup(A)) == NULL) goto err;
}
if (Ai != NULL)
{
if ((ret->Ai = BN_dup(Ai)) == NULL) goto err;
}
ret->mod = mod;
ret->counter = BN_BLINDING_COUNTER;
return(ret);
err:
if (ret != NULL) BN_BLINDING_free(ret);
......@@ -91,6 +166,7 @@ void BN_BLINDING_free(BN_BLINDING *r)
if (r->A != NULL) BN_free(r->A );
if (r->Ai != NULL) BN_free(r->Ai);
if (r->e != NULL) BN_free(r->e );
OPENSSL_free(r);
}
......@@ -104,15 +180,32 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
goto err;
}
if (--(b->counter) == 0 && b->e != NULL &&
!(b->flags & BN_BLINDING_NO_RECREATE))
{
/* re-create blinding parameters */
if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL))
goto err;
}
else if (!(b->flags & BN_BLINDING_NO_UPDATE))
{
if (!BN_mod_mul(b->A,b->A,b->A,b->mod,ctx)) goto err;
if (!BN_mod_mul(b->Ai,b->Ai,b->Ai,b->mod,ctx)) goto err;
}
ret=1;
err:
if (b->counter == 0)
b->counter = BN_BLINDING_COUNTER;
return(ret);
}
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
{
return BN_BLINDING_convert_ex(n, NULL, b, ctx);
}
int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
{
bn_check_top(n);
......@@ -121,10 +214,19 @@ int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
BNerr(BN_F_BN_BLINDING_CONVERT,BN_R_NOT_INITIALIZED);
return(0);
}
return(BN_mod_mul(n,n,b->A,b->mod,ctx));
if (r != NULL)
BN_copy(r, b->Ai);
return BN_mod_mul(n,n,b->A,b->mod,ctx);
}
int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
{
return BN_BLINDING_invert_ex(n, NULL, b, ctx);
}
int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
{
int ret;
......@@ -134,7 +236,13 @@ int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
BNerr(BN_F_BN_BLINDING_INVERT,BN_R_NOT_INITIALIZED);
return(0);
}
if ((ret=BN_mod_mul(n,n,b->Ai,b->mod,ctx)) >= 0)
if (r != NULL)
ret = BN_mod_mul(n, n, r, b->mod, ctx);
else
ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
if (ret >= 0)
{
if (!BN_BLINDING_update(b,ctx))
return(0);
......@@ -143,3 +251,105 @@ int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
return(ret);
}
unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *b)
{
return b->thread_id;
}
void BN_BLINDING_set_thread_id(BN_BLINDING *b, unsigned long n)
{
b->thread_id = n;
}
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b)
{
return b->flags;
}
void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags)
{
b->flags = flags;
}
BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx),
BN_MONT_CTX *m_ctx)
{
int retry_counter = 32;
BIGNUM *a, *ai;
BN_BLINDING *ret = NULL;
if (b == NULL)
ret = BN_BLINDING_new(NULL, NULL, m);
else
ret = b;
if (ret == NULL)
goto err;
if (ret->A == NULL && (ret->A = BN_new()) == NULL)
goto err;
if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL)
goto err;
if (e != NULL)
{
if (ret->e != NULL)
BN_free(ret->e);
ret->e = BN_dup(e);
}
if (ret->e == NULL)
goto err;
if (bn_mod_exp != NULL)
ret->bn_mod_exp = bn_mod_exp;
if (m_ctx != NULL)
ret->m_ctx = m_ctx;
do {
if (!BN_rand_range(ret->A, ret->mod)) goto err;
if (BN_mod_inverse(ret->Ai, ret->A, ret->mod, ctx) == NULL)
{
/* this should almost never happen for good RSA keys */
unsigned long error = ERR_peek_last_error();
if (ERR_GET_REASON(error) == BN_R_NO_INVERSE)
{
if (retry_counter-- == 0)
{
BNerr(BN_F_BN_BLINDING_CREATE_PARAM,
BN_R_TOO_MANY_ITERATIONS);
goto err;
}
ERR_clear_error();
}
else
goto err;
}
else
break;
} while (1);
if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL)
{
if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx))
goto err;
}
else
{
if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx))
goto err;
}
return ret;
err:
if (b == NULL && ret != NULL)
{
BN_BLINDING_free(ret);
ret = NULL;
}
return ret;
}
......@@ -72,6 +72,7 @@ static ERR_STRING_DATA BN_str_functs[]=
{
{ERR_FUNC(BN_F_BNRAND), "BNRAND"},
{ERR_FUNC(BN_F_BN_BLINDING_CONVERT), "BN_BLINDING_convert"},
{ERR_FUNC(BN_F_BN_BLINDING_CREATE_PARAM), "BN_BLINDING_create_param"},
{ERR_FUNC(BN_F_BN_BLINDING_INVERT), "BN_BLINDING_invert"},
{ERR_FUNC(BN_F_BN_BLINDING_NEW), "BN_BLINDING_new"},
{ERR_FUNC(BN_F_BN_BLINDING_UPDATE), "BN_BLINDING_update"},
......
......@@ -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
......
......@@ -212,64 +212,78 @@ err:
return(r);
}
static int rsa_eay_blinding(RSA *rsa, BN_CTX *ctx)
static BN_BLINDING *rsa_get_blinding(RSA *rsa, BIGNUM **r, int *local, BN_CTX *ctx)
{
BN_BLINDING *ret;
if (rsa->blinding == NULL)
{
if (rsa->blinding == NULL)
{
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);
if (rsa->blinding == NULL)
rsa->blinding = RSA_setup_blinding(rsa, ctx);
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
return 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)
ret = rsa->blinding;
if (ret == NULL)
return NULL;
static BN_BLINDING *setup_blinding(RSA *rsa, BN_CTX *ctx)
if (BN_BLINDING_get_thread_id(ret) != CRYPTO_thread_id())
{
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)
*local = 0;
if (rsa->mt_blinding == 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;
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;
return ret;
}
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 (!BN_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;
}
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);
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
{
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;
}
}
/* 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;
......@@ -279,8 +293,9 @@ 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);
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)
if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx))
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) &&
......@@ -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;
......@@ -401,8 +395,9 @@ 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);
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)
if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx))
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) ||
......@@ -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);
......
......@@ -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"},
......
......@@ -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)
{
......
......@@ -3305,3 +3305,11 @@ BN_set_negative 3704 EXIST::FUNCTION:
BIO_new_dgram 3705 EXIST::FUNCTION:
BIO_s_datagram 3706 EXIST::FUNCTION:DGRAM
BIO_dgram_non_fatal_error 3707 EXIST::FUNCTION:
RSA_setup_blinding 3708 EXIST::FUNCTION:RSA
BN_BLINDING_set_thread_id 3709 EXIST::FUNCTION:
BN_BLINDING_convert_ex 3710 EXIST::FUNCTION:
BN_BLINDING_create_param 3711 EXIST::FUNCTION:
BN_BLINDING_set_flags 3712 EXIST::FUNCTION:
BN_BLINDING_invert_ex 3713 EXIST::FUNCTION:
BN_BLINDING_get_thread_id 3714 EXIST::FUNCTION:
BN_BLINDING_get_flags 3715 EXIST::FUNCTION:
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册