-
Notifications
You must be signed in to change notification settings - Fork 37
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
POLYVAL universal hash function for AES-GCM(-SIV) #13
Conversation
RFC 8452 Appendix A contains ample information about how to implement GHASH in terms of POLYVAL, and also test vectors that can be used for both. Here is a slightly modified/reformatted version of the text from RFC 8452 Appendix A which describes the conversions and test vectors for them: -- snip -- Functions
|
8470b83
to
b6d62a0
Compare
Added a test with a vector from RFC 8452 Appendix A, which is at least now confirming that the implementation is presently broken. Now the joy of figuring out what's wrong... -- Since that's mildly terrifying to say about cryptography code, there's one way we can have extremely high confidence in the implementation's correctness, and that's through formal verification. Fortunately Galois has done all of the hard work there, and have written Cryptol specifications for all of the parts of AES-GCM-SIV including POLYVAL: https://github.com/GaloisInc/AES-GCM-SIV-proof/blob/master/proof/cryptol-specs/intrinsics.cry Using Galois' SAW (Software Analysis Workbench), it's possible to formally prove equivalence both to the reference Cryptol implementation and to Shay Gueron's reference C code (as Galois already used SAW to prove formal equivalence between the reference C code and Galois' Cryptol implementation): https://github.com/GaloisInc/AES-GCM-SIV-proof/blob/master/proof/cryptol-specs/polyval_proof.saw SAW can only prove equivalence and cannot prove a program is free of e.g. timing sidechannels, however my understanding is it also integrates with ProVerif which has some of those sort of capabilities. All that said, after I have a basic test vector passing, I will investigate using SAW to prove the implementation's correctness. |
81b46ac
to
80a3f90
Compare
7a42045
to
16999f5
Compare
Okay, the tests vectors are passing! Removing draft but leaving |
1182f2b
to
a068859
Compare
@newpavlov well, I'd call this "done" for an initial cut except:
I am going to push a commit bumping MSRV to 1.32.0 in Separately (ideally from this PR, saved for a follow-up) I will look at adapting the BearSSL implementation of GHASH, which is probably the best we're going to get out of a portable software implementation in terms of both constant-time operation and performance (~150MB/sec): https://bearssl.org/gitweb/?p=BearSSL;a=blob;f=src/hash/ghash_ctmul64.c |
Confirm it works with MSRV 1.32.0: https://travis-ci.org/RustCrypto/MACs/builds/576637449 Given that, and the fact we presently need to split the build out anyway to accommodate either |
Oof, I guess having any 2018 edition crate in the workspace breaks https://travis-ci.org/RustCrypto/MACs/jobs/576645142 I can temporarily work around that with a |
ff27089
to
b931e84
Compare
I gave up on attempting a 2018 edition upgrade for @newpavlov I'd say I'm "done" with this PR, aside from addressing any feedback. Can you review? I think it'd be a lot better with a portable, "performance"-oriented constant time implementation, and/or if it actually implemented GHASH in terms of POLYVAL, but other than that I think this is a reasonable start. |
Implements POLYVAL using Shay Gueron's techniques for efficient field multiplications using PCLMULQDQ. More information on these techniques here: https://blog.quarkslab.com/reversing-a-finite-field-multiplication-optimization.html
@newpavlov or if nothing else, are you okay with the changes to |
@tarcieri After a cursory look I have just two small nits:
As a temporary solution it looks good to me. But we will need to simplify it after completion of 2018 edition migration. |
The POLYVAL tests are failing on Rust 1.27.0, but passing on newer versions, suggesting there may be something amiss with `core::arch` support for `pclmulqdq` on older Rust versions. This bumps it up to our ideal MSRV, as 1.32.0+ would allow us to replace the dependency on the `byteorder` crate with equivalent `core` functions.
Eliminates the dependency on `crypto-mac` by using a built-in `Tag` type which impl's `subtle::ConstantTimeEq`. Ideally this would probably get extracted into some other trait, e.g. `UniversalHash`, but for now just use concrete types per crate.
@newpavlov done. I also made the same changes to the Perhaps it'd be good to define a |
@tarcieri |
POLYVAL is a GHASH-like universal hash function defined over GF(2^128). It's a sort of "mirror image" of GHASH optimized for little endian architectures. As such, it can be used as the core of GHASH.
This is an implementation I wrote awhile ago based on (at the time)
draft-irtf-cfrg-gcmsiv
(now RFC 8452 Section 3). It is definitely unfinished andhas never been run against test vectorsis presently failing the test vectors, so for now ASSUME IT IS BROKEN AND SHOULD NOT BE USEDpasses the test vectors!The implementation uses Shay Gueron's techniques for efficient finite field multiplication with PCLMULQDQ, including a Montgomery fast reduction method. For background on how these work, see this excellent blog post by QuarksLab:
https://blog.quarkslab.com/reversing-a-finite-field-multiplication-optimization.html
When using these techniques, it's still not as fast as I'd like, but certainly acceptable performance (edit: updated):
It contains a fallback implementation used when PCLMULQDQ isn't available (gated under the off-by-default
insecure-soft
cargo feature) which is both non-constant-time (😱) and abysmally slow: