ChaCha ASM Test
I have observed that the ChaCha cipher may have very rarely divergent code paths for AVX vs. SSE.
I have seen this in earlier CryptoPP releases but ran my tests using the latest 8.5.0 release.
I have found on multiple occasions that ChaCha encrypted files decrypt with usually a single flipped bit on other machines. The file will decrypt as expected on the machine that encrypted it.
We run sha256 checks on the decrypted files on both ends. The hashes mismatch as expected when a bit is flipped.
After seeing this behavior in a production environment, I wrote an isolated fuzz test to confirm with garbage files that I could reproduce the behavior.
Included In This Test
- the Visual Studio solution and project used to build the test executable
- the single source file
- a reproducible example in the
- a minimal built executable
cryptopp-chacha-asm-test.exewith hard-coded key, nonce, and filepath
- the input file which causes the behavior
- sample encrypted file with AVX
- sample encrypted file without AVX
- a minimal built executable
- a very minimal test case with a specific key and nonce which produce differing results on (presumably) AVX vs SSE paths
- the source code that was used for the original fuzz test to find a key/nonce/file combo that gives inconsistent behavior, see the
When run from Visual Studio the process will use the
run/ directory as its working directory.
Cryptopp was built as a static library, x64 multi-threaded debug (\MTd) using Visual Studio 2019 v16.10.0, on Windows 10 Pro v10.0.19043, using the .sln file provided with the source code.
Both machines are running Windows 10 Pro v10.0.19043.
CPUs on each machine:
The 3700X supports AVX, the i7-990X does not.
The fuzz test in the source code was run on both machines described above until an encrypted sha mismatch was found.
Out of about ~50GB worth of 1MB files which were created and then encrypted on two different machines, only one key + nonce + file combination produced a flipped-bit file.
example/ directory contains a ready-to-run executable. Or, you can build the source yourself using the provided Visual Studio solution. You will need to put a static x64 \MTd
cryptlib.lib in the
The original fuzz test code is commented out. One key/nonce/file combination which produce the flipped bit is hard-coded into
The reproducing combo is:
run_459_file_76.bin(from fuzz test run 459, file 76)
- hex-encoded key
- hex-encoded nonce
The test will:
- calculate the sha256 hash of
- encrypt that file to
- calculate the sha256 hash of the encrypted file
- print the original sha256 and the encrypted sha256
The encrypted files on each machine differ by a single bit at
The encrypted sha from an AVX-capable CPU is
The encrypted sha on non-AVX-capable CPU is
If avx is disabled in CryptoPP using
CRYPTOPP_DISABLE_AVX2, the resulting encrypted file's sha256 matches on both machines (
8f16...). You can replace
libs/debug/cryptlib-no-avx.lib to see the encrypted hash change on an AVX-capable machine.