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

Revert "argon2: improve const compatibility (#438)" #447

Merged
merged 1 commit into from
Aug 7, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions argon2/src/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,20 +52,18 @@ pub enum Algorithm {

impl Default for Algorithm {
fn default() -> Algorithm {
Algorithm::DEFAULT
Algorithm::Argon2id
}
}

impl Algorithm {
/// Default Algorithm (recommended).
pub const DEFAULT: Algorithm = Algorithm::Argon2id;
/// Parse an [`Algorithm`] from the provided string.
pub fn new(id: impl AsRef<str>) -> Result<Self> {
id.as_ref().parse()
}

/// Get the identifier string for this PBKDF2 [`Algorithm`].
pub const fn as_str(&self) -> &'static str {
pub fn as_str(&self) -> &'static str {
match self {
Algorithm::Argon2d => "argon2d",
Algorithm::Argon2i => "argon2i",
Expand All @@ -76,7 +74,7 @@ impl Algorithm {
/// Get the [`Ident`] that corresponds to this Argon2 [`Algorithm`].
#[cfg(feature = "password-hash")]
#[cfg_attr(docsrs, doc(cfg(feature = "password-hash")))]
pub const fn ident(&self) -> Ident<'static> {
pub fn ident(&self) -> Ident<'static> {
match self {
Algorithm::Argon2d => ARGON2D_IDENT,
Algorithm::Argon2i => ARGON2I_IDENT,
Expand All @@ -85,7 +83,7 @@ impl Algorithm {
}

/// Serialize primitive type as little endian bytes
pub(crate) const fn to_le_bytes(self) -> [u8; 4] {
pub(crate) fn to_le_bytes(self) -> [u8; 4] {
(self as u32).to_le_bytes()
}
}
Expand Down
11 changes: 4 additions & 7 deletions argon2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ pub struct Argon2<'key> {

impl Default for Argon2<'_> {
fn default() -> Self {
Self::DEFAULT
Self::new(Algorithm::default(), Version::default(), Params::default())
}
}

Expand All @@ -190,11 +190,8 @@ impl fmt::Debug for Argon2<'_> {
}

impl<'key> Argon2<'key> {
/// Default parameters (recommended).
pub const DEFAULT: Argon2<'static> =
Argon2::new(Algorithm::DEFAULT, Version::DEFAULT, Params::DEFAULT);
/// Create a new Argon2 context.
pub const fn new(algorithm: Algorithm, version: Version, params: Params) -> Self {
pub fn new(algorithm: Algorithm, version: Version, params: Params) -> Self {
Self {
algorithm,
version,
Expand Down Expand Up @@ -473,7 +470,7 @@ impl<'key> Argon2<'key> {
}

/// Get default configured [`Params`].
pub const fn params(&self) -> &Params {
pub fn params(&self) -> &Params {
&self.params
}

Expand Down Expand Up @@ -534,7 +531,7 @@ impl<'key> Argon2<'key> {
digest.finalize()
}

const fn verify_inputs(pwd: &[u8], salt: &[u8]) -> Result<()> {
fn verify_inputs(pwd: &[u8], salt: &[u8]) -> Result<()> {
if pwd.len() > MAX_PWD_LEN {
return Err(Error::PwdTooLong);
}
Expand Down
104 changes: 33 additions & 71 deletions argon2/src/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,33 +104,36 @@ impl Params {
/// - `t_cost`: number of iterations. Between 1 and (2^32)-1.
/// - `p_cost`: degree of parallelism. Between 1 and 255.
/// - `output_len`: size of the KDF output in bytes. Default 32.
pub const fn new(
m_cost: u32,
t_cost: u32,
p_cost: u32,
output_len: Option<usize>,
) -> Result<Self> {
ParamsBuilder::new_params(m_cost, t_cost, p_cost, None, None, output_len).build()
pub fn new(m_cost: u32, t_cost: u32, p_cost: u32, output_len: Option<usize>) -> Result<Self> {
let mut builder = ParamsBuilder::new();

builder.m_cost(m_cost).t_cost(t_cost).p_cost(p_cost);

if let Some(len) = output_len {
builder.output_len(len);
}

builder.build()
}

/// Memory size, expressed in kibibytes. Between 1 and (2^32)-1.
///
/// Value is an integer in decimal (1 to 10 digits).
pub const fn m_cost(&self) -> u32 {
pub fn m_cost(&self) -> u32 {
self.m_cost
}

/// Number of iterations. Between 1 and (2^32)-1.
///
/// Value is an integer in decimal (1 to 10 digits).
pub const fn t_cost(&self) -> u32 {
pub fn t_cost(&self) -> u32 {
self.t_cost
}

/// Degree of parallelism. Between 1 and 255.
///
/// Value is an integer in decimal (1 to 3 digits).
pub const fn p_cost(&self) -> u32 {
pub fn p_cost(&self) -> u32 {
self.p_cost
}

Expand Down Expand Up @@ -161,25 +164,25 @@ impl Params {
}

/// Length of the output (in bytes).
pub const fn output_len(&self) -> Option<usize> {
pub fn output_len(&self) -> Option<usize> {
self.output_len
}

/// Get the number of lanes.
#[allow(clippy::cast_possible_truncation)]
pub(crate) const fn lanes(&self) -> usize {
pub(crate) fn lanes(&self) -> usize {
self.p_cost as usize
}

/// Get the number of blocks in a lane.
pub(crate) const fn lane_length(&self) -> usize {
pub(crate) fn lane_length(&self) -> usize {
self.segment_length() * SYNC_POINTS
}

/// Get the segment length given the configured `m_cost` and `p_cost`.
///
/// Minimum memory_blocks = 8*`L` blocks, where `L` is the number of lanes.
pub(crate) const fn segment_length(&self) -> usize {
pub(crate) fn segment_length(&self) -> usize {
let m_cost = self.m_cost as usize;

let memory_blocks = if m_cost < 2 * SYNC_POINTS * self.lanes() {
Expand All @@ -192,7 +195,7 @@ impl Params {
}

/// Get the number of blocks required given the configured `m_cost` and `p_cost`.
pub const fn block_count(&self) -> usize {
pub fn block_count(&self) -> usize {
self.segment_length() * self.lanes() * SYNC_POINTS
}
}
Expand All @@ -214,6 +217,7 @@ macro_rules! param_buf {
/// Length of byte array
len: usize,
}

impl $ty {
/// Maximum length in bytes
pub const MAX_LEN: usize = $max_len;
Expand All @@ -229,12 +233,6 @@ macro_rules! param_buf {
Ok(Self { bytes, len })
}

/// Empty value.
pub const EMPTY: Self = Self {
bytes: [0u8; Self::MAX_LEN],
len: 0,
};

#[doc = "Decode"]
#[doc = $name]
#[doc = " from a B64 string"]
Expand All @@ -251,12 +249,12 @@ macro_rules! param_buf {
}

/// Get the length in bytes.
pub const fn len(&self) -> usize {
pub fn len(&self) -> usize {
self.len
}

/// Is this value empty?
pub const fn is_empty(&self) -> bool {
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
Expand Down Expand Up @@ -386,27 +384,8 @@ pub struct ParamsBuilder {

impl ParamsBuilder {
/// Create a new builder with the default parameters.
pub const fn new() -> Self {
Self::DEFAULT
}
/// Create a new builder with the provided parameters.
/// This function exists to allow for const construction of ParamsBuilder with custom parameters.
pub const fn new_params(
m_cost: u32,
t_cost: u32,
p_cost: u32,
keyid: Option<KeyId>,
data: Option<AssociatedData>,
output_len: Option<usize>,
) -> Self {
Self {
m_cost,
t_cost,
p_cost,
keyid,
data,
output_len,
}
pub fn new() -> Self {
Self::default()
}

/// Set memory size, expressed in kibibytes, between 1 and (2^32)-1.
Expand Down Expand Up @@ -449,7 +428,7 @@ impl ParamsBuilder {
///
/// This performs validations to ensure that the given parameters are valid
/// and compatible with each other, and will return an error if they are not.
pub const fn build(&self) -> Result<Params> {
pub fn build(&self) -> Result<Params> {
if self.m_cost < Params::MIN_M_COST {
return Err(Error::MemoryTooLittle);
}
Expand Down Expand Up @@ -486,15 +465,9 @@ impl ParamsBuilder {
}
}

let keyid = match self.keyid {
Some(keyid) => keyid,
None => KeyId::EMPTY,
};
let keyid = self.keyid.unwrap_or_default();

let data = match self.data {
Some(data) => data,
None => AssociatedData::EMPTY,
};
let data = self.data.unwrap_or_default();

let params = Params {
m_cost: self.m_cost,
Expand All @@ -509,19 +482,14 @@ impl ParamsBuilder {
}

/// Create a new [`Argon2`] context using the provided algorithm/version.
pub const fn context(&self, algorithm: Algorithm, version: Version) -> Result<Argon2<'_>> {
Ok(Argon2::new(
algorithm,
version,
match self.build() {
Ok(params) => params,
Err(e) => return Err(e),
},
))
pub fn context(&self, algorithm: Algorithm, version: Version) -> Result<Argon2<'_>> {
Ok(Argon2::new(algorithm, version, self.build()?))
}
/// Default parameters (recommended).
pub const DEFAULT: ParamsBuilder = {
let params = Params::DEFAULT;
}

impl Default for ParamsBuilder {
fn default() -> Self {
let params = Params::default();
Self {
m_cost: params.m_cost,
t_cost: params.t_cost,
Expand All @@ -530,12 +498,6 @@ impl ParamsBuilder {
data: None,
output_len: params.output_len,
}
};
}

impl Default for ParamsBuilder {
fn default() -> Self {
Self::DEFAULT
}
}

Expand Down
6 changes: 2 additions & 4 deletions argon2/src/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,15 @@ pub enum Version {
}

impl Version {
/// Default Version (recommended).
pub const DEFAULT: Version = Version::V0x13;
/// Serialize version as little endian bytes
pub(crate) const fn to_le_bytes(self) -> [u8; 4] {
pub(crate) fn to_le_bytes(self) -> [u8; 4] {
(self as u32).to_le_bytes()
}
}

impl Default for Version {
fn default() -> Self {
Self::DEFAULT
Self::V0x13
}
}

Expand Down