192f3ab15Sopenharmony_ci#[cfg(not(boringssl))]
292f3ab15Sopenharmony_ciuse libc::c_int;
392f3ab15Sopenharmony_ciuse std::convert::TryInto;
492f3ab15Sopenharmony_ci#[cfg(not(boringssl))]
592f3ab15Sopenharmony_ciuse std::ptr;
692f3ab15Sopenharmony_ci
792f3ab15Sopenharmony_ciuse crate::cvt;
892f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
992f3ab15Sopenharmony_ciuse crate::hash::MessageDigest;
1092f3ab15Sopenharmony_ci#[cfg(not(boringssl))]
1192f3ab15Sopenharmony_ciuse crate::symm::Cipher;
1292f3ab15Sopenharmony_ciuse openssl_macros::corresponds;
1392f3ab15Sopenharmony_ci
1492f3ab15Sopenharmony_ci#[derive(Clone, Eq, PartialEq, Hash, Debug)]
1592f3ab15Sopenharmony_cipub struct KeyIvPair {
1692f3ab15Sopenharmony_ci    pub key: Vec<u8>,
1792f3ab15Sopenharmony_ci    pub iv: Option<Vec<u8>>,
1892f3ab15Sopenharmony_ci}
1992f3ab15Sopenharmony_ci
2092f3ab15Sopenharmony_ci/// Derives a key and an IV from various parameters.
2192f3ab15Sopenharmony_ci///
2292f3ab15Sopenharmony_ci/// If specified, `salt` must be 8 bytes in length.
2392f3ab15Sopenharmony_ci///
2492f3ab15Sopenharmony_ci/// If the total key and IV length is less than 16 bytes and MD5 is used then
2592f3ab15Sopenharmony_ci/// the algorithm is compatible with the key derivation algorithm from PKCS#5
2692f3ab15Sopenharmony_ci/// v1.5 or PBKDF1 from PKCS#5 v2.0.
2792f3ab15Sopenharmony_ci///
2892f3ab15Sopenharmony_ci/// New applications should not use this and instead use
2992f3ab15Sopenharmony_ci/// `pbkdf2_hmac` or another more modern key derivation algorithm.
3092f3ab15Sopenharmony_ci#[corresponds(EVP_BytesToKey)]
3192f3ab15Sopenharmony_ci#[allow(clippy::useless_conversion)]
3292f3ab15Sopenharmony_ci#[cfg(not(boringssl))]
3392f3ab15Sopenharmony_cipub fn bytes_to_key(
3492f3ab15Sopenharmony_ci    cipher: Cipher,
3592f3ab15Sopenharmony_ci    digest: MessageDigest,
3692f3ab15Sopenharmony_ci    data: &[u8],
3792f3ab15Sopenharmony_ci    salt: Option<&[u8]>,
3892f3ab15Sopenharmony_ci    count: i32,
3992f3ab15Sopenharmony_ci) -> Result<KeyIvPair, ErrorStack> {
4092f3ab15Sopenharmony_ci    unsafe {
4192f3ab15Sopenharmony_ci        assert!(data.len() <= c_int::max_value() as usize);
4292f3ab15Sopenharmony_ci        let salt_ptr = match salt {
4392f3ab15Sopenharmony_ci            Some(salt) => {
4492f3ab15Sopenharmony_ci                assert_eq!(salt.len(), ffi::PKCS5_SALT_LEN as usize);
4592f3ab15Sopenharmony_ci                salt.as_ptr()
4692f3ab15Sopenharmony_ci            }
4792f3ab15Sopenharmony_ci            None => ptr::null(),
4892f3ab15Sopenharmony_ci        };
4992f3ab15Sopenharmony_ci
5092f3ab15Sopenharmony_ci        ffi::init();
5192f3ab15Sopenharmony_ci
5292f3ab15Sopenharmony_ci        let mut iv = cipher.iv_len().map(|l| vec![0; l]);
5392f3ab15Sopenharmony_ci
5492f3ab15Sopenharmony_ci        let cipher = cipher.as_ptr();
5592f3ab15Sopenharmony_ci        let digest = digest.as_ptr();
5692f3ab15Sopenharmony_ci
5792f3ab15Sopenharmony_ci        let len = cvt(ffi::EVP_BytesToKey(
5892f3ab15Sopenharmony_ci            cipher,
5992f3ab15Sopenharmony_ci            digest,
6092f3ab15Sopenharmony_ci            salt_ptr,
6192f3ab15Sopenharmony_ci            ptr::null(),
6292f3ab15Sopenharmony_ci            data.len() as c_int,
6392f3ab15Sopenharmony_ci            count.into(),
6492f3ab15Sopenharmony_ci            ptr::null_mut(),
6592f3ab15Sopenharmony_ci            ptr::null_mut(),
6692f3ab15Sopenharmony_ci        ))?;
6792f3ab15Sopenharmony_ci
6892f3ab15Sopenharmony_ci        let mut key = vec![0; len as usize];
6992f3ab15Sopenharmony_ci        let iv_ptr = iv
7092f3ab15Sopenharmony_ci            .as_mut()
7192f3ab15Sopenharmony_ci            .map(|v| v.as_mut_ptr())
7292f3ab15Sopenharmony_ci            .unwrap_or(ptr::null_mut());
7392f3ab15Sopenharmony_ci
7492f3ab15Sopenharmony_ci        cvt(ffi::EVP_BytesToKey(
7592f3ab15Sopenharmony_ci            cipher,
7692f3ab15Sopenharmony_ci            digest,
7792f3ab15Sopenharmony_ci            salt_ptr,
7892f3ab15Sopenharmony_ci            data.as_ptr(),
7992f3ab15Sopenharmony_ci            data.len() as c_int,
8092f3ab15Sopenharmony_ci            count as c_int,
8192f3ab15Sopenharmony_ci            key.as_mut_ptr(),
8292f3ab15Sopenharmony_ci            iv_ptr,
8392f3ab15Sopenharmony_ci        ))?;
8492f3ab15Sopenharmony_ci
8592f3ab15Sopenharmony_ci        Ok(KeyIvPair { key, iv })
8692f3ab15Sopenharmony_ci    }
8792f3ab15Sopenharmony_ci}
8892f3ab15Sopenharmony_ci
8992f3ab15Sopenharmony_ci/// Derives a key from a password and salt using the PBKDF2-HMAC algorithm with a digest function.
9092f3ab15Sopenharmony_ci#[corresponds(PKCS5_PBKDF2_HMAC)]
9192f3ab15Sopenharmony_cipub fn pbkdf2_hmac(
9292f3ab15Sopenharmony_ci    pass: &[u8],
9392f3ab15Sopenharmony_ci    salt: &[u8],
9492f3ab15Sopenharmony_ci    iter: usize,
9592f3ab15Sopenharmony_ci    hash: MessageDigest,
9692f3ab15Sopenharmony_ci    key: &mut [u8],
9792f3ab15Sopenharmony_ci) -> Result<(), ErrorStack> {
9892f3ab15Sopenharmony_ci    unsafe {
9992f3ab15Sopenharmony_ci        ffi::init();
10092f3ab15Sopenharmony_ci        cvt(ffi::PKCS5_PBKDF2_HMAC(
10192f3ab15Sopenharmony_ci            pass.as_ptr() as *const _,
10292f3ab15Sopenharmony_ci            pass.len().try_into().unwrap(),
10392f3ab15Sopenharmony_ci            salt.as_ptr(),
10492f3ab15Sopenharmony_ci            salt.len().try_into().unwrap(),
10592f3ab15Sopenharmony_ci            iter.try_into().unwrap(),
10692f3ab15Sopenharmony_ci            hash.as_ptr(),
10792f3ab15Sopenharmony_ci            key.len().try_into().unwrap(),
10892f3ab15Sopenharmony_ci            key.as_mut_ptr(),
10992f3ab15Sopenharmony_ci        ))
11092f3ab15Sopenharmony_ci        .map(|_| ())
11192f3ab15Sopenharmony_ci    }
11292f3ab15Sopenharmony_ci}
11392f3ab15Sopenharmony_ci
11492f3ab15Sopenharmony_ci/// Derives a key from a password and salt using the scrypt algorithm.
11592f3ab15Sopenharmony_ci///
11692f3ab15Sopenharmony_ci/// Requires OpenSSL 1.1.0 or newer.
11792f3ab15Sopenharmony_ci#[corresponds(EVP_PBE_scrypt)]
11892f3ab15Sopenharmony_ci#[cfg(any(ossl110, boringssl))]
11992f3ab15Sopenharmony_ci#[allow(clippy::useless_conversion)]
12092f3ab15Sopenharmony_cipub fn scrypt(
12192f3ab15Sopenharmony_ci    pass: &[u8],
12292f3ab15Sopenharmony_ci    salt: &[u8],
12392f3ab15Sopenharmony_ci    n: u64,
12492f3ab15Sopenharmony_ci    r: u64,
12592f3ab15Sopenharmony_ci    p: u64,
12692f3ab15Sopenharmony_ci    maxmem: u64,
12792f3ab15Sopenharmony_ci    key: &mut [u8],
12892f3ab15Sopenharmony_ci) -> Result<(), ErrorStack> {
12992f3ab15Sopenharmony_ci    unsafe {
13092f3ab15Sopenharmony_ci        ffi::init();
13192f3ab15Sopenharmony_ci        cvt(ffi::EVP_PBE_scrypt(
13292f3ab15Sopenharmony_ci            pass.as_ptr() as *const _,
13392f3ab15Sopenharmony_ci            pass.len(),
13492f3ab15Sopenharmony_ci            salt.as_ptr() as *const _,
13592f3ab15Sopenharmony_ci            salt.len(),
13692f3ab15Sopenharmony_ci            n,
13792f3ab15Sopenharmony_ci            r,
13892f3ab15Sopenharmony_ci            p,
13992f3ab15Sopenharmony_ci            maxmem.try_into().unwrap(),
14092f3ab15Sopenharmony_ci            key.as_mut_ptr() as *mut _,
14192f3ab15Sopenharmony_ci            key.len(),
14292f3ab15Sopenharmony_ci        ))
14392f3ab15Sopenharmony_ci        .map(|_| ())
14492f3ab15Sopenharmony_ci    }
14592f3ab15Sopenharmony_ci}
14692f3ab15Sopenharmony_ci
14792f3ab15Sopenharmony_ci#[cfg(test)]
14892f3ab15Sopenharmony_cimod tests {
14992f3ab15Sopenharmony_ci    use crate::hash::MessageDigest;
15092f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
15192f3ab15Sopenharmony_ci    use crate::symm::Cipher;
15292f3ab15Sopenharmony_ci
15392f3ab15Sopenharmony_ci    // Test vectors from
15492f3ab15Sopenharmony_ci    // https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c
15592f3ab15Sopenharmony_ci    #[test]
15692f3ab15Sopenharmony_ci    fn pbkdf2_hmac_sha256() {
15792f3ab15Sopenharmony_ci        let mut buf = [0; 16];
15892f3ab15Sopenharmony_ci
15992f3ab15Sopenharmony_ci        super::pbkdf2_hmac(b"passwd", b"salt", 1, MessageDigest::sha256(), &mut buf).unwrap();
16092f3ab15Sopenharmony_ci        assert_eq!(
16192f3ab15Sopenharmony_ci            buf,
16292f3ab15Sopenharmony_ci            &[
16392f3ab15Sopenharmony_ci                0x55_u8, 0xac_u8, 0x04_u8, 0x6e_u8, 0x56_u8, 0xe3_u8, 0x08_u8, 0x9f_u8, 0xec_u8,
16492f3ab15Sopenharmony_ci                0x16_u8, 0x91_u8, 0xc2_u8, 0x25_u8, 0x44_u8, 0xb6_u8, 0x05_u8,
16592f3ab15Sopenharmony_ci            ][..]
16692f3ab15Sopenharmony_ci        );
16792f3ab15Sopenharmony_ci
16892f3ab15Sopenharmony_ci        super::pbkdf2_hmac(
16992f3ab15Sopenharmony_ci            b"Password",
17092f3ab15Sopenharmony_ci            b"NaCl",
17192f3ab15Sopenharmony_ci            80000,
17292f3ab15Sopenharmony_ci            MessageDigest::sha256(),
17392f3ab15Sopenharmony_ci            &mut buf,
17492f3ab15Sopenharmony_ci        )
17592f3ab15Sopenharmony_ci        .unwrap();
17692f3ab15Sopenharmony_ci        assert_eq!(
17792f3ab15Sopenharmony_ci            buf,
17892f3ab15Sopenharmony_ci            &[
17992f3ab15Sopenharmony_ci                0x4d_u8, 0xdc_u8, 0xd8_u8, 0xf6_u8, 0x0b_u8, 0x98_u8, 0xbe_u8, 0x21_u8, 0x83_u8,
18092f3ab15Sopenharmony_ci                0x0c_u8, 0xee_u8, 0x5e_u8, 0xf2_u8, 0x27_u8, 0x01_u8, 0xf9_u8,
18192f3ab15Sopenharmony_ci            ][..]
18292f3ab15Sopenharmony_ci        );
18392f3ab15Sopenharmony_ci    }
18492f3ab15Sopenharmony_ci
18592f3ab15Sopenharmony_ci    // Test vectors from
18692f3ab15Sopenharmony_ci    // https://git.lysator.liu.se/nettle/nettle/blob/nettle_3.1.1_release_20150424/testsuite/pbkdf2-test.c
18792f3ab15Sopenharmony_ci    #[test]
18892f3ab15Sopenharmony_ci    fn pbkdf2_hmac_sha512() {
18992f3ab15Sopenharmony_ci        let mut buf = [0; 64];
19092f3ab15Sopenharmony_ci
19192f3ab15Sopenharmony_ci        super::pbkdf2_hmac(b"password", b"NaCL", 1, MessageDigest::sha512(), &mut buf).unwrap();
19292f3ab15Sopenharmony_ci        assert_eq!(
19392f3ab15Sopenharmony_ci            &buf[..],
19492f3ab15Sopenharmony_ci            &[
19592f3ab15Sopenharmony_ci                0x73_u8, 0xde_u8, 0xcf_u8, 0xa5_u8, 0x8a_u8, 0xa2_u8, 0xe8_u8, 0x4f_u8, 0x94_u8,
19692f3ab15Sopenharmony_ci                0x77_u8, 0x1a_u8, 0x75_u8, 0x73_u8, 0x6b_u8, 0xb8_u8, 0x8b_u8, 0xd3_u8, 0xc7_u8,
19792f3ab15Sopenharmony_ci                0xb3_u8, 0x82_u8, 0x70_u8, 0xcf_u8, 0xb5_u8, 0x0c_u8, 0xb3_u8, 0x90_u8, 0xed_u8,
19892f3ab15Sopenharmony_ci                0x78_u8, 0xb3_u8, 0x05_u8, 0x65_u8, 0x6a_u8, 0xf8_u8, 0x14_u8, 0x8e_u8, 0x52_u8,
19992f3ab15Sopenharmony_ci                0x45_u8, 0x2b_u8, 0x22_u8, 0x16_u8, 0xb2_u8, 0xb8_u8, 0x09_u8, 0x8b_u8, 0x76_u8,
20092f3ab15Sopenharmony_ci                0x1f_u8, 0xc6_u8, 0x33_u8, 0x60_u8, 0x60_u8, 0xa0_u8, 0x9f_u8, 0x76_u8, 0x41_u8,
20192f3ab15Sopenharmony_ci                0x5e_u8, 0x9f_u8, 0x71_u8, 0xea_u8, 0x47_u8, 0xf9_u8, 0xe9_u8, 0x06_u8, 0x43_u8,
20292f3ab15Sopenharmony_ci                0x06_u8,
20392f3ab15Sopenharmony_ci            ][..]
20492f3ab15Sopenharmony_ci        );
20592f3ab15Sopenharmony_ci
20692f3ab15Sopenharmony_ci        super::pbkdf2_hmac(
20792f3ab15Sopenharmony_ci            b"pass\0word",
20892f3ab15Sopenharmony_ci            b"sa\0lt",
20992f3ab15Sopenharmony_ci            1,
21092f3ab15Sopenharmony_ci            MessageDigest::sha512(),
21192f3ab15Sopenharmony_ci            &mut buf,
21292f3ab15Sopenharmony_ci        )
21392f3ab15Sopenharmony_ci        .unwrap();
21492f3ab15Sopenharmony_ci        assert_eq!(
21592f3ab15Sopenharmony_ci            &buf[..],
21692f3ab15Sopenharmony_ci            &[
21792f3ab15Sopenharmony_ci                0x71_u8, 0xa0_u8, 0xec_u8, 0x84_u8, 0x2a_u8, 0xbd_u8, 0x5c_u8, 0x67_u8, 0x8b_u8,
21892f3ab15Sopenharmony_ci                0xcf_u8, 0xd1_u8, 0x45_u8, 0xf0_u8, 0x9d_u8, 0x83_u8, 0x52_u8, 0x2f_u8, 0x93_u8,
21992f3ab15Sopenharmony_ci                0x36_u8, 0x15_u8, 0x60_u8, 0x56_u8, 0x3c_u8, 0x4d_u8, 0x0d_u8, 0x63_u8, 0xb8_u8,
22092f3ab15Sopenharmony_ci                0x83_u8, 0x29_u8, 0x87_u8, 0x10_u8, 0x90_u8, 0xe7_u8, 0x66_u8, 0x04_u8, 0xa4_u8,
22192f3ab15Sopenharmony_ci                0x9a_u8, 0xf0_u8, 0x8f_u8, 0xe7_u8, 0xc9_u8, 0xf5_u8, 0x71_u8, 0x56_u8, 0xc8_u8,
22292f3ab15Sopenharmony_ci                0x79_u8, 0x09_u8, 0x96_u8, 0xb2_u8, 0x0f_u8, 0x06_u8, 0xbc_u8, 0x53_u8, 0x5e_u8,
22392f3ab15Sopenharmony_ci                0x5a_u8, 0xb5_u8, 0x44_u8, 0x0d_u8, 0xf7_u8, 0xe8_u8, 0x78_u8, 0x29_u8, 0x6f_u8,
22492f3ab15Sopenharmony_ci                0xa7_u8,
22592f3ab15Sopenharmony_ci            ][..]
22692f3ab15Sopenharmony_ci        );
22792f3ab15Sopenharmony_ci
22892f3ab15Sopenharmony_ci        super::pbkdf2_hmac(
22992f3ab15Sopenharmony_ci            b"passwordPASSWORDpassword",
23092f3ab15Sopenharmony_ci            b"salt\0\0\0",
23192f3ab15Sopenharmony_ci            50,
23292f3ab15Sopenharmony_ci            MessageDigest::sha512(),
23392f3ab15Sopenharmony_ci            &mut buf,
23492f3ab15Sopenharmony_ci        )
23592f3ab15Sopenharmony_ci        .unwrap();
23692f3ab15Sopenharmony_ci        assert_eq!(
23792f3ab15Sopenharmony_ci            &buf[..],
23892f3ab15Sopenharmony_ci            &[
23992f3ab15Sopenharmony_ci                0x01_u8, 0x68_u8, 0x71_u8, 0xa4_u8, 0xc4_u8, 0xb7_u8, 0x5f_u8, 0x96_u8, 0x85_u8,
24092f3ab15Sopenharmony_ci                0x7f_u8, 0xd2_u8, 0xb9_u8, 0xf8_u8, 0xca_u8, 0x28_u8, 0x02_u8, 0x3b_u8, 0x30_u8,
24192f3ab15Sopenharmony_ci                0xee_u8, 0x2a_u8, 0x39_u8, 0xf5_u8, 0xad_u8, 0xca_u8, 0xc8_u8, 0xc9_u8, 0x37_u8,
24292f3ab15Sopenharmony_ci                0x5f_u8, 0x9b_u8, 0xda_u8, 0x1c_u8, 0xcd_u8, 0x1b_u8, 0x6f_u8, 0x0b_u8, 0x2f_u8,
24392f3ab15Sopenharmony_ci                0xc3_u8, 0xad_u8, 0xda_u8, 0x50_u8, 0x54_u8, 0x12_u8, 0xe7_u8, 0x9d_u8, 0x89_u8,
24492f3ab15Sopenharmony_ci                0x00_u8, 0x56_u8, 0xc6_u8, 0x2e_u8, 0x52_u8, 0x4c_u8, 0x7d_u8, 0x51_u8, 0x15_u8,
24592f3ab15Sopenharmony_ci                0x4b_u8, 0x1a_u8, 0x85_u8, 0x34_u8, 0x57_u8, 0x5b_u8, 0xd0_u8, 0x2d_u8, 0xee_u8,
24692f3ab15Sopenharmony_ci                0x39_u8,
24792f3ab15Sopenharmony_ci            ][..]
24892f3ab15Sopenharmony_ci        );
24992f3ab15Sopenharmony_ci    }
25092f3ab15Sopenharmony_ci
25192f3ab15Sopenharmony_ci    #[test]
25292f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
25392f3ab15Sopenharmony_ci    fn bytes_to_key() {
25492f3ab15Sopenharmony_ci        let salt = [16_u8, 34_u8, 19_u8, 23_u8, 141_u8, 4_u8, 207_u8, 221_u8];
25592f3ab15Sopenharmony_ci
25692f3ab15Sopenharmony_ci        let data = [
25792f3ab15Sopenharmony_ci            143_u8, 210_u8, 75_u8, 63_u8, 214_u8, 179_u8, 155_u8, 241_u8, 242_u8, 31_u8, 154_u8,
25892f3ab15Sopenharmony_ci            56_u8, 198_u8, 145_u8, 192_u8, 64_u8, 2_u8, 245_u8, 167_u8, 220_u8, 55_u8, 119_u8,
25992f3ab15Sopenharmony_ci            233_u8, 136_u8, 139_u8, 27_u8, 71_u8, 242_u8, 119_u8, 175_u8, 65_u8, 207_u8,
26092f3ab15Sopenharmony_ci        ];
26192f3ab15Sopenharmony_ci
26292f3ab15Sopenharmony_ci        let expected_key = vec![
26392f3ab15Sopenharmony_ci            249_u8, 115_u8, 114_u8, 97_u8, 32_u8, 213_u8, 165_u8, 146_u8, 58_u8, 87_u8, 234_u8,
26492f3ab15Sopenharmony_ci            3_u8, 43_u8, 250_u8, 97_u8, 114_u8, 26_u8, 98_u8, 245_u8, 246_u8, 238_u8, 177_u8,
26592f3ab15Sopenharmony_ci            229_u8, 161_u8, 183_u8, 224_u8, 174_u8, 3_u8, 6_u8, 244_u8, 236_u8, 255_u8,
26692f3ab15Sopenharmony_ci        ];
26792f3ab15Sopenharmony_ci        let expected_iv = vec![
26892f3ab15Sopenharmony_ci            4_u8, 223_u8, 153_u8, 219_u8, 28_u8, 142_u8, 234_u8, 68_u8, 227_u8, 69_u8, 98_u8,
26992f3ab15Sopenharmony_ci            107_u8, 208_u8, 14_u8, 236_u8, 60_u8,
27092f3ab15Sopenharmony_ci        ];
27192f3ab15Sopenharmony_ci
27292f3ab15Sopenharmony_ci        assert_eq!(
27392f3ab15Sopenharmony_ci            super::bytes_to_key(
27492f3ab15Sopenharmony_ci                Cipher::aes_256_cbc(),
27592f3ab15Sopenharmony_ci                MessageDigest::sha1(),
27692f3ab15Sopenharmony_ci                &data,
27792f3ab15Sopenharmony_ci                Some(&salt),
27892f3ab15Sopenharmony_ci                1,
27992f3ab15Sopenharmony_ci            )
28092f3ab15Sopenharmony_ci            .unwrap(),
28192f3ab15Sopenharmony_ci            super::KeyIvPair {
28292f3ab15Sopenharmony_ci                key: expected_key,
28392f3ab15Sopenharmony_ci                iv: Some(expected_iv),
28492f3ab15Sopenharmony_ci            }
28592f3ab15Sopenharmony_ci        );
28692f3ab15Sopenharmony_ci    }
28792f3ab15Sopenharmony_ci
28892f3ab15Sopenharmony_ci    #[test]
28992f3ab15Sopenharmony_ci    #[cfg(any(ossl110, boringssl))]
29092f3ab15Sopenharmony_ci    fn scrypt() {
29192f3ab15Sopenharmony_ci        let pass = "pleaseletmein";
29292f3ab15Sopenharmony_ci        let salt = "SodiumChloride";
29392f3ab15Sopenharmony_ci        let expected =
29492f3ab15Sopenharmony_ci            "7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613\
29592f3ab15Sopenharmony_ci             f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887";
29692f3ab15Sopenharmony_ci
29792f3ab15Sopenharmony_ci        let mut actual = [0; 64];
29892f3ab15Sopenharmony_ci        super::scrypt(
29992f3ab15Sopenharmony_ci            pass.as_bytes(),
30092f3ab15Sopenharmony_ci            salt.as_bytes(),
30192f3ab15Sopenharmony_ci            16384,
30292f3ab15Sopenharmony_ci            8,
30392f3ab15Sopenharmony_ci            1,
30492f3ab15Sopenharmony_ci            0,
30592f3ab15Sopenharmony_ci            &mut actual,
30692f3ab15Sopenharmony_ci        )
30792f3ab15Sopenharmony_ci        .unwrap();
30892f3ab15Sopenharmony_ci        assert_eq!(hex::encode(&actual[..]), expected);
30992f3ab15Sopenharmony_ci    }
31092f3ab15Sopenharmony_ci}
311