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
This commit is contained in:
parent
05886a6f77
commit
800e400de5
12
CHANGES
12
CHANGES
@ -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
|
||||
|
@ -1,4 +1,57 @@
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@ -103,16 +179,33 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
|
||||
BNerr(BN_F_BN_BLINDING_UPDATE,BN_R_NOT_INITIALIZED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
||||
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 (rsa->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;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
ret = rsa->blinding;
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
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
|
||||
{
|
||||
if (!BN_rand_range(A,rsa->n)) goto err;
|
||||
}
|
||||
if ((Ai=BN_mod_inverse(NULL,A,rsa->n,ctx)) == NULL) goto err;
|
||||
*local = 1;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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
|
||||
{
|
||||
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;
|
||||
@ -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);
|
||||
|
@ -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,60 +316,101 @@ 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 ((ctx=BN_CTX_new()) == NULL) goto err;
|
||||
}
|
||||
else
|
||||
ctx=p_ctx;
|
||||
|
||||
/* XXXXX: Shouldn't this be RSA_blinding_off(rsa)? */
|
||||
if (rsa->blinding != NULL)
|
||||
{
|
||||
BN_BLINDING_free(rsa->blinding);
|
||||
rsa->blinding = NULL;
|
||||
}
|
||||
RSA_blinding_off(rsa);
|
||||
|
||||
/* 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 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;
|
||||
}
|
||||
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))
|
||||
rsa->blinding = RSA_setup_blinding(rsa, ctx);
|
||||
if (rsa->blinding == NULL)
|
||||
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;
|
||||
err:
|
||||
if (Ai != NULL) BN_free(Ai);
|
||||
BN_CTX_end(ctx);
|
||||
if (ctx != p_ctx) BN_CTX_free(ctx);
|
||||
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) return 0;
|
||||
}
|
||||
else
|
||||
ctx = in_ctx;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
e = BN_CTX_get(ctx);
|
||||
if (e == NULL)
|
||||
{
|
||||
RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rsa->e == NULL)
|
||||
{
|
||||
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 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);
|
||||
}
|
||||
|
||||
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:
|
||||
BN_CTX_end(ctx);
|
||||
if (in_ctx == NULL)
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int RSA_memory_lock(RSA *r)
|
||||
{
|
||||
int i,j,k,off;
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user