1use crate::{
6 error::*,
7 pk11::sym_key::import_sym_key,
8 util::{assert_nss_initialized, map_nss_secstatus, ScopedPtr},
9};
10use std::{
11 mem,
12 os::raw::{c_uchar, c_uint},
13};
14
15const AES_GCM_TAG_LENGTH: usize = 16;
16
17#[derive(Debug, Copy, Clone)]
18pub enum Operation {
19 Encrypt,
20 Decrypt,
21}
22
23pub fn aes_gcm_crypt(
24 key: &[u8],
25 nonce: &[u8],
26 aad: &[u8],
27 data: &[u8],
28 operation: Operation,
29) -> Result<Vec<u8>> {
30 let mut gcm_params = nss_sys::CK_GCM_PARAMS {
31 pIv: nonce.as_ptr() as nss_sys::CK_BYTE_PTR,
32 ulIvLen: nss_sys::CK_ULONG::try_from(nonce.len())?,
33 ulIvBits: nss_sys::CK_ULONG::try_from(
34 nonce.len().checked_mul(8).ok_or(ErrorKind::InternalError)?,
35 )?,
36 pAAD: aad.as_ptr() as nss_sys::CK_BYTE_PTR,
37 ulAADLen: nss_sys::CK_ULONG::try_from(aad.len())?,
38 ulTagBits: nss_sys::CK_ULONG::try_from(AES_GCM_TAG_LENGTH * 8)?,
39 };
40 let mut params = nss_sys::SECItem {
41 type_: nss_sys::SECItemType::siBuffer as u32,
42 data: &mut gcm_params as *mut _ as *mut c_uchar,
43 len: c_uint::try_from(mem::size_of::<nss_sys::CK_GCM_PARAMS>())?,
44 };
45 common_crypt(
46 nss_sys::CKM_AES_GCM.into(),
47 key,
48 data,
49 AES_GCM_TAG_LENGTH,
50 &mut params,
51 operation,
52 )
53}
54
55pub fn aes_cbc_crypt(
56 key: &[u8],
57 nonce: &[u8],
58 data: &[u8],
59 operation: Operation,
60) -> Result<Vec<u8>> {
61 let mut params = nss_sys::SECItem {
62 type_: nss_sys::SECItemType::siBuffer as u32,
63 data: nonce.as_ptr() as *mut c_uchar,
64 len: c_uint::try_from(nonce.len())?,
65 };
66 common_crypt(
67 nss_sys::CKM_AES_CBC_PAD.into(),
68 key,
69 data,
70 usize::try_from(nss_sys::AES_BLOCK_SIZE)?, &mut params,
72 operation,
73 )
74}
75
76pub fn common_crypt(
77 mech: nss_sys::CK_MECHANISM_TYPE,
78 key: &[u8],
79 data: &[u8],
80 extra_data_len: usize,
81 params: &mut nss_sys::SECItem,
82 operation: Operation,
83) -> Result<Vec<u8>> {
84 assert_nss_initialized();
85 let sym_key = import_sym_key(mech, nss_sys::CKA_ENCRYPT.into(), key)?;
89 let result_max_len = data
91 .len()
92 .checked_add(extra_data_len)
93 .ok_or(ErrorKind::InternalError)?;
94 let mut out_len: c_uint = 0;
95 let mut out = vec![0u8; result_max_len];
96 let result_max_len_uint = c_uint::try_from(result_max_len)?;
97 let data_len = c_uint::try_from(data.len())?;
98 let f = match operation {
99 Operation::Decrypt => nss_sys::PK11_Decrypt,
100 Operation::Encrypt => nss_sys::PK11_Encrypt,
101 };
102 map_nss_secstatus(|| unsafe {
103 f(
104 sym_key.as_mut_ptr(),
105 mech,
106 params,
107 out.as_mut_ptr(),
108 &mut out_len,
109 result_max_len_uint,
110 data.as_ptr(),
111 data_len,
112 )
113 })?;
114 out.truncate(usize::try_from(out_len)?);
115 Ok(out)
116}