-
Notifications
You must be signed in to change notification settings - Fork 187
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
Timing safety #7
Comments
This version of the collision detection library checks if any unavoidable attack conditions are not satisfied to opportunistically skip work. Because of this it can not execute in constant time. If you need constant time then you at least need to disable unavoidable attack conditions, but may require further code changes, e.g.: |
Thank you, Marc! I now see that even if we did make the scalar So focusing on the case of For speed, maybe the original check, with its short-circuit evaluation, should be reached instead when Related: I guess (and assume above) that (Of course, C and CPUs don't actually guarantee us constant time either way, but so far the practice has been that bitwise ops achieve it.) |
@solardiz I have an ignorant question: What is the advantage or motivation for a constant time approach over opportunistically skipping work? Wouldn't a constant time approach end up being slower than the current implementation? |
Constant time is a requirement for some uses, ensuring no information on sensitive hashed data is leaked via timing discrepancies, particularly during the execution of a network protocol. The cost of turning off the speedup using UBCs is significant, but may remain unnoticable to the end-user. |
Thanks for the explanation
…On Tue, Feb 28, 2017 at 10:32 AM Marc Stevens ***@***.***> wrote:
Constant time is a requirement for some uses, ensuring no information on
sensitive hashed data is leaked via timing discrepancies, particularly
during the execution of a network protocol.
The cost of turning off the speedup using UBCs is significant, but may
remain unnoticable to the end-user.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#7 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAREPM5GtnkKY1zrs4a4VlhHuN5j1DXCks5rhD4pgaJpZM4MLWVb>
.
|
@zbeekman The advantage/motivation or lack thereof depends on the use case - in some cases the timing leaks could allow for practically relevant attacks, in many others they won't. Having to consider potential attacks of this sort on a case-by-case basis prevents this implementation from being a universal drop-in replacement to typical implementations of SHA-1. I think that's a major limitation and drawback. It'd be so much simpler and thus better to be able to say that we can always replace this with that and be safe. Not being able to do that universally defeats much of the would-be point of having this collision-attack-detecting implementation: we'd be replacing risk of collisions (and need to evaluate their relevance and risk impact in a given case) with risk of timing leaks (and need to evaluate their relevance and risk impact in a given case), so not necessarily simplifying our reasoning. Yes, a constant time implementation will definitely be slower. From the code, my guess is it'd be tens of times slower, but we need to benchmark and see. For some use cases, this performance cost is clearly acceptable - perhaps more clearly (that is, easier to reason about) than the risks of timing leaks. As Marc pointed out, a constant time implementation almost already exists - it's just a matter of setting the flags differently, and making minor(?) code and documentation changes. I think only minor changes are needed except for the case of actually fully detecting a collision. Making that case constant time as well would require more invasive changes and perhaps generation of different safe mode hashes than the current code produces. Luckily, the probability of false positives is low enough that this can probably be disregarded, except if triggered on purpose - not to produce a collision, but to force a timing leak. That last possibility might in fact be important (at least for the ease of reasoning), so maybe it's worth considering those more invasive changes as well. |
Thanks for the detailed explanation
…On Tue, Feb 28, 2017 at 10:45 AM Solar Designer ***@***.***> wrote:
@zbeekman <https://github.com/zbeekman> The advantage/motivation or lack
thereof depends on the use case - in some cases the timing leaks could
allow for practically relevant attacks, in many others they won't. Having
to consider potential attacks of this sort on a case-by-case basis prevents
this implementation from being a universal drop-in replacement to typical
implementations of SHA-1. I think that's a major limitation and drawback.
It'd be so much simpler and thus better to be able to say that we can
always replace this with that and be safe. Not being able to do that
universally defeats much of the would-be point of having this
collision-attack-detecting implementation: we'd be replacing risk of
collisions (and need to evaluate their relevance and risk impact in a given
case) with risk of timing leaks (and need to evaluate their relevance and
risk impact in a given case), so not necessarily simplifying our reasoning.
Yes, a constant time implementation will definitely be slower. From the
code, my guess is it'd be tens of times slower, but we need to benchmark
and see. For some use cases, this performance cost is clearly acceptable -
perhaps more clearly (that is, easier to reason about) than the risks of
timing leaks.
As Marc pointed out, a constant time implementation almost already exists
- it's just a matter of setting the flags differently, and making minor(?)
code and documentation changes.
I think only minor changes are needed except for the case of actually
fully detecting a collision. Making that case constant time as well would
require more invasive changes and perhaps generation of different safe mode
hashes than the current code produces. Luckily, the probability of false
positives is low enough that this can probably be disregarded, except if
triggered on purpose - not to produce a collision, but to force a timing
leak. That last possibility might in fact be important (at least for the
ease of reasoning), so maybe it's worth considering those more invasive
changes as well.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#7 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAREPEGv7yj9bk5FnoqRFFpmMHgM4kEeks5rhEElgaJpZM4MLWVb>
.
|
I had totally missed the paper, which says the performance difference is around 16 times: https://eprint.iacr.org/2017/173 |
For constant-time we should be able to activate the SIMD stuff to get a nice factor back. |
I've made the constant-time changes to the comparisons. |
Will constant time always be enabled, or will there be a separate API and/or build flag to switch between optimized and constant time? P.S. I forgot (perhaps optimistically) that people might still be using SHA1 for password authentication, HMAC, etc. which is partially what prompted the question about constant time... (I'm not in info-sec, just a hobby interest) |
This is already a run-time option, see README.
|
great, thanks, sorry to have overlooked that. |
No problem, it wasn't very clear. |
Kudos for the impressive results and this very interesting project! Also, let me apologize in advance for reporting the obvious, as well as in case I am missing something about the below; I only looked at the code and didn't actually trigger any of the issues described here. I just felt these concerns needed to be brought up somewhere in here, as people might start actually using this code very soon.
As far as I can tell, the current implementation of the collision detector is not timing-safe, containing conditional branches based on data (and not only when a collision attack is fully detected, which could be acceptable). If this code is meant for actual use rather than just as a proof-of-concept perhaps this should be fixed - or at least it should be documented.
Specifically, there are many "if (mask & DV_...)" in ubc_check.c (coming from sha1collisiondetection-tools/parse_bitrel/parse_bitrel.cpp, so that one should be enhanced and the file regenerated), as well as some relevant if's in sha1.c: sha1_process(). There are also some in ubc_check_verify.c, but since this file is only needed for testing (right?), I guess they're OK to stay as-is (but maybe this is best to document in a comment).
ubc_check_simd.cinc got this right (I mean timing-safe) as it is, so I think parse_bitrel.cpp simply needs to have its SIMD logic replicated for its scalar code generation as well. And sha1.c needs to be edited manually.
For a conceptually similar yet much simpler example (almost trivial), here's my crypt_blowfish bug workaround from 2011, where it deviates from computing the correct hash only when a would-be-collision is detected and does so in a timing-safe manner:
http://cvsweb.openwall.com/cgi/cvsweb.cgi/Owl/packages/glibc/crypt_blowfish/crypt_blowfish.c.diff?r1=1.19;r2=1.20
The text was updated successfully, but these errors were encountered: