From 279da69658f1e9fda3e8e1c464ffbf666c6f232c Mon Sep 17 00:00:00 2001 From: Giovanni Bajo Date: Wed, 21 Sep 2011 17:45:18 +0200 Subject: [PATCH] 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. --- src/headers/tfm.h | 24 +++++----- src/numtheory/fp_prime_random_ex.c | 77 ++++++++++++++---------------- 2 files changed, 48 insertions(+), 53 deletions(-) diff --git a/src/headers/tfm.h b/src/headers/tfm.h index 9d2bbac..d62f977 100644 --- a/src/headers/tfm.h +++ b/src/headers/tfm.h @@ -1,10 +1,10 @@ /* TomsFastMath, a fast ISO C bignum library. - * + * * This project is meant to fill in where LibTomMath * falls short. That is speed ;-) * * This project is public domain and free for all purposes. - * + * * Tom St Denis, tomstdenis@gmail.com */ #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 */ #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 Or if you're on a 64-bit machine doing RSA as a 1024-bit integer == 16 digits ;-) */ #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) Less important on 64-bit machines as 32 digits == 2048 bits */ @@ -81,7 +81,7 @@ /* #define TFM_PRESCOTT */ /* 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 */ @@ -106,7 +106,7 @@ /* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */ #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! #endif #if !defined(TFM_X86_64) && !defined(TFM_NO_ASM) @@ -121,7 +121,7 @@ /* try to detect x86-32 */ #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! #endif #if !defined(TFM_X86) && !defined(TFM_NO_ASM) @@ -185,7 +185,7 @@ #undef TFM_PPC32 #undef TFM_PPC64 #undef TFM_AVR32 - #undef TFM_ASM + #undef TFM_ASM #endif /* ECC helpers */ @@ -249,6 +249,7 @@ #endif typedef ulong64 fp_digit; typedef unsigned long fp_word __attribute__ ((mode(TI))); + #define DIGIT_SHIFT 6 #else /* this is to make porting into LibTomCrypt easier :-) */ #ifndef CRYPT @@ -262,6 +263,7 @@ #endif typedef unsigned long fp_digit; typedef ulong64 fp_word; + #define DIGIT_SHIFT 5 #endif /* # of digits this is */ @@ -290,7 +292,7 @@ /* a FP type */ typedef struct { fp_digit dp[FP_SIZE]; - int used, + int used, sign; } 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] */ 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 */ int fp_count_bits(fp_int *a); diff --git a/src/numtheory/fp_prime_random_ex.c b/src/numtheory/fp_prime_random_ex.c index 106d216..7db5e9e 100644 --- a/src/numtheory/fp_prime_random_ex.c +++ b/src/numtheory/fp_prime_random_ex.c @@ -1,22 +1,28 @@ /* TomsFastMath, a fast ISO C bignum library. - * + * * This project is meant to fill in where LibTomMath * falls short. That is speed ;-) * * This project is public domain and free for all purposes. - * + * * Tom St Denis, tomstdenis@gmail.com */ #include +#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! */ -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; - int res, err, bsize, maskOR_msb_offset; + fp_digit maskAND_msb, maskOR_lsb; + int res, err, bsize, dsize; /* sanity check the input */ - if (size <= 1 || t <= 0) { + if (size <= 1) { 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; } - /* calc the byte size */ - bsize = (size>>3)+(size&7?1:0); + /* calc the digit size */ + dsize = (size + DIGIT_BIT - 1) >> DIGIT_SHIFT; - /* we need a buffer of bsize bytes */ - tmp = malloc(bsize); - 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)); - } + /* calc the maskAND value for the MSbyte */ + maskAND_msb = FP_MASK >> ((DIGIT_BIT - (size & (DIGIT_BIT-1))) & (DIGIT_BIT-1)); /* get the maskOR_lsb */ 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 { /* read the bytes */ - if (cb(tmp, bsize, dat) != bsize) { - err = FP_VAL; - goto error; + if (cb((unsigned char*)&a->dp[0], dsize*DIGIT_BIT, dat) != dsize*DIGIT_BIT) { + return FP_VAL; } - - /* work over the MSbyte */ - tmp[0] &= maskAND; - tmp[0] |= 1 << ((size - 1) & 7); + a->used = dsize; - /* mix in the maskORs */ - tmp[maskOR_msb_offset] |= maskOR_msb; - tmp[bsize-1] |= maskOR_lsb; + /* make sure the MSbyte has the required number of bits */ + a->dp[dsize-1] &= maskAND_msb; - /* read it in */ - fp_read_unsigned_bin(a, tmp, bsize); + /* modify the LSbyte as requested */ + 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? */ 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 */ fp_sub_d(a, 1, a); fp_div_2(a, a); - + /* is it prime? */ 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); } - err = FP_OKAY; -error: - free(tmp); - return err; + return FP_OKAY; } /* $Source$ */