sp_int.c: add sp_mod_word() gated on WOLFSSL_SP_MOD_WORD_RP for runtimes lacking intrinsic support for int128 % int64; for linuxkm, use WOLFSSL_SP_DIV_WORD_HALF and the new WOLFSSL_SP_MOD_WORD_RP.

This commit is contained in:
Daniel Pouzzner
2020-09-04 23:17:17 -05:00
parent 8f130f3642
commit fdbd6addd0
2 changed files with 78 additions and 13 deletions

View File

@ -808,11 +808,7 @@ static WC_INLINE sp_int_digit sp_div_word(sp_int_digit hi, sp_int_digit lo,
sp_int_digit r; sp_int_digit r;
w = ((sp_int_word)hi << SP_WORD_SIZE) | lo; w = ((sp_int_word)hi << SP_WORD_SIZE) | lo;
#ifdef WOLFSSL_LINUXKM
do_div(w, d);
#else
w /= d; w /= d;
#endif
r = (sp_int_digit)w; r = (sp_int_digit)w;
return r; return r;
@ -1471,9 +1467,73 @@ int sp_mulmod(sp_int* a, sp_int* b, sp_int* m, sp_int* r)
} }
#endif #endif
#ifdef WOLFSSL_SP_MOD_WORD_RP
/* Calculate the word w modulo the digit d into r: r = w mod d
*
* w SP integer word, dividend and result.
* d SP integer digit, modulus.
*
* returns MP_VAL when d is 0 and MP_OKAY otherwise.
*/
static WC_INLINE int sp_mod_word(sp_int_word *w, sp_int_digit d) {
sp_int_word x;
int x_shift;
if (*w == 0)
return 0;
if (d == 0)
return MP_VAL;
/* Russian Peasant algorithm for division, optimized:
*
* first, shift x leftward just enough to be greater than w/2.
* this can be done by counting the leading zeros of each,
* shifting so that x has one less leading zero, and then doing a
* final comparison.
*
* textbook logic:
*
* while (x <= w/2)
* x <<= 1;
*/
x_shift = ((int)__builtin_clzll(d) + (SP_WORD_SIZE - 1));
if ((*w >> SP_WORD_SIZE) == 0)
x_shift -=
#if SP_WORD_SIZE == 64
(int)__builtin_clzll((uint64_t)*w)
#elif SP_WORD_SIZE == 32
(int)__builtin_clz((uint32_t)*w)
#else
#error unexpected SP_WORD_SIZE
#endif
+ SP_WORD_SIZE;
else
x_shift -=
#if SP_WORD_SIZE == 64
(int)__builtin_clzll((uint64_t)(*w >> SP_WORD_SIZE))
#elif SP_WORD_SIZE == 32
(int)__builtin_clz((uint32_t)(*w >> SP_WORD_SIZE))
#else
#error unexpected SP_WORD_SIZE
#endif
;
if (x_shift < 0)
x_shift = 0;
x = (sp_int_word)d << x_shift;
if (x <= (*w>>1))
x <<= 1;
while (*w >= (sp_int_word)d) {
if (*w >= x)
*w -= x;
x >>= 1;
}
return MP_OKAY;
}
#endif /* WOLFSSL_SP_MOD_WORD_RP */
/* Calculate a modulo the digit d into r: r = a mod d /* Calculate a modulo the digit d into r: r = a mod d
* *
* a SP integer to square. * a SP integer, dividend.
* d SP integer digit, modulus. * d SP integer digit, modulus.
* r SP integer digit, result. * r SP integer digit, result.
* returns MP_VAL when d is 0 and MP_OKAY otherwise. * returns MP_VAL when d is 0 and MP_OKAY otherwise.
@ -1483,7 +1543,6 @@ static int sp_mod_d(sp_int* a, const sp_int_digit d, sp_int_digit* r)
int err = MP_OKAY; int err = MP_OKAY;
int i; int i;
sp_int_word w = 0; sp_int_word w = 0;
sp_int_digit t;
if (d == 0) if (d == 0)
err = MP_VAL; err = MP_VAL;
@ -1491,13 +1550,17 @@ static int sp_mod_d(sp_int* a, const sp_int_digit d, sp_int_digit* r)
if (err == MP_OKAY) { if (err == MP_OKAY) {
for (i = a->used - 1; i >= 0; i--) { for (i = a->used - 1; i >= 0; i--) {
w = (w << SP_WORD_SIZE) | a->dp[i]; w = (w << SP_WORD_SIZE) | a->dp[i];
#ifdef WOLFSSL_LINUXKM #ifdef WOLFSSL_SP_MOD_WORD_RP
t = (sp_int_digit)w; if (sp_mod_word(&w, d) == MP_VAL) {
do_div(t, d); err = MP_VAL;
break;
}
#else #else
t = (sp_int_digit)(w / d); {
sp_int_digit t = (sp_int_digit)(w / d);
w -= (sp_int_word)t * d;
}
#endif #endif
w -= (sp_int_word)t * d;
} }
*r = (sp_int_digit)w; *r = (sp_int_digit)w;

View File

@ -2093,8 +2093,6 @@ extern void uITRON4_free(void *p) ;
#define SIZEOF_LONG 8 #define SIZEOF_LONG 8
#define SIZEOF_LONG_LONG 8 #define SIZEOF_LONG_LONG 8
#define CHAR_BIT 8 #define CHAR_BIT 8
/* tweak the autotools-detected feature set to accommodate switch from user to kernel space: */
#undef HAVE_STRINGS_H #undef HAVE_STRINGS_H
#undef HAVE_ERRNO_H #undef HAVE_ERRNO_H
#undef HAVE_THREAD_LS #undef HAVE_THREAD_LS
@ -2105,6 +2103,10 @@ extern void uITRON4_free(void *p) ;
#define WOLFSSL_USER_IO #define WOLFSSL_USER_IO
#define USE_WOLF_STRTOK #define USE_WOLF_STRTOK
#define WOLFSSL_SP_DIV_64 #define WOLFSSL_SP_DIV_64
#define WOLFSSL_SP_DIV_WORD_HALF
#define SP_HALF_SIZE 32
#define SP_HALF_MAX 4294967295U
#define WOLFSSL_SP_MOD_WORD_RP
#define WOLFSSL_OLD_PRIME_CHECK #define WOLFSSL_OLD_PRIME_CHECK
#endif #endif