1use super::sys;
2
3#[derive(Debug, PartialEq, Eq)]
5pub enum Error {
6 BadParam(&'static str),
10
11 Code(ErrorCode),
13
14 Unknown,
17}
18
19impl Error {
20 pub(crate) fn check_code(code: sys::Argon2_ErrorCodes) -> Result<(), Error> {
21 if code == 0 {
22 Ok(())
23 } else {
24 if let Some(err_code) = ErrorCode::from_c(code as sys::Argon2_ErrorCodes) {
25 Err(Error::Code(err_code))
26 } else {
27 Err(Error::Unknown)
28 }
29 }
30 }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35#[repr(i32)]
36pub enum ErrorCode {
37 OutputPtrNull = sys::Argon2_ErrorCodes_ARGON2_OUTPUT_PTR_NULL,
38 OutputTooShort = sys::Argon2_ErrorCodes_ARGON2_OUTPUT_TOO_SHORT,
39 OutputTooLong = sys::Argon2_ErrorCodes_ARGON2_OUTPUT_TOO_LONG,
40 PwdTooShort = sys::Argon2_ErrorCodes_ARGON2_PWD_TOO_SHORT,
41 PwdTooLong = sys::Argon2_ErrorCodes_ARGON2_PWD_TOO_LONG,
42 SaltTooShort = sys::Argon2_ErrorCodes_ARGON2_SALT_TOO_SHORT,
43 SaltTooLong = sys::Argon2_ErrorCodes_ARGON2_SALT_TOO_LONG,
44 AdTooShort = sys::Argon2_ErrorCodes_ARGON2_AD_TOO_SHORT,
45 AdTooLong = sys::Argon2_ErrorCodes_ARGON2_AD_TOO_LONG,
46 SecretTooShort = sys::Argon2_ErrorCodes_ARGON2_SECRET_TOO_SHORT,
47 SecretTooLong = sys::Argon2_ErrorCodes_ARGON2_SECRET_TOO_LONG,
48 TimeTooSmall = sys::Argon2_ErrorCodes_ARGON2_TIME_TOO_SMALL,
49 TimeTooLarge = sys::Argon2_ErrorCodes_ARGON2_TIME_TOO_LARGE,
50 MemoryTooLittle = sys::Argon2_ErrorCodes_ARGON2_MEMORY_TOO_LITTLE,
51 MemoryTooMuch = sys::Argon2_ErrorCodes_ARGON2_MEMORY_TOO_MUCH,
52 LanesTooFew = sys::Argon2_ErrorCodes_ARGON2_LANES_TOO_FEW,
53 LanesTooMany = sys::Argon2_ErrorCodes_ARGON2_LANES_TOO_MANY,
54 PwdPtrMismatch = sys::Argon2_ErrorCodes_ARGON2_PWD_PTR_MISMATCH,
55 SaltPtrMismatch = sys::Argon2_ErrorCodes_ARGON2_SALT_PTR_MISMATCH,
56 SecretPtrMismatch = sys::Argon2_ErrorCodes_ARGON2_SECRET_PTR_MISMATCH,
57 AdPtrMismatch = sys::Argon2_ErrorCodes_ARGON2_AD_PTR_MISMATCH,
58 MemoryAllocationError = sys::Argon2_ErrorCodes_ARGON2_MEMORY_ALLOCATION_ERROR,
59 FreeMemoryCbkNull = sys::Argon2_ErrorCodes_ARGON2_FREE_MEMORY_CBK_NULL,
60 AllocateMemoryCbkNull = sys::Argon2_ErrorCodes_ARGON2_ALLOCATE_MEMORY_CBK_NULL,
61 IncorrectParameter = sys::Argon2_ErrorCodes_ARGON2_INCORRECT_PARAMETER,
62 IncorrectType = sys::Argon2_ErrorCodes_ARGON2_INCORRECT_TYPE,
63 OutPtrMismatch = sys::Argon2_ErrorCodes_ARGON2_OUT_PTR_MISMATCH,
64 ThreadsTooFew = sys::Argon2_ErrorCodes_ARGON2_THREADS_TOO_FEW,
65 ThreadsTooMany = sys::Argon2_ErrorCodes_ARGON2_THREADS_TOO_MANY,
66 MissingArgs = sys::Argon2_ErrorCodes_ARGON2_MISSING_ARGS,
67 EncodingFail = sys::Argon2_ErrorCodes_ARGON2_ENCODING_FAIL,
68 DecodingFail = sys::Argon2_ErrorCodes_ARGON2_DECODING_FAIL,
69 ThreadFail = sys::Argon2_ErrorCodes_ARGON2_THREAD_FAIL,
70 DecodingLengthFail = sys::Argon2_ErrorCodes_ARGON2_DECODING_LENGTH_FAIL,
71 VerifyMismatch = sys::Argon2_ErrorCodes_ARGON2_VERIFY_MISMATCH,
72}
73
74impl ErrorCode {
75 pub fn message(self) -> &'static str {
77 super::error_message(self)
78 }
79
80 fn from_c(c_error_code: sys::Argon2_ErrorCodes) -> Option<ErrorCode> {
82 match c_error_code {
83 sys::Argon2_ErrorCodes_ARGON2_OUTPUT_PTR_NULL => Some(ErrorCode::OutputPtrNull),
84 sys::Argon2_ErrorCodes_ARGON2_OUTPUT_TOO_SHORT => Some(ErrorCode::OutputTooShort),
85 sys::Argon2_ErrorCodes_ARGON2_OUTPUT_TOO_LONG => Some(ErrorCode::OutputTooLong),
86 sys::Argon2_ErrorCodes_ARGON2_PWD_TOO_SHORT => Some(ErrorCode::PwdTooShort),
87 sys::Argon2_ErrorCodes_ARGON2_PWD_TOO_LONG => Some(ErrorCode::PwdTooLong),
88 sys::Argon2_ErrorCodes_ARGON2_SALT_TOO_SHORT => Some(ErrorCode::SaltTooShort),
89 sys::Argon2_ErrorCodes_ARGON2_SALT_TOO_LONG => Some(ErrorCode::SaltTooLong),
90 sys::Argon2_ErrorCodes_ARGON2_AD_TOO_SHORT => Some(ErrorCode::AdTooShort),
91 sys::Argon2_ErrorCodes_ARGON2_AD_TOO_LONG => Some(ErrorCode::AdTooLong),
92 sys::Argon2_ErrorCodes_ARGON2_SECRET_TOO_SHORT => Some(ErrorCode::SecretTooShort),
93 sys::Argon2_ErrorCodes_ARGON2_SECRET_TOO_LONG => Some(ErrorCode::SecretTooLong),
94 sys::Argon2_ErrorCodes_ARGON2_TIME_TOO_SMALL => Some(ErrorCode::TimeTooSmall),
95 sys::Argon2_ErrorCodes_ARGON2_TIME_TOO_LARGE => Some(ErrorCode::TimeTooLarge),
96 sys::Argon2_ErrorCodes_ARGON2_MEMORY_TOO_LITTLE => Some(ErrorCode::MemoryTooLittle),
97 sys::Argon2_ErrorCodes_ARGON2_MEMORY_TOO_MUCH => Some(ErrorCode::MemoryTooMuch),
98 sys::Argon2_ErrorCodes_ARGON2_LANES_TOO_FEW => Some(ErrorCode::LanesTooFew),
99 sys::Argon2_ErrorCodes_ARGON2_LANES_TOO_MANY => Some(ErrorCode::LanesTooMany),
100 sys::Argon2_ErrorCodes_ARGON2_PWD_PTR_MISMATCH => Some(ErrorCode::PwdPtrMismatch),
101 sys::Argon2_ErrorCodes_ARGON2_SALT_PTR_MISMATCH => Some(ErrorCode::SaltPtrMismatch),
102 sys::Argon2_ErrorCodes_ARGON2_SECRET_PTR_MISMATCH => Some(ErrorCode::SecretPtrMismatch),
103 sys::Argon2_ErrorCodes_ARGON2_AD_PTR_MISMATCH => Some(ErrorCode::AdPtrMismatch),
104 sys::Argon2_ErrorCodes_ARGON2_MEMORY_ALLOCATION_ERROR => Some(ErrorCode::MemoryAllocationError),
105 sys::Argon2_ErrorCodes_ARGON2_FREE_MEMORY_CBK_NULL => Some(ErrorCode::FreeMemoryCbkNull),
106 sys::Argon2_ErrorCodes_ARGON2_ALLOCATE_MEMORY_CBK_NULL => Some(ErrorCode::AllocateMemoryCbkNull),
107 sys::Argon2_ErrorCodes_ARGON2_INCORRECT_PARAMETER => Some(ErrorCode::IncorrectParameter),
108 sys::Argon2_ErrorCodes_ARGON2_INCORRECT_TYPE => Some(ErrorCode::IncorrectType),
109 sys::Argon2_ErrorCodes_ARGON2_OUT_PTR_MISMATCH => Some(ErrorCode::OutPtrMismatch),
110 sys::Argon2_ErrorCodes_ARGON2_THREADS_TOO_FEW => Some(ErrorCode::ThreadsTooFew),
111 sys::Argon2_ErrorCodes_ARGON2_THREADS_TOO_MANY => Some(ErrorCode::ThreadsTooMany),
112 sys::Argon2_ErrorCodes_ARGON2_MISSING_ARGS => Some(ErrorCode::MissingArgs),
113 sys::Argon2_ErrorCodes_ARGON2_ENCODING_FAIL => Some(ErrorCode::EncodingFail),
114 sys::Argon2_ErrorCodes_ARGON2_DECODING_FAIL => Some(ErrorCode::DecodingFail),
115 sys::Argon2_ErrorCodes_ARGON2_THREAD_FAIL => Some(ErrorCode::ThreadFail),
116 sys::Argon2_ErrorCodes_ARGON2_DECODING_LENGTH_FAIL => Some(ErrorCode::DecodingLengthFail),
117 sys::Argon2_ErrorCodes_ARGON2_VERIFY_MISMATCH => Some(ErrorCode::VerifyMismatch),
118
119 _ => None,
120 }
121 }
122
123 pub(crate) fn to_c(self: ErrorCode) -> sys::Argon2_ErrorCodes {
125 match self {
126 ErrorCode::OutputPtrNull => sys::Argon2_ErrorCodes_ARGON2_OUTPUT_PTR_NULL,
127 ErrorCode::OutputTooShort => sys::Argon2_ErrorCodes_ARGON2_OUTPUT_TOO_SHORT,
128 ErrorCode::OutputTooLong => sys::Argon2_ErrorCodes_ARGON2_OUTPUT_TOO_LONG,
129 ErrorCode::PwdTooShort => sys::Argon2_ErrorCodes_ARGON2_PWD_TOO_SHORT,
130 ErrorCode::PwdTooLong => sys::Argon2_ErrorCodes_ARGON2_PWD_TOO_LONG,
131 ErrorCode::SaltTooShort => sys::Argon2_ErrorCodes_ARGON2_SALT_TOO_SHORT,
132 ErrorCode::SaltTooLong => sys::Argon2_ErrorCodes_ARGON2_SALT_TOO_LONG,
133 ErrorCode::AdTooShort => sys::Argon2_ErrorCodes_ARGON2_AD_TOO_SHORT,
134 ErrorCode::AdTooLong => sys::Argon2_ErrorCodes_ARGON2_AD_TOO_LONG,
135 ErrorCode::SecretTooShort => sys::Argon2_ErrorCodes_ARGON2_SECRET_TOO_SHORT,
136 ErrorCode::SecretTooLong => sys::Argon2_ErrorCodes_ARGON2_SECRET_TOO_LONG,
137 ErrorCode::TimeTooSmall => sys::Argon2_ErrorCodes_ARGON2_TIME_TOO_SMALL,
138 ErrorCode::TimeTooLarge => sys::Argon2_ErrorCodes_ARGON2_TIME_TOO_LARGE,
139 ErrorCode::MemoryTooLittle => sys::Argon2_ErrorCodes_ARGON2_MEMORY_TOO_LITTLE,
140 ErrorCode::MemoryTooMuch => sys::Argon2_ErrorCodes_ARGON2_MEMORY_TOO_MUCH,
141 ErrorCode::LanesTooFew => sys::Argon2_ErrorCodes_ARGON2_LANES_TOO_FEW,
142 ErrorCode::LanesTooMany => sys::Argon2_ErrorCodes_ARGON2_LANES_TOO_MANY,
143 ErrorCode::PwdPtrMismatch => sys::Argon2_ErrorCodes_ARGON2_PWD_PTR_MISMATCH,
144 ErrorCode::SaltPtrMismatch => sys::Argon2_ErrorCodes_ARGON2_SALT_PTR_MISMATCH,
145 ErrorCode::SecretPtrMismatch => sys::Argon2_ErrorCodes_ARGON2_SECRET_PTR_MISMATCH,
146 ErrorCode::AdPtrMismatch => sys::Argon2_ErrorCodes_ARGON2_AD_PTR_MISMATCH,
147 ErrorCode::MemoryAllocationError => sys::Argon2_ErrorCodes_ARGON2_MEMORY_ALLOCATION_ERROR,
148 ErrorCode::FreeMemoryCbkNull => sys::Argon2_ErrorCodes_ARGON2_FREE_MEMORY_CBK_NULL,
149 ErrorCode::AllocateMemoryCbkNull => sys::Argon2_ErrorCodes_ARGON2_ALLOCATE_MEMORY_CBK_NULL,
150 ErrorCode::IncorrectParameter => sys::Argon2_ErrorCodes_ARGON2_INCORRECT_PARAMETER,
151 ErrorCode::IncorrectType => sys::Argon2_ErrorCodes_ARGON2_INCORRECT_TYPE,
152 ErrorCode::OutPtrMismatch => sys::Argon2_ErrorCodes_ARGON2_OUT_PTR_MISMATCH,
153 ErrorCode::ThreadsTooFew => sys::Argon2_ErrorCodes_ARGON2_THREADS_TOO_FEW,
154 ErrorCode::ThreadsTooMany => sys::Argon2_ErrorCodes_ARGON2_THREADS_TOO_MANY,
155 ErrorCode::MissingArgs => sys::Argon2_ErrorCodes_ARGON2_MISSING_ARGS,
156 ErrorCode::EncodingFail => sys::Argon2_ErrorCodes_ARGON2_ENCODING_FAIL,
157 ErrorCode::DecodingFail => sys::Argon2_ErrorCodes_ARGON2_DECODING_FAIL,
158 ErrorCode::ThreadFail => sys::Argon2_ErrorCodes_ARGON2_THREAD_FAIL,
159 ErrorCode::DecodingLengthFail => sys::Argon2_ErrorCodes_ARGON2_DECODING_LENGTH_FAIL,
160 ErrorCode::VerifyMismatch => sys::Argon2_ErrorCodes_ARGON2_VERIFY_MISMATCH,
161 }
162 }
163}
164
165#[derive(Debug, Clone, Copy)]
167pub enum Variant {
168 D = 0,
169 I = 1,
170 ID = 2,
171}
172
173impl Variant {
174 #[inline]
176 #[allow(dead_code)]
177 fn from_c(c_variant: sys::Argon2_type) -> Variant {
178 match c_variant {
179 sys::Argon2_type_Argon2_d => Variant::D,
180 sys::Argon2_type_Argon2_i => Variant::I,
181 sys::Argon2_type_Argon2_id => Variant::ID,
182 _ => panic!("Unimplemented version {}", c_variant),
183 }
184 }
185
186 #[inline]
188 pub(crate) fn to_c(self) -> sys::Argon2_type {
189 match self {
190 Variant::D => sys::Argon2_type_Argon2_d,
191 Variant::I => sys::Argon2_type_Argon2_i,
192 Variant::ID => sys::Argon2_type_Argon2_id,
193 }
194 }
195}
196
197#[derive(Debug, Clone, Copy)]
199pub enum Version {
200 Version10 = 0x10,
202
203 Version13 = 0x13,
205}
206
207impl Version {
208 pub fn to_int(self) -> u32 {
210 match self {
211 Version::Version10 => 0x10,
212 Version::Version13 => 0x13,
213 }
214 }
215
216 pub fn from_int(n: u32) -> Option<Version> {
218 match n {
219 0x10 => Some(Version::Version10),
220 0x13 => Some(Version::Version13),
221 _ => None,
222 }
223 }
224
225 #[inline]
227 #[allow(dead_code)]
228 pub(crate) fn from_c(c_version: sys::Argon2_version) -> Version {
229 match c_version {
230 sys::Argon2_version_ARGON2_VERSION_10 => Version::Version10,
231 sys::Argon2_version_ARGON2_VERSION_13 => Version::Version13,
232 _ => panic!("Unimplemented version 0x{:X}", c_version),
233 }
234 }
235
236 #[inline]
238 pub(crate) fn to_c(self) -> sys::Argon2_version {
239 match self {
240 Version::Version10 => sys::Argon2_version_ARGON2_VERSION_10,
241 Version::Version13 => sys::Argon2_version_ARGON2_VERSION_13,
242 }
243 }
244}
245
246impl Default for Version {
247 fn default() -> Version {
249 Version::Version13
250 }
251}
252
253bitflags::bitflags! {
254 pub struct Flags: u32 {
256 const DEFAULT = 0;
258 const CLEAR_PASSWORD = 1 << 0;
260 const CLEAR_SECRET = 1 << 1;
262 }
263}
264
265pub struct Context<'o, 'p, 'sa, 'se, 'ad> {
267 pub out: &'o mut [u8],
269 pub pwd: Option<&'p mut [u8]>,
271 pub salt: Option<&'sa mut [u8]>,
273 pub secret: Option<&'se mut [u8]>,
275 pub ad: Option<&'ad mut [u8]>,
277
278 pub t_cost: u32,
280 pub m_cost: u32,
282 pub lanes: u32,
284 pub threads:u32,
286
287 pub version: Version,
289
290 pub flags: Flags,
292}
293
294impl<'o, 'p, 'sa, 'se, 'ad> Context<'o, 'p, 'sa, 'se, 'ad> {
295 pub const MIN_LANES: u32 = 1;
297 pub const MAX_LANES: u32 = 0xFFFFFF;
299
300 pub const SYNC_POINTS: u32 = 4;
302
303 pub const MIN_THREADS: u32 = 1;
305 pub const MAX_THREADS: u32 = 0xFFFFFF;
307
308 pub const MIN_OUTLEN: u32 = 4;
310 pub const MAX_OUTLEN: u32 = 0xFFFFFFFF;
312
313 pub const MIN_TIME: u32 = 1;
315 pub const MAX_TIME: u32 = 0xFFFFFFFF;
317
318 pub const MIN_PWD_LENGTH: u32 = 0;
320 pub const MAX_PWD_LENGTH: u32 = 0xFFFFFFFF;
322
323 pub const MIN_AD_LENGTH: u32 = 0;
325 pub const MAX_AD_LENGTH: u32 = 0xFFFFFFFF;
327
328 pub const MIN_SALT_LENGTH: u32 = 8;
330 pub const MAX_SALT_LENGTH: u32 = 0xFFFFFFFF;
332
333 pub const MIN_SECRET_LENGTH: u32 = 0;
335 pub const MAX_SECRET_LENGTH: u32 = 0xFFFFFFFF;
337
338 pub(crate) fn try_to_c(&mut self) -> Result<sys::Argon2_Context, Error> {
339 Ok(sys::Argon2_Context {
340 out: self.out.as_mut_ptr(),
341 outlen: try_conv("context.out.len", self.out.len())?,
342 pwd: opt_slice_ptr_mut(&mut self.pwd),
343 pwdlen: opt_slice_len_u32("context.pwd.len", &self.pwd)?,
344 salt: opt_slice_ptr_mut(&mut self.salt),
345 saltlen: opt_slice_len_u32("context.salt.len", &self.salt)?,
346 secret: opt_slice_ptr_mut(&mut self.secret),
347 secretlen: opt_slice_len_u32("context.secret.len", &self.secret)?,
348 ad: opt_slice_ptr_mut(&mut self.ad),
349 adlen: opt_slice_len_u32("context.ad.len", &self.ad)?,
350 t_cost: self.t_cost,
351 m_cost: self.m_cost,
352 lanes: self.lanes,
353 threads: self.threads,
354 version: self.version.to_c() as _,
355 allocate_cbk: None,
356 free_cbk: None,
357 flags: self.flags.bits(),
358 })
359 }
360}
361
362pub struct OwnedContext {
364 pub out: Vec<u8>,
366 pub pwd: Option<Vec<u8>>,
368 pub salt: Option<Vec<u8>>,
370 pub secret: Option<Vec<u8>>,
372 pub ad: Option<Vec<u8>>,
374
375 pub t_cost: u32,
377 pub m_cost: u32,
379 pub lanes: u32,
381 pub threads:u32,
383
384 pub version: Version,
386
387 pub flags: Flags,
389}
390
391impl OwnedContext {
392 pub fn borrowed<'a>(&'a mut self) -> Context<'a, 'a, 'a, 'a, 'a> {
393 Context {
394 out: &mut self.out,
395 pwd: self.pwd.as_mut().map(|v| &mut v[0..]),
396 salt: self.salt.as_mut().map(|v| &mut v[0..]),
397 secret: self.secret.as_mut().map(|v| &mut v[0..]),
398 ad: self.ad.as_mut().map(|v| &mut v[0..]),
399 t_cost: self.t_cost,
400 m_cost: self.m_cost,
401 lanes: self.lanes,
402 threads: self.threads,
403 version: self.version,
404 flags: self.flags.clone(),
405 }
406 }
407
408 pub(crate) fn try_to_c(&mut self) -> Result<sys::Argon2_Context, Error> {
409 Ok(sys::Argon2_Context {
410 out: self.out.as_mut_ptr(),
411 outlen: try_conv("context.out.len", self.out.len())?,
412 pwd: opt_slice_ptr_mut(&mut self.pwd),
413 pwdlen: opt_slice_len_u32("context.pwd.len", &self.pwd)?,
414 salt: opt_slice_ptr_mut(&mut self.salt),
415 saltlen: opt_slice_len_u32("context.salt.len", &self.salt)?,
416 secret: opt_slice_ptr_mut(&mut self.secret),
417 secretlen: opt_slice_len_u32("context.secret.len", &self.secret)?,
418 ad: opt_slice_ptr_mut(&mut self.ad),
419 adlen: opt_slice_len_u32("context.ad.len", &self.ad)?,
420 t_cost: self.t_cost,
421 m_cost: self.m_cost,
422 lanes: self.lanes,
423 threads: self.threads,
424 version: self.version.to_c() as _,
425 allocate_cbk: None,
426 free_cbk: None,
427 flags: self.flags.bits(),
428 })
429 }
430}
431
432impl<'o, 'p, 'sa, 'se, 'ad> std::convert::TryFrom<&mut Context<'o, 'p, 'sa, 'se, 'ad>> for sys::Argon2_Context {
433 type Error = self::Error;
434
435 fn try_from(context: &mut Context<'o, 'p, 'sa, 'se, 'ad>) -> Result<Self, Self::Error> {
436 context.try_to_c()
437 }
438}
439
440impl std::convert::TryFrom<&mut OwnedContext> for sys::Argon2_Context {
441 type Error = self::Error;
442
443 fn try_from(context: &mut OwnedContext) -> Result<Self, Self::Error> {
444 context.try_to_c()
445 }
446}
447
448#[inline]
450pub(crate) fn try_conv<T, U: std::convert::TryFrom<T>>(param: &'static str, input: T) -> Result<U, Error> {
451 U::try_from(input).map_err(|_| Error::BadParam(param))
452}
453
454#[inline]
456pub(crate) fn opt_slice_len<T, S: AsRef<[T]>>(opt: &Option<S>) -> usize {
457 opt.as_ref().map(|s| s.as_ref().len()).unwrap_or(0)
458}
459
460#[inline]
463pub(crate) fn opt_slice_len_u32<T, S: AsRef<[T]>>(param: &'static str, opt: &Option<S>) -> Result<u32, Error> {
464 try_conv(param, opt.as_ref().map(|s| s.as_ref().len()).unwrap_or(0))
465}
466
467#[inline]
470pub(crate) fn opt_slice_ptr_mut<T, S: AsMut<[T]>>(opt: &mut Option<S>) -> *mut T {
471 opt.as_mut()
472 .map(|s| s.as_mut().as_mut_ptr())
473 .unwrap_or(std::ptr::null_mut())
474}
475
476#[inline]
479pub(crate) fn opt_slice_ptr<T, S: AsRef<[T]>>(opt: &Option<S>) -> *const T {
480 opt.as_ref()
481 .map(|s| s.as_ref().as_ptr())
482 .unwrap_or(std::ptr::null())
483}