-
Notifications
You must be signed in to change notification settings - Fork 29
Add Valgrind-based detection of variable-latency instructions #693
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
Conversation
b325192
to
bfd3e2a
Compare
I temporarily added one of the KyberSlash2 vulnerabilities in bfd3e2a to test this this is actually working as intended. It looks something like this:
Interestingly this triggers on all versions of gcc (-Os) and clang (-Oz). The former was known and is what we used in the KyberSlash paper, the latter was not known to me and we didn't mention it in the KyberSlash paper. |
The scalar decompression routines so far used a division by {16,32,1024,2048}. This is not a security concern since even when compiled into variable-time `div` instructions as these functions are only operating on public ciphertexts (the one that comes out of encapsulation, not the one that comes out of re-encryption). Yet, it appears good style -- and it avoids having to declassify the ciphertext in constant-time tests -- to avoid the division altogether and use a shift instead. Note that since the operands are unsigned, there is no difference between shift and division. Signed-off-by: Hanno Becker <beckphan@amazon.co.uk> Signed-off-by: Matthias J. Kannwischer <matthias@kannwischer.eu>
This commit builds on top of #687 which added Valgrind-based constant-time tests detecting secret-dependent memory accesses and conditional branches. This commit extends this to also detect secret-dependent divisions such as those that lead to the KyberSlash vulnerability. See https://kyberslash.cr.yp.to/. We test for that by using the patch to Valgrind proposed in the KyberSlash paper (see same link). It adds an option --variable-latency-errors=no|yes to valgrind which defaults to no. If you set it to yes, it will complain if you use undefined values in division instructions. This patch has also been sent to the valgrind developers, but was so far not merged. Luckily our nix setup makes it very easy to add a patched valgrind and cache it in the Github cache. Initially this detected some divisions in the scalar_decompress_x functions (divisions by powers of two) when compiling with -O0. Luckily these functions only operate on public ciphertexts (the ct that comes out of encapsulation, not the ct that that comes out of re-encryption). I verified this is the case by explicitly declassifying the ciphertext that comes out of encapsulation which confirmed that there are no further divisions. While this is fine (this ciphertext is public!), it's rather unnecessary as we really don't need divisions there. I instead opted to replace those / divisions in the code by shifts (which is what the compilers do with anything from -O1 anyway). The nix setup may be of independent interest as it makes it very easy to use the patched valgrind (and also a number of different compilers). You can simply run nix develop .#ci_valgrind-varlat_gcc14 and you'll magically end up in a shell with a patched valgrind and gcc14. Currently we have ci_valgrind-varlat_clang14 ci_valgrind-varlat_clang15 ci_valgrind-varlat_clang16 ci_valgrind-varlat_clang17 ci_valgrind-varlat_clang18 ci_valgrind-varlat_clang19 ci_valgrind-varlat_gcc48 ci_valgrind-varlat_gcc49 ci_valgrind-varlat_gcc7 ci_valgrind-varlat_gcc11 ci_valgrind-varlat_gcc12 ci_valgrind-varlat_gcc13 ci_valgrind-varlat_gcc14 This commit also adds new workflows to the CI using those shells and testing our library with the following flags: {-Oz,-Os,-O3,-Ofast,-O3 -ffastmath,-O2,-O1,-O0}. Signed-off-by: Matthias J. Kannwischer <matthias@kannwischer.eu>
bfd3e2a
to
3456da6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, thanks a lot @mkannwischer.
Do we need new CI tests or can we just amend the existing ones?
Also, do you want to remark the existence of those CT tests in the README? Might be worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's get this in. nix cleanup and/or README additions can come separately
This commit builds on top of
#687
which added Valgrind-based constant-time tests detecting
secret-dependent memory accesses and conditional branches.
This commit extends this to also detect secret-dependent
divisions such as those that lead to the KyberSlash
vulnerability.
See https://kyberslash.cr.yp.to/.
We test for that by using the patch to Valgrind proposed
in the KyberSlash paper (see same link).
It adds an option --variable-latency-errors=no|yes to valgrind
which defaults to no. If you set it to yes, it will complain if
you use undefined in division instructions.
This patch has also been sent to the valgrind developers, but was
so far not merged. Luckily our nix setup makes it very easy to
add a patched valgrind and cache it in the Github cache.
Initially this detected some divisions in the scalar_decompress_x
functions (divisions by powers of two) when compiling with -O0.
Luckily these functions only operate on public ciphertexts
(the ct that comes out of encapsulation, not the ct that that
comes out of re-encryption).
I verified this is the case by explicitly declassifying
the ciphertext that comes out of encapsulation which confirmed
that there are no further divisions.
While this is fine (this ciphertext is public!), it's rather
unnecessary as we really don't need divisions there.
I instead opted to replace those / divisions in the code
by shifts (which is what the compilers do with anything
from -O1 anyway).
The nix setup may be of independent interest as it makes it very easy
to use the patched valgrind (and also a number of different compilers).
You can simply run
nix develop .#ci_valgrind-varlat_gcc14
and you'll magically end up in a shell with a patched valgrind
and gcc14.
Currently we have
ci_valgrind-varlat_clang14
ci_valgrind-varlat_clang15
ci_valgrind-varlat_clang16
ci_valgrind-varlat_clang17
ci_valgrind-varlat_clang18
ci_valgrind-varlat_clang19
ci_valgrind-varlat_gcc48
ci_valgrind-varlat_gcc49
ci_valgrind-varlat_gcc7
ci_valgrind-varlat_gcc11
ci_valgrind-varlat_gcc12
ci_valgrind-varlat_gcc13
ci_valgrind-varlat_gcc14
This commit also adds new workflows to the CI using those shells
and testing our library with the following flags:
{-Oz,-Os,-O3,-Ofast,-O3 -ffastmath,-O2,-O1,-O0}.