diff options
Diffstat (limited to 'third_party/rust/rust-argon2/src/context.rs')
-rw-r--r-- | third_party/rust/rust-argon2/src/context.rs | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/third_party/rust/rust-argon2/src/context.rs b/third_party/rust/rust-argon2/src/context.rs new file mode 100644 index 0000000000..34eb076d1e --- /dev/null +++ b/third_party/rust/rust-argon2/src/context.rs @@ -0,0 +1,213 @@ +// Copyright (c) 2017 Martijn Rijkeboer <mrr@sru-systems.com> +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use super::common; +use super::config::Config; +use super::error::Error; +use super::result::Result; + +/// Structure containing settings for the Argon2 algorithm. A combination of +/// the original argon2_context and argon2_instance_t. +#[derive(Debug, PartialEq)] +pub struct Context<'a> { + /// The config for this context. + pub config: Config<'a>, + + /// The length of a lane. + pub lane_length: u32, + + /// The number of memory blocks. + pub memory_blocks: u32, + + /// The password. + pub pwd: &'a [u8], + + /// The salt. + pub salt: &'a [u8], + + /// The length of a segment. + pub segment_length: u32, +} + +impl<'a> Context<'a> { + /// Attempts to create a new context. + pub fn new(config: Config<'a>, pwd: &'a [u8], salt: &'a [u8]) -> Result<Context<'a>> { + if config.lanes < common::MIN_LANES { + return Err(Error::LanesTooFew); + } else if config.lanes > common::MAX_LANES { + return Err(Error::LanesTooMany); + } + + let lanes = config.lanes; + if config.mem_cost < common::MIN_MEMORY { + return Err(Error::MemoryTooLittle); + } else if config.mem_cost > common::MAX_MEMORY { + return Err(Error::MemoryTooMuch); + } else if config.mem_cost < 8 * lanes { + return Err(Error::MemoryTooLittle); + } + + if config.time_cost < common::MIN_TIME { + return Err(Error::TimeTooSmall); + } else if config.time_cost > common::MAX_TIME { + return Err(Error::TimeTooLarge); + } + + let pwd_len = pwd.len(); + if pwd_len < common::MIN_PWD_LENGTH as usize { + return Err(Error::PwdTooShort); + } else if pwd_len > common::MAX_PWD_LENGTH as usize { + return Err(Error::PwdTooLong); + } + + let salt_len = salt.len(); + if salt_len < common::MIN_SALT_LENGTH as usize { + return Err(Error::SaltTooShort); + } else if salt_len > common::MAX_SALT_LENGTH as usize { + return Err(Error::SaltTooLong); + } + + let secret_len = config.secret.len(); + if secret_len < common::MIN_SECRET_LENGTH as usize { + return Err(Error::SecretTooShort); + } else if secret_len > common::MAX_SECRET_LENGTH as usize { + return Err(Error::SecretTooLong); + } + + let ad_len = config.ad.len(); + if ad_len < common::MIN_AD_LENGTH as usize { + return Err(Error::AdTooShort); + } else if ad_len > common::MAX_AD_LENGTH as usize { + return Err(Error::AdTooLong); + } + + if config.hash_length < common::MIN_HASH_LENGTH { + return Err(Error::OutputTooShort); + } else if config.hash_length > common::MAX_HASH_LENGTH { + return Err(Error::OutputTooLong); + } + + let mut memory_blocks = config.mem_cost; + if memory_blocks < 2 * common::SYNC_POINTS * lanes { + memory_blocks = 2 * common::SYNC_POINTS * lanes; + } + + let segment_length = memory_blocks / (lanes * common::SYNC_POINTS); + let memory_blocks = segment_length * (lanes * common::SYNC_POINTS); + let lane_length = segment_length * common::SYNC_POINTS; + + Ok(Context { + config: config, + lane_length: lane_length, + memory_blocks: memory_blocks, + pwd: pwd, + salt: salt, + segment_length: segment_length, + }) + } +} + + +#[cfg(test)] +mod tests { + + use error::Error; + use super::*; + use thread_mode::ThreadMode; + use variant::Variant; + use version::Version; + + #[test] + fn new_returns_correct_instance() { + let config = Config { + ad: b"additionaldata", + hash_length: 32, + lanes: 4, + mem_cost: 4096, + secret: b"secret", + thread_mode: ThreadMode::Sequential, + time_cost: 3, + variant: Variant::Argon2i, + version: Version::Version13, + }; + let pwd = b"password"; + let salt = b"somesalt"; + let result = Context::new(config.clone(), pwd, salt); + assert!(result.is_ok()); + + let context = result.unwrap(); + assert_eq!(context.config, config); + assert_eq!(context.pwd, pwd); + assert_eq!(context.salt, salt); + assert_eq!(context.memory_blocks, 4096); + assert_eq!(context.segment_length, 256); + assert_eq!(context.lane_length, 1024); + } + + #[test] + fn new_with_too_little_mem_cost_returns_correct_error() { + let config = Config { + mem_cost: 7, + ..Default::default() + }; + assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::MemoryTooLittle)); + } + + #[test] + fn new_with_less_than_8_x_lanes_mem_cost_returns_correct_error() { + let config = Config { + lanes: 4, + mem_cost: 31, + ..Default::default() + }; + assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::MemoryTooLittle)); + } + + #[test] + fn new_with_too_small_time_cost_returns_correct_error() { + let config = Config { + time_cost: 0, + ..Default::default() + }; + assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::TimeTooSmall)); + } + + #[test] + fn new_with_too_few_lanes_returns_correct_error() { + let config = Config { + lanes: 0, + ..Default::default() + }; + assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::LanesTooFew)); + } + + #[test] + fn new_with_too_many_lanes_returns_correct_error() { + let config = Config { + lanes: 1 << 24, + ..Default::default() + }; + assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::LanesTooMany)); + } + + #[test] + fn new_with_too_short_salt_returns_correct_error() { + let config = Default::default(); + let salt = [0u8; 7]; + assert_eq!(Context::new(config, &[0u8; 8], &salt), Err(Error::SaltTooShort)); + } + + #[test] + fn new_with_too_short_hash_length_returns_correct_error() { + let config = Config { + hash_length: 3, + ..Default::default() + }; + assert_eq!(Context::new(config, &[0u8; 8], &[0u8; 8]), Err(Error::OutputTooShort)); + } +} |