1use crate::device::Device;
6use crate::error::{check_error, Result, QuacError, ErrorCode};
7use crate::ffi;
8use crate::types::{KeyType, KeyUsage};
9
10use std::ffi::CString;
11
12#[derive(Debug, Clone)]
14pub struct KeyInfo {
15 pub slot: u32,
17 pub key_type: KeyType,
19 pub algorithm: i32,
21 pub usage: KeyUsage,
23 pub label: String,
25 pub created: u64,
27 pub exportable: bool,
29}
30
31impl KeyInfo {
32 pub(crate) fn from_ffi(info: &ffi::quac_key_info_t) -> Self {
33 use std::ffi::CStr;
34
35 Self {
36 slot: info.slot,
37 key_type: KeyType::from_raw(info.key_type).unwrap_or(KeyType::Secret),
38 algorithm: info.algorithm,
39 usage: KeyUsage::from_bits_truncate(info.usage),
40 label: unsafe {
41 CStr::from_ptr(info.label.as_ptr())
42 .to_string_lossy()
43 .into_owned()
44 },
45 created: info.created,
46 exportable: info.exportable != 0,
47 }
48 }
49}
50
51#[derive(Clone)]
86pub struct Keys {
87 device: Device,
88}
89
90impl Keys {
91 pub(crate) fn new(device: Device) -> Self {
93 Self { device }
94 }
95
96 pub fn store(
107 &self,
108 slot: u32,
109 key_type: KeyType,
110 algorithm: i32,
111 usage: KeyUsage,
112 label: &str,
113 key_data: &[u8],
114 ) -> Result<()> {
115 let c_label = CString::new(label).map_err(|_| {
116 QuacError::InvalidParameter("Label contains null bytes".into())
117 })?;
118
119 let result = unsafe {
120 ffi::quac_key_store(
121 self.device.handle(),
122 slot,
123 key_type.to_raw(),
124 algorithm,
125 usage.bits(),
126 c_label.as_ptr(),
127 key_data.as_ptr(),
128 key_data.len(),
129 )
130 };
131
132 check_error(result)
133 }
134
135 pub fn load(&self, slot: u32) -> Result<Vec<u8>> {
145 let _info = self.get_info(slot)?;
147 let max_size = 8192; let mut key_data = vec![0u8; max_size];
150 let mut key_len = max_size;
151
152 let result = unsafe {
153 ffi::quac_key_load(
154 self.device.handle(),
155 slot,
156 key_data.as_mut_ptr(),
157 &mut key_len,
158 )
159 };
160
161 check_error(result)?;
162 key_data.truncate(key_len);
163
164 Ok(key_data)
165 }
166
167 pub fn get_info(&self, slot: u32) -> Result<KeyInfo> {
177 let mut info = ffi::quac_key_info_t::default();
178 let result = unsafe {
179 ffi::quac_key_get_info(self.device.handle(), slot, &mut info)
180 };
181 check_error(result)?;
182 Ok(KeyInfo::from_ffi(&info))
183 }
184
185 pub fn delete(&self, slot: u32) -> Result<()> {
191 let result = unsafe { ffi::quac_key_delete(self.device.handle(), slot) };
192 check_error(result)
193 }
194
195 pub fn list(&self) -> Result<Vec<u32>> {
201 let capacity = self.get_slot_count()? as usize;
202 let mut slots = vec![0u32; capacity];
203 let mut count = capacity;
204
205 let result = unsafe {
206 ffi::quac_key_list(
207 self.device.handle(),
208 slots.as_mut_ptr(),
209 &mut count,
210 )
211 };
212
213 check_error(result)?;
214 slots.truncate(count);
215
216 Ok(slots)
217 }
218
219 pub fn get_slot_count(&self) -> Result<u32> {
221 let result = unsafe { ffi::quac_key_get_slot_count(self.device.handle()) };
222 if result < 0 {
223 check_error(result)?;
224 }
225 Ok(result as u32)
226 }
227
228 pub fn get_free_slot(&self) -> Result<u32> {
234 let result = unsafe { ffi::quac_key_get_free_slot(self.device.handle()) };
235 if result < 0 {
236 return Err(QuacError::from_code(ErrorCode::KeyNotFound));
237 }
238 Ok(result as u32)
239 }
240
241 pub fn clear_all(&self) -> Result<()> {
245 let result = unsafe { ffi::quac_key_clear_all(self.device.handle()) };
246 check_error(result)
247 }
248
249 pub fn is_slot_occupied(&self, slot: u32) -> Result<bool> {
251 match self.get_info(slot) {
252 Ok(_) => Ok(true),
253 Err(QuacError::Native { code: ErrorCode::KeyNotFound, .. }) => Ok(false),
254 Err(e) => Err(e),
255 }
256 }
257
258 pub fn store_keypair(
270 &self,
271 slot: u32,
272 algorithm: i32,
273 label: &str,
274 public_key: &[u8],
275 secret_key: &[u8],
276 ) -> Result<()> {
277 self.store(
278 slot,
279 KeyType::Public,
280 algorithm,
281 KeyUsage::VERIFY,
282 &format!("{}-pub", label),
283 public_key,
284 )?;
285
286 self.store(
287 slot + 1,
288 KeyType::Private,
289 algorithm,
290 KeyUsage::SIGN,
291 &format!("{}-priv", label),
292 secret_key,
293 )?;
294
295 Ok(())
296 }
297}
298
299impl std::fmt::Debug for Keys {
300 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
301 f.debug_struct("Keys").finish()
302 }
303}
304
305#[cfg(test)]
306mod tests {
307 use super::*;
308
309 #[test]
310 fn test_key_usage_flags() {
311 let usage = KeyUsage::ENCRYPT | KeyUsage::DECRYPT;
312 assert!(usage.contains(KeyUsage::ENCRYPT));
313 assert!(usage.contains(KeyUsage::DECRYPT));
314 assert!(!usage.contains(KeyUsage::SIGN));
315 }
316}