add feature detection macro MP_HAS
This commit is contained in:
parent
584405ff8e
commit
8c1b296e86
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
110
bn_mp_mul.c
110
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;
|
||||
}
|
||||
|
@ -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) */
|
||||
|
42
bn_mp_sqr.c
42
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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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 <sys/random.h>
|
||||
#include <errno.h>
|
||||
|
||||
@ -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 <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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
|
||||
|
44
demo/test.c
44
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),
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user