Remove usage of malloc() from fp_prime_random_ex.

This is the only instance of dynamic memory in TFM. It can be avoided
by writing directly into the dp[] array, and it does not violate C
aliasing rules which specifically allow access on objects through char*.
It does not matter the platform-specific representation of digits since
we are filling them with random data anyway.
This commit is contained in:
Giovanni Bajo 2011-09-21 17:45:18 +02:00
parent 08b3654ac4
commit 279da69658
2 changed files with 48 additions and 53 deletions

View File

@ -1,10 +1,10 @@
/* TomsFastMath, a fast ISO C bignum library. /* TomsFastMath, a fast ISO C bignum library.
* *
* This project is meant to fill in where LibTomMath * This project is meant to fill in where LibTomMath
* falls short. That is speed ;-) * falls short. That is speed ;-)
* *
* This project is public domain and free for all purposes. * This project is public domain and free for all purposes.
* *
* Tom St Denis, tomstdenis@gmail.com * Tom St Denis, tomstdenis@gmail.com
*/ */
#ifndef TFM_H_ #ifndef TFM_H_
@ -27,13 +27,13 @@
/* externally define this symbol to ignore the default settings, useful for changing the build from the make process */ /* externally define this symbol to ignore the default settings, useful for changing the build from the make process */
#ifndef TFM_ALREADY_SET #ifndef TFM_ALREADY_SET
/* do we want the large set of small multiplications ? /* do we want the large set of small multiplications ?
Enable these if you are going to be doing a lot of small (<= 16 digit) multiplications say in ECC Enable these if you are going to be doing a lot of small (<= 16 digit) multiplications say in ECC
Or if you're on a 64-bit machine doing RSA as a 1024-bit integer == 16 digits ;-) Or if you're on a 64-bit machine doing RSA as a 1024-bit integer == 16 digits ;-)
*/ */
#define TFM_SMALL_SET #define TFM_SMALL_SET
/* do we want huge code /* do we want huge code
Enable these if you are doing 20, 24, 28, 32, 48, 64 digit multiplications (useful for RSA) Enable these if you are doing 20, 24, 28, 32, 48, 64 digit multiplications (useful for RSA)
Less important on 64-bit machines as 32 digits == 2048 bits Less important on 64-bit machines as 32 digits == 2048 bits
*/ */
@ -81,7 +81,7 @@
/* #define TFM_PRESCOTT */ /* #define TFM_PRESCOTT */
/* Do we want timing resistant fp_exptmod() ? /* Do we want timing resistant fp_exptmod() ?
* This makes it slower but also timing invariant with respect to the exponent * This makes it slower but also timing invariant with respect to the exponent
*/ */
/* #define TFM_TIMING_RESISTANT */ /* #define TFM_TIMING_RESISTANT */
@ -106,7 +106,7 @@
/* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */ /* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */
#if defined(__x86_64__) #if defined(__x86_64__)
#if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM) #if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM)
#error x86-64 detected, x86-32/SSE2/ARM optimizations are not valid! #error x86-64 detected, x86-32/SSE2/ARM optimizations are not valid!
#endif #endif
#if !defined(TFM_X86_64) && !defined(TFM_NO_ASM) #if !defined(TFM_X86_64) && !defined(TFM_NO_ASM)
@ -121,7 +121,7 @@
/* try to detect x86-32 */ /* try to detect x86-32 */
#if defined(__i386__) && !defined(TFM_SSE2) #if defined(__i386__) && !defined(TFM_SSE2)
#if defined(TFM_X86_64) || defined(TFM_ARM) #if defined(TFM_X86_64) || defined(TFM_ARM)
#error x86-32 detected, x86-64/ARM optimizations are not valid! #error x86-32 detected, x86-64/ARM optimizations are not valid!
#endif #endif
#if !defined(TFM_X86) && !defined(TFM_NO_ASM) #if !defined(TFM_X86) && !defined(TFM_NO_ASM)
@ -185,7 +185,7 @@
#undef TFM_PPC32 #undef TFM_PPC32
#undef TFM_PPC64 #undef TFM_PPC64
#undef TFM_AVR32 #undef TFM_AVR32
#undef TFM_ASM #undef TFM_ASM
#endif #endif
/* ECC helpers */ /* ECC helpers */
@ -249,6 +249,7 @@
#endif #endif
typedef ulong64 fp_digit; typedef ulong64 fp_digit;
typedef unsigned long fp_word __attribute__ ((mode(TI))); typedef unsigned long fp_word __attribute__ ((mode(TI)));
#define DIGIT_SHIFT 6
#else #else
/* this is to make porting into LibTomCrypt easier :-) */ /* this is to make porting into LibTomCrypt easier :-) */
#ifndef CRYPT #ifndef CRYPT
@ -262,6 +263,7 @@
#endif #endif
typedef unsigned long fp_digit; typedef unsigned long fp_digit;
typedef ulong64 fp_word; typedef ulong64 fp_word;
#define DIGIT_SHIFT 5
#endif #endif
/* # of digits this is */ /* # of digits this is */
@ -290,7 +292,7 @@
/* a FP type */ /* a FP type */
typedef struct { typedef struct {
fp_digit dp[FP_SIZE]; fp_digit dp[FP_SIZE];
int used, int used,
sign; sign;
} fp_int; } fp_int;
@ -434,9 +436,9 @@ int fp_isprime(fp_int *a);
/* callback for fp_prime_random, should fill dst with random bytes and return how many read [upto len] */ /* callback for fp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int tfm_prime_callback(unsigned char *dst, int len, void *dat); typedef int tfm_prime_callback(unsigned char *dst, int len, void *dat);
#define fp_prime_random(a, t, size, bbs, cb, dat) fp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?TFM_PRIME_BBS:0, cb, dat) #define fp_prime_random(a, size, bbs, cb, dat) fp_prime_random_ex(a, ((size) * 8) + 1, (bbs==1)?TFM_PRIME_BBS:0, cb, dat)
int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat); int fp_prime_random_ex(fp_int *a, int size, int flags, tfm_prime_callback cb, void *dat);
/* radix conersions */ /* radix conersions */
int fp_count_bits(fp_int *a); int fp_count_bits(fp_int *a);

View File

@ -1,22 +1,28 @@
/* TomsFastMath, a fast ISO C bignum library. /* TomsFastMath, a fast ISO C bignum library.
* *
* This project is meant to fill in where LibTomMath * This project is meant to fill in where LibTomMath
* falls short. That is speed ;-) * falls short. That is speed ;-)
* *
* This project is public domain and free for all purposes. * This project is public domain and free for all purposes.
* *
* Tom St Denis, tomstdenis@gmail.com * Tom St Denis, tomstdenis@gmail.com
*/ */
#include <tfm.h> #include <tfm.h>
#define fp_on_bitnum(a, bitnum) \
a->dp[(bitnum) >> DIGIT_SHIFT] |= 1 << ((bitnum) & (DIGIT_BIT-1));
#define fp_off_bitnum(a, bitnum) \
a->dp[(bitnum) >> DIGIT_SHIFT] &= ~(1 << ((bitnum) & (DIGIT_BIT-1)));
/* This is possibly the mother of all prime generation functions, muahahahahaha! */ /* This is possibly the mother of all prime generation functions, muahahahahaha! */
int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat) int fp_prime_random_ex(fp_int *a, int size, int flags, tfm_prime_callback cb, void *dat)
{ {
unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb; fp_digit maskAND_msb, maskOR_lsb;
int res, err, bsize, maskOR_msb_offset; int res, err, bsize, dsize;
/* sanity check the input */ /* sanity check the input */
if (size <= 1 || t <= 0) { if (size <= 1) {
return FP_VAL; return FP_VAL;
} }
@ -25,26 +31,11 @@ int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback
flags |= TFM_PRIME_BBS; flags |= TFM_PRIME_BBS;
} }
/* calc the byte size */ /* calc the digit size */
bsize = (size>>3)+(size&7?1:0); dsize = (size + DIGIT_BIT - 1) >> DIGIT_SHIFT;
/* we need a buffer of bsize bytes */ /* calc the maskAND value for the MSbyte */
tmp = malloc(bsize); maskAND_msb = FP_MASK >> ((DIGIT_BIT - (size & (DIGIT_BIT-1))) & (DIGIT_BIT-1));
if (tmp == NULL) {
return FP_MEM;
}
/* calc the maskAND value for the MSbyte*/
maskAND = 0xFF >> ((8 - (size & 7)) & 7);
/* calc the maskOR_msb */
maskOR_msb = 0;
maskOR_msb_offset = (size - 2) >> 3;
if (flags & TFM_PRIME_2MSB_ON) {
maskOR_msb |= 1 << ((size - 2) & 7);
} else if (flags & TFM_PRIME_2MSB_OFF) {
maskAND &= ~(1 << ((size - 2) & 7));
}
/* get the maskOR_lsb */ /* get the maskOR_lsb */
maskOR_lsb = 1; maskOR_lsb = 1;
@ -54,21 +45,26 @@ int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback
do { do {
/* read the bytes */ /* read the bytes */
if (cb(tmp, bsize, dat) != bsize) { if (cb((unsigned char*)&a->dp[0], dsize*DIGIT_BIT, dat) != dsize*DIGIT_BIT) {
err = FP_VAL; return FP_VAL;
goto error;
} }
a->used = dsize;
/* work over the MSbyte */
tmp[0] &= maskAND;
tmp[0] |= 1 << ((size - 1) & 7);
/* mix in the maskORs */ /* make sure the MSbyte has the required number of bits */
tmp[maskOR_msb_offset] |= maskOR_msb; a->dp[dsize-1] &= maskAND_msb;
tmp[bsize-1] |= maskOR_lsb;
/* read it in */ /* modify the LSbyte as requested */
fp_read_unsigned_bin(a, tmp, bsize); a->dp[0] |= maskOR_lsb;
/* turn on the MSbit to force the requested magnitude */
fp_on_bitnum(a, size-1);
/* modify the 2nd MSBit */
if (flags & TFM_PRIME_2MSB_ON) {
fp_on_bitnum(a, size-2);
} else if (flags & TFM_PRIME_2MSB_OFF) {
fp_off_bitnum(a, size-2);
}
/* is it prime? */ /* is it prime? */
res = fp_isprime(a); res = fp_isprime(a);
@ -78,7 +74,7 @@ int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback
/* see if (a-1)/2 is prime */ /* see if (a-1)/2 is prime */
fp_sub_d(a, 1, a); fp_sub_d(a, 1, a);
fp_div_2(a, a); fp_div_2(a, a);
/* is it prime? */ /* is it prime? */
res = fp_isprime(a); res = fp_isprime(a);
} }
@ -90,10 +86,7 @@ int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback
fp_add_d(a, 1, a); fp_add_d(a, 1, a);
} }
err = FP_OKAY; return FP_OKAY;
error:
free(tmp);
return err;
} }
/* $Source$ */ /* $Source$ */