提交 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 @@ ...@@ -4,6 +4,18 @@
Changes between 0.9.7g and 0.9.8 [xx XXX xxxx] 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. *) Add support for DTLS.
[Nagendra Modadugu <nagendra@cs.stanford.edu> and Ben Laurie] [Nagendra Modadugu <nagendra@cs.stanford.edu> and Ben Laurie]
......
...@@ -274,16 +274,6 @@ struct bignum_st ...@@ -274,16 +274,6 @@ struct bignum_st
int flags; 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 */ /* Used for montgomery multiplication */
struct bn_mont_ctx_st struct bn_mont_ctx_st
{ {
...@@ -521,11 +511,26 @@ void BN_MONT_CTX_free(BN_MONT_CTX *mont); ...@@ -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); 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_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); void BN_BLINDING_free(BN_BLINDING *b);
int BN_BLINDING_update(BN_BLINDING *b,BN_CTX *ctx); 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_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 #ifndef OPENSSL_NO_DEPRECATED
void BN_set_params(int mul,int high,int low,int mont); void BN_set_params(int mul,int high,int low,int mont);
...@@ -727,6 +732,7 @@ void ERR_load_BN_strings(void); ...@@ -727,6 +732,7 @@ void ERR_load_BN_strings(void);
/* Function codes. */ /* Function codes. */
#define BN_F_BNRAND 114 #define BN_F_BNRAND 114
#define BN_F_BN_BLINDING_CONVERT 100 #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_INVERT 101
#define BN_F_BN_BLINDING_NEW 102 #define BN_F_BN_BLINDING_NEW 102
#define BN_F_BN_BLINDING_UPDATE 103 #define BN_F_BN_BLINDING_UPDATE 103
......
/* crypto/bn/bn_blind.c */ /* 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) /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved. * All rights reserved.
* *
...@@ -60,11 +113,28 @@ ...@@ -60,11 +113,28 @@
#include "cryptlib.h" #include "cryptlib.h"
#include "bn_lcl.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_BLINDING *ret=NULL;
bn_check_top(Ai);
bn_check_top(mod); bn_check_top(mod);
if ((ret=(BN_BLINDING *)OPENSSL_malloc(sizeof(BN_BLINDING))) == NULL) 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) ...@@ -73,11 +143,16 @@ BN_BLINDING *BN_BLINDING_new(BIGNUM *A, BIGNUM *Ai, BIGNUM *mod)
return(NULL); return(NULL);
} }
memset(ret,0,sizeof(BN_BLINDING)); memset(ret,0,sizeof(BN_BLINDING));
if ((ret->A=BN_new()) == NULL) goto err; if (A != NULL)
if ((ret->Ai=BN_new()) == NULL) goto err; {
if (!BN_copy(ret->A,A)) goto err; if ((ret->A = BN_dup(A)) == NULL) goto err;
if (!BN_copy(ret->Ai,Ai)) goto err; }
ret->mod=mod; if (Ai != NULL)
{
if ((ret->Ai = BN_dup(Ai)) == NULL) goto err;
}
ret->mod = mod;
ret->counter = BN_BLINDING_COUNTER;
return(ret); return(ret);
err: err:
if (ret != NULL) BN_BLINDING_free(ret); if (ret != NULL) BN_BLINDING_free(ret);
...@@ -91,6 +166,7 @@ void BN_BLINDING_free(BN_BLINDING *r) ...@@ -91,6 +166,7 @@ void BN_BLINDING_free(BN_BLINDING *r)
if (r->A != NULL) BN_free(r->A ); if (r->A != NULL) BN_free(r->A );
if (r->Ai != NULL) BN_free(r->Ai); if (r->Ai != NULL) BN_free(r->Ai);
if (r->e != NULL) BN_free(r->e );
OPENSSL_free(r); OPENSSL_free(r);
} }
...@@ -103,16 +179,33 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) ...@@ -103,16 +179,33 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
BNerr(BN_F_BN_BLINDING_UPDATE,BN_R_NOT_INITIALIZED); BNerr(BN_F_BN_BLINDING_UPDATE,BN_R_NOT_INITIALIZED);
goto err; goto err;
} }
if (!BN_mod_mul(b->A,b->A,b->A,b->mod,ctx)) goto err; if (--(b->counter) == 0 && b->e != NULL &&
if (!BN_mod_mul(b->Ai,b->Ai,b->Ai,b->mod,ctx)) goto err; !(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; ret=1;
err: err:
if (b->counter == 0)
b->counter = BN_BLINDING_COUNTER;
return(ret); return(ret);
} }
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) 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); bn_check_top(n);
...@@ -121,10 +214,19 @@ int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) ...@@ -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); BNerr(BN_F_BN_BLINDING_CONVERT,BN_R_NOT_INITIALIZED);
return(0); 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) 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; int ret;
...@@ -134,7 +236,13 @@ int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) ...@@ -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); BNerr(BN_F_BN_BLINDING_INVERT,BN_R_NOT_INITIALIZED);
return(0); 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)) if (!BN_BLINDING_update(b,ctx))
return(0); return(0);
...@@ -143,3 +251,105 @@ int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) ...@@ -143,3 +251,105 @@ int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
return(ret); 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[]= ...@@ -72,6 +72,7 @@ static ERR_STRING_DATA BN_str_functs[]=
{ {
{ERR_FUNC(BN_F_BNRAND), "BNRAND"}, {ERR_FUNC(BN_F_BNRAND), "BNRAND"},
{ERR_FUNC(BN_F_BN_BLINDING_CONVERT), "BN_BLINDING_convert"}, {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_INVERT), "BN_BLINDING_invert"},
{ERR_FUNC(BN_F_BN_BLINDING_NEW), "BN_BLINDING_new"}, {ERR_FUNC(BN_F_BN_BLINDING_NEW), "BN_BLINDING_new"},
{ERR_FUNC(BN_F_BN_BLINDING_UPDATE), "BN_BLINDING_update"}, {ERR_FUNC(BN_F_BN_BLINDING_UPDATE), "BN_BLINDING_update"},
......
...@@ -156,6 +156,7 @@ struct rsa_st ...@@ -156,6 +156,7 @@ struct rsa_st
* NULL */ * NULL */
char *bignum_data; char *bignum_data;
BN_BLINDING *blinding; BN_BLINDING *blinding;
BN_BLINDING *mt_blinding;
}; };
#define RSA_3 0x3L #define RSA_3 0x3L
...@@ -279,6 +280,7 @@ int RSA_verify_ASN1_OCTET_STRING(int type, ...@@ -279,6 +280,7 @@ int RSA_verify_ASN1_OCTET_STRING(int type,
int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); int RSA_blinding_on(RSA *rsa, BN_CTX *ctx);
void RSA_blinding_off(RSA *rsa); 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, int RSA_padding_add_PKCS1_type_1(unsigned char *to,int tlen,
const unsigned char *f,int fl); const unsigned char *f,int fl);
...@@ -341,6 +343,7 @@ void ERR_load_RSA_strings(void); ...@@ -341,6 +343,7 @@ void ERR_load_RSA_strings(void);
#define RSA_F_RSA_PADDING_CHECK_SSLV23 114 #define RSA_F_RSA_PADDING_CHECK_SSLV23 114
#define RSA_F_RSA_PRINT 115 #define RSA_F_RSA_PRINT 115
#define RSA_F_RSA_PRINT_FP 116 #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 117
#define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118 #define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118
#define RSA_F_RSA_VERIFY 119 #define RSA_F_RSA_VERIFY 119
...@@ -367,6 +370,7 @@ void ERR_load_RSA_strings(void); ...@@ -367,6 +370,7 @@ void ERR_load_RSA_strings(void);
#define RSA_R_INVALID_MESSAGE_LENGTH 131 #define RSA_R_INVALID_MESSAGE_LENGTH 131
#define RSA_R_IQMP_NOT_INVERSE_OF_Q 126 #define RSA_R_IQMP_NOT_INVERSE_OF_Q 126
#define RSA_R_KEY_SIZE_TOO_SMALL 120 #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_NULL_BEFORE_BLOCK_MISSING 113
#define RSA_R_N_DOES_NOT_EQUAL_P_Q 127 #define RSA_R_N_DOES_NOT_EQUAL_P_Q 127
#define RSA_R_OAEP_DECODING_ERROR 121 #define RSA_R_OAEP_DECODING_ERROR 121
......
...@@ -212,64 +212,78 @@ err: ...@@ -212,64 +212,78 @@ err:
return(r); 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)
{ {
int ret = 1; BN_BLINDING *ret;
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;
}
#define BLINDING_HELPER(rsa, ctx, err_instr) \ if (rsa->blinding == NULL)
do { \ {
if((!((rsa)->flags & RSA_FLAG_NO_BLINDING)) && \ if (rsa->blinding == NULL)
((rsa)->blinding == NULL) && \ {
!rsa_eay_blinding(rsa, ctx)) \ CRYPTO_w_lock(CRYPTO_LOCK_RSA);
err_instr \ if (rsa->blinding == NULL)
} while(0) rsa->blinding = RSA_setup_blinding(rsa, ctx);
CRYPTO_w_unlock(CRYPTO_LOCK_RSA);
}
}
static BN_BLINDING *setup_blinding(RSA *rsa, BN_CTX *ctx) ret = rsa->blinding;
{ if (ret == NULL)
BIGNUM *A, *Ai; return NULL;
BN_BLINDING *ret = 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); return ret;
* this should be placed in a new function of its own, but for reasons }
* of binary compatibility can't */
BN_CTX_start(ctx); static int rsa_blinding_convert(BN_BLINDING *b, int local, BIGNUM *f,
A = BN_CTX_get(ctx); BIGNUM *r, BN_CTX *ctx)
if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL) {
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 */ int ret;
RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0.0); CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
if (!BN_pseudo_rand_range(A,rsa->n)) goto err; 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 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 */ /* 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)
{ {
BIGNUM *f,*ret; BIGNUM *f, *ret, *br;
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;
...@@ -278,9 +292,10 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, ...@@ -278,9 +292,10 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
if ((ctx=BN_CTX_new()) == NULL) goto err; if ((ctx=BN_CTX_new()) == NULL) goto err;
BN_CTX_start(ctx); BN_CTX_start(ctx);
f = BN_CTX_get(ctx); f = BN_CTX_get(ctx);
br = BN_CTX_get(ctx);
ret = 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); buf = OPENSSL_malloc(num);
if(!f || !ret || !buf) if(!f || !ret || !buf)
{ {
...@@ -312,17 +327,9 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, ...@@ -312,17 +327,9 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
goto err; 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))
{ {
blinding = rsa_get_blinding(rsa, &br, &local_blinding, ctx);
if (blinding == NULL) if (blinding == NULL)
{ {
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); 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, ...@@ -331,20 +338,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
} }
if (blinding != NULL) if (blinding != NULL)
{ if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx))
if (blinding->thread_id != CRYPTO_thread_id()) goto err;
{
/* 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) &&
...@@ -361,7 +356,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, ...@@ -361,7 +356,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
} }
if (blinding) 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 /* put in leading 0 bytes if the number is less than the
* length of the modulus */ * length of the modulus */
...@@ -377,8 +373,6 @@ err: ...@@ -377,8 +373,6 @@ err:
BN_CTX_end(ctx); BN_CTX_end(ctx);
BN_CTX_free(ctx); BN_CTX_free(ctx);
} }
if (local_blinding)
BN_BLINDING_free(blinding);
if (buf != NULL) if (buf != NULL)
{ {
OPENSSL_cleanse(buf,num); OPENSSL_cleanse(buf,num);
...@@ -390,7 +384,7 @@ err: ...@@ -390,7 +384,7 @@ err:
static int RSA_eay_private_decrypt(int flen, const unsigned char *from, static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding) unsigned char *to, RSA *rsa, int padding)
{ {
BIGNUM *f,*ret; BIGNUM *f, *ret, *br;
int j,num=0,r= -1; int j,num=0,r= -1;
unsigned char *p; unsigned char *p;
unsigned char *buf=NULL; unsigned char *buf=NULL;
...@@ -400,9 +394,10 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, ...@@ -400,9 +394,10 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
if((ctx = BN_CTX_new()) == NULL) goto err; if((ctx = BN_CTX_new()) == NULL) goto err;
BN_CTX_start(ctx); BN_CTX_start(ctx);
f = BN_CTX_get(ctx); f = BN_CTX_get(ctx);
br = BN_CTX_get(ctx);
ret = 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); buf = OPENSSL_malloc(num);
if(!f || !ret || !buf) if(!f || !ret || !buf)
{ {
...@@ -427,39 +422,19 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, ...@@ -427,39 +422,19 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
goto err; 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))
{ {
blinding = rsa_get_blinding(rsa, &br, &local_blinding, ctx);
if (blinding == NULL) 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; goto err;
} }
} }
if (blinding != NULL) if (blinding != NULL)
{ if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx))
if (blinding->thread_id != CRYPTO_thread_id()) goto err;
{
/* 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) ||
...@@ -478,7 +453,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, ...@@ -478,7 +453,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
} }
if (blinding) 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; 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 */
...@@ -512,8 +488,6 @@ err: ...@@ -512,8 +488,6 @@ err:
BN_CTX_end(ctx); BN_CTX_end(ctx);
BN_CTX_free(ctx); BN_CTX_free(ctx);
} }
if (local_blinding)
BN_BLINDING_free(blinding);
if (buf != NULL) if (buf != NULL)
{ {
OPENSSL_cleanse(buf,num); OPENSSL_cleanse(buf,num);
......
...@@ -91,6 +91,7 @@ static ERR_STRING_DATA RSA_str_functs[]= ...@@ -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_PADDING_CHECK_SSLV23), "RSA_padding_check_SSLv23"},
{ERR_FUNC(RSA_F_RSA_PRINT), "RSA_print"}, {ERR_FUNC(RSA_F_RSA_PRINT), "RSA_print"},
{ERR_FUNC(RSA_F_RSA_PRINT_FP), "RSA_print_fp"}, {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), "RSA_sign"},
{ERR_FUNC(RSA_F_RSA_SIGN_ASN1_OCTET_STRING), "RSA_sign_ASN1_OCTET_STRING"}, {ERR_FUNC(RSA_F_RSA_SIGN_ASN1_OCTET_STRING), "RSA_sign_ASN1_OCTET_STRING"},
{ERR_FUNC(RSA_F_RSA_VERIFY), "RSA_verify"}, {ERR_FUNC(RSA_F_RSA_VERIFY), "RSA_verify"},
...@@ -120,6 +121,7 @@ static ERR_STRING_DATA RSA_str_reasons[]= ...@@ -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_INVALID_MESSAGE_LENGTH),"invalid message length"},
{ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q) ,"iqmp not inverse of q"}, {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_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_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_N_DOES_NOT_EQUAL_P_Q) ,"n does not equal p q"},
{ERR_REASON(RSA_R_OAEP_DECODING_ERROR) ,"oaep decoding error"}, {ERR_REASON(RSA_R_OAEP_DECODING_ERROR) ,"oaep decoding error"},
......
...@@ -179,6 +179,7 @@ RSA *RSA_new_method(ENGINE *engine) ...@@ -179,6 +179,7 @@ RSA *RSA_new_method(ENGINE *engine)
ret->_method_mod_p=NULL; ret->_method_mod_p=NULL;
ret->_method_mod_q=NULL; ret->_method_mod_q=NULL;
ret->blinding=NULL; ret->blinding=NULL;
ret->mt_blinding=NULL;
ret->bignum_data=NULL; ret->bignum_data=NULL;
ret->flags=ret->meth->flags; ret->flags=ret->meth->flags;
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data); CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data);
...@@ -232,6 +233,7 @@ void RSA_free(RSA *r) ...@@ -232,6 +233,7 @@ void RSA_free(RSA *r)
if (r->dmq1 != NULL) BN_clear_free(r->dmq1); if (r->dmq1 != NULL) BN_clear_free(r->dmq1);
if (r->iqmp != NULL) BN_clear_free(r->iqmp); if (r->iqmp != NULL) BN_clear_free(r->iqmp);
if (r->blinding != NULL) BN_BLINDING_free(r->blinding); 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); if (r->bignum_data != NULL) OPENSSL_free_locked(r->bignum_data);
OPENSSL_free(r); OPENSSL_free(r);
} }
...@@ -314,59 +316,100 @@ void RSA_blinding_off(RSA *rsa) ...@@ -314,59 +316,100 @@ void RSA_blinding_off(RSA *rsa)
rsa->flags |= RSA_FLAG_NO_BLINDING; 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; 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 else
ctx=p_ctx; ctx = in_ctx;
/* XXXXX: Shouldn't this be RSA_blinding_off(rsa)? */ BN_CTX_start(ctx);
if (rsa->blinding != NULL) e = BN_CTX_get(ctx);
if (e == NULL)
{ {
BN_BLINDING_free(rsa->blinding); RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
rsa->blinding = NULL; goto err;
} }
/* NB: similar code appears in setup_blinding (rsa_eay.c); if (rsa->e == NULL)
* 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 */ e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0.0); if (e == NULL)
if (!BN_pseudo_rand_range(A,rsa->n)) goto err; {
RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT);
goto err;
}
} }
else 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)) ret = BN_BLINDING_create_param(NULL, e, rsa->n, ctx,
goto err; rsa->meth->bn_mod_exp, rsa->_method_mod_n);
if ((rsa->blinding=BN_BLINDING_new(A,Ai,rsa->n)) == NULL) goto err; BN_BLINDING_set_thread_id(ret, CRYPTO_thread_id());
/* 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;
err: err:
if (Ai != NULL) BN_free(Ai);
BN_CTX_end(ctx); BN_CTX_end(ctx);
if (ctx != p_ctx) BN_CTX_free(ctx); if (in_ctx == NULL)
return(ret); BN_CTX_free(ctx);
}
return ret;
}
int RSA_memory_lock(RSA *r) int RSA_memory_lock(RSA *r)
{ {
......
...@@ -3305,3 +3305,11 @@ BN_set_negative 3704 EXIST::FUNCTION: ...@@ -3305,3 +3305,11 @@ BN_set_negative 3704 EXIST::FUNCTION:
BIO_new_dgram 3705 EXIST::FUNCTION: BIO_new_dgram 3705 EXIST::FUNCTION:
BIO_s_datagram 3706 EXIST::FUNCTION:DGRAM BIO_s_datagram 3706 EXIST::FUNCTION:DGRAM
BIO_dgram_non_fatal_error 3707 EXIST::FUNCTION: 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.
先完成此消息的编辑!
想要评论请 注册