nss/pk11/
context.rs
1use crate::{
6 error::*,
7 pk11::{
8 sym_key::import_sym_key,
9 types::{Context, SymKey},
10 },
11 util::{assert_nss_initialized, map_nss_secstatus, ScopedPtr},
12};
13use std::ptr;
14
15#[derive(Copy, Clone, Debug)]
16#[repr(u8)]
17pub enum HashAlgorithm {
18 SHA256,
19 SHA384,
20}
21
22impl HashAlgorithm {
23 fn result_len(&self) -> u32 {
24 match self {
25 HashAlgorithm::SHA256 => nss_sys::SHA256_LENGTH,
26 HashAlgorithm::SHA384 => nss_sys::SHA384_LENGTH,
27 }
28 }
29
30 fn as_hmac_mechanism(&self) -> u32 {
31 match self {
32 HashAlgorithm::SHA256 => nss_sys::CKM_SHA256_HMAC,
33 HashAlgorithm::SHA384 => nss_sys::CKM_SHA384_HMAC,
34 }
35 }
36
37 pub(crate) fn as_hkdf_mechanism(&self) -> u32 {
38 match self {
39 HashAlgorithm::SHA256 => nss_sys::CKM_NSS_HKDF_SHA256,
40 HashAlgorithm::SHA384 => nss_sys::CKM_NSS_HKDF_SHA384,
41 }
42 }
43}
44
45impl From<&HashAlgorithm> for nss_sys::SECOidTag {
46 fn from(alg: &HashAlgorithm) -> Self {
47 match alg {
48 HashAlgorithm::SHA256 => nss_sys::SECOidTag::SEC_OID_SHA256,
49 HashAlgorithm::SHA384 => nss_sys::SECOidTag::SEC_OID_SHA384,
50 }
51 }
52}
53
54pub fn hash_buf(algorithm: &HashAlgorithm, data: &[u8]) -> Result<Vec<u8>> {
55 assert_nss_initialized();
56 let result_len = usize::try_from(algorithm.result_len())?;
57 let mut out = vec![0u8; result_len];
58 let data_len = i32::try_from(data.len())?;
59 map_nss_secstatus(|| unsafe {
60 nss_sys::PK11_HashBuf(
61 Into::<nss_sys::SECOidTag>::into(algorithm) as u32,
62 out.as_mut_ptr(),
63 data.as_ptr(),
64 data_len,
65 )
66 })?;
67 Ok(out)
68}
69
70pub fn hmac_sign(digest_alg: &HashAlgorithm, sym_key_bytes: &[u8], data: &[u8]) -> Result<Vec<u8>> {
71 let mech = digest_alg.as_hmac_mechanism();
72 let sym_key = import_sym_key(mech.into(), nss_sys::CKA_SIGN.into(), sym_key_bytes)?;
73 let context = create_context_by_sym_key(mech.into(), nss_sys::CKA_SIGN.into(), &sym_key)?;
74 hash_buf_with_context(&context, data)
75}
76
77fn hash_buf_with_context(context: &Context, data: &[u8]) -> Result<Vec<u8>> {
79 assert_nss_initialized();
80 map_nss_secstatus(|| unsafe { nss_sys::PK11_DigestBegin(context.as_mut_ptr()) })?;
81 let data_len = u32::try_from(data.len())?;
82 map_nss_secstatus(|| unsafe {
83 nss_sys::PK11_DigestOp(context.as_mut_ptr(), data.as_ptr(), data_len)
84 })?;
85 let mut out_len: u32 = 0;
88 let mut out = vec![0u8; nss_sys::HASH_LENGTH_MAX as usize];
89 map_nss_secstatus(|| unsafe {
90 nss_sys::PK11_DigestFinal(
91 context.as_mut_ptr(),
92 out.as_mut_ptr(),
93 &mut out_len,
94 nss_sys::HASH_LENGTH_MAX,
95 )
96 })?;
97 out.truncate(usize::try_from(out_len)?);
98 Ok(out)
99}
100
101pub fn create_context_by_sym_key(
105 mechanism: nss_sys::CK_MECHANISM_TYPE,
106 operation: nss_sys::CK_ATTRIBUTE_TYPE,
107 sym_key: &SymKey,
108) -> Result<Context> {
109 assert_nss_initialized();
110 let param = nss_sys::SECItem {
111 type_: nss_sys::SECItemType::siBuffer as u32,
112 data: ptr::null_mut(),
113 len: 0,
114 };
115 unsafe {
116 Context::from_ptr(nss_sys::PK11_CreateContextBySymKey(
117 mechanism,
118 operation,
119 sym_key.as_mut_ptr(),
120 ¶m,
121 ))
122 }
123}