From 8c1b296e864cf955ef3cd83b9ee66154bc291eba Mon Sep 17 00:00:00 2001 From: Daniel Mendler Date: Mon, 8 Apr 2019 23:48:39 +0200 Subject: [PATCH] add feature detection macro MP_HAS --- bn_mp_div_d.c | 4 +- bn_mp_exptmod.c | 39 +++++--------- bn_mp_invmod.c | 12 ++--- bn_mp_mul.c | 110 ++++++++++++++-------------------------- bn_mp_reduce.c | 14 ++--- bn_mp_sqr.c | 42 +++++---------- bn_s_mp_exptmod.c | 8 ++- bn_s_mp_exptmod_fast.c | 94 ++++++++++++++++------------------ bn_s_mp_mul_high_digs.c | 5 +- bn_s_mp_rand_platform.c | 63 ++++++++++------------- demo/test.c | 44 ++++++++++++++++ tommath_class.h | 1 + tommath_private.h | 5 ++ 13 files changed, 199 insertions(+), 242 deletions(-) diff --git a/bn_mp_div_d.c b/bn_mp_div_d.c index 569f594..a1f1212 100644 --- a/bn_mp_div_d.c +++ b/bn_mp_div_d.c @@ -43,12 +43,10 @@ mp_err mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d) return MP_OKAY; } -#ifdef BN_MP_DIV_3_C /* three? */ - if (b == 3u) { + if (MP_HAS(MP_DIV_3) && b == 3u) { return mp_div_3(a, c, d); } -#endif /* no easy answer [c'est la vie]. Just division */ if ((err = mp_init_size(&q, a->used)) != MP_OKAY) { diff --git a/bn_mp_exptmod.c b/bn_mp_exptmod.c index 95a1dcb..f6846cc 100644 --- a/bn_mp_exptmod.c +++ b/bn_mp_exptmod.c @@ -19,10 +19,13 @@ mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) /* if exponent X is negative we have to recurse */ if (X->sign == MP_NEG) { -#ifdef BN_MP_INVMOD_C mp_int tmpG, tmpX; mp_err err; + if (!MP_HAS(MP_INVMOD)) { + return MP_VAL; + } + /* first compute 1/G mod P */ if ((err = mp_init(&tmpG)) != MP_OKAY) { return err; @@ -46,50 +49,32 @@ mp_err mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y) err = mp_exptmod(&tmpG, &tmpX, P, Y); mp_clear_multi(&tmpG, &tmpX, NULL); return err; -#else - /* no invmod */ - return MP_VAL; -#endif } /* modified diminished radix reduction */ -#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C) - if (mp_reduce_is_2k_l(P) == MP_YES) { + if (MP_HAS(MP_REDUCE_IS_2K_L) && MP_HAS(MP_REDUCE_2K_L) && MP_HAS(S_MP_EXPTMOD) && + mp_reduce_is_2k_l(P) == MP_YES) { return s_mp_exptmod(G, X, P, Y, 1); } -#endif -#ifdef BN_MP_DR_IS_MODULUS_C - /* is it a DR modulus? */ - dr = (mp_dr_is_modulus(P) == MP_YES) ? 1 : 0; -#else - /* default to no */ - dr = 0; -#endif + /* is it a DR modulus? default to no */ + dr = MP_HAS(MP_DR_IS_MODULUS) && mp_dr_is_modulus(P) == MP_YES ? 1 : 0; -#ifdef BN_MP_REDUCE_IS_2K_C /* if not, is it a unrestricted DR modulus? */ - if (dr == 0) { + if (MP_HAS(MP_REDUCE_IS_2K) && dr == 0) { dr = (mp_reduce_is_2k(P) == MP_YES) ? 2 : 0; } -#endif /* if the modulus is odd or dr != 0 use the montgomery method */ -#ifdef BN_S_MP_EXPTMOD_FAST_C - if (MP_IS_ODD(P) || (dr != 0)) { + if (MP_HAS(S_MP_EXPTMOD_FAST) && (MP_IS_ODD(P) || (dr != 0))) { return s_mp_exptmod_fast(G, X, P, Y, dr); - } else { -#endif -#ifdef BN_S_MP_EXPTMOD_C + } else if (MP_HAS(S_MP_EXPTMOD)) { /* otherwise use the generic Barrett reduction technique */ return s_mp_exptmod(G, X, P, Y, 0); -#else + } else { /* no exptmod for evens */ return MP_VAL; -#endif -#ifdef BN_S_MP_EXPTMOD_FAST_C } -#endif } #endif diff --git a/bn_mp_invmod.c b/bn_mp_invmod.c index d5d6bbc..7b35a24 100644 --- a/bn_mp_invmod.c +++ b/bn_mp_invmod.c @@ -11,17 +11,13 @@ mp_err mp_invmod(const mp_int *a, const mp_int *b, mp_int *c) return MP_VAL; } -#ifdef BN_S_MP_INVMOD_FAST_C /* if the modulus is odd we can use a faster routine instead */ - if (MP_IS_ODD(b)) { + if (MP_HAS(S_MP_INVMOD_FAST) && MP_IS_ODD(b)) { return s_mp_invmod_fast(a, b, c); } -#endif -#ifdef BN_S_MP_INVMOD_SLOW_C - return s_mp_invmod_slow(a, b, c); -#else - return MP_VAL; -#endif + return MP_HAS(S_MP_INVMOD_SLOW) + ? s_mp_invmod_slow(a, b, c) + : MP_VAL; } #endif diff --git a/bn_mp_mul.c b/bn_mp_mul.c index f0ca04a..a09a68b 100644 --- a/bn_mp_mul.c +++ b/bn_mp_mul.c @@ -6,80 +6,46 @@ /* high level multiplication (handles sign) */ mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c) { - mp_err err; - mp_sign neg; -#ifdef BN_S_MP_BALANCE_MUL_C - int len_b, len_a; -#endif - neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; -#ifdef BN_S_MP_BALANCE_MUL_C - len_a = a->used; - len_b = b->used; + mp_err err; + int min_len = MP_MIN(a->used, b->used), + max_len = MP_MAX(a->used, b->used), + digs = a->used + b->used + 1; + mp_sign neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; - if (len_a == len_b) { - goto GO_ON; - } - /* - * Check sizes. The smaller one needs to be larger than the Karatsuba cut-off. - * The bigger one needs to be at least about one KARATSUBA_MUL_CUTOFF bigger - * to make some sense, but it depends on architecture, OS, position of the - * stars... so YMMV. - * Using it to cut the input into slices small enough for fast_s_mp_mul_digs - * was actually slower on the author's machine, but YMMV. - */ - if ((MP_MIN(len_a, len_b) < MP_KARATSUBA_MUL_CUTOFF) - || ((MP_MAX(len_a, len_b) / 2) < MP_KARATSUBA_MUL_CUTOFF)) { - goto GO_ON; - } - /* - * Not much effect was observed below a ratio of 1:2, but again: YMMV. - */ - if ((MP_MAX(len_a, len_b) / MP_MIN(len_a, len_b)) < 2) { - goto GO_ON; - } - - err = s_mp_balance_mul(a,b,c); - goto END; - -GO_ON: -#endif - - /* use Toom-Cook? */ -#ifdef BN_S_MP_TOOM_MUL_C - if (MP_MIN(a->used, b->used) >= MP_TOOM_MUL_CUTOFF) { + if (MP_HAS(S_MP_BALANCE_MUL) && + /* Check sizes. The smaller one needs to be larger than the Karatsuba cut-off. + * The bigger one needs to be at least about one MP_KARATSUBA_MUL_CUTOFF bigger + * to make some sense, but it depends on architecture, OS, position of the + * stars... so YMMV. + * Using it to cut the input into slices small enough for fast_s_mp_mul_digs + * was actually slower on the author's machine, but YMMV. + */ + (min_len >= MP_KARATSUBA_MUL_CUTOFF) && + (max_len / 2 >= MP_KARATSUBA_MUL_CUTOFF) && + /* Not much effect was observed below a ratio of 1:2, but again: YMMV. */ + (max_len >= (2 * min_len))) { + err = s_mp_balance_mul(a,b,c); + } else if (MP_HAS(S_MP_TOOM_MUL) && + (min_len >= MP_TOOM_MUL_CUTOFF)) { err = s_mp_toom_mul(a, b, c); - } else -#endif -#ifdef BN_S_MP_KARATSUBA_MUL_C - /* use Karatsuba? */ - if (MP_MIN(a->used, b->used) >= MP_KARATSUBA_MUL_CUTOFF) { - err = s_mp_karatsuba_mul(a, b, c); - } else -#endif - { - /* can we use the fast multiplier? - * - * The fast multiplier can be used if the output will - * have less than MP_WARRAY digits and the number of - * digits won't affect carry propagation - */ - int digs = a->used + b->used + 1; - -#ifdef BN_S_MP_MUL_DIGS_FAST_C - if ((digs < MP_WARRAY) && - (MP_MIN(a->used, b->used) <= MP_MAXFAST)) { - err = s_mp_mul_digs_fast(a, b, c, digs); - } else -#endif - { -#ifdef BN_S_MP_MUL_DIGS_C - err = s_mp_mul_digs(a, b, c, a->used + b->used + 1); -#else - err = MP_VAL; -#endif - } - } -END: + } else if (MP_HAS(S_MP_KARATSUBA_MUL) && + (min_len >= MP_KARATSUBA_MUL_CUTOFF)) { + err = s_mp_karatsuba_mul(a, b, c); + } else if (MP_HAS(S_MP_MUL_DIGS_FAST) && + /* can we use the fast multiplier? + * + * The fast multiplier can be used if the output will + * have less than MP_WARRAY digits and the number of + * digits won't affect carry propagation + */ + (digs < MP_WARRAY) && + (min_len <= MP_MAXFAST)) { + err = s_mp_mul_digs_fast(a, b, c, digs); + } else if (MP_HAS(S_MP_MUL_DIGS)) { + err = s_mp_mul_digs(a, b, c, digs); + } else { + err = MP_VAL; + } c->sign = (c->used > 0) ? neg : MP_ZPOS; return err; } diff --git a/bn_mp_reduce.c b/bn_mp_reduce.c index 5748550..3c669d4 100644 --- a/bn_mp_reduce.c +++ b/bn_mp_reduce.c @@ -26,21 +26,17 @@ mp_err mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu) if ((err = mp_mul(&q, mu, &q)) != MP_OKAY) { goto CLEANUP; } - } else { -#ifdef BN_S_MP_MUL_HIGH_DIGS_C + } else if (MP_HAS(S_MP_MUL_HIGH_DIGS)) { if ((err = s_mp_mul_high_digs(&q, mu, &q, um)) != MP_OKAY) { goto CLEANUP; } -#elif defined(BN_S_MP_MUL_HIGH_DIGS_FAST_C) + } else if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST)) { if ((err = s_mp_mul_high_digs_fast(&q, mu, &q, um)) != MP_OKAY) { goto CLEANUP; } -#else - { - err = MP_VAL; - goto CLEANUP; - } -#endif + } else { + err = MP_VAL; + goto CLEANUP; } /* q3 = q2 / b**(k+1) */ diff --git a/bn_mp_sqr.c b/bn_mp_sqr.c index d4c7d17..d99cacc 100644 --- a/bn_mp_sqr.c +++ b/bn_mp_sqr.c @@ -7,35 +7,21 @@ mp_err mp_sqr(const mp_int *a, mp_int *b) { mp_err err; - -#ifdef BN_S_MP_TOOM_SQR_C - /* use Toom-Cook? */ - if (a->used >= MP_TOOM_SQR_CUTOFF) { + if (MP_HAS(S_MP_TOOM_SQR) && /* use Toom-Cook? */ + a->used >= MP_TOOM_SQR_CUTOFF) { err = s_mp_toom_sqr(a, b); - /* Karatsuba? */ - } else -#endif -#ifdef BN_S_MP_KARATSUBA_SQR_C - if (a->used >= MP_KARATSUBA_SQR_CUTOFF) { - err = s_mp_karatsuba_sqr(a, b); - } else -#endif - { -#ifdef BN_S_MP_SQR_FAST_C - /* can we use the fast comba multiplier? */ - if ((((a->used * 2) + 1) < MP_WARRAY) && - (a->used < (MP_MAXFAST / 2))) { - err = s_mp_sqr_fast(a, b); - } else -#endif - { -#ifdef BN_S_MP_SQR_C - err = s_mp_sqr(a, b); -#else - err = MP_VAL; -#endif - } - } + } else if (MP_HAS(S_MP_KARATSUBA_SQR) && /* Karatsuba? */ + a->used >= MP_KARATSUBA_SQR_CUTOFF) { + err = s_mp_karatsuba_sqr(a, b); + } else if (MP_HAS(S_MP_SQR_FAST) && /* can we use the fast comba multiplier? */ + (((a->used * 2) + 1) < MP_WARRAY) && + (a->used < (MP_MAXFAST / 2))) { + err = s_mp_sqr_fast(a, b); + } else if (MP_HAS(S_MP_SQR)) { + err = s_mp_sqr(a, b); + } else { + err = MP_VAL; + } b->sign = MP_ZPOS; return err; } diff --git a/bn_s_mp_exptmod.c b/bn_s_mp_exptmod.c index 5d5510f..ee82d7a 100644 --- a/bn_s_mp_exptmod.c +++ b/bn_s_mp_exptmod.c @@ -5,8 +5,10 @@ #ifdef MP_LOW_MEM # define TAB_SIZE 32 +# define MAX_WINSIZE 5 #else # define TAB_SIZE 256 +# define MAX_WINSIZE 0 #endif mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) @@ -35,11 +37,7 @@ mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y winsize = 8; } -#ifdef MP_LOW_MEM - if (winsize > 5) { - winsize = 5; - } -#endif + winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize; /* init M array */ /* init first cell */ diff --git a/bn_s_mp_exptmod_fast.c b/bn_s_mp_exptmod_fast.c index 43a2ba1..56e2b2b 100644 --- a/bn_s_mp_exptmod_fast.c +++ b/bn_s_mp_exptmod_fast.c @@ -13,8 +13,10 @@ #ifdef MP_LOW_MEM # define TAB_SIZE 32 +# define MAX_WINSIZE 5 #else # define TAB_SIZE 256 +# define MAX_WINSIZE 0 #endif mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) @@ -48,11 +50,7 @@ mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_i winsize = 8; } -#ifdef MP_LOW_MEM - if (winsize > 5) { - winsize = 5; - } -#endif + winsize = MAX_WINSIZE ? MP_MIN(MAX_WINSIZE, winsize) : winsize; /* init M array */ /* init first cell */ @@ -73,52 +71,46 @@ mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_i /* determine and setup reduction code */ if (redmode == 0) { -#ifdef BN_MP_MONTGOMERY_SETUP_C - /* now setup montgomery */ - if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) { - goto LBL_M; - } -#else - err = MP_VAL; - goto LBL_M; -#endif - - /* automatically pick the comba one if available (saves quite a few calls/ifs) */ -#ifdef BN_S_MP_MONTGOMERY_REDUCE_FAST_C - if ((((P->used * 2) + 1) < MP_WARRAY) && - (P->used < MP_MAXFAST)) { - redux = s_mp_montgomery_reduce_fast; - } else -#endif - { -#ifdef BN_MP_MONTGOMERY_REDUCE_C - /* use slower baseline Montgomery method */ - redux = mp_montgomery_reduce; -#else + if (MP_HAS(MP_MONTGOMERY_SETUP)) { + /* now setup montgomery */ + if ((err = mp_montgomery_setup(P, &mp)) != MP_OKAY) { + goto LBL_M; + } + } else { + err = MP_VAL; + goto LBL_M; + } + + /* automatically pick the comba one if available (saves quite a few calls/ifs) */ + if (MP_HAS(S_MP_MONTGOMERY_REDUCE_FAST) && + (((P->used * 2) + 1) < MP_WARRAY) && + (P->used < MP_MAXFAST)) { + redux = s_mp_montgomery_reduce_fast; + } else if (MP_HAS(MP_MONTGOMERY_REDUCE)) { + /* use slower baseline Montgomery method */ + redux = mp_montgomery_reduce; + } else { err = MP_VAL; goto LBL_M; -#endif } } else if (redmode == 1) { -#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C) - /* setup DR reduction for moduli of the form B**k - b */ - mp_dr_setup(P, &mp); - redux = mp_dr_reduce; -#else - err = MP_VAL; - goto LBL_M; -#endif - } else { -#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) + if (MP_HAS(MP_DR_SETUP) && MP_HAS(MP_DR_REDUCE)) { + /* setup DR reduction for moduli of the form B**k - b */ + mp_dr_setup(P, &mp); + redux = mp_dr_reduce; + } else { + err = MP_VAL; + goto LBL_M; + } + } else if (MP_HAS(MP_REDUCE_2K_SETUP) && MP_HAS(MP_REDUCE_2K)) { /* setup DR reduction for moduli of the form 2**k - b */ if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { goto LBL_M; } redux = mp_reduce_2k; -#else + } else { err = MP_VAL; goto LBL_M; -#endif } /* setup result */ @@ -134,20 +126,20 @@ mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_i */ if (redmode == 0) { -#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C - /* now we need R mod m */ - if ((err = mp_montgomery_calc_normalization(&res, P)) != MP_OKAY) { - goto LBL_RES; - } + if (MP_HAS(MP_MONTGOMERY_CALC_NORMALIZATION)) { + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization(&res, P)) != MP_OKAY) { + goto LBL_RES; + } - /* now set M[1] to G * R mod m */ - if ((err = mp_mulmod(G, &res, P, &M[1])) != MP_OKAY) { + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod(G, &res, P, &M[1])) != MP_OKAY) { + goto LBL_RES; + } + } else { + err = MP_VAL; goto LBL_RES; } -#else - err = MP_VAL; - goto LBL_RES; -#endif } else { mp_set(&res, 1uL); if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { diff --git a/bn_s_mp_mul_high_digs.c b/bn_s_mp_mul_high_digs.c index e5e1ba4..2bb2a50 100644 --- a/bn_s_mp_mul_high_digs.c +++ b/bn_s_mp_mul_high_digs.c @@ -16,12 +16,11 @@ mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) mp_digit tmpx, *tmpt, *tmpy; /* can we use the fast multiplier? */ -#ifdef BN_S_MP_MUL_HIGH_DIGS_FAST_C - if (((a->used + b->used + 1) < MP_WARRAY) + if (MP_HAS(S_MP_MUL_HIGH_DIGS_FAST) + && ((a->used + b->used + 1) < MP_WARRAY) && (MP_MIN(a->used, b->used) < MP_MAXFAST)) { return s_mp_mul_high_digs_fast(a, b, c, digs); } -#endif if ((err = mp_init_size(&t, a->used + b->used + 1)) != MP_OKAY) { return err; diff --git a/bn_s_mp_rand_platform.c b/bn_s_mp_rand_platform.c index 1349b7c..950faed 100644 --- a/bn_s_mp_rand_platform.c +++ b/bn_s_mp_rand_platform.c @@ -8,11 +8,16 @@ * - Windows */ #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) -# define MP_ARC4RANDOM +#define BN_S_READ_ARC4RANDOM_C +static mp_err s_read_arc4random(void *p, size_t n) +{ + arc4random_buf(p, n); + return MP_OKAY; +} #endif #if defined(_WIN32) || defined(_WIN32_WCE) -#define MP_WIN_CSP +#define BN_S_READ_WINCSP_C #ifndef _WIN32_WINNT #define _WIN32_WINNT 0x0400 @@ -33,7 +38,7 @@ # pragma warning(pop) #endif -static mp_err s_read_win_csp(void *p, size_t n) +static mp_err s_read_wincsp(void *p, size_t n) { static HCRYPTPROV hProv = 0; if (hProv == 0) { @@ -50,9 +55,9 @@ static mp_err s_read_win_csp(void *p, size_t n) } #endif /* WIN32 */ -#if !defined(MP_WIN_CSP) && defined(__linux__) && defined(__GLIBC_PREREQ) +#if !defined(BN_S_READ_WINCSP_C) && defined(__linux__) && defined(__GLIBC_PREREQ) #if __GLIBC_PREREQ(2, 25) -#define MP_GETRANDOM +#define BN_S_READ_GETRANDOM_C #include #include @@ -78,7 +83,8 @@ static mp_err s_read_getrandom(void *p, size_t n) /* We assume all platforms besides windows provide "/dev/urandom". * In case yours doesn't, define MP_NO_DEV_URANDOM at compile-time. */ -#if !defined(MP_WIN_CSP) && !defined(MP_NO_DEV_URANDOM) +#if !defined(BN_S_READ_WINCSP_C) && !defined(MP_NO_DEV_URANDOM) +#define BN_S_READ_URANDOM_C #ifndef MP_DEV_URANDOM #define MP_DEV_URANDOM "/dev/urandom" #endif @@ -86,7 +92,7 @@ static mp_err s_read_getrandom(void *p, size_t n) #include #include -static mp_err s_read_dev_urandom(void *p, size_t n) +static mp_err s_read_urandom(void *p, size_t n) { int fd; char *q = (char *)p; @@ -115,6 +121,7 @@ static mp_err s_read_dev_urandom(void *p, size_t n) #endif #if defined(MP_PRNG_ENABLE_LTM_RNG) +#define B_S_READ_LTM_RNG unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void)); void (*ltm_rng_callback)(void); @@ -128,37 +135,21 @@ static mp_err s_read_ltm_rng(void *p, size_t n) } #endif +mp_err s_read_arc4random(void *p, size_t n); +mp_err s_read_wincsp(void *p, size_t n); +mp_err s_read_getrandom(void *p, size_t n); +mp_err s_read_urandom(void *p, size_t n); +mp_err s_read_ltm_rng(void *p, size_t n); + mp_err s_mp_rand_platform(void *p, size_t n) { -#if defined(MP_ARC4RANDOM) - arc4random_buf(p, n); - return MP_OKAY; -#else - - mp_err res = MP_ERR; - -#if defined(MP_WIN_CSP) - res = s_read_win_csp(p, n); - if (res == MP_OKAY) return res; -#endif - -#if defined(MP_GETRANDOM) - res = s_read_getrandom(p, n); - if (res == MP_OKAY) return res; -#endif - -#if defined(MP_DEV_URANDOM) - res = s_read_dev_urandom(p, n); - if (res == MP_OKAY) return res; -#endif - -#if defined(MP_PRNG_ENABLE_LTM_RNG) - res = s_read_ltm_rng(p, n); - if (res == MP_OKAY) return res; -#endif - - return res; -#endif + mp_err err = MP_ERR; + if ((err != MP_OKAY) && MP_HAS(S_READ_ARC4RANDOM)) err = s_read_arc4random(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_GETRANDOM)) err = s_read_getrandom(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_URANDOM)) err = s_read_urandom(p, n); + if ((err != MP_OKAY) && MP_HAS(S_READ_LTM_RNG)) err = s_read_ltm_rng(p, n); + return err; } #endif diff --git a/demo/test.c b/demo/test.c index 11f243f..7ea3225 100644 --- a/demo/test.c +++ b/demo/test.c @@ -50,6 +50,49 @@ static uint64_t uabs64(int64_t x) return x > 0 ? (uint64_t)x : -(uint64_t)x; } +/* This function prototype is needed + * to test dead code elimination + * which is used for feature detection. + * + * If the feature detection does not + * work as desired we will get a linker error. + */ +void does_not_exist(void); + +static int test_feature_detection(void) +{ +#define BN_TEST_FEATURE1_C + if (!MP_HAS(TEST_FEATURE1)) { + does_not_exist(); + return EXIT_FAILURE; + } + +#define BN_TEST_FEATURE2_C 1 + if (MP_HAS(TEST_FEATURE2)) { + does_not_exist(); + return EXIT_FAILURE; + } + +#define BN_TEST_FEATURE3_C 0 + if (MP_HAS(TEST_FEATURE3)) { + does_not_exist(); + return EXIT_FAILURE; + } + +#define BN_TEST_FEATURE4_C something + if (MP_HAS(TEST_FEATURE4)) { + does_not_exist(); + return EXIT_FAILURE; + } + + if (MP_HAS(TEST_FEATURE5)) { + does_not_exist(); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + static int test_trivial_stuff(void) { mp_int a, b, c, d; @@ -2046,6 +2089,7 @@ int unit_tests(int argc, char **argv) int (*fn)(void); } test[] = { #define T(n) { #n, test_##n } + T(feature_detection), T(trivial_stuff), T(mp_get_set_i32), T(mp_get_set_i64), diff --git a/tommath_class.h b/tommath_class.h index ae4405f..cc94e16 100644 --- a/tommath_class.h +++ b/tommath_class.h @@ -860,6 +860,7 @@ # define BN_MP_SUB_C # define BN_S_MP_MUL_DIGS_C # define BN_S_MP_MUL_HIGH_DIGS_C +# define BN_S_MP_MUL_HIGH_DIGS_FAST_C # define BN_S_MP_SUB_C #endif diff --git a/tommath_private.h b/tommath_private.h index 3271d7e..8e89561 100644 --- a/tommath_private.h +++ b/tommath_private.h @@ -140,6 +140,11 @@ extern void *MP_CALLOC(size_t nmemb, size_t size); extern void MP_FREE(void *mem, size_t size); #endif +/* feature detection macro */ +#define MP_STRINGIZE(x) MP__STRINGIZE(x) +#define MP__STRINGIZE(x) ""#x"" +#define MP_HAS(x) (sizeof(MP_STRINGIZE(BN_##x##_C)) == 1) + /* TODO: Remove private_mp_word as soon as deprecated mp_word is removed from tommath. */ #undef mp_word typedef private_mp_word mp_word;