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

@ -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 */
@ -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

@ -9,14 +9,20 @@
*/ */
#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 */
tmp = malloc(bsize);
if (tmp == NULL) {
return FP_MEM;
}
/* calc the maskAND value for the MSbyte */ /* calc the maskAND value for the MSbyte */
maskAND = 0xFF >> ((8 - (size & 7)) & 7); maskAND_msb = FP_MASK >> ((DIGIT_BIT - (size & (DIGIT_BIT-1))) & (DIGIT_BIT-1));
/* 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 */ /* make sure the MSbyte has the required number of bits */
tmp[0] &= maskAND; a->dp[dsize-1] &= maskAND_msb;
tmp[0] |= 1 << ((size - 1) & 7);
/* mix in the maskORs */ /* modify the LSbyte as requested */
tmp[maskOR_msb_offset] |= maskOR_msb; a->dp[0] |= maskOR_lsb;
tmp[bsize-1] |= maskOR_lsb;
/* read it in */ /* turn on the MSbit to force the requested magnitude */
fp_read_unsigned_bin(a, tmp, bsize); 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);
@ -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$ */