-
Notifications
You must be signed in to change notification settings - Fork 101
Argon2 refactor #247
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
Argon2 refactor #247
Conversation
fa8ac4c to
73930b2
Compare
|
Looks promising at first glance. I can review in depth whenever you're finished. |
|
Yeah it's ready. |
argon2/src/lib.rs
Outdated
| block::Block, | ||
| error::{Error, Result}, | ||
| params::{Params, ParamsBuilder}, | ||
| instance::{Argon2, MAX_PWD_LEN, MAX_SALT_LEN, MAX_SECRET_LEN, MIN_SALT_LEN}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is the new home of the Argon2 type, it might make sense to rename the module, although I can't think of a better name than argon2.
Alternatively the Argon2 type could live in the toplevel module of the crate.
argon2/src/memory_view.rs
Outdated
| let segment = unsafe { | ||
| let start_ptr = | ||
| base_ptr.add(lane * self.lane_length() + self.slice * self.segment_length); | ||
| slice::from_raw_parts_mut(start_ptr as *mut Block, self.segment_length) | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks as if it's mutably aliasing a region of memory declared immutable. If so, that's unsound, given this method has a safe API.
Seems like a showstopper unless it can be addressed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
base_ptr is indeed a const pointer because we cannot call as_mut_ptr since the mutable reference to the memory is behind an immutable reference to self.
However, it is sound to create a mutable slice from start_ptr with self.segment_length elements because:
MemoryViewholds a mutable reference to the memory and therefore has exclusive access.- The
cur_lanefield is incremented every time a mutable slice is returned and is not used elsewhere, so the slicesnext_segmentreturns never overlap. - The
slicefield is never modified, and thelanemethod specifically avoids the parts of the memory thatnext_segmentreturns.
|
Regarding the use of unsafe code and mutable aliasing, I'd suggest taking a look at this comment I left when the parallel implementation was originally added: I think there's a safe strategy possible, even in a multithreaded context, and I would really like to see something like My suggestion would be borrowing the Argon2 memory mutably, then mutably borrow splitting it into Argon2 "slices" (as described in the paper) using either |
|
I had considered splitting the memory that way but the issue i ran into is that an Argon2 slice consists of a number of Rust slices, one for each lane, and I didn't want to use an allocation to keep track of the references when it could be avoided with unsafe code. I suppose the problem lies in the memory layout since Argon2 slices divide the memory into columns and lanes divide it into rows, while it would make more sense for that to be swapped. Changing the memory layout might be the key to a safe implementation, but it would mean the memory has to be copied into the standard layout for the |
|
I would prefer not to have two implementations, one parallel and one sequential, which take Instead, I think it would make more sense to have a It's okay for such a type to use |
7774790 to
925639b
Compare
|
@pjottos saw you pushed some semi-recent changes to this branch. I looked through them and it's really looking great! I'm fine to merge this pretty much as-is, but I had a couple notes:
Otherwise great job! |
|
That sounds good! |
|
Thank you! I'm going to submit a followup with a few small fixes |
- Bump version to `0.5.0-pre` (#247 contained breaking changes) - Use pointer casts to convert `Block` integer array to byte array - Rename `permutate!` to `permute!` (former isn't in OED, latter is)
- Bump version to `0.5.0-pre` (#247 contained breaking changes) - Use pointer casts to convert `Block` integer array to byte array - Rename `permutate!` to `permute!` (former isn't in OED, latter is)
This was broken in #247, which added unsafe pointer casts to access the contents of a block, which only works on little endian targets. This reverts back to something closer to the previous code, which used `u64::{from_le_bytes, to_le_bytes}` instead. It also adds cross tests for PPC32 to spot future regressions.
This was broken in #247, which added unsafe pointer casts to access the contents of a block, which only works on little endian targets. This reverts back to something closer to the previous code, which used `u64::{from_le_bytes, to_le_bytes}` instead. It also adds cross tests for PPC32 to spot future regressions.
This was broken in #247, which added unsafe pointer casts to access the contents of a block, which only works on little endian targets. This reverts back to something closer to the previous code, which used `u64::{from_le_bytes, to_le_bytes}` instead. It also adds cross tests for PPC32 to spot future regressions.
This was broken in #247, which added unsafe pointer casts to access the contents of a block, which only works on little endian targets. This reverts back to something closer to the previous code, which used `u64::{from_le_bytes, to_le_bytes}` instead. It also adds cross tests for PPC32 to spot future regressions.
Practically a rewrite of the argon2 crate.
Summary of changes:
self, but instead separating lanes into a mutable slice (current segment) and 2 immutable slices (before and after the segment).Instancestruct has been merged with theArgon2struct since it was basically just a copy of it.Argon2struct has a new method,fill_memory, which omits the calculation of a hash. This is used in e.g. RandomX.ParamsBuilderdon't returnResults anymore and takeselfby reference to make it more ergonomic.