Skip to content
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: move segment length calculation to Memory type #159

Merged
merged 1 commit into from Apr 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
25 changes: 13 additions & 12 deletions argon2/src/instance.rs
Expand Up @@ -52,9 +52,6 @@ pub(crate) struct Instance<'a> {
/// Number of passes
passes: u32,

/// Segment length
segment_length: u32,

/// Lane length
lane_length: u32,

Expand Down Expand Up @@ -97,12 +94,13 @@ impl<'a> Instance<'a> {
mut initial_hash: digest::Output<Blake2b>,
memory: Memory<'a>,
) -> Result<Self, Error> {
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,
Expand Down Expand Up @@ -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 {
Expand All @@ -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;
Expand Down Expand Up @@ -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 }
}
};

Expand All @@ -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()
}
}

Expand Down
31 changes: 11 additions & 20 deletions argon2/src/lib.rs
Expand Up @@ -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,
Expand Down Expand Up @@ -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")))]
Expand Down Expand Up @@ -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]`.
Expand Down Expand Up @@ -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")]
Expand Down
38 changes: 31 additions & 7 deletions argon2/src/memory.rs
Expand Up @@ -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
Expand All @@ -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
}
}