Merge pull request #2894 from SparkiDev/ecc_cr_fix

Change constant time and cache resistant ECC mulmod
This commit is contained in:
toddouska
2020-04-13 16:36:22 -07:00
committed by GitHub
3 changed files with 93 additions and 57 deletions

View File

@ -2534,8 +2534,10 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
#define WINSIZE 4 #define WINSIZE 4
#define M_POINTS 8 #define M_POINTS 8
int first = 1, bitbuf = 0, bitcpy = 0, j; int first = 1, bitbuf = 0, bitcpy = 0, j;
#else #elif defined(WC_NO_CACHE_RESISTANT)
#define M_POINTS 4 #define M_POINTS 4
#else
#define M_POINTS 5
#endif #endif
ecc_point *tG, *M[M_POINTS]; ecc_point *tG, *M[M_POINTS];
@ -2824,6 +2826,11 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
#ifdef WC_NO_CACHE_RESISTANT #ifdef WC_NO_CACHE_RESISTANT
if (err == MP_OKAY) if (err == MP_OKAY)
err = wc_ecc_copy_point(M[0], M[2]); err = wc_ecc_copy_point(M[0], M[2]);
#else
if (err == MP_OKAY)
err = wc_ecc_copy_point(M[0], M[3]);
if (err == MP_OKAY)
err = wc_ecc_copy_point(M[1], M[4]);
#endif #endif
/* setup sliding window */ /* setup sliding window */
@ -2867,78 +2874,68 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
if (err == MP_OKAY) if (err == MP_OKAY)
err = ecc_projective_dbl_point(M[i], M[i], a, modulus, mp); err = ecc_projective_dbl_point(M[i], M[i], a, modulus, mp);
} }
mode |= i;
#else #else
if (err == MP_OKAY) if (err == MP_OKAY)
err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus, err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus, mp);
mp);
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_copy(M[2]->x, err = mp_cond_copy(M[2]->x, i, M[0]->x);
(mp_int*)
( ((size_t)M[0]->x & wc_off_on_addr[mode&(i )]) +
((size_t)M[1]->x & wc_off_on_addr[mode&(i^1)]) +
((size_t)M[2]->x & wc_off_on_addr[mode^1])) );
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_copy(M[2]->y, err = mp_cond_copy(M[2]->y, i, M[0]->y);
(mp_int*)
( ((size_t)M[0]->y & wc_off_on_addr[mode&(i )]) +
((size_t)M[1]->y & wc_off_on_addr[mode&(i^1)]) +
((size_t)M[2]->y & wc_off_on_addr[mode^1])) );
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_copy(M[2]->z, err = mp_cond_copy(M[2]->z, i, M[0]->z);
(mp_int*) if (err == MP_OKAY)
( ((size_t)M[0]->z & wc_off_on_addr[mode&(i )]) + err = mp_cond_copy(M[2]->x, i ^ 1, M[1]->x);
((size_t)M[1]->z & wc_off_on_addr[mode&(i^1)]) + if (err == MP_OKAY)
((size_t)M[2]->z & wc_off_on_addr[mode^1])) ); err = mp_cond_copy(M[2]->y, i ^ 1, M[1]->y);
if (err == MP_OKAY)
err = mp_cond_copy(M[2]->z, i ^ 1, M[1]->z);
/* instead of using M[i] for double, which leaks key bit to cache
* monitor, use M[2] as temp, make sure address calc is constant,
* keep M[0] and M[1] in cache */
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_copy((mp_int*) err = mp_cond_copy(M[0]->x, i ^ 1, M[2]->x);
( ((size_t)M[0]->x & wc_off_on_addr[i^1]) +
((size_t)M[1]->x & wc_off_on_addr[i])),
M[2]->x);
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_copy((mp_int*) err = mp_cond_copy(M[0]->y, i ^ 1, M[2]->y);
( ((size_t)M[0]->y & wc_off_on_addr[i^1]) +
((size_t)M[1]->y & wc_off_on_addr[i])),
M[2]->y);
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_copy((mp_int*) err = mp_cond_copy(M[0]->z, i ^ 1, M[2]->z);
( ((size_t)M[0]->z & wc_off_on_addr[i^1]) +
((size_t)M[1]->z & wc_off_on_addr[i])),
M[2]->z);
if (err == MP_OKAY) if (err == MP_OKAY)
err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp); err = mp_cond_copy(M[1]->x, i, M[2]->x);
/* copy M[2] back to M[i] */
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_copy((mp_int*) err = mp_cond_copy(M[1]->y, i, M[2]->y);
(((size_t)M[2]->x & wc_off_on_addr[mode^1]) +
((size_t)M[3]->x & wc_off_on_addr[mode])),
(mp_int*)
( ((size_t)M[0]->x & wc_off_on_addr[i^1]) +
((size_t)M[1]->x & wc_off_on_addr[i])) );
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_copy((mp_int*) err = mp_cond_copy(M[1]->z, i, M[2]->z);
(((size_t)M[2]->y & wc_off_on_addr[mode^1]) +
((size_t)M[3]->y & wc_off_on_addr[mode])),
(mp_int*)
( ((size_t)M[0]->y & wc_off_on_addr[i^1]) +
((size_t)M[1]->y & wc_off_on_addr[i])) );
if (err == MP_OKAY) if (err == MP_OKAY)
err = mp_copy((mp_int*) err = ecc_projective_dbl_point(M[2], M[2], a, modulus, mp);
(((size_t)M[2]->z & wc_off_on_addr[mode^1]) + if (err == MP_OKAY)
((size_t)M[3]->z & wc_off_on_addr[mode])), err = mp_cond_copy(M[2]->x, i ^ 1, M[0]->x);
(mp_int*) if (err == MP_OKAY)
( ((size_t)M[0]->z & wc_off_on_addr[i^1]) + err = mp_cond_copy(M[2]->y, i ^ 1, M[0]->y);
((size_t)M[1]->z & wc_off_on_addr[i])) ); if (err == MP_OKAY)
err = mp_cond_copy(M[2]->z, i ^ 1, M[0]->z);
if (err == MP_OKAY)
err = mp_cond_copy(M[2]->x, i, M[1]->x);
if (err == MP_OKAY)
err = mp_cond_copy(M[2]->y, i, M[1]->y);
if (err == MP_OKAY)
err = mp_cond_copy(M[2]->z, i, M[1]->z);
if (err == MP_OKAY)
err = mp_cond_copy(M[3]->x, (mode ^ 1) & i, M[0]->x);
if (err == MP_OKAY)
err = mp_cond_copy(M[3]->y, (mode ^ 1) & i, M[0]->y);
if (err == MP_OKAY)
err = mp_cond_copy(M[3]->z, (mode ^ 1) & i, M[0]->z);
if (err == MP_OKAY)
err = mp_cond_copy(M[4]->x, (mode ^ 1) & i, M[1]->x);
if (err == MP_OKAY)
err = mp_cond_copy(M[4]->y, (mode ^ 1) & i, M[1]->y);
if (err == MP_OKAY)
err = mp_cond_copy(M[4]->z, (mode ^ 1) & i, M[1]->z);
#endif /* WC_NO_CACHE_RESISTANT */
if (err != MP_OKAY) if (err != MP_OKAY)
break; break;
mode |= i; mode |= i;
#endif /* WC_NO_CACHE_RESISTANT */
} /* end for */ } /* end for */
} }

View File

@ -89,6 +89,45 @@ mp_digit get_digit(mp_int* a, int n)
return (n >= a->used || n < 0) ? 0 : a->dp[n]; return (n >= a->used || n < 0) ? 0 : a->dp[n];
} }
/* Conditionally copy a into b. Performed in constant time.
*
* a MP integer to copy.
* copy On 1, copy a into b. on 0 leave b unchanged.
* b MP integer to copy into.
* returns BAD_FUNC_ARG when a or b is NULL, MEMORY_E when growing b fails and
* MP_OKAY otherwise.
*/
int mp_cond_copy(mp_int* a, int copy, mp_int* b)
{
int err = MP_OKAY;
int i;
mp_digit mask = (mp_digit)0 - copy;
if (a == NULL || b == NULL)
err = BAD_FUNC_ARG;
/* Ensure b has enough space to copy a into */
if (err == MP_OKAY)
err = mp_grow(b, a->used + 1);
if (err == MP_OKAY) {
/* When mask 0, b is unchanged2
* When mask all set, b ^ b ^ a = a
*/
/* Conditionaly copy all digits and then number of used diigits.
* get_digit() returns 0 when index greater than available digit.
*/
for (i = 0; i < a->used; i++) {
b->dp[i] ^= (get_digit(a, i) ^ get_digit(b, i)) & mask;
}
for (; i < b->used; i++) {
b->dp[i] ^= (get_digit(a, i) ^ get_digit(b, i)) & mask;
}
b->used ^= (a->used ^ b->used) & (int)mask;
}
return err;
}
#ifndef WC_NO_RNG #ifndef WC_NO_RNG
int get_rand_digit(WC_RNG* rng, mp_digit* d) int get_rand_digit(WC_RNG* rng, mp_digit* d)
{ {
@ -337,7 +376,6 @@ int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst)
return err; return err;
} }
#endif /* HAVE_WOLF_BIGINT */ #endif /* HAVE_WOLF_BIGINT */
#endif /* USE_FAST_MATH || !NO_BIG_INT */ #endif /* USE_FAST_MATH || !NO_BIG_INT */

View File

@ -54,6 +54,7 @@ MP_API int get_digit_count(mp_int* a);
MP_API mp_digit get_digit(mp_int* a, int n); MP_API mp_digit get_digit(mp_int* a, int n);
MP_API int get_rand_digit(WC_RNG* rng, mp_digit* d); MP_API int get_rand_digit(WC_RNG* rng, mp_digit* d);
WOLFSSL_API int mp_cond_copy(mp_int* a, int copy, mp_int* b);
WOLFSSL_API int mp_rand(mp_int* a, int digits, WC_RNG* rng); WOLFSSL_API int mp_rand(mp_int* a, int digits, WC_RNG* rng);
enum { enum {