skf_rs/engine/
device.rs

1use crate::engine::app::SkfAppImpl;
2use crate::engine::crypto;
3use crate::engine::crypto::ManagedKeyImpl;
4use crate::engine::symbol::ModDev;
5use crate::error::SkfErr;
6use crate::helper::{mem, param};
7use crate::{
8    AppAttr, AppManager, DeviceAuth, DeviceCrypto, DeviceCtl, DeviceInformation, ECCEncryptedData,
9    ECCPrivateKeyBlob, ECCPublicKeyBlob, ECCSignatureBlob, ManagedKey, SkfApp, SkfBlockCipher,
10    SkfDevice, Version,
11};
12use crate::{Error, Result};
13use skf_api::native::error::SAR_OK;
14use skf_api::native::types::{
15    DeviceInfo, ECCCipherBlob, BYTE, CHAR, DEV_LOCK_FOREVER, DWORD, HANDLE, LPSTR, ULONG,
16};
17use std::fmt::Debug;
18use std::sync::Arc;
19use std::time::Duration;
20use tracing::{instrument, trace};
21
22pub(crate) struct SkfDeviceImpl {
23    lib: Arc<libloading::Library>,
24    symbols: ModDev,
25    handle: HANDLE,
26    name: String,
27}
28
29impl SkfDeviceImpl {
30    /// Initialize
31    ///
32    /// [handle] - Native handle
33    ///
34    /// [lib] - The library handle
35    pub fn new(handle: HANDLE, name: &str, lib: &Arc<libloading::Library>) -> Result<Self> {
36        let lc = Arc::clone(lib);
37        let symbols = ModDev::load_symbols(lib)?;
38        Ok(Self {
39            lib: lc,
40            symbols,
41            handle,
42            name: name.to_string(),
43        })
44    }
45
46    #[instrument]
47    fn disconnect(&mut self) -> Result<()> {
48        if let Some(ref func) = self.symbols.dev_dis_connect {
49            let ret = unsafe { func(self.handle) };
50            trace!("[SKF_DisConnectDev]: ret = {}", ret);
51            if ret != SAR_OK {
52                return Err(Error::Skf(SkfErr::of_code(ret)));
53            }
54            self.handle = std::ptr::null();
55        }
56        Ok(())
57    }
58}
59
60impl Debug for SkfDeviceImpl {
61    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
62        write!(f, "SkfDeviceImpl({})", &self.name)
63    }
64}
65
66impl DeviceAuth for SkfDeviceImpl {
67    #[instrument(skip(data))]
68    fn device_auth(&self, data: &[u8]) -> Result<()> {
69        let func = self.symbols.dev_auth.as_ref().expect("Symbol not load");
70        let ret = unsafe {
71            func(
72                self.handle,
73                data.as_ptr() as *const BYTE,
74                data.len() as ULONG,
75            )
76        };
77        trace!("[SKF_DevAuth]: ret = {}", ret);
78        if ret != SAR_OK {
79            return Err(Error::Skf(SkfErr::of_code(ret)));
80        }
81        Ok(())
82    }
83
84    #[instrument(skip(key))]
85    fn change_device_auth_key(&self, key: &[u8]) -> Result<()> {
86        let func = self
87            .symbols
88            .dev_change_auth_key
89            .as_ref()
90            .expect("Symbol not load");
91        let ret = unsafe { func(self.handle, key.as_ptr() as *const BYTE, key.len() as ULONG) };
92        trace!("[SKF_ChangeDevAuthKey]: ret = {}", ret);
93        if ret != SAR_OK {
94            return Err(Error::Skf(SkfErr::of_code(ret)));
95        }
96        Ok(())
97    }
98}
99
100impl DeviceCtl for SkfDeviceImpl {
101    #[instrument]
102    fn set_label(&self, label: &str) -> Result<()> {
103        let func = self
104            .symbols
105            .dev_set_label
106            .as_ref()
107            .expect("Symbol not load");
108        let label = param::as_cstring("label", label)?;
109        let ret = unsafe { func(self.handle, label.as_ptr() as *const CHAR) };
110        trace!("[SKF_SetLabel]: ret = {}", ret);
111        if ret != SAR_OK {
112            return Err(Error::Skf(SkfErr::of_code(ret)));
113        }
114        Ok(())
115    }
116
117    #[instrument]
118    fn info(&self) -> Result<DeviceInformation> {
119        let func = self.symbols.dev_get_info.as_ref().expect("Symbol not load");
120        let mut data = DeviceInfo::default();
121        let ret = unsafe { func(self.handle, &mut data) };
122        trace!("[SKF_GetDevInfo]: ret = {}", ret);
123        if ret != SAR_OK {
124            return Err(Error::Skf(SkfErr::of_code(ret)));
125        }
126        Ok(DeviceInformation::from(&data))
127    }
128
129    #[instrument]
130    fn lock(&self, timeout: Option<Duration>) -> Result<()> {
131        let func = self.symbols.dev_lock.as_ref().expect("Symbol not load");
132        let timeout = timeout
133            .map(|ref v| v.as_millis() as ULONG)
134            .unwrap_or(DEV_LOCK_FOREVER);
135        let ret = unsafe { func(self.handle, timeout) };
136        trace!("[SKF_LockDev]: ret = {}", ret);
137        if ret != SAR_OK {
138            return Err(Error::Skf(SkfErr::of_code(ret)));
139        }
140        Ok(())
141    }
142
143    #[instrument]
144    fn unlock(&self) -> Result<()> {
145        let func = self.symbols.dev_unlock.as_ref().expect("Symbol not load");
146        let ret = unsafe { func(self.handle) };
147        trace!("[SKF_UnlockDev]: ret = {}", ret);
148        if ret != SAR_OK {
149            return Err(Error::Skf(SkfErr::of_code(ret)));
150        }
151        Ok(())
152    }
153    #[instrument]
154    fn transmit(&self, command: &[u8], recv_capacity: usize) -> Result<Vec<u8>> {
155        let func = self.symbols.dev_transmit.as_ref().expect("Symbol not load");
156        let mut len: ULONG = recv_capacity as ULONG;
157        let mut buffer = Vec::<u8>::with_capacity(recv_capacity);
158        let ret = unsafe {
159            func(
160                self.handle,
161                command.as_ptr() as *const BYTE,
162                command.len() as ULONG,
163                buffer.as_mut_ptr() as *mut BYTE,
164                &mut len,
165            )
166        };
167        trace!("[SKF_Transmit]: ret = {}", ret);
168        if ret != SAR_OK {
169            return Err(Error::Skf(SkfErr::of_code(ret)));
170        }
171        trace!("[SKF_Transmit]: output len = {}", len);
172        unsafe { buffer.set_len(len as usize) };
173        Ok(buffer)
174    }
175}
176
177impl DeviceCrypto for SkfDeviceImpl {
178    #[instrument]
179    fn gen_random(&self, len: usize) -> Result<Vec<u8>> {
180        let func = self.symbols.gen_random.as_ref().expect("Symbol not load");
181        let mut buffer = Vec::<u8>::with_capacity(len);
182        let ret = unsafe { func(self.handle, buffer.as_mut_ptr() as *mut BYTE, len as ULONG) };
183        trace!("[SKF_GenRandom]: ret = {}", ret);
184        if ret != SAR_OK {
185            return Err(Error::Skf(SkfErr::of_code(ret)));
186        }
187        unsafe { buffer.set_len(len) };
188        Ok(buffer)
189    }
190
191    #[instrument(skip(key))]
192    fn set_symmetric_key(&self, alg_id: u32, key: &[u8]) -> Result<Box<dyn ManagedKey>> {
193        let func = self
194            .symbols
195            .sym_key_import
196            .as_ref()
197            .expect("Symbol not load");
198        let mut handle: HANDLE = std::ptr::null_mut();
199        let ret = unsafe {
200            func(
201                self.handle,
202                key.as_ptr() as *const BYTE,
203                alg_id,
204                &mut handle,
205            )
206        };
207        trace!("[SKF_SetSymmKey]: ret = {}", ret);
208        if ret != SAR_OK {
209            return Err(Error::Skf(SkfErr::of_code(ret)));
210        }
211        let managed_key = ManagedKeyImpl::try_new(handle, &self.lib)?;
212        Ok(Box::new(managed_key))
213    }
214
215    #[instrument(skip(key, data))]
216    fn ext_ecc_encrypt(&self, key: &ECCPublicKeyBlob, data: &[u8]) -> Result<ECCEncryptedData> {
217        let func = self
218            .symbols
219            .ecc_ext_encrypt
220            .as_ref()
221            .expect("Symbol not load");
222        let buff_size = ECCCipherBlob::size_of(data.len());
223        let mut buff: Vec<u8> = vec![0; buff_size];
224
225        let ret = unsafe {
226            func(
227                self.handle,
228                key as *const ECCPublicKeyBlob,
229                data.as_ptr() as *const BYTE,
230                data.len() as ULONG,
231                buff.as_mut_ptr() as *mut ECCCipherBlob,
232            )
233        };
234        trace!("[SKF_ExtECCEncrypt]: ret = {}", ret);
235        if ret != SAR_OK {
236            return Err(Error::Skf(SkfErr::of_code(ret)));
237        }
238        let blob = unsafe {
239            let cb = &*(buff.as_ptr() as *const ECCCipherBlob);
240            let mut cipher: Vec<u8> = vec![];
241            if cb.cipher_len > 0 {
242                let len = cb.cipher_len as usize;
243                cipher = vec![0; len];
244                std::ptr::copy(cb.cipher.as_ptr(), cipher.as_mut_ptr(), len);
245            }
246            ECCEncryptedData {
247                ec_x: cb.x_coordinate,
248                ec_y: cb.y_coordinate,
249                hash: cb.hash,
250                cipher,
251            }
252        };
253        Ok(blob)
254    }
255
256    #[instrument(skip(key, cipher))]
257    fn ext_ecc_decrypt(
258        &self,
259        key: &ECCPrivateKeyBlob,
260        cipher: &ECCEncryptedData,
261    ) -> Result<Vec<u8>> {
262        let func = self
263            .symbols
264            .ecc_ext_decrypt
265            .as_ref()
266            .expect("Symbol not load");
267        let cipher_mem = cipher.blob_bytes();
268        let mut buff: Vec<u8> = Vec::with_capacity(cipher.cipher.len());
269        let mut buff_len: ULONG = buff.capacity() as ULONG;
270
271        let ret = unsafe {
272            func(
273                self.handle,
274                key as *const ECCPrivateKeyBlob,
275                cipher_mem.as_ptr() as *const ECCCipherBlob,
276                buff.as_mut_ptr() as *mut BYTE,
277                &mut buff_len,
278            )
279        };
280        trace!("[SKF_ExtECCDecrypt]: ret = {}", ret);
281        if ret != SAR_OK {
282            return Err(Error::Skf(SkfErr::of_code(ret)));
283        }
284
285        trace!("[SKF_ExtECCDecrypt]: len = {}", buff_len);
286        unsafe { buff.set_len(buff_len as usize) };
287
288        Ok(buff)
289    }
290
291    #[instrument(skip(key, data))]
292    fn ext_ecc_sign(&self, key: &ECCPrivateKeyBlob, data: &[u8]) -> Result<ECCSignatureBlob> {
293        let func = self.symbols.ecc_ext_sign.as_ref().expect("Symbol not load");
294
295        let mut sign = ECCSignatureBlob::default();
296        let ret = unsafe {
297            func(
298                self.handle,
299                key as *const ECCPrivateKeyBlob,
300                data.as_ptr() as *const BYTE,
301                data.len() as ULONG,
302                &mut sign,
303            )
304        };
305        trace!("[SKF_ExtECCSign]: ret = {}", ret);
306        if ret != SAR_OK {
307            return Err(Error::Skf(SkfErr::of_code(ret)));
308        }
309
310        Ok(sign)
311    }
312
313    #[instrument(skip(key, data, signature))]
314    fn ext_ecc_verify(
315        &self,
316        key: &ECCPublicKeyBlob,
317        data: &[u8],
318        signature: &ECCSignatureBlob,
319    ) -> Result<()> {
320        let func = self
321            .symbols
322            .ecc_ext_verify
323            .as_ref()
324            .expect("Symbol not load");
325
326        let ret = unsafe {
327            func(
328                self.handle,
329                key as *const ECCPublicKeyBlob,
330                data.as_ptr() as *const BYTE,
331                data.len() as ULONG,
332                signature as *const ECCSignatureBlob,
333            )
334        };
335        trace!("[SKF_ExtECCVerify]: ret = {}", ret);
336        if ret != SAR_OK {
337            return Err(Error::Skf(SkfErr::of_code(ret)));
338        }
339        Ok(())
340    }
341
342    #[instrument(skip(key, hash, signature))]
343    fn ecc_verify(
344        &self,
345        key: &ECCPublicKeyBlob,
346        hash: &[u8],
347        signature: &ECCSignatureBlob,
348    ) -> Result<()> {
349        let func = self.symbols.ecc_verify.as_ref().expect("Symbol not load");
350
351        let ret = unsafe {
352            func(
353                self.handle,
354                key as *const ECCPublicKeyBlob,
355                hash.as_ptr() as *const BYTE,
356                hash.len() as ULONG,
357                signature as *const ECCSignatureBlob,
358            )
359        };
360        trace!("[SKF_ECCVerify]: ret = {}", ret);
361        if ret != SAR_OK {
362            return Err(Error::Skf(SkfErr::of_code(ret)));
363        }
364        Ok(())
365    }
366
367    #[instrument(skip(agreement_key, responder_key, responder_tmp_key, responder_id))]
368    fn ecc_gen_session_key(
369        &self,
370        agreement_key: &dyn ManagedKey,
371        responder_key: &ECCPublicKeyBlob,
372        responder_tmp_key: &ECCPublicKeyBlob,
373        responder_id: &[u8],
374    ) -> Result<Box<dyn ManagedKey>> {
375        let func = self.symbols.ecc_gen_sk.as_ref().expect("Symbol not load");
376
377        let mut handle: HANDLE = std::ptr::null_mut();
378        let ret = unsafe {
379            func(
380                *agreement_key.as_ref(),
381                responder_key,
382                responder_tmp_key,
383                responder_id.as_ptr() as *const BYTE,
384                responder_id.len() as ULONG,
385                &mut handle,
386            )
387        };
388        trace!("[SKF_GenerateKeyWithECC]: ret = {}", ret);
389        if ret != SAR_OK {
390            return Err(Error::Skf(SkfErr::of_code(ret)));
391        }
392        let managed_key = ManagedKeyImpl::try_new(handle, &self.lib)?;
393        Ok(Box::new(managed_key))
394    }
395}
396impl AppManager for SkfDeviceImpl {
397    #[instrument]
398    fn enumerate_app_name(&self) -> Result<Vec<String>> {
399        let func = self.symbols.app_enum.as_ref().expect("Symbol not load");
400        let mut len: ULONG = 0;
401        let ret = unsafe { func(self.handle, std::ptr::null_mut(), &mut len) };
402        if ret != SAR_OK {
403            return Err(Error::Skf(SkfErr::of_code(ret)));
404        }
405        trace!("[SKF_EnumApplication]: desired len = {}", len);
406        if len == 0 {
407            return Ok(vec![]);
408        }
409        let mut buff = Vec::<CHAR>::with_capacity(len as usize);
410        let ret = unsafe { func(self.handle, buff.as_mut_ptr(), &mut len) };
411        trace!("[SKF_EnumApplication]: ret = {}", ret);
412        if ret != SAR_OK {
413            return Err(Error::Skf(SkfErr::of_code(ret)));
414        }
415        unsafe { buff.set_len(len as usize) };
416        trace!(
417            "[SKF_EnumApplication]: app list = {}",
418            String::from_utf8_lossy(&buff)
419        );
420        // The spec says string list end with two '\0',but vendor may not do it
421        let list = unsafe { mem::parse_cstr_list_lossy(buff.as_ptr(), buff.len()) };
422        Ok(list)
423    }
424
425    #[instrument(skip(attr))]
426    fn create_app(&self, name: &str, attr: &AppAttr) -> Result<Box<dyn SkfApp>> {
427        let func = self.symbols.app_create.as_ref().expect("Symbol not load");
428        let c_name = param::as_cstring("name", name)?;
429        let admin_pin = param::as_cstring("AppAttr.admin_pin", &attr.admin_pin)?;
430        let user_pin = param::as_cstring("AppAttr.user_pin", &attr.user_pin)?;
431        let mut handle: HANDLE = std::ptr::null_mut();
432        let ret = unsafe {
433            func(
434                self.handle,
435                c_name.as_ptr() as *const CHAR,
436                admin_pin.as_ptr() as *const CHAR,
437                attr.admin_pin_retry_count as DWORD,
438                user_pin.as_ptr() as *const CHAR,
439                attr.user_pin_retry_count as DWORD,
440                attr.create_file_rights as DWORD,
441                &mut handle,
442            )
443        };
444        trace!("[SKF_CreateApplication]: ret = {}", ret);
445        if ret != SAR_OK {
446            return Err(Error::Skf(SkfErr::of_code(ret)));
447        }
448        let app = SkfAppImpl::new(handle, name, &self.lib)?;
449        Ok(Box::new(app))
450    }
451
452    #[instrument]
453    fn open_app(&self, name: &str) -> Result<Box<dyn SkfApp>> {
454        let func = self.symbols.app_open.as_ref().expect("Symbol not load");
455        let c_name = param::as_cstring("name", name)?;
456        let mut handle: HANDLE = std::ptr::null_mut();
457        let ret = unsafe { func(self.handle, c_name.as_ptr() as LPSTR, &mut handle) };
458        trace!("[SKF_OpenApplication]: ret = {}", ret);
459        if ret != SAR_OK {
460            return Err(Error::Skf(SkfErr::of_code(ret)));
461        }
462        let app = SkfAppImpl::new(handle, name, &self.lib)?;
463        Ok(Box::new(app))
464    }
465
466    #[instrument]
467    fn delete_app(&self, name: &str) -> Result<()> {
468        let func = self.symbols.app_delete.as_ref().expect("Symbol not load");
469        let name = param::as_cstring("name", name)?;
470        let ret = unsafe { func(self.handle, name.as_ptr() as LPSTR) };
471        trace!("[SKF_DeleteApplication]: ret = {}", ret);
472        if ret != SAR_OK {
473            return Err(Error::Skf(SkfErr::of_code(ret)));
474        }
475        Ok(())
476    }
477}
478
479impl SkfDevice for SkfDeviceImpl {
480    fn block_cipher(&self) -> Result<Box<dyn SkfBlockCipher + Send + Sync>> {
481        let crypto = crypto::SkfBlockCipherImpl::new(&self.lib)?;
482        Ok(Box::new(crypto))
483    }
484
485    fn name(&self) -> &str {
486        &self.name
487    }
488}
489impl Drop for SkfDeviceImpl {
490    fn drop(&mut self) {
491        let _ = self.disconnect();
492    }
493}
494
495impl From<&DeviceInfo> for DeviceInformation {
496    fn from(value: &DeviceInfo) -> Self {
497        let version = Version {
498            major: value.version.major,
499            minor: value.version.minor,
500        };
501        let manufacturer: String = unsafe {
502            mem::parse_cstr_lossy(value.manufacturer.as_ptr(), value.manufacturer.len())
503                .unwrap_or("".to_string())
504        };
505        let issuer: String = unsafe {
506            mem::parse_cstr_lossy(value.issuer.as_ptr(), value.issuer.len())
507                .unwrap_or("".to_string())
508        };
509        let label: String = unsafe {
510            mem::parse_cstr_lossy(value.label.as_ptr(), value.label.len()).unwrap_or("".to_string())
511        };
512        let serial_number = unsafe {
513            mem::parse_cstr_lossy(value.serial_number.as_ptr(), value.serial_number.len())
514                .unwrap_or("".to_string())
515        };
516        let hw_version = Version {
517            major: value.hw_version.major,
518            minor: value.hw_version.minor,
519        };
520        let firmware_version = Version {
521            major: value.firmware_version.major,
522            minor: value.firmware_version.minor,
523        };
524        let alg_sym_cap = value.alg_sym_cap;
525        let alg_asym_cap = value.alg_asym_cap;
526        let alg_hash_cap = value.alg_hash_cap;
527        let dev_auth_alg_id = value.dev_auth_alg_id;
528        let total_space = value.total_space;
529        let free_space = value.free_space;
530        let max_ecc_buffer_size = value.max_ecc_buffer_size;
531        let max_buffer_size = value.max_buffer_size;
532        let reserved = value.reserved;
533        Self {
534            version,
535            manufacturer,
536            issuer,
537            label,
538            serial_number,
539            hw_version,
540            firmware_version,
541            alg_sym_cap,
542            alg_asym_cap,
543            alg_hash_cap,
544            dev_auth_alg_id,
545            total_space,
546            free_space,
547            max_ecc_buffer_size,
548            max_buffer_size,
549            reserved,
550        }
551    }
552}