skf-rs 0.8.1

Rust wrapper for GM/T 0016-2012(Smart token cryptography application interface specification).
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
// FIXME: fix allow(dead_code) in the future
#![allow(dead_code)]
mod engine;
mod error;
pub mod helper;
pub mod spec;

use skf_api::native::types::{ECCPrivateKeyBlob, ECCPublicKeyBlob, ECCSignatureBlob, HANDLE};
use std::fmt::Debug;
use std::time::Duration;

pub type Error = error::Error;
pub type Result<T> = std::result::Result<T, Error>;

pub type Engine = engine::Engine;
pub type LibLoader = engine::LibLoader;

#[derive(Debug)]
pub struct PluginEvent {
    pub device_name: String,
    pub event: u8,
}

/// 256-bit hash value
pub type HASH256 = [u8; 32];

/// ECC encrypt output,Wrapper of [DST](https://doc.rust-lang.org/reference/dynamically-sized-types.html) `ECCCipherBlob`
#[derive(Debug)]
pub struct ECCEncryptedData {
    pub ec_x: [u8; 64],
    pub ec_y: [u8; 64],
    pub hash: HASH256,
    pub cipher: Vec<u8>,
}
impl Default for ECCEncryptedData {
    fn default() -> Self {
        Self {
            ec_x: [0; 64],
            ec_y: [0; 64],
            hash: [0; 32],
            cipher: vec![],
        }
    }
}

/// ECC Enveloped key,Wrapper of [DST](https://doc.rust-lang.org/reference/dynamically-sized-types.html) `EnvelopedKeyBlob`
#[derive(Debug)]
pub struct EnvelopedKeyData {
    pub version: u32,
    pub sym_alg_id: u32,
    pub bits: u32,
    pub encrypted_pri_key: [u8; 64],
    pub pub_key: ECCPublicKeyBlob,
    pub ecc_cipher: ECCEncryptedData,
}

impl Default for EnvelopedKeyData {
    fn default() -> Self {
        Self {
            version: 0,
            sym_alg_id: 0,
            bits: 0,
            encrypted_pri_key: [0u8; 64],
            pub_key: ECCPublicKeyBlob::default(),
            ecc_cipher: ECCEncryptedData::default(),
        }
    }
}

#[derive(Debug, Default)]
pub struct Version {
    pub major: u8,
    pub minor: u8,
}

#[derive(Debug)]
pub struct DeviceInformation {
    pub version: Version,
    pub manufacturer: String,
    pub issuer: String,
    pub label: String,
    pub serial_number: String,
    pub hw_version: Version,
    pub firmware_version: Version,
    pub alg_sym_cap: u32,
    pub alg_asym_cap: u32,
    pub alg_hash_cap: u32,
    pub dev_auth_alg_id: u32,
    pub total_space: u32,
    pub free_space: u32,
    pub max_ecc_buffer_size: u32,
    pub max_buffer_size: u32,
    pub reserved: [u8; 64],
}

pub const DEV_STATE_ABSENT: u32 = 0;
pub const DEV_STATE_PRESENT: u32 = 1;
pub const DEV_STATE_UNKNOWN: u32 = 2;

pub trait DeviceManager {
    /// Enumerate all devices
    ///
    /// [presented_only] - Enumerate only presented devices,false means list all supported devices by underlying driver
    fn enumerate_device_name(&self, presented_only: bool) -> Result<Vec<String>>;

    /// Get device state
    ///
    /// [device_name] - The device name
    ///
    /// # state value
    /// - [DEV_STATE_ABSENT]
    /// - [DEV_STATE_PRESENT]
    /// - [DEV_STATE_UNKNOWN]
    fn device_state(&self, device_name: &str) -> Result<u32>;

    /// Wait for plug event,This function will block current thread
    ///
    /// If error happens, Error will be returned,otherwise `Some(PluginEvent)` will be returned
    ///
    /// `Ok(None)` means no event
    fn wait_plug_event(&self) -> Result<Option<PluginEvent>>;

    /// Cancel wait for plug event
    fn cancel_wait_plug_event(&self) -> Result<()>;

    /// Connect device with device name
    ///
    /// [device_name] - The device name
    fn connect(&self, device_name: &str) -> Result<Box<dyn SkfDevice>>;

    /// Connect to device by enumerate all devices and select one,if no device matches the selector, None will be returned
    ///
    /// [selector] - The device selector,if device list is not empty, the selector will be invoked to select one
    ///
    /// ## error
    /// - `Error::NotFound` returned means there is no device to connect,or the selector returns None
    fn connect_selected(
        &self,
        selector: fn(Vec<&str>) -> Option<&str>,
    ) -> Result<Box<dyn SkfDevice>>;
}

pub trait DeviceCtl {
    /// Set label of device
    ///
    /// [label] - The label.
    ///
    /// # specification note
    /// - `label`: should less than 32 bytes
    fn set_label(&self, label: &str) -> Result<()>;

    /// Get device info,e.g. vendor id,product id
    fn info(&self) -> Result<DeviceInformation>;

    /// Lock device for exclusive access
    ///
    /// [timeout] - The lock timeout,`None` means wait forever
    fn lock(&self, timeout: Option<Duration>) -> Result<()>;

    /// Unlock device
    fn unlock(&self) -> Result<()>;

    /// Transmit data to execute,and get response
    ///
    /// [command] - The command to execute
    ///
    /// [recv_capacity] - The capacity of receive buffer
    /// # specification note
    ///
    /// This function is for testing purpose
    fn transmit(&self, command: &[u8], recv_capacity: usize) -> Result<Vec<u8>>;
}

/// Cryptographic services provided by SKF device objects
pub trait DeviceCrypto {
    /// Generate random data
    ///
    /// [len] - The random data length to generate,in bytes
    fn gen_random(&self, len: usize) -> Result<Vec<u8>>;

    /// Import plain symmetric key(AKA session key)
    ///
    /// [alg_id] - The algorithm id,see [CryptoAlgorithm]
    ///
    /// [key] - The symmetric key
    /// ## Owner object lifetime requirement
    /// If owner object([SkfDevice]) is dropped, the key will be invalid
    fn set_symmetric_key(&self, alg_id: u32, key: &[u8]) -> Result<Box<dyn ManagedKey>>;

    /// Encrypt data,using external ecc public key
    ///
    /// [key] - The public key
    ///
    /// [data] - The data to encrypt
    fn ext_ecc_encrypt(&self, key: &ECCPublicKeyBlob, data: &[u8]) -> Result<ECCEncryptedData>;

    /// Decrypt data,using external ecc private key
    ///
    /// [key] - The private key
    ///
    /// [cipher] - The encrypted data,returned by `ext_ecc_encrypt`
    fn ext_ecc_decrypt(
        &self,
        key: &ECCPrivateKeyBlob,
        cipher: &ECCEncryptedData,
    ) -> Result<Vec<u8>>;

    /// Sign data,using external ecc private key
    ///
    /// [key] - The private key
    ///
    /// [data] - The data to sign
    fn ext_ecc_sign(&self, key: &ECCPrivateKeyBlob, data: &[u8]) -> Result<ECCSignatureBlob>;

    /// Verify signature,using external ecc public key
    ///
    /// [key] - The public key
    ///
    /// [data] - The data to verify
    ///
    /// [signature] - The signature,returned by `ext_ecc_sign`
    fn ext_ecc_verify(
        &self,
        key: &ECCPublicKeyBlob,
        data: &[u8],
        signature: &ECCSignatureBlob,
    ) -> Result<()>;

    /// Verify signature
    ///
    /// [key] - The public key
    ///
    /// [hash] - The hash value of data.
    /// When using the SM2 algorithm, the data is the result of pre-processing the data to be
    /// signed through the SM2 signature pre-processing. The pre-processing procedure follows `GM/T 0009`.
    ///
    /// [signature] - The signature,returned by `ext_ecc_sign`
    fn ecc_verify(
        &self,
        key: &ECCPublicKeyBlob,
        hash: &[u8],
        signature: &ECCSignatureBlob,
    ) -> Result<()>;

    /// Key exchange step: generate session key for initiator
    ///
    /// see [SKF_GenerateKeyWithECC] for more details
    ///
    /// [agreement_key] - The agreement key,returned by `SkfContainer::sk_gen_agreement_data`
    ///
    /// [responder_key] - The responder's public key
    ///
    /// [responder_tmp_key] - The responder's temporary public key,returned by `SkfContainer::sk_gen_agreement_data_and_key`
    ///
    /// [responder_id] - Responder's ID,max 32 bytes
    fn ecc_gen_session_key(
        &self,
        agreement_key: &dyn ManagedKey,
        responder_key: &ECCPublicKeyBlob,
        responder_tmp_key: &ECCPublicKeyBlob,
        responder_id: &[u8],
    ) -> Result<Box<dyn ManagedKey>>;
}

#[derive(Debug, Default)]
pub struct AppAttr {
    pub admin_pin: String,
    pub admin_pin_retry_count: u32,
    pub user_pin: String,
    pub user_pin_retry_count: u32,
    pub create_file_rights: u32,
}

/// Application management
pub trait AppManager {
    ///  Enumerate all apps in the device,return app names
    fn enumerate_app_name(&self) -> Result<Vec<String>>;

    /// Create app in the device
    ///
    /// [name] - The app name
    ///
    /// [attr] - The attribute of app
    /// ## Owner object lifetime requirement
    /// If owner object([SkfDevice]) is dropped, the `SkfApp` object will be invalid
    fn create_app(&self, name: &str, attr: &AppAttr) -> Result<Box<dyn SkfApp>>;

    /// Open app
    ///
    /// [name] - The app name to open
    /// ## Owner object lifetime requirement
    /// If owner object([SkfDevice]) is dropped, the `SkfApp` object will be invalid
    fn open_app(&self, name: &str) -> Result<Box<dyn SkfApp>>;
    /// Delete app
    ///
    /// [name] - The app name to delete
    fn delete_app(&self, name: &str) -> Result<()>;
}

/// Device authentication
pub trait DeviceAuth {
    /// Device authentication
    ///
    /// [data] - The authentication data
    ///
    /// ## authentication process
    /// 1. Call the `SKF_GetRandom` function to get an 8-byte random number `RND` from the device,
    ///    and pads it to the block size of the cryptographic algorithm with `0x00` to form the data block `D0`
    /// 2. Encrypts `D0` to get the encrypted result `D1`, and calls `SKF_DevAuth`, sending `D1` to the device
    /// 3. Upon receiving `D1`, the device verifies whether `D1` is correct. If correct, the device authentication passes, otherwise the device authentication fails.
    fn device_auth(&self, data: &[u8]) -> Result<()>;

    /// Change device authentication key
    ///
    /// [key] - The new authentication key
    fn change_device_auth_key(&self, key: &[u8]) -> Result<()>;
}

/// Represents a device instance,call `DeviceManager::connect()` or `DeviceManager::connect_selected()` to get one
/// ## Disconnect
/// Device instance is disconnected when `Drop`
pub trait SkfDevice: DeviceCtl + DeviceAuth + AppManager + DeviceCrypto {
    /// Block cipher service
    fn block_cipher(&self) -> Result<Box<dyn SkfBlockCipher + Send + Sync>>;

    /// The name when it is opened
    fn name(&self) -> &str;
}

/// PIN type: Admin
pub const PIN_TYPE_ADMIN: u8 = 0;

/// PIN type: User
pub const PIN_TYPE_USER: u8 = 1;

/// PIN information
#[derive(Debug, Default)]
pub struct PinInfo {
    pub max_retry_count: u32,
    pub remain_retry_count: u32,
    pub default_pin: bool,
}

pub trait AppSecurity {
    /// Lock device for exclusive access
    ///
    /// [pin_type] - The pin type, can be `PIN_TYPE_ADMIN` or `PIN_TYPE_USER`
    ///
    /// [old_pin] - The old pin
    ///
    /// [new_pin] - The new pin
    ///
    /// ## specification note
    /// - PIN verification failed: The value of remaining retry count will be returned, `0` means the PIN has been locked
    /// - PIN verification success: `None` will be returned
    ///
    /// ## Error
    /// - `Error::PinVerifyFailed` returned when PIN verification failed
    ///
    fn change_pin(&self, pin_type: u8, old_pin: &str, new_pin: &str) -> Result<()>;

    /// Verify PIN to get access rights
    ///
    /// [pin_type] - The pin type,can be `PIN_TYPE_ADMIN` or `PIN_TYPE_USER`
    ///
    /// [pin] - The pin value
    /// ## specification note
    /// - PIN verification failed: The value of remaining retry count will be returned, `0` means the PIN has been locked
    /// - PIN verification success: `None` will be returned
    ///
    /// ## Error
    /// - `Error::PinVerifyFailed` returned when PIN verification failed
    fn verify_pin(&self, pin_type: u8, pin: &str) -> Result<()>;

    /// Get PIN info
    ///
    /// [pin_type] - The pin type,can be `PIN_TYPE_ADMIN` or `PIN_TYPE_USER`
    fn pin_info(&self, pin_type: u8) -> Result<PinInfo>;

    /// Unlock user PIN
    ///
    /// [admin_pin] - The admin PIN
    ///
    /// [new_pin] - The new PIN
    ///
    /// [recv_capacity] - The capacity of receive buffer
    /// # specification note
    /// - PIN verification failed: The value of remaining retry count will be returned, `0` means the PIN has been locked
    /// - PIN verification success: `None` will be returned
    ///
    /// ## Error
    /// - `Error::PinVerifyFailed` returned when PIN verification failed
    fn unblock_pin(&self, admin_pin: &str, new_pin: &str) -> Result<()>;

    /// Clear secure state
    fn clear_secure_state(&self) -> Result<()>;
}

/// File permission: none
pub const FILE_PERM_NONE: u32 = 0x00000000;
/// File permission: permit to admin account
pub const FILE_PERM_ADMIN: u32 = 0x00000001;
/// File permission: permit to user account
pub const FILE_PERM_USER: u32 = 0x00000010;
/// File permission: permit to everyone
pub const FILE_PERM_EVERYONE: u32 = 0x000000FF;
#[derive(Debug, Default)]
pub struct FileAttr {
    pub file_name: String,
    pub file_size: usize,
    pub read_rights: u32,
    pub write_rights: u32,
}

#[derive(Debug)]
pub struct FileAttrBuilder {
    file_name: String,
    file_size: usize,
    read_rights: u32,
    write_rights: u32,
}
pub trait FileManager {
    ///  Enumerate all file in the app,return file names
    fn enumerate_file_name(&self) -> Result<Vec<String>>;

    /// Create file in the app
    ///
    ///[attr] - The file attribute
    ///
    /// ## file name
    ///
    /// The file name,should less than 32 bytes, It will be truncated if it is too long
    fn create_file(&self, attr: &FileAttr) -> Result<()>;

    /// Delete file from app
    ///
    /// [name] - The file name to delete
    fn delete_file(&self, name: &str) -> Result<()>;
    /// Read data from file
    ///
    /// [name] - The file name
    ///
    /// [offset] - File offset to read
    ///
    /// [size] - Read size,in bytes
    ///
    /// ## specification note
    /// actual read size may be less than [size]
    fn read_file(&self, name: &str, offset: u32, size: usize) -> Result<Vec<u8>>;
    /// Write date to file
    ///
    /// [name] - The file name
    ///
    /// [offset] - File offset to write
    ///
    /// [data] - The data to write
    fn write_file(&self, name: &str, offset: u32, data: &[u8]) -> Result<()>;
    /// Get file attribute info
    ///
    /// [name] - The file name
    fn get_file_info(&self, name: &str) -> Result<FileAttr>;
}

pub trait ContainerManager {
    ///  Enumerate all apps in the app,return container names
    fn enumerate_container_name(&self) -> Result<Vec<String>>;

    /// Create container in the app
    ///
    /// [name] - The container name
    fn create_container(&self, name: &str) -> Result<Box<dyn SkfContainer>>;

    /// Open container by  name
    ///
    /// [name] - The container name
    fn open_container(&self, name: &str) -> Result<Box<dyn SkfContainer>>;

    /// Delete container by name
    ///
    /// [name] - The container name
    fn delete_container(&self, name: &str) -> Result<()>;
}

/// Represents an Application instance
/// ## Close
/// Application instance is closed when `Drop`
pub trait SkfApp: AppSecurity + FileManager + ContainerManager {
    /// The name when it is opened
    fn name(&self) -> &str;
}

const CONTAINER_TYPE_UNKNOWN: u32 = 0;
const CONTAINER_TYPE_RSA: u32 = 0;
const CONTAINER_TYPE_ECC: u32 = 0;

/// Represents a Container instance
/// ## Close
/// Container instance is closed when `Drop`
/// ## Owner object lifetime requirement
/// If owner object([SkfApp]) is dropped, the `SkfContainer` object will be invalid
pub trait SkfContainer {
    /// The name when it is opened
    fn name(&self) -> &str;

    /// Get container type,the value of type can be:
    /// - [CONTAINER_TYPE_UNKNOWN]
    /// - [CONTAINER_TYPE_RSA]
    /// - [CONTAINER_TYPE_ECC]
    fn get_type(&self) -> Result<u32>;

    /// Import certificate to container
    ///
    /// [signer] - True means The imported certificate is used for sign
    ///
    /// [data] - The certificate data
    fn import_certificate(&self, signer: bool, data: &[u8]) -> Result<()>;

    /// Export certificate from container
    ///
    /// [signer] - True means The exported certificate is used for sign
    fn export_certificate(&self, signer: bool) -> Result<Vec<u8>>;

    /// Generate ECC key pair(signing part),the private key will be stored in the container.
    ///
    /// see [SKF_GenECCKeyPair] for more details
    ///
    /// [alg_id] - The algorithm id, supported values is `SGD_SM2_1`
    fn ecc_gen_key_pair(&self, alg_id: u32) -> Result<ECCPublicKeyBlob>;

    /// Import ECC key pair( encryption part) to container.
    ///
    /// see [SKF_ImportECCKeyPair] for more details
    ///
    /// [enveloped_key] - The enveloped key data
    ///
    /// ## permission state requirement
    /// user permission
    fn ecc_import_key_pair(&self, enveloped_key: &EnvelopedKeyData) -> Result<()>;

    /// Export ECC public key from container.
    ///
    /// see [SKF_ExportPublicKey] for more details
    ///
    /// [sign_part] - True means The exported public key is used for sign
    fn ecc_export_public_key(&self, sign_part: bool) -> Result<Vec<u8>>;

    /// Sign data use signing key in the container
    ///
    /// see [SKF_ECCSignData] for more details
    ///
    /// [hash] - The hash value of data.
    /// When using the SM2 algorithm, the data is the result of pre-processing the data to be
    /// signed through the SM2 signature pre-processing. The pre-processing procedure follows `GM/T 0009`.
    fn ecc_sign(&self, hash: &[u8]) -> Result<ECCSignatureBlob>;

    /// Key exchange step: generate ephemeral public key and  agreement key for initiator
    ///
    /// see [SKF_GenerateAgreementDataWithECC] for more details
    ///
    /// [alg_id] - The algorithm id used for session key generation
    ///
    /// [id] - Initiator's ID,max 32 bytes
    ///
    /// ## Return value
    /// return ephemeral public key and key agreement handle
    fn sk_gen_agreement_data(
        &self,
        alg_id: u32,
        id: &[u8],
    ) -> Result<(ECCPublicKeyBlob, Box<dyn ManagedKey>)>;

    /// Key exchange step: generate ephemeral public key and session key for responder
    ///
    /// see [SKF_GenerateAgreementDataAndKeyWithECC] for more details
    ///
    /// [alg_id] - The algorithm id used for session key generation
    ///
    /// [initiator_key] - Initiator's public key
    ///
    /// [initiator_tmp_key] - Initiator's ephemeral public key
    ///
    /// [initiator_id] - Initiator's ID,max 32 bytes
    ///
    /// [responder_id] - Responder's ID,max 32 bytes
    ///
    /// ## Return value
    /// return ephemeral public key and session key handle
    fn sk_gen_agreement_data_and_key(
        &self,
        alg_id: u32,
        initiator_key: &ECCPublicKeyBlob,
        initiator_tmp_key: &ECCPublicKeyBlob,
        initiator_id: &[u8],
        responder_id: &[u8],
    ) -> Result<(ECCPublicKeyBlob, Box<dyn ManagedKey>)>;

    /// Import session key
    ///
    /// see [SKF_ImportSessionKey] for more details
    ///
    /// [alg_id] - The algorithm id
    ///
    /// [key_data] - The session key data
    fn sk_import(&self, alg_id: u32, key_data: &[u8]) -> Result<Box<dyn ManagedKey>>;

    /// Generate session key and export it
    ///
    /// [alg_id] - The algorithm id used for session key generation
    ///
    /// [key] - The public key,used for encrypt session key
    fn sk_export(
        &self,
        alg_id: u32,
        key: &ECCPublicKeyBlob,
    ) -> Result<(Box<dyn ManagedKey>, ECCEncryptedData)>;
}

pub type Hash256 = [u8; 32];

/// Block cipher parameter,wrapper of `BlockCipherParam`
#[derive(Debug, Default)]
pub struct BlockCipherParameter {
    /// IV data,max 32 bytes,Empty means no IV
    pub iv: Vec<u8>,
    /// padding type,
    /// - 0: None
    /// - 1: PKCS7
    pub padding_type: u8,
    pub feed_bit_len: u32,
}

/// Represents a key object
/// ## Close
/// key object is closed when `Drop`
pub trait ManagedKey: AsRef<HANDLE> {}

/// Block cipher service
pub trait SkfBlockCipher {
    /// Initialize encryption
    ///
    /// [key] - The key object
    ///
    /// [param] - The encryption parameter
    fn encrypt_init(&self, key: &dyn ManagedKey, param: &BlockCipherParameter) -> Result<()>;

    /// Encrypt data
    ///
    /// [data] - The data to encrypt
    ///
    /// [buffer_size] - The buffer size to receive encrypted data,it depends on the encryption parameter passed by `encrypt_init` and crypto algorithm
    ///
    /// see `SKF_Encrypt` for more details
    fn encrypt(&self, key: &dyn ManagedKey, data: &[u8], buffer_size: usize) -> Result<Vec<u8>>;

    /// Encrypting multiple groups of data.
    ///
    /// [data] - The data to encrypt
    ///
    /// [buffer_size] - The buffer size to receive encrypted data,it depends on the encryption parameter passed by `encrypt_init` and crypto algorithm
    ///
    /// see `SKF_EncryptUpdate` for more details
    fn encrypt_update(
        &self,
        key: &dyn ManagedKey,
        data: &[u8],
        buffer_size: usize,
    ) -> Result<Vec<u8>>;

    /// Finish encrypting multiple groups of data, return the remaining encrypted result
    ///
    /// [buffer_size] - The buffer size to receive encrypted data,it depends on the encryption parameter passed by `encrypt_init` and crypto algorithm
    ///
    /// see `SKF_EncryptFinal` for more details
    fn encrypt_final(&self, key: &dyn ManagedKey, buffer_size: usize) -> Result<Vec<u8>>;

    /// Initialize decryption
    ///
    /// [key] - The key object
    ///
    /// [param] - The decryption parameter
    ///
    /// see `SKF_DecryptInit` for more details
    fn decrypt_init(&self, key: &dyn ManagedKey, param: &BlockCipherParameter) -> Result<()>;

    /// Decrypt data
    ///
    /// [data] - The data to decrypt
    ///
    /// [buffer_size] - The buffer size to receive decrypted data,it depends on the decryption parameter passed by `decrypt_init` and crypto algorithm
    ///
    /// see `SKF_Decrypt` for more details
    fn decrypt(&self, key: &dyn ManagedKey, data: &[u8], buffer_size: usize) -> Result<Vec<u8>>;

    /// Decrypting multiple groups of data.
    ///
    /// [data] - The data to decrypt
    ///
    /// [buffer_size] - The buffer size to receive decrypted data,it depends on the encryption parameter passed by `decrypt_init` and crypto algorithm
    ///
    /// see `SKF_EncryptUpdate` for more details
    fn decrypt_update(
        &self,
        key: &dyn ManagedKey,
        data: &[u8],
        buffer_size: usize,
    ) -> Result<Vec<u8>>;

    /// Finish decrypting multiple groups of data, return the remaining decrypted result
    ///
    /// [buffer_size] - The buffer size to receive decrypted data,it depends on the decryption parameter passed by `decrypt_init` and crypto algorithm
    ///
    /// see `SKF_EncryptFinal` for more details
    fn decrypt_final(&self, key: &dyn ManagedKey, buffer_size: usize) -> Result<Vec<u8>>;
}