From 9cb8c4bcb78fd3388f10ed626e853a225c33faed Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 10 Feb 2019 13:16:12 +0000 Subject: [PATCH] mp_cond_swap: add a brute-force 'volatile'. With this change, my new side-channel test system gets a 100% pass rate when compiled with clang -O3 on Ubuntu 18.10. Previously, it had three failing tests (namely the three ECC multiply functions), all due to inconsistent control flow inside mp_cond_swap. I admit I don't really understand whether this is really necessary or not, so I'm playing it safe. The problem _seems_ to be that clang has generated one version of the cond_swap loop using integer arithmetic and another using MMX vectors, so the obvious suspect is alignment - probably mp_cond_swap is processing an iteration of the loop up front until its pointer is 16-byte aligned and then switching over to the vectorised version. But on the other hand, when I experimentally tried forcing allocations to be 16- or even 32-byte aligned, it didn't make a difference. And I don't speak x86 vector instructions very well (in fact barely at all), so I'm not even completely sure of whether the code I was reading did what I thought it did; so I'm more comfortable with simply applying brute force to get some code generation that the automated test is genuinely happy with. --- mpint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mpint.c b/mpint.c index fa33121b..4dcb8b83 100644 --- a/mpint.c +++ b/mpint.c @@ -115,7 +115,7 @@ void mp_select_into(mp_int *dest, mp_int *src0, mp_int *src1, void mp_cond_swap(mp_int *x0, mp_int *x1, unsigned swap) { assert(x0->nw == x1->nw); - BignumInt mask = -(BignumInt)(1 & swap); + volatile BignumInt mask = -(BignumInt)(1 & swap); for (size_t i = 0; i < x0->nw; i++) { BignumInt diff = (x0->w[i] ^ x1->w[i]) & mask; x0->w[i] ^= diff;