Coverage Report

Created: 2025-02-22 06:51

/src/password-hashes/fuzz/fuzz_targets/scrypt.rs
Line
Count
Source (jump to first uncovered line)
1
#![no_main]
2
use libfuzzer_sys::arbitrary::{Arbitrary, Result, Unstructured};
3
use libfuzzer_sys::fuzz_target;
4
use scrypt::password_hash::{
5
    Ident, PasswordHash, PasswordHasher, PasswordVerifier, Salt, SaltString,
6
};
7
use scrypt::{scrypt, Scrypt};
8
9
#[derive(Debug)]
10
pub struct ScryptRandParams(pub scrypt::Params);
11
12
impl<'a> Arbitrary<'a> for ScryptRandParams {
13
801
    fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
14
801
        let log_n = u.int_in_range(0..=15)?;
15
801
        let r = u.int_in_range(1..=16)?;
16
801
        let p = u.int_in_range(1..=8)?;
17
801
        let len = u.int_in_range(10..=64)?;
18
19
801
        let params = scrypt::Params::new(log_n, r, p, len).unwrap();
20
801
        Ok(Self(params))
21
801
    }
22
}
23
24
fuzz_target!(|data: (&[u8], &[u8], ScryptRandParams)| {
25
    let (password, salt, ScryptRandParams(params)) = data;
26
27
    if password.len() > 64 {
28
        return;
29
    }
30
31
    if salt.len() < Salt::MIN_LENGTH || salt.len() > (6 * Salt::MAX_LENGTH) / 8 {
32
        return;
33
    }
34
35
    // Check direct hashing
36
    let mut result = [0u8; 64];
37
    scrypt(password, salt, &params, &mut result).unwrap();
38
39
    // Check PHC hashing
40
    let salt_string = SaltString::encode_b64(salt).unwrap();
41
    let phc_hash = Scrypt
42
        .hash_password_customized(
43
            password,
44
            Some(Ident::new_unwrap("scrypt")),
45
            None,
46
            params,
47
            &salt_string,
48
        )
49
        .unwrap()
50
        .to_string();
51
52
    // Check PHC verification
53
    let hash = PasswordHash::new(&phc_hash).unwrap();
54
    Scrypt.verify_password(password, &hash).unwrap();
55
});