Argon2 fails to behave the same as the reference implementation when used with multiple lanes. Worse, I believe it reads uninitialised memory, making its behaviour non-deterministic (not to mention undefined). Unfortunately the current test suite is insufficient here: libsodium uses only one lane, and by unfortunate coincidence the test vectors from the RFC don’t catch the error.
The error here is selecting the wrong reference set (and ultimately the wrong reference block). There are 3 criteria we fail to observe:
When selecting other lanes the reference set does not include the current segment. Only fully completed segments are valid.
On the first slice of the first pass, only the current lane is valid. Other lanes have no completed segment yet.
When the current block is the first of the segment, we remove the last block from the reference set, even when selecting it from another lane. (This avoids internal collisions triggered by several lanes selecting the same previous & reference blocks.)
Argon2 fails to behave the same as the reference implementation when used with multiple lanes. Worse, I believe it reads uninitialised memory, making its behaviour non-deterministic (not to mention undefined). Unfortunately the current test suite is insufficient here: libsodium uses only one lane, and by unfortunate coincidence the test vectors from the RFC don’t catch the error.
The error here is selecting the wrong reference set (and ultimately the wrong reference block). There are 3 criteria we fail to observe:
To be fixed & shipped ASAP.