mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-06 13:40:50 +02:00
mp_cond_swap_ct: branchless masked XOR
This commit is contained in:
+34
-7
@@ -549,21 +549,48 @@ int mp_exch (mp_int * a, mp_int * b)
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Constant-time conditional swap: must not branch on m (leaks scalar bit).
|
||||
* m must be 0 or 1. The t parameter is unused; XOR is performed in place
|
||||
* with a single-digit stack scratch so callers don't need to clear t->dp. */
|
||||
int mp_cond_swap_ct_ex (mp_int * a, mp_int * b, int c, int m, mp_int * t)
|
||||
{
|
||||
(void)c;
|
||||
int i;
|
||||
int err;
|
||||
int imask;
|
||||
int idiff;
|
||||
mp_digit mask;
|
||||
mp_digit d;
|
||||
|
||||
(void)t;
|
||||
if (m == 1)
|
||||
mp_exch(a, b);
|
||||
|
||||
m &= 1;
|
||||
imask = -m;
|
||||
mask = (mp_digit)0 - (mp_digit)m;
|
||||
|
||||
if ((err = mp_grow(a, c)) != MP_OKAY)
|
||||
return err;
|
||||
if ((err = mp_grow(b, c)) != MP_OKAY)
|
||||
return err;
|
||||
|
||||
idiff = (a->used ^ b->used) & imask;
|
||||
a->used ^= idiff;
|
||||
b->used ^= idiff;
|
||||
idiff = (a->sign ^ b->sign) & imask;
|
||||
a->sign ^= idiff;
|
||||
b->sign ^= idiff;
|
||||
|
||||
for (i = 0; i < c; i++) {
|
||||
d = (a->dp[i] ^ b->dp[i]) & mask;
|
||||
a->dp[i] ^= d;
|
||||
b->dp[i] ^= d;
|
||||
}
|
||||
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
int mp_cond_swap_ct (mp_int * a, mp_int * b, int c, int m)
|
||||
{
|
||||
(void)c;
|
||||
if (m == 1)
|
||||
mp_exch(a, b);
|
||||
return MP_OKAY;
|
||||
return mp_cond_swap_ct_ex(a, b, c, m, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -66406,6 +66406,52 @@ static wc_test_ret_t mp_test_mont(mp_int* a, mp_int* m, mp_int* n, mp_int* r, WC
|
||||
}
|
||||
#endif
|
||||
|
||||
/* mp_cond_swap_ct resolves to sp_cond_swap_ct in SP-math builds, which is only
|
||||
* compiled when HAVE_ECC && ECC_TIMING_RESISTANT && !WC_NO_CACHE_RESISTANT.
|
||||
* Gate the test to match. */
|
||||
#if !defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_SP_MATH_ALL)
|
||||
#define MP_TEST_COND_SWAP_AVAILABLE
|
||||
#elif defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT) && \
|
||||
!defined(WC_NO_CACHE_RESISTANT)
|
||||
#define MP_TEST_COND_SWAP_AVAILABLE
|
||||
#endif
|
||||
|
||||
#ifdef MP_TEST_COND_SWAP_AVAILABLE
|
||||
static wc_test_ret_t mp_test_cond_swap(mp_int* a, mp_int* b)
|
||||
{
|
||||
int ret;
|
||||
int c;
|
||||
|
||||
mp_zero(a);
|
||||
mp_zero(b);
|
||||
ret = mp_set_int(a, 0x12345678);
|
||||
if (ret != 0) return WC_TEST_RET_ENC_EC(ret);
|
||||
ret = mp_set_int(b, 0x9abcdef0);
|
||||
if (ret != 0) return WC_TEST_RET_ENC_EC(ret);
|
||||
c = (a->used > b->used) ? a->used : b->used;
|
||||
|
||||
/* m == 0: no swap. */
|
||||
ret = mp_cond_swap_ct(a, b, c, 0);
|
||||
if (ret != 0) return WC_TEST_RET_ENC_EC(ret);
|
||||
if (a->dp[0] != 0x12345678 || b->dp[0] != 0x9abcdef0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
|
||||
/* m == 1: swap. */
|
||||
ret = mp_cond_swap_ct(a, b, c, 1);
|
||||
if (ret != 0) return WC_TEST_RET_ENC_EC(ret);
|
||||
if (a->dp[0] != 0x9abcdef0 || b->dp[0] != 0x12345678)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
|
||||
/* m == 1 again: swap back. */
|
||||
ret = mp_cond_swap_ct(a, b, c, 1);
|
||||
if (ret != 0) return WC_TEST_RET_ENC_EC(ret);
|
||||
if (a->dp[0] != 0x12345678 || b->dp[0] != 0x9abcdef0)
|
||||
return WC_TEST_RET_ENC_NC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* MP_TEST_COND_SWAP_AVAILABLE */
|
||||
|
||||
WOLFSSL_TEST_SUBROUTINE wc_test_ret_t mp_test(void)
|
||||
{
|
||||
WC_RNG rng;
|
||||
@@ -66719,6 +66765,10 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t mp_test(void)
|
||||
if ((ret = mp_test_mont(a, b, r1, r2, &rng)) != 0)
|
||||
goto done;
|
||||
#endif
|
||||
#ifdef MP_TEST_COND_SWAP_AVAILABLE
|
||||
if ((ret = mp_test_cond_swap(a, b)) != 0)
|
||||
goto done;
|
||||
#endif
|
||||
|
||||
done:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user