Skip to content

Commit 575ce49

Browse files
committed
mp_cond_swap_ct: branchless masked XOR
1 parent f3c3687 commit 575ce49

1 file changed

Lines changed: 45 additions & 8 deletions

File tree

wolfcrypt/src/integer.c

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -549,21 +549,58 @@ int mp_exch (mp_int * a, mp_int * b)
549549
return MP_OKAY;
550550
}
551551

552+
/* Constant-time conditional swap: must not branch on m (leaks scalar bit).
553+
* m is normalized to 0 or 1 so a non-zero non-one value still acts as a
554+
* swap rather than producing a partial-XOR mask. */
552555
int mp_cond_swap_ct_ex (mp_int * a, mp_int * b, int c, int m, mp_int * t)
553556
{
554-
(void)c;
555-
(void)t;
556-
if (m == 1)
557-
mp_exch(a, b);
557+
int i;
558+
int err;
559+
int imask;
560+
mp_digit mask;
561+
562+
m &= 1;
563+
imask = -m;
564+
mask = (mp_digit)0 - (mp_digit)m;
565+
566+
if ((err = mp_grow(a, c)) != MP_OKAY)
567+
return err;
568+
if ((err = mp_grow(b, c)) != MP_OKAY)
569+
return err;
570+
if ((err = mp_grow(t, c)) != MP_OKAY)
571+
return err;
572+
573+
t->used = (a->used ^ b->used) & imask;
574+
t->sign = (a->sign ^ b->sign) & imask;
575+
for (i = 0; i < c; i++) {
576+
t->dp[i] = (a->dp[i] ^ b->dp[i]) & mask;
577+
}
578+
a->used ^= t->used;
579+
a->sign ^= t->sign;
580+
for (i = 0; i < c; i++) {
581+
a->dp[i] ^= t->dp[i];
582+
}
583+
b->used ^= t->used;
584+
b->sign ^= t->sign;
585+
for (i = 0; i < c; i++) {
586+
b->dp[i] ^= t->dp[i];
587+
}
588+
558589
return MP_OKAY;
559590
}
560591

561592
int mp_cond_swap_ct (mp_int * a, mp_int * b, int c, int m)
562593
{
563-
(void)c;
564-
if (m == 1)
565-
mp_exch(a, b);
566-
return MP_OKAY;
594+
mp_int t;
595+
int err;
596+
597+
if ((err = mp_init(&t)) != MP_OKAY)
598+
return err;
599+
600+
err = mp_cond_swap_ct_ex(a, b, c, m, &t);
601+
602+
mp_clear(&t);
603+
return err;
567604
}
568605

569606

0 commit comments

Comments
 (0)