Integrate my implementation of a countermeasure against

Bleichenbacher's DSA attack.  With this implementation, the expected
number of iterations never exceeds 2.

New semantics for BN_rand_range():
BN_rand_range(r, min, range) now generates r such that
     min <= r < min+range.
(Previously, BN_rand_range(r, min, max) generated r such that
     min <= r < max.
It is more convenient to have the range; also the previous
prototype was misleading because max was larger than
the actual maximum.)
This commit is contained in:
Bodo Möller 2001-02-08 12:14:51 +00:00
parent 7edc5ed90a
commit 35ed8cb8b6
6 changed files with 67 additions and 12 deletions

View file

@ -5,7 +5,7 @@
*) Add new function BN_rand_range(), and fix DSA_sign_setup() to prevent *) Add new function BN_rand_range(), and fix DSA_sign_setup() to prevent
Bleichenbacher's DSA attack. Bleichenbacher's DSA attack.
[Ulf Moeller] [Ulf Moeller, Bodo Moeller]
*) Update Rijndael code to version 3.0 and change EVP AES ciphers to *) Update Rijndael code to version 3.0 and change EVP AES ciphers to
handle the new API. Currently only ECB, CBC modes supported. Add new handle the new API. Currently only ECB, CBC modes supported. Add new

View file

@ -329,7 +329,7 @@ BIGNUM *BN_CTX_get(BN_CTX *ctx);
void BN_CTX_end(BN_CTX *ctx); void BN_CTX_end(BN_CTX *ctx);
int BN_rand(BIGNUM *rnd, int bits, int top,int bottom); int BN_rand(BIGNUM *rnd, int bits, int top,int bottom);
int BN_pseudo_rand(BIGNUM *rnd, int bits, int top,int bottom); int BN_pseudo_rand(BIGNUM *rnd, int bits, int top,int bottom);
int BN_rand_range(BIGNUM *rnd, BIGNUM *min, BIGNUM *max); int BN_rand_range(BIGNUM *rnd, BIGNUM *min, BIGNUM *range);
int BN_num_bits(const BIGNUM *a); int BN_num_bits(const BIGNUM *a);
int BN_num_bits_word(BN_ULONG); int BN_num_bits_word(BN_ULONG);
BIGNUM *BN_new(void); BIGNUM *BN_new(void);
@ -527,6 +527,7 @@ int BN_bntest_rand(BIGNUM *rnd, int bits, int top,int bottom);
#define BN_F_BN_MPI2BN 112 #define BN_F_BN_MPI2BN 112
#define BN_F_BN_NEW 113 #define BN_F_BN_NEW 113
#define BN_F_BN_RAND 114 #define BN_F_BN_RAND 114
#define BN_F_BN_RAND_RANGE 122
#define BN_F_BN_USUB 115 #define BN_F_BN_USUB 115
/* Reason codes. */ /* Reason codes. */
@ -539,6 +540,7 @@ int BN_bntest_rand(BIGNUM *rnd, int bits, int top,int bottom);
#define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105 #define BN_R_EXPAND_ON_STATIC_BIGNUM_DATA 105
#define BN_R_INPUT_NOT_REDUCED 110 #define BN_R_INPUT_NOT_REDUCED 110
#define BN_R_INVALID_LENGTH 106 #define BN_R_INVALID_LENGTH 106
#define BN_R_INVALID_RANGE 115
#define BN_R_NOT_A_SQUARE 111 #define BN_R_NOT_A_SQUARE 111
#define BN_R_NOT_INITIALIZED 107 #define BN_R_NOT_INITIALIZED 107
#define BN_R_NO_INVERSE 108 #define BN_R_NO_INVERSE 108

View file

@ -87,6 +87,7 @@ static ERR_STRING_DATA BN_str_functs[]=
{ERR_PACK(0,BN_F_BN_MPI2BN,0), "BN_mpi2bn"}, {ERR_PACK(0,BN_F_BN_MPI2BN,0), "BN_mpi2bn"},
{ERR_PACK(0,BN_F_BN_NEW,0), "BN_new"}, {ERR_PACK(0,BN_F_BN_NEW,0), "BN_new"},
{ERR_PACK(0,BN_F_BN_RAND,0), "BN_rand"}, {ERR_PACK(0,BN_F_BN_RAND,0), "BN_rand"},
{ERR_PACK(0,BN_F_BN_RAND_RANGE,0), "BN_rand_range"},
{ERR_PACK(0,BN_F_BN_USUB,0), "BN_usub"}, {ERR_PACK(0,BN_F_BN_USUB,0), "BN_usub"},
{0,NULL} {0,NULL}
}; };
@ -102,6 +103,7 @@ static ERR_STRING_DATA BN_str_reasons[]=
{BN_R_EXPAND_ON_STATIC_BIGNUM_DATA ,"expand on static bignum data"}, {BN_R_EXPAND_ON_STATIC_BIGNUM_DATA ,"expand on static bignum data"},
{BN_R_INPUT_NOT_REDUCED ,"input not reduced"}, {BN_R_INPUT_NOT_REDUCED ,"input not reduced"},
{BN_R_INVALID_LENGTH ,"invalid length"}, {BN_R_INVALID_LENGTH ,"invalid length"},
{BN_R_INVALID_RANGE ,"invalid range"},
{BN_R_NOT_A_SQUARE ,"not a square"}, {BN_R_NOT_A_SQUARE ,"not a square"},
{BN_R_NOT_INITIALIZED ,"not initialized"}, {BN_R_NOT_INITIALIZED ,"not initialized"},
{BN_R_NO_INVERSE ,"no inverse"}, {BN_R_NO_INVERSE ,"no inverse"},

View file

@ -169,13 +169,62 @@ int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
} }
#endif #endif
/* random number r: min <= r < max */ /* random number r: min <= r < min+range */
int BN_rand_range(BIGNUM *r, BIGNUM *min, BIGNUM *max) int BN_rand_range(BIGNUM *r, BIGNUM *min, BIGNUM *range)
{
int n;
if (range->neg || BN_is_zero(range))
{
BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE);
return 0;
}
n = BN_num_bits(range); /* n > 0 */
if (n == 1)
{
if (!BN_zero(r)) return 0;
}
else if (BN_is_bit_set(range, n - 2))
{ {
int n = BN_num_bits(max);
do do
{ {
/* range = 11..._2, so each iteration succeeds with probability > .5 */
if (!BN_rand(r, n, 0, 0)) return 0; if (!BN_rand(r, n, 0, 0)) return 0;
} while ((min && BN_cmp(r, min) < 0) || BN_cmp(r, max) >= 0); fprintf(stderr, "?");
}
while (BN_cmp(r, range) >= 0);
fprintf(stderr, "! (11...)\n");
}
else
{
/* range = 10..._2,
* so 3*range (= 11..._2) is exactly one bit longer than range */
do
{
if (!BN_rand(r, n + 1, 0, 0)) return 0;
/* If r < 3*range, use r := r MOD range
* (which is either r, r - range, or r - 2*range).
* Otherwise, iterate once more.
* Since 3*range = 11..._2, each iteration succeeds with
* probability > .5. */
if (BN_cmp(r ,range) >= 0)
{
if (!BN_sub(r, r, range)) return 0;
if (BN_cmp(r, range) >= 0)
if (!BN_sub(r, r, range)) return 0;
}
fprintf(stderr, "?");
}
while (BN_cmp(r, range) >= 0);
fprintf(stderr, "! (10...)\n");
}
if (min != NULL)
{
if (!BN_add(r, r, min)) return 0;
}
return 1; return 1;
} }

View file

@ -180,7 +180,9 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
kinv=NULL; kinv=NULL;
/* Get random k */ /* Get random k */
if (!BN_rand_range(&k, BN_value_one(), dsa->q)) goto err; do
if (!BN_rand_range(&k, NULL, dsa->q)) goto err;
while (BN_is_zero(&k));
if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P)) if ((dsa->method_mont_p == NULL) && (dsa->flags & DSA_FLAG_CACHE_MONT_P))
{ {

View file

@ -12,7 +12,7 @@ BN_rand, BN_pseudo_rand - generate pseudo-random number
int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom); int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom);
int BN_rand_range(BIGNUM *rnd, BIGNUM *min, BIGNUM *max); int BN_rand_range(BIGNUM *rnd, BIGNUM *min, BIGNUM *range);
=head1 DESCRIPTION =head1 DESCRIPTION
@ -28,8 +28,8 @@ non-cryptographic purposes and for certain purposes in cryptographic
protocols, but usually not for key generation etc. protocols, but usually not for key generation etc.
BN_rand_range() generates a cryptographically strong pseudo-random BN_rand_range() generates a cryptographically strong pseudo-random
number B<rnd> in the range B<min> E<lt>= B<rnd> E<lt> B<max>. B<min> number B<rnd> in the range B<min> E<lt>= B<rnd> E<lt> B<min> + B<range>.
may be NULL, in that case 0 E<lt>= B<rnd> E<lt> B<max>. B<min> may be NULL, in that case 0 E<lt>= B<rnd> E<lt> B<range>.
The PRNG must be seeded prior to calling BN_rand() or BN_rand_range(). The PRNG must be seeded prior to calling BN_rand() or BN_rand_range().