1use crate::util::{assert_nss_initialized, map_nss_secstatus, sec_item_as_slice, ScopedPtr};
6use crate::{
7 error::*,
8 pk11::{
9 slot::get_internal_slot,
10 types::{AlgorithmID, SymKey},
11 },
12};
13
14pub use crate::pk11::context::HashAlgorithm;
17use nss_sys::SECOidTag;
18
19pub fn pbkdf2_key_derive(
23 password: &[u8],
24 salt: &[u8],
25 iterations: u32,
26 hash_algorithm: HashAlgorithm,
27 out: &mut [u8],
28) -> Result<()> {
29 assert_nss_initialized();
30 let oid_tag = match hash_algorithm {
31 HashAlgorithm::SHA256 => SECOidTag::SEC_OID_HMAC_SHA256 as u32,
32 HashAlgorithm::SHA384 => SECOidTag::SEC_OID_HMAC_SHA384 as u32,
33 };
34 let mut sec_salt = nss_sys::SECItem {
35 len: u32::try_from(salt.len())?,
36 data: salt.as_ptr() as *mut u8,
37 type_: 0,
38 };
39 let alg_id = unsafe {
40 AlgorithmID::from_ptr(nss_sys::PK11_CreatePBEV2AlgorithmID(
41 SECOidTag::SEC_OID_PKCS5_PBKDF2 as u32,
42 SECOidTag::SEC_OID_HMAC_SHA1 as u32,
43 oid_tag,
44 i32::try_from(out.len())?,
45 i32::try_from(iterations)?,
46 &mut sec_salt as *mut nss_sys::SECItem,
47 ))?
48 };
49
50 let slot = get_internal_slot()?;
51 let mut sec_pw = nss_sys::SECItem {
52 len: u32::try_from(password.len())?,
53 data: password.as_ptr() as *mut u8,
54 type_: 0,
55 };
56 let sym_key = unsafe {
57 SymKey::from_ptr(nss_sys::PK11_PBEKeyGen(
58 slot.as_mut_ptr(),
59 alg_id.as_mut_ptr(),
60 &mut sec_pw as *mut nss_sys::SECItem,
61 nss_sys::PR_FALSE,
62 std::ptr::null_mut(),
63 ))?
64 };
65 map_nss_secstatus(|| unsafe { nss_sys::PK11_ExtractKeyValue(sym_key.as_mut_ptr()) })?;
66
67 let mut key_data = unsafe { *nss_sys::PK11_GetKeyData(sym_key.as_mut_ptr()) };
70 let buf = unsafe { sec_item_as_slice(&mut key_data)? };
71 if buf.len() != out.len() {
73 return Err(ErrorKind::InternalError.into());
74 }
75 out.swap_with_slice(buf);
76 Ok(())
77}