diff --git a/argon2/src/instance.rs b/argon2/src/instance.rs index c0c6c054..b83fa5f8 100644 --- a/argon2/src/instance.rs +++ b/argon2/src/instance.rs @@ -52,9 +52,6 @@ pub(crate) struct Instance<'a> { /// Number of passes passes: u32, - /// Segment length - segment_length: u32, - /// Lane length lane_length: u32, @@ -97,12 +94,13 @@ impl<'a> Instance<'a> { mut initial_hash: digest::Output, memory: Memory<'a>, ) -> Result { + let lane_length = memory.segment_length() * SYNC_POINTS; + let mut instance = Instance { version: context.version, memory, passes: context.t_cost, - segment_length: context.segment_length(), - lane_length: context.segment_length() * SYNC_POINTS, + lane_length, lanes: context.lanes, threads: context.threads, alg, @@ -272,7 +270,7 @@ impl<'a> Instance<'a> { // Offset of the current block let mut curr_offset = position.lane * self.lane_length - + position.slice * self.segment_length + + position.slice * self.memory.segment_length() + starting_index; let mut prev_offset = if 0 == curr_offset % self.lane_length { @@ -283,7 +281,7 @@ impl<'a> Instance<'a> { curr_offset - 1 }; - for i in starting_index..self.segment_length { + for i in starting_index..self.memory.segment_length() { // 1.1 Rotating prev_offset if needed if curr_offset % self.lane_length == 1 { prev_offset = curr_offset - 1; @@ -361,16 +359,19 @@ impl<'a> Instance<'a> { position.index - 1 // all but the previous } else if same_lane { // The same lane => add current segment - position.slice * self.segment_length + position.index - 1 + position.slice * self.memory.segment_length() + position.index - 1 } else { - position.slice * self.segment_length - if position.index == 0 { 1 } else { 0 } + position.slice * self.memory.segment_length() + - if position.index == 0 { 1 } else { 0 } } } else { // Second pass if same_lane { - self.lane_length - self.segment_length + position.index - 1 + self.lane_length - self.memory.segment_length() + position.index - 1 } else { - self.lane_length - self.segment_length - if position.index == 0 { 1 } else { 0 } + self.lane_length + - self.memory.segment_length() + - if position.index == 0 { 1 } else { 0 } } }; @@ -389,7 +390,7 @@ impl<'a> Instance<'a> { start_position = if position.slice == SYNC_POINTS - 1 { 0 } else { - (position.slice + 1) * self.segment_length + (position.slice + 1) * self.memory.segment_length() } } diff --git a/argon2/src/lib.rs b/argon2/src/lib.rs index 54e6fea2..933d8953 100644 --- a/argon2/src/lib.rs +++ b/argon2/src/lib.rs @@ -87,7 +87,11 @@ pub use crate::error::Error; #[cfg_attr(docsrs, doc(cfg(feature = "password-hash")))] pub use password_hash::{self, PasswordHash, PasswordHasher, PasswordVerifier}; -use crate::{block::Block, instance::Instance, memory::Memory}; +use crate::{ + block::Block, + instance::Instance, + memory::{Memory, SYNC_POINTS}, +}; use blake2::{digest, Blake2b, Digest}; use core::{ convert::TryFrom, @@ -149,9 +153,6 @@ pub const MAX_SECRET: usize = 0xFFFFFFFF; /// Memory block size in bytes pub const BLOCK_SIZE: usize = 1024; -/// Number of synchronization points between lanes per pass -const SYNC_POINTS: u32 = 4; - /// Argon2d algorithm identifier #[cfg(feature = "password-hash")] #[cfg_attr(docsrs, doc(cfg(feature = "password-hash")))] @@ -478,15 +479,17 @@ impl<'key> Argon2<'key> { return Err(Error::AdTooLong); } - let memory_blocks = (self.segment_length() * self.lanes * SYNC_POINTS) as usize; - // Hashing all inputs let initial_hash = self.initial_hash(alg, pwd, salt, ad, out); + let segment_length = Memory::segment_length_for_params(self.m_cost, self.lanes); + let blocks_count = (segment_length * self.lanes * SYNC_POINTS) as usize; + // TODO(tarcieri): support for stack-allocated memory blocks (i.e. no alloc) - let mut memory = vec![Block::default(); memory_blocks]; + let mut blocks = vec![Block::default(); blocks_count]; - Instance::hash(self, alg, initial_hash, Memory::new(&mut memory), out) + let memory = Memory::new(&mut blocks, segment_length); + Instance::hash(self, alg, initial_hash, memory, out) } /// Hashes all the inputs into `blockhash[PREHASH_DIGEST_LENGTH]`. @@ -521,18 +524,6 @@ impl<'key> Argon2<'key> { digest.update(ad); digest.finalize() } - - pub(crate) fn segment_length(&self) -> u32 { - // Align memory size - // Minimum memory_blocks = 8L blocks, where L is the number of lanes - let memory_blocks = if self.m_cost < 2 * SYNC_POINTS * self.lanes { - 2 * SYNC_POINTS * self.lanes - } else { - self.m_cost - }; - - memory_blocks / (self.lanes * SYNC_POINTS) - } } #[cfg(feature = "password-hash")] diff --git a/argon2/src/memory.rs b/argon2/src/memory.rs index ef7e7a98..970705f0 100644 --- a/argon2/src/memory.rs +++ b/argon2/src/memory.rs @@ -2,21 +2,38 @@ use crate::Block; +/// Number of synchronization points between lanes per pass +pub(crate) const SYNC_POINTS: u32 = 4; + /// Structure containing references to the memory blocks pub(crate) struct Memory<'a> { /// Memory blocks data: &'a mut [Block], - /// Size of the memory in blocks - size: usize, + /// Size of a memory segment in blocks + segment_length: u32, } impl<'a> Memory<'a> { - /// Instantiate a new memory struct - pub(crate) fn new(data: &'a mut [Block]) -> Self { - let size = data.len(); + /// Align memory size. + /// + /// Minimum memory_blocks = 8*`L` blocks, where `L` is the number of lanes. + pub(crate) fn segment_length_for_params(m_cost: u32, lanes: u32) -> u32 { + let memory_blocks = if m_cost < 2 * SYNC_POINTS * lanes { + 2 * SYNC_POINTS * lanes + } else { + m_cost + }; + + memory_blocks / (lanes * SYNC_POINTS) + } - Self { data, size } + /// Instantiate a new memory struct + pub(crate) fn new(data: &'a mut [Block], segment_length: u32) -> Self { + Self { + data, + segment_length, + } } /// Get a copy of the block @@ -30,7 +47,14 @@ impl<'a> Memory<'a> { } /// Size of the memory + #[inline] pub(crate) fn len(&self) -> usize { - self.size + self.data.len() + } + + /// Size of a memory segment + #[inline] + pub(crate) fn segment_length(&self) -> u32 { + self.segment_length } }