1use crate::{
6 error::*,
7 pk11::slot::{generate_random, get_internal_slot},
8 util::{map_nss_secstatus, ScopedPtr},
9};
10use std::{
11 ops::Deref,
12 os::raw::{c_int, c_uchar, c_uint, c_void},
13 ptr,
14};
15
16scoped_ptr!(SymKey, nss_sys::PK11SymKey, nss_sys::PK11_FreeSymKey);
17scoped_ptr!(
18 PrivateKey,
19 nss_sys::SECKEYPrivateKey,
20 nss_sys::SECKEY_DestroyPrivateKey
21);
22scoped_ptr!(
23 PublicKey,
24 nss_sys::SECKEYPublicKey,
25 nss_sys::SECKEY_DestroyPublicKey
26);
27scoped_ptr!(
28 GenericObject,
29 nss_sys::PK11GenericObject,
30 nss_sys::PK11_DestroyGenericObject
31);
32
33scoped_ptr!(
34 Certificate,
35 nss_sys::CERTCertificate,
36 nss_sys::CERT_DestroyCertificate
37);
38
39scoped_ptr!(Context, nss_sys::PK11Context, pk11_destroy_context_true);
40scoped_ptr!(Slot, nss_sys::PK11SlotInfo, nss_sys::PK11_FreeSlot);
41
42scoped_ptr!(
43 AlgorithmID,
44 nss_sys::SECAlgorithmID,
45 secoid_destroy_algorithm_id_true
46);
47
48#[inline]
49unsafe fn secoid_destroy_algorithm_id_true(alg_id: *mut nss_sys::SECAlgorithmID) {
50 nss_sys::SECOID_DestroyAlgorithmID(alg_id, nss_sys::PR_TRUE);
51}
52
53#[inline]
54unsafe fn pk11_destroy_context_true(context: *mut nss_sys::PK11Context) {
55 nss_sys::PK11_DestroyContext(context, nss_sys::PR_TRUE);
56}
57
58pub(crate) unsafe trait Pkcs11Object: ScopedPtr {
64 const PK11_OBJECT_TYPE: nss_sys::PK11ObjectType;
65 fn read_raw_attribute(
66 &self,
67 attribute_type: nss_sys::CK_ATTRIBUTE_TYPE,
68 ) -> Result<ScopedSECItem> {
69 let mut out_sec = ScopedSECItem::empty(nss_sys::SECItemType::siBuffer);
70 map_nss_secstatus(|| unsafe {
71 nss_sys::PK11_ReadRawAttribute(
72 Self::PK11_OBJECT_TYPE as u32,
73 self.as_mut_ptr() as *mut c_void,
74 attribute_type,
75 out_sec.as_mut_ref(),
76 )
77 })?;
78 Ok(out_sec)
79 }
80}
81
82unsafe impl Pkcs11Object for GenericObject {
83 const PK11_OBJECT_TYPE: nss_sys::PK11ObjectType = nss_sys::PK11ObjectType::PK11_TypeGeneric;
84}
85unsafe impl Pkcs11Object for PrivateKey {
86 const PK11_OBJECT_TYPE: nss_sys::PK11ObjectType = nss_sys::PK11ObjectType::PK11_TypePrivKey;
87}
88unsafe impl Pkcs11Object for PublicKey {
89 const PK11_OBJECT_TYPE: nss_sys::PK11ObjectType = nss_sys::PK11ObjectType::PK11_TypePubKey;
90}
91unsafe impl Pkcs11Object for SymKey {
92 const PK11_OBJECT_TYPE: nss_sys::PK11ObjectType = nss_sys::PK11ObjectType::PK11_TypeSymKey;
93}
94
95unsafe impl Send for PrivateKey {}
98unsafe impl Send for PublicKey {}
99
100impl PrivateKey {
101 pub fn convert_to_public_key(&self) -> Result<PublicKey> {
102 Ok(unsafe { PublicKey::from_ptr(nss_sys::SECKEY_ConvertToPublicKey(self.as_mut_ptr()))? })
103 }
104
105 pub(crate) fn from_private_key_template(
110 mut template: Vec<nss_sys::CK_ATTRIBUTE>,
111 ) -> Result<Self> {
112 let mut obj_id_buf = vec![0u8; 160 / 8];
114 generate_random(&mut obj_id_buf)?;
115 let mut obj_id = nss_sys::SECItem {
116 type_: nss_sys::SECItemType::siBuffer as u32,
117 data: obj_id_buf.as_ptr() as *mut c_uchar,
118 len: c_uint::try_from(obj_id_buf.len())?,
119 };
120 let slot = get_internal_slot()?;
121 let mut pre_existing_key = unsafe {
122 nss_sys::PK11_FindKeyByKeyID(slot.as_mut_ptr(), &mut obj_id, std::ptr::null_mut())
123 };
124 if !pre_existing_key.is_null() {
125 unsafe {
131 destroy_private_key_without_destroying_pkcs11_object(pre_existing_key);
132 }
133 generate_random(&mut obj_id_buf)?;
135 pre_existing_key = unsafe {
136 nss_sys::PK11_FindKeyByKeyID(slot.as_mut_ptr(), &mut obj_id, std::ptr::null_mut())
137 };
138 if !pre_existing_key.is_null() {
139 unsafe {
140 destroy_private_key_without_destroying_pkcs11_object(pre_existing_key);
141 }
142 return Err(ErrorKind::InternalError.into());
143 }
144 }
145 let template_len = c_int::try_from(template.len())?;
146 let id_attr: &mut nss_sys::CK_ATTRIBUTE = template
147 .iter_mut()
148 .find(|&&mut attr| {
149 attr.type_ == (nss_sys::CKA_ID as nss_sys::CK_ATTRIBUTE_TYPE)
150 && attr.pValue.is_null()
151 && attr.ulValueLen == 0
152 })
153 .ok_or(ErrorKind::InternalError)?;
154 id_attr.pValue = obj_id_buf.as_mut_ptr() as *mut c_void;
155 id_attr.ulValueLen = nss_sys::CK_ULONG::try_from(obj_id_buf.len())?;
156 let _obj = unsafe {
160 GenericObject::from_ptr(nss_sys::PK11_CreateGenericObject(
161 slot.as_mut_ptr(),
162 template.as_mut_ptr(),
163 template_len,
164 nss_sys::PR_FALSE,
165 ))?
166 };
167 Ok(unsafe {
169 PrivateKey::from_ptr(nss_sys::PK11_FindKeyByKeyID(
170 slot.as_mut_ptr(),
171 &mut obj_id,
172 std::ptr::null_mut(),
173 ))?
174 })
175 }
176}
177
178pub(crate) struct ScopedSECItem {
181 wrapped: nss_sys::SECItem,
182}
183
184impl ScopedSECItem {
185 pub(crate) fn empty(r#type: nss_sys::SECItemType) -> Self {
186 ScopedSECItem {
187 wrapped: nss_sys::SECItem {
188 type_: r#type as u32,
189 data: ptr::null_mut(),
190 len: 0,
191 },
192 }
193 }
194
195 pub(crate) fn as_mut_ref(&mut self) -> &mut nss_sys::SECItem {
196 &mut self.wrapped
197 }
198}
199
200impl Deref for ScopedSECItem {
201 type Target = nss_sys::SECItem;
202 #[inline]
203 fn deref(&self) -> &nss_sys::SECItem {
204 &self.wrapped
205 }
206}
207
208impl Drop for ScopedSECItem {
209 fn drop(&mut self) {
210 unsafe {
211 nss_sys::SECITEM_FreeItem(&mut self.wrapped, nss_sys::PR_FALSE);
214 }
215 }
216}
217
218unsafe fn destroy_private_key_without_destroying_pkcs11_object(
224 key: *mut nss_sys::SECKEYPrivateKey,
225) {
226 assert!(!key.is_null());
227 nss_sys::PK11_FreeSlot((*key).pkcs11Slot);
228 nss_sys::PORT_FreeArena((*key).arena, nss_sys::PR_TRUE);
229}