Closed jvdsn closed 5 months ago
Seems like the server should in fact send failing test cases about 1/4 times: https://github.com/usnistgov/ACVP-Server/blob/master/gen-val/src/orleans/src/NIST.CVP.ACVTS.Libraries.Orleans.Grains/Aead/OracleObserverAesGcmSivCaseGrain.cs#L19. Why does the server later think those cases are valid?
Joachim,
I hope you don't mind: I'm an interested third-party, not affiliated with NIST. I ran your set of test cases above on an independent implementation of GCM-SIV. I confirmed tcId 481 and 487 fail tag validation, while all other test cases pass both tag validation and plaintext match to expected results. If you have additional test cases that would benefit from independent confirmation, I'd be happy to provide further results.
Are you able to run YOUR implementation against the test cases defined in the "offline" ACVP-Server test file for GCM-SIV? It's in the folder:
ACVP-Server/tree/master/gen-val/json-files/ACVP-AES-GCM-SIV-1.0
I found that all of the GCM-SIV encrypt test cases in that file pass, while a number of decrypt test cases fail on tag validation for the cipher implementations I've tested. The test file indicates those failing test cases should pass however, so there's the issue I've been diagnosing. My study of these cases suggests there may be a tag computation issue by ACVP-Server. If you are able to run the test cases in that file, your results would be helpful / confirmatory.
FWIW, the GCM-SIV implementation I used on your test cases passes every test case in the specs and repositories I rely upon (e.g., RFC8452, BoringSSL, Wycheproof, metalnem, ...). It's only the handful of decrypt test cases in the NIST ACVP-Server "offline file" that are producing failures.
--Don
@dspdon yes, that file has the same issue. Specifically, for tcId
62, 66, 70, 72, 73, 80, 81, 82, 85, 91, 95, 98, 103, 107, 109, 111, 113, and 115, BoringSSL reports a tag validation failure. However, the expectedResults.json
does not contain any of those values.
In fact, I believe I found the issue. Compare https://github.com/usnistgov/ACVP-Server/blob/master/gen-val/src/orleans/src/NIST.CVP.ACVTS.Libraries.Orleans.Grains/Aead/OracleObserverAesGcmCaseGrain.cs#L72-L76 (AES-GCM):
if (shouldFail)
{
result.Tag = _rand.GetDifferentBitStringOfSameSize(result.Tag);
result.TestPassed = false;
}
with https://github.com/usnistgov/ACVP-Server/blob/master/gen-val/src/orleans/src/NIST.CVP.ACVTS.Libraries.Orleans.Grains/Aead/OracleObserverAesGcmSivCaseGrain.cs#L77-L80 (AES-GCM-SIV):
if (shouldFail)
{
result.CipherText = _rand.GetDifferentBitStringOfSameSize(result.CipherText);
}
The server never sets result.TestPassed = false;
!! I opened #308 in the hopes NIST can resolve this.
Same set of 18 failed test cases that I see. Thanks for confirming this, and for the link to the PR you opened. Nice job on that.
We plan to address this as part of our next hotfix deployment. I'll update this ticket after the fix has been deployed to Demo.
environment Demo
testSessionId 475095
vsId 2098825
Algorithm registration
I am trying to test AES-GCM-SIV using BoringSSL. Encryption works great (no failures), however I'm having a strange issue with decryption. For decryption, the server sometimes gives me test vectors for which BoringSSL thinks the tag is invalid. This is quite expected to me and is in line with other tests (e.g. GCM and CCM). However, when I try to submit
"testPassed":false
to the server, the server complains that there should actually be a plaintext! So, somehow the server thinks that the tag is valid.This issue doesn't happen all the time, it seems to happen about 1/4 vectors. For the remaining 3/4 vectors, both BoringSSL and the server agree that the tag is valid. Crucially, when BoringSSL and the server agree, the output plaintext is identical. This doesn't really make sense to me, because that would mean that the decryption routines for BoringSSL and the server function identically.
In fact, at the time of writing, the server does not provide any ciphertexts for which it thinks the tag is invalid. This can be confirmed by requesting vectors with expected values (testId and vsId above). Excerpt:
In this test group, BoringSSL thinks that test case 481 and 487 should not validly decrypt:
However, the expected values returned by the server are:
Then, I inspected BoringSSL using GDB to review what the plaintext would be, assuming BoringSSL didn't discard it because of the tag issue. This is the result:
D20F630C13A5A939E7D09F552F2A0F
. This does not match at all what the server thinks the plaintext would be. However, we know that for other test cases (e.g. 482), BoringSSL and the server fully agree on the plaintext.Perhaps this is really a problem in BoringSSL? I tried to replicate this using OpenSSL. OpenSSL added AES-GCM-SIV in version 3.2.0 and as far as I can see, its implementation is independent from BoringSSL (which added AES-GCM-SIV a long time ago). This is the code I used:
and this is the output:
The first statement tries to encrypt what BoringSSL thinks the plaintext would be. Note that the result doesn't match the provided ciphertext for test case 481. The second statement tries to encrypt what the server thinks the plaintext is. Again, the result also doesn't match the provided ciphertext for 481. The third statement tries to decrypt the provided ciphertext for 481, using OpenSSL's implementation. This decryption fails, as with BoringSSL, due to an error (presumably invalid tag).
Then, the fourth statement encrypts what BoringSSL and the server agree the plaintext is for 482. The result of the encryption is indeed the provided ciphertext for 482. Finally, the fifth statement decrypts the provided ciphertext for 482. BoringSSL, OpenSSL, and the server agree that the result is
f7e231d8b36f1812fb550a5e84869a
.I looked at the server source code for a bit but I couldn't find an obvious issue. Without access to a running server it is quite hard to debug why exactly the server returns
46B52AB340B0F02776ED60B2C8E442
for 481. Still, please let me know if I can be of any help. I will try to find another independent (perhaps Rust or Python) AES-GCM-SIV implementation to see if this issue exists there as well.