multiple timing side channels
Jussi Kivilinna
jussi.kivilinna at iki.fi
Tue Nov 10 21:09:20 CET 2015
On 10.11.2015 19:49, Taylor R Campbell wrote:
> Date: Tue, 10 Nov 2015 17:00:37 +0900
> From: NIIBE Yutaka <gniibe at fsij.org>
>
> On 11/08/2015 07:08 AM, Taylor R Campbell wrote:
> > - In conditional mpi swapping, _gcry_mpi_cond_swap branches depending
> > on the swap condition:
> >
> > (mpi/mpiutil.c, _gcry_mpi_cond_swap)
> > 576 mpi_limb_t mask = ((mpi_limb_t)0) - !!swap;
> >
> > Some compilers may not turn this into a branch -- but some do.
> > Presumably this is intended to run in constant time because it is used
> > in code that operates on secrets, so I suggest it be documented as
> > such. (Easy fix: saturate instead of !!, e.g. iterate swap |= (swap
> > << (1<<i)) | (swap >> (1<<i)) for i in 0..6.)
>
> I understand your point. It is possible for compilers to turn this
> into a branch, that's true, but I haven't had any experience for
> existing compilers for libgcrypt (for supported architectures), so
> far. Let me consider. It would be also good considering its API
> itself.
>
> It's certainly worth naming, with cheaper CPU-specific versions. The
> last time I ran into this, I wrote down that `it's not hard to find
> CPU/compiler combinations with branches for ``!res'' ' -- but I
> foolishly neglected to write down which combinations.
>
> Another possibly cheaper generic option, with fewer shifts, is:
>
> for (i = 1; i < CHAR_BIT*sizeof(swap); i <<= 1)
> swap |= swap >> i;
> swap = ~((swap & 1) - 1);
>
> (It is, of course, theoretically possible for a compiler would
> translate even this into a conditional branch -- but I've never heard
> of a compiler doing that, and that would be rather surprising to many
> people.)
>
Another is to do '!!' by bit-wise ORing number and its negative and
extracting sign-bit, which will be set only if number was non-zero:
/* Convert non-zero values to '1' and zero to '0'. */
static inline int is_not_zero(unsigned long val)
{
val |= -val; /* sign-bit will be set if 'val != 0' */
return (val >> (CHAR_BIT * sizeof(val) - 1)) & 1;
}
...
mpi_limb_t mask = ((mpi_limb_t)0) - is_not_zero(swap);
With above GCC/x86-64 generates four instructions (in: swap = rdx,
out: mask = rdx):
mov %rdx,%rax
neg %rax
or %rax,%rdx
sar $0x3f,%rdx
Which is same amount as with original '!!swap' (in: swap = rdx,
out: mask = r10):
xor %r10d,%r10d
test %rdx,%rdx
setne %r10b
neg %r10
-Jussi
More information about the Gcrypt-devel
mailing list