pub const fn validate_inputs(
out_len: usize,
pwd_len: usize,
salt_len: usize,
secret_len: usize,
ad_len: usize,
m_cost: u32,
t_cost: u32,
lanes: u32,
threads: u32,
) -> Result<(), Error>Expand description
validate_inputs() from src/core.c, in the exact same order.
The order is load-bearing: when several inputs are invalid, the C reference returns the error for whichever check runs first, and the differential tests compare error codes.
Checks the C performs that are omitted here, with the reason:
context == NULL→ARGON2_INCORRECT_PARAMETER: no null contexts in Rust.out == NULL→ARGON2_OUTPUT_PTR_NULL: no null slices in Rust.- the four
*_PTR_MISMATCHchecks: a Rust slice always has a valid pointer. ARGON2_MIN_PWD_LENGTH > pwdlen,ARGON2_MIN_AD_LENGTH > adlen,ARGON2_MIN_SECRET > secretlen: those minima are all 0, so the checks can never fire (and would be tautological comparisons in Rust).- the two allocator-callback checks: this crate has no allocator callbacks.
Note the C computes 8 * context->lanes in uint32_t, before lanes has
been range-checked, so it can wrap. u32::wrapping_mul reproduces that:
lanes = 0xFFFF_FFFF yields MemoryTooLittle, not LanesTooMany.
§Prefer Params::validate_for
This free function is the escape hatch, not the main path.
Params::validate_for calls it with five of the nine arguments filled in
from the receiver: the tag length (out_len, from Params::tag_len_bytes)
and the four cost values (m_cost, t_cost, lanes, threads). It leaves
the caller exactly the four buffer lengths, pwd_len, salt_len,
secret_len and ad_len. Those five values come from a Params that
ParamsBuilder::build already ran through this function, so they cannot
drift from the costs the hash will actually run with, and core takes that
route on every hash.
Reach for this function directly only when the C’s exact check ordering is
what is wanted, which is the one thing the Params route cannot give you:
ParamsBuilder::build validates the cost parameters at construction time,
so a caller who supplies both a bad m_cost and a short salt sees the
m_cost error where the C reports ARGON2_SALT_TOO_SHORT (the divergence
note on Params spells this out).
decode_string is the in-crate example: it calls this function directly on
the decoded fields and only builds its Params afterwards, so that a
malformed PHC string yields the same error code validate_inputs()
(core.c:388-513) yields in the C.
use argon2_rust::Error;
use argon2_rust::params::{Memory, Params, validate_inputs};
let params = Params::builder().memory(Memory::kib(19_456)).passes(2).build()?;
// Four arguments. The tag length and the four costs come from `params`.
assert_eq!(params.validate_for(8, 16, 0, 0), Ok(()));
// The same check spelled out. The five values `params` would have supplied
// have to be repeated by hand and kept in step with it.
assert_eq!(validate_inputs(32, 8, 16, 0, 0, 19_456, 2, 1, 1), Ok(()));
// `out_len` and `pwd_len` transposed, which is the pair `validate_for`
// takes off the call site entirely. Both are `usize` and adjacent, so this
// compiles, and there is no error to notice: the password length 8 is now
// the tag length, 8 clears `MIN_OUTLEN` (4), and the call says `Ok(())`
// while agreeing to a 64-bit tag.
assert_eq!(validate_inputs(8, 32, 16, 0, 0, 19_456, 2, 1, 1), Ok(()));
// The method form cannot be told that. `out_len` is not one of its four
// arguments; it comes from the `Params`, which holds it at 32.
assert_eq!(params.tag_len_bytes(), 32);
assert_eq!(params.validate_for(32, 16, 0, 0), Ok(()));