-
Notifications
You must be signed in to change notification settings - Fork 85
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
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
mod version; | ||
|
||
pub use crate::{ | ||
algorithm::Algorithm, | ||
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:
MemoryView
holds a mutable reference to the memory and therefore has exclusive access.- The
cur_lane
field is incremented every time a mutable slice is returned and is not used elsewhere, so the slicesnext_segment
returns never overlap. - The
slice
field is never modified, and thelane
method specifically avoids the parts of the memory thatnext_segment
returns.
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).Instance
struct has been merged with theArgon2
struct since it was basically just a copy of it.Argon2
struct has a new method,fill_memory
, which omits the calculation of a hash. This is used in e.g. RandomX.ParamsBuilder
don't returnResult
s anymore and takeself
by reference to make it more ergonomic.