password-hashes
password-hashes copied to clipboard
argon2: add parallelism
Adds a ~~default-enabled~~ parallel feature, with an ~~otherwise~~ optional dependency on rayon, and parallelize the filling of blocks using the memory views mentioned above.
Coordinated shared access in the memory blocks is implemented with a SegmentViewIter iterator, which implements either rayon::iter::ParallelIterator or core::iter::Iterator and returns SegmentView views into the Argon2 blocks memory that are safe to be used in parallel.
The views alias in the regions that are read-only, but are disjoint in the regions where mutation happens. Effectively, they implement, with a combination of mutable borrowing and runtime checking, the cooperative contract outlined in RFC 9106. This is similar to what was suggested in #380.
To avoid aliasing mutable references into the entire buffer of blocks (which would be UB), pointers are used up to the moment where a reference (shared or mutable) into a specific block is returned. At that point, aliasing is no longer possible.
The following tests have been tried in and pass Miri (modulo unrelated warnings):
reference_argon2i_v0x13_2_8_2
reference_argon2id_v0x13_2_8_2
(Running these in Miri is quite slow, taking ~5 minutes each, so I only ran the most obviously relevant tests for now).
~~Finally, the alignment of Blocks increases to 128 bytes for better prevention of false sharing on modern platforms. The new value is based on notes on crossbeam-utils::CachePadded.~~
I also took some inspiration from an intermediate snapshot of #247, before the parallel implementation was removed, as well as from an implementation without any safe abstractions I just worked on for the rust-argon2 crate (sru-systems/rust-argon2#56).