Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change constant time and cache resistant ECC mulmod #2894

Merged
merged 1 commit into from
Apr 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 54 additions & 57 deletions wolfcrypt/src/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2534,8 +2534,10 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
#define WINSIZE 4
#define M_POINTS 8
int first = 1, bitbuf = 0, bitcpy = 0, j;
#else
#elif defined(WC_NO_CACHE_RESISTANT)
#define M_POINTS 4
#else
#define M_POINTS 5
#endif

ecc_point *tG, *M[M_POINTS];
Expand Down Expand Up @@ -2824,6 +2826,11 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
#ifdef WC_NO_CACHE_RESISTANT
if (err == MP_OKAY)
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

/* setup sliding window */
Expand Down Expand Up @@ -2867,78 +2874,68 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
if (err == MP_OKAY)
err = ecc_projective_dbl_point(M[i], M[i], a, modulus, mp);
}

mode |= i;
#else
if (err == MP_OKAY)
err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus,
mp);
err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus, mp);
if (err == MP_OKAY)
err = mp_cond_copy(M[2]->x, i, M[0]->x);
if (err == MP_OKAY)
err = mp_cond_copy(M[2]->y, i, M[0]->y);
if (err == MP_OKAY)
err = mp_cond_copy(M[2]->z, i, M[0]->z);
if (err == MP_OKAY)
err = mp_cond_copy(M[2]->x, i ^ 1, M[1]->x);
if (err == MP_OKAY)
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);

if (err == MP_OKAY)
err = mp_cond_copy(M[0]->x, i ^ 1, M[2]->x);
if (err == MP_OKAY)
err = mp_cond_copy(M[0]->y, i ^ 1, M[2]->y);
if (err == MP_OKAY)
err = mp_cond_copy(M[0]->z, i ^ 1, M[2]->z);
if (err == MP_OKAY)
err = mp_cond_copy(M[1]->x, i, M[2]->x);
if (err == MP_OKAY)
err = mp_cond_copy(M[1]->y, i, M[2]->y);
if (err == MP_OKAY)
err = mp_cond_copy(M[1]->z, i, M[2]->z);

if (err == MP_OKAY)
err = ecc_projective_dbl_point(M[2], M[2], a, modulus, mp);
if (err == MP_OKAY)
err = mp_cond_copy(M[2]->x, i ^ 1, M[0]->x);
if (err == MP_OKAY)
err = mp_copy(M[2]->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])) );
err = mp_cond_copy(M[2]->y, i ^ 1, M[0]->y);
if (err == MP_OKAY)
err = mp_copy(M[2]->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])) );
err = mp_cond_copy(M[2]->z, i ^ 1, M[0]->z);
if (err == MP_OKAY)
err = mp_copy(M[2]->z,
(mp_int*)
( ((size_t)M[0]->z & wc_off_on_addr[mode&(i )]) +
((size_t)M[1]->z & wc_off_on_addr[mode&(i^1)]) +
((size_t)M[2]->z & wc_off_on_addr[mode^1])) );

/* 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 */
err = mp_cond_copy(M[2]->x, i, M[1]->x);
if (err == MP_OKAY)
err = mp_copy((mp_int*)
( ((size_t)M[0]->x & wc_off_on_addr[i^1]) +
((size_t)M[1]->x & wc_off_on_addr[i])),
M[2]->x);
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_copy((mp_int*)
( ((size_t)M[0]->y & wc_off_on_addr[i^1]) +
((size_t)M[1]->y & wc_off_on_addr[i])),
M[2]->y);
err = mp_cond_copy(M[3]->x, (mode ^ 1) & i, M[0]->x);
if (err == MP_OKAY)
err = mp_copy((mp_int*)
( ((size_t)M[0]->z & wc_off_on_addr[i^1]) +
((size_t)M[1]->z & wc_off_on_addr[i])),
M[2]->z);
err = mp_cond_copy(M[3]->y, (mode ^ 1) & i, M[0]->y);
if (err == MP_OKAY)
err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp);
/* copy M[2] back to M[i] */
err = mp_cond_copy(M[3]->z, (mode ^ 1) & i, M[0]->z);
if (err == MP_OKAY)
err = mp_copy((mp_int*)
(((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])) );
err = mp_cond_copy(M[4]->x, (mode ^ 1) & i, M[1]->x);
if (err == MP_OKAY)
err = mp_copy((mp_int*)
(((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])) );
err = mp_cond_copy(M[4]->y, (mode ^ 1) & i, M[1]->y);
if (err == MP_OKAY)
err = mp_copy((mp_int*)
(((size_t)M[2]->z & wc_off_on_addr[mode^1]) +
((size_t)M[3]->z & wc_off_on_addr[mode])),
(mp_int*)
( ((size_t)M[0]->z & wc_off_on_addr[i^1]) +
((size_t)M[1]->z & wc_off_on_addr[i])) );
err = mp_cond_copy(M[4]->z, (mode ^ 1) & i, M[1]->z);
#endif /* WC_NO_CACHE_RESISTANT */

if (err != MP_OKAY)
break;

mode |= i;
#endif /* WC_NO_CACHE_RESISTANT */
} /* end for */
}

Expand Down
40 changes: 39 additions & 1 deletion wolfcrypt/src/wolfmath.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,45 @@ mp_digit get_digit(mp_int* a, int 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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good but please add a basic comment here describing why and what this does for ease of future maintenance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments added.

{
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
int get_rand_digit(WC_RNG* rng, mp_digit* d)
{
Expand Down Expand Up @@ -337,7 +376,6 @@ int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst)

return err;
}

#endif /* HAVE_WOLF_BIGINT */

#endif /* USE_FAST_MATH || !NO_BIG_INT */
1 change: 1 addition & 0 deletions wolfssl/wolfcrypt/wolfmath.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 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);

enum {
Expand Down