Skip to main content

kryoptic_lib/
lib.rs

1// Copyright 2023 Simo Sorce
2// See LICENSE.txt file for terms
3
4//#![warn(missing_docs)]
5
6//! This is Kryoptic
7//!
8//! A cryptographic software token using the PKCS#11 standard API
9
10use std::cell::RefCell;
11use std::collections::HashMap;
12use std::sync::{LazyLock, RwLock, RwLockReadGuard, RwLockWriteGuard};
13
14mod attribute;
15mod config;
16mod defaults;
17mod encryption;
18mod error;
19mod kasn1;
20mod mechanism;
21mod misc;
22mod native;
23mod object;
24mod ossl;
25mod rng;
26mod session;
27mod slot;
28mod storage;
29mod token;
30
31/* Include algorithms based on selected features */
32include!("enabled.rs");
33
34#[cfg(feature = "fips")]
35mod fips;
36
37#[cfg(feature = "log")]
38mod log;
39
40pub mod fns;
41pub mod pkcs11;
42
43use config::Config;
44use error::Result;
45use pkcs11::*;
46use rng::RNG;
47use session::Session;
48use slot::Slot;
49use token::Token;
50
51use fns::digest::*;
52use fns::dualcrypto::*;
53use fns::encryption::*;
54use fns::general::*;
55use fns::keymgmt::*;
56use fns::objmgmt::*;
57use fns::sessmgmt::*;
58use fns::signing::*;
59use fns::stmgmt::*;
60use fns::*;
61
62thread_local!(
63    /// Thread-local instance of the Cryptographically Secure Pseudo-Random Number
64    /// Generator (CSPRNG). This is used to avoid contention and locking between
65    /// different threads.
66    static CSPRNG: RefCell<RNG> = RefCell::new(
67        RNG::new("HMAC DRBG SHA256").unwrap()
68    )
69);
70
71/// Fill a buffer with random data
72///
73/// Uses the instantaited CSPRNG to fill the buffer with random data
74fn get_random_data(data: &mut [u8]) -> Result<()> {
75    CSPRNG.with(|rng| rng.borrow_mut().generate_random(data))
76}
77
78/// Add seed data to the CSPRNG
79///
80/// This is not counted as entropy but just as additional data
81fn random_add_seed(data: &[u8]) -> Result<()> {
82    CSPRNG.with(|rng| rng.borrow_mut().add_seed(data))
83}
84
85/// Global state for the PKCS#11 library.
86/// Manages slots, sessions, and handle generation.
87pub(crate) struct State {
88    /// Hash map that stores actual slots, indexed by their Slot ID number.
89    slots: HashMap<CK_SLOT_ID, Slot>,
90    /// Map that holds mappings between session handles and slot ids.
91    /// Sessions are stored in slots, so this allows to quickly find the
92    /// correct slot when there is a need to get a session from a handle.
93    sessionmap: HashMap<CK_SESSION_HANDLE, CK_SLOT_ID>,
94    /// Holds the next available session handle number. Session handles are
95    /// unique and never repeating for the life time of the program.
96    next_handle: CK_ULONG,
97}
98
99impl State {
100    /// Initializes the global state. Clears existing slots and sessions.
101    pub(crate) fn initialize(&mut self) {
102        #[cfg(feature = "fips")]
103        fips::provider::init();
104
105        self.slots.clear();
106        self.sessionmap.clear();
107        self.next_handle = 1;
108    }
109
110    /// Finalizes the global state. Finalizes all slots and clears state.
111    /// Returns the first error encountered during slot finalization, if any.
112    pub(crate) fn finalize(&mut self) -> CK_RV {
113        if !self.is_initialized() {
114            return CKR_CRYPTOKI_NOT_INITIALIZED;
115        }
116        let mut ret = CKR_OK;
117        for (_key, slot) in self.slots.iter_mut() {
118            let err = match slot.finalize() {
119                Ok(()) => CKR_OK,
120                Err(e) => e.rv(),
121            };
122            /* record the first error only */
123            if ret == CKR_OK {
124                ret = err;
125            }
126        }
127        self.slots.clear();
128        self.sessionmap.clear();
129        self.next_handle = 0;
130        ret
131    }
132
133    /// Checks if the global state has been initialized.
134    pub(crate) fn is_initialized(&self) -> bool {
135        self.next_handle != 0
136    }
137
138    /// Gets a reference to a slot by its ID.
139    fn get_slot(&self, slot_id: CK_SLOT_ID) -> Result<&Slot> {
140        if !self.is_initialized() {
141            return Err(CKR_CRYPTOKI_NOT_INITIALIZED)?;
142        }
143        match self.slots.get(&slot_id) {
144            Some(ref s) => Ok(s),
145            None => Err(CKR_SLOT_ID_INVALID)?,
146        }
147    }
148
149    /// Gets a mutable reference to a slot by its ID.
150    fn get_slot_mut(&mut self, slot_id: CK_SLOT_ID) -> Result<&mut Slot> {
151        if !self.is_initialized() {
152            return Err(CKR_CRYPTOKI_NOT_INITIALIZED)?;
153        }
154        match self.slots.get_mut(&slot_id) {
155            Some(s) => Ok(s),
156            None => Err(CKR_SLOT_ID_INVALID)?,
157        }
158    }
159
160    /// Returns a sorted vector of all configured slot IDs.
161    pub(crate) fn get_slots_ids(&self) -> Vec<CK_SLOT_ID> {
162        let mut slotids = Vec::<CK_SLOT_ID>::with_capacity(self.slots.len());
163        for k in self.slots.keys() {
164            slotids.push(*k)
165        }
166        slotids.sort_unstable();
167        slotids
168    }
169
170    /// Adds a new slot to the global state.
171    pub(crate) fn add_slot(
172        &mut self,
173        slot_id: CK_SLOT_ID,
174        slot: Slot,
175    ) -> Result<()> {
176        if self.slots.contains_key(&slot_id) {
177            return Err(CKR_CRYPTOKI_ALREADY_INITIALIZED)?;
178        }
179        self.slots.insert(slot_id, slot);
180        Ok(())
181    }
182
183    /// Gets a read lock guard for a session by its handle.
184    pub(crate) fn get_session(
185        &self,
186        handle: CK_SESSION_HANDLE,
187    ) -> Result<RwLockReadGuard<'_, Session>> {
188        let slot_id = match self.sessionmap.get(&handle) {
189            Some(s) => *s,
190            None => return Err(CKR_SESSION_HANDLE_INVALID)?,
191        };
192        self.get_slot(slot_id)?.get_session(handle)
193    }
194
195    /// Gets a write lock guard for a session by its handle.
196    pub(crate) fn get_session_mut(
197        &self,
198        handle: CK_SESSION_HANDLE,
199    ) -> Result<RwLockWriteGuard<'_, Session>> {
200        let slot_id = match self.sessionmap.get(&handle) {
201            Some(s) => *s,
202            None => return Err(CKR_SESSION_HANDLE_INVALID)?,
203        };
204        self.get_slot(slot_id)?.get_session_mut(handle)
205    }
206
207    /// Creates a new session on a specified slot and returns its handle.
208    /// Associates the session handle with the slot ID.
209    fn new_session(
210        &mut self,
211        slot_id: CK_SLOT_ID,
212        user_type: CK_USER_TYPE,
213        flags: CK_FLAGS,
214    ) -> Result<CK_SESSION_HANDLE> {
215        let handle = self.next_handle;
216        self.get_slot_mut(slot_id)?
217            .add_session(handle, Session::new(slot_id, user_type, flags)?);
218        self.sessionmap.insert(handle, slot_id);
219        self.next_handle += 1;
220        Ok(handle)
221    }
222
223    /// Checks if a slot has any active sessions.
224    fn has_sessions(&self, slot_id: CK_SLOT_ID) -> Result<bool> {
225        Ok(self.get_slot(slot_id)?.has_sessions())
226    }
227
228    /// Checks if a slot has any active read-only sessions.
229    fn has_ro_sessions(&self, slot_id: CK_SLOT_ID) -> Result<bool> {
230        Ok(self.get_slot(slot_id)?.has_ro_sessions())
231    }
232
233    /// Changes the state for all sessions associated with a given slot ID
234    /// based on the provided user type.
235    pub fn change_session_states(
236        &self,
237        slot_id: CK_SLOT_ID,
238        user_type: CK_USER_TYPE,
239    ) -> Result<()> {
240        self.get_slot(slot_id)?.change_session_states(user_type)
241    }
242
243    /// Invalidates the session state for all sessions on a slot.
244    pub fn invalidate_session_states(&self, slot_id: CK_SLOT_ID) -> Result<()> {
245        self.get_slot(slot_id)?.invalidate_session_states();
246        Ok(())
247    }
248
249    /// Drops a session by its handle.
250    ///
251    /// Logs out the token if it's the last session.
252    fn drop_session(&mut self, handle: CK_SESSION_HANDLE) -> Result<()> {
253        let slot_id = match self.sessionmap.get(&handle) {
254            Some(s) => *s,
255            None => return Err(CKR_SESSION_HANDLE_INVALID)?,
256        };
257        self.get_slot_mut(slot_id)?.drop_session(handle);
258        self.sessionmap.remove(&handle);
259        /* The specs requires the last session to logout the token */
260        if !self.has_sessions(slot_id)? {
261            self.get_token_from_slot_mut(slot_id)?.logout();
262        }
263        Ok(())
264    }
265
266    /// Drops all sessions associated with a specific slot and returns their
267    /// handles.
268    fn drop_all_sessions_slot(
269        &mut self,
270        slot_id: CK_SLOT_ID,
271    ) -> Result<Vec<CK_SESSION_HANDLE>> {
272        self.sessionmap.retain(|_key, val| *val != slot_id);
273        Ok(self.get_slot_mut(slot_id)?.drop_all_sessions())
274    }
275
276    /// Gets a read lock guard for the token on a specified slot.
277    pub(crate) fn get_token_from_slot(
278        &self,
279        slot_id: CK_SLOT_ID,
280    ) -> Result<RwLockReadGuard<'_, Token>> {
281        self.get_slot(slot_id)?.get_token()
282    }
283
284    /// Gets a write lock guard for the token on a specified slot.
285    pub(crate) fn get_token_from_slot_mut(
286        &self,
287        slot_id: CK_SLOT_ID,
288    ) -> Result<RwLockWriteGuard<'_, Token>> {
289        self.get_slot(slot_id)?.get_token_mut(false)
290    }
291
292    /// Gets a write lock guard for the token on a specified slot, bypassing
293    /// initialization checks (used during initialization itself).
294    pub(crate) fn get_token_from_slot_mut_nochecks(
295        &self,
296        slot_id: CK_SLOT_ID,
297    ) -> Result<RwLockWriteGuard<'_, Token>> {
298        self.get_slot(slot_id)?.get_token_mut(true)
299    }
300
301    /// Gets a read lock guard for the token associated with a session handle.
302    pub(crate) fn get_token_from_session(
303        &self,
304        handle: CK_SESSION_HANDLE,
305    ) -> Result<RwLockReadGuard<'_, Token>> {
306        let slot_id = match self.sessionmap.get(&handle) {
307            Some(s) => *s,
308            None => return Err(CKR_SESSION_HANDLE_INVALID)?,
309        };
310        self.get_slot(slot_id)?.get_token()
311    }
312
313    /// Gets a write lock guard for the token associated with a session handle.
314    pub(crate) fn get_token_from_session_mut(
315        &self,
316        handle: CK_SESSION_HANDLE,
317    ) -> Result<RwLockWriteGuard<'_, Token>> {
318        let slot_id = match self.sessionmap.get(&handle) {
319            Some(s) => *s,
320            None => return Err(CKR_SESSION_HANDLE_INVALID)?,
321        };
322        self.get_slot(slot_id)?.get_token_mut(false)
323    }
324
325    /// Gets the FIPS behavior configuration for a specific slot.
326    #[cfg(feature = "fips")]
327    pub fn get_fips_behavior(
328        &self,
329        slot_id: CK_SLOT_ID,
330    ) -> Result<&config::FipsBehavior> {
331        Ok(self.get_slot(slot_id)?.get_fips_behavior())
332    }
333
334    /// Sets the FIPS behavior configuration for a specific slot.
335    #[cfg(all(test, feature = "fips"))]
336    pub fn set_fips_behavior(
337        &mut self,
338        slot_id: CK_SLOT_ID,
339        behavior: config::FipsBehavior,
340    ) -> Result<()> {
341        Ok(self.get_slot_mut(slot_id)?.set_fips_behavior(behavior))
342    }
343}
344
345/// Global state holder for the library.
346pub(crate) struct GlobalState {
347    pub(crate) state: RwLock<State>,
348}
349
350impl GlobalState {
351    pub fn rlock(&self) -> Result<RwLockReadGuard<'_, State>> {
352        match self.state.read() {
353            Ok(r) => {
354                if !r.is_initialized() {
355                    return Err(CKR_CRYPTOKI_NOT_INITIALIZED)?;
356                }
357                Ok(r)
358            }
359            Err(_) => return Err(CKR_GENERAL_ERROR)?,
360        }
361    }
362
363    pub fn wlock(&self) -> Result<RwLockWriteGuard<'_, State>> {
364        match self.state.write() {
365            Ok(w) => {
366                if !w.is_initialized() {
367                    return Err(CKR_CRYPTOKI_NOT_INITIALIZED)?;
368                }
369                Ok(w)
370            }
371            Err(_) => return Err(CKR_GENERAL_ERROR)?,
372        }
373    }
374
375    pub fn wlock_noinitcheck(&self) -> Result<RwLockWriteGuard<'_, State>> {
376        match self.state.write() {
377            Ok(w) => Ok(w),
378            Err(_) => return Err(CKR_GENERAL_ERROR)?,
379        }
380    }
381}
382
383/// Global, lazily initialized, read-write locked state for the PKCS#11 library.
384pub(crate) static STATE: LazyLock<GlobalState> =
385    LazyLock::new(|| GlobalState {
386        state: RwLock::new(State {
387            slots: HashMap::new(),
388            sessionmap: HashMap::new(),
389            next_handle: 0,
390        }),
391    });
392
393/// Initializes the FIPS approval indicator on a session based on the key and
394/// operation. Used at the beginning of a cryptographic operation.
395/// (useful when an input key needs to be checked at initialization) */
396#[cfg(feature = "fips")]
397pub(crate) fn init_fips_approval(
398    mut session: RwLockWriteGuard<'_, Session>,
399    mechanism: CK_MECHANISM_TYPE,
400    op: CK_FLAGS,
401    key: Option<&object::Object>,
402) {
403    let key_ok = fips::indicators::is_approved(mechanism, op, key, None);
404    session.set_fips_indicator(key_ok);
405}
406
407/// Finalizes the FIPS approval indicator on a session based on the outcome
408/// of the cryptographic operation. Used at the end of an operation.
409/// Only downgrades an approval status, never upgrades a non-approved status.
410#[cfg(feature = "fips")]
411pub(crate) fn finalize_fips_approval(
412    mut session: RwLockWriteGuard<'_, Session>,
413    operation_approved: Option<bool>,
414) {
415    let provisional = match session.get_fips_indicator() {
416        Some(b) => b,
417        None => true,
418    };
419    if provisional {
420        session.set_fips_indicator(match operation_approved {
421            Some(b) => b,
422            None => false,
423        });
424    }
425}
426
427/// Global configuration holder for the library.
428pub(crate) struct GlobalConfig {
429    pub(crate) conf: RwLock<Config>,
430}
431
432impl GlobalConfig {
433    pub fn rlock(&self) -> Result<RwLockReadGuard<'_, Config>> {
434        match self.conf.read() {
435            Ok(r) => Ok(r),
436            Err(_) => return Err(CKR_GENERAL_ERROR)?,
437        }
438    }
439
440    pub fn wlock(&self) -> Result<RwLockWriteGuard<'_, Config>> {
441        match self.conf.write() {
442            Ok(w) => Ok(w),
443            Err(_) => return Err(CKR_GENERAL_ERROR)?,
444        }
445    }
446}
447
448/// Global, lazily initialized, read-write locked configuration instance.
449pub(crate) static CONFIG: LazyLock<GlobalConfig> =
450    LazyLock::new(|| GlobalConfig {
451        conf: RwLock::new(Config::new()),
452    });
453
454/// tests helper
455#[cfg(test)]
456pub fn add_slot(slot: config::Slot) -> CK_RV {
457    let mut conf = match CONFIG.wlock() {
458        Ok(v) => v,
459        Err(e) => return e.rv(),
460    };
461    if conf.add_slot(slot).is_err() {
462        return CKR_GENERAL_ERROR;
463    }
464    CKR_OK
465}
466
467#[cfg(test)]
468fn force_load_config() -> CK_RV {
469    let testconf = match Config::default_config() {
470        Ok(conf) => conf,
471        Err(e) => return e.rv(),
472    };
473    if testconf.slots.len() == 0 {
474        return CKR_GENERAL_ERROR;
475    }
476    let mut conf = match CONFIG.wlock() {
477        Ok(v) => v,
478        Err(e) => return e.rv(),
479    };
480    for slot in testconf.slots {
481        match conf.add_slot(slot) {
482            Ok(v) => v,
483            Err(e) => return e.rv(),
484        };
485    }
486    return CKR_OK;
487}
488
489#[cfg(all(test, feature = "fips", feature = "nssdb"))]
490fn get_fips_behavior(
491    slot_id: CK_SLOT_ID,
492    save: &mut config::FipsBehavior,
493) -> CK_RV {
494    let rstate = match STATE.rlock() {
495        Ok(v) => v,
496        Err(e) => return e.rv(),
497    };
498    let behavior = match rstate.get_fips_behavior(slot_id) {
499        Ok(v) => v,
500        Err(e) => return e.rv(),
501    };
502    *save = behavior.clone();
503    CKR_OK
504}
505
506#[cfg(all(test, feature = "fips"))]
507fn set_fips_behavior(slot_id: CK_SLOT_ID, val: config::FipsBehavior) -> CK_RV {
508    let mut wstate = match STATE.wlock() {
509        Ok(v) => v,
510        Err(e) => return e.rv(),
511    };
512    match wstate.set_fips_behavior(slot_id, val) {
513        Ok(()) => CKR_OK,
514        Err(e) => e.rv(),
515    }
516}
517
518/// Check that the mechanism is allowed by the Key object
519///
520/// Verifies that the mechanism is listed in the CKA_ALLOWED_MECHANISMS
521/// attribute if such attribute is present, otherwise allows everything.
522
523pub(crate) fn check_allowed_mechs(
524    mech: &CK_MECHANISM,
525    key: &object::Object,
526) -> CK_RV {
527    let allowed = match key.get_attr(CKA_ALLOWED_MECHANISMS) {
528        Some(attr) => attr,
529        None => return CKR_OK,
530    };
531
532    let mechsvec = allowed.get_value();
533    if mechsvec.len() % misc::CK_ULONG_SIZE != 0 {
534        /* not a multiple of CK_MECHANISM_TYPE values,
535         * bail out, this should never happen, malformed key */
536        return CKR_GENERAL_ERROR;
537    }
538    let mechsnum = mechsvec.len() / misc::CK_ULONG_SIZE;
539    for n in 0..mechsnum {
540        let cursor = n * misc::CK_ULONG_SIZE;
541        let mut mslice = [0u8; misc::CK_ULONG_SIZE];
542        mslice
543            .copy_from_slice(&mechsvec[cursor..(cursor + misc::CK_ULONG_SIZE)]);
544        let m = CK_MECHANISM_TYPE::from_ne_bytes(mslice);
545        if mech.mechanism == m {
546            return CKR_OK;
547        }
548    }
549    return CKR_MECHANISM_INVALID;
550}
551
552/// Holds the version of the implemented interface to return by default
553pub(crate) static IMPLEMENTED_VERSION: CK_VERSION =
554    CK_VERSION { major: 3, minor: 2 };
555
556static MANUFACTURER_ID: [CK_UTF8CHAR; 32usize] =
557    *b"Kryoptic                        ";
558static LIBRARY_DESCRIPTION: [CK_UTF8CHAR; 32usize] =
559    *b"Kryoptic PKCS11 Module          ";
560static LIBRARY_VERSION: CK_VERSION = CK_VERSION { major: 0, minor: 0 };
561
562/// The default module info data
563pub(crate) static MODULE_INFO: CK_INFO = CK_INFO {
564    cryptokiVersion: IMPLEMENTED_VERSION,
565    manufacturerID: MANUFACTURER_ID,
566    flags: 0,
567    libraryDescription: LIBRARY_DESCRIPTION,
568    libraryVersion: LIBRARY_VERSION,
569};
570
571/// FFI Compatible structure that holds the PKCS#11 v2.40 functions table
572pub(crate) static FNLIST_240: CK_FUNCTION_LIST = CK_FUNCTION_LIST {
573    version: CK_VERSION {
574        major: 2,
575        minor: 40,
576    },
577    C_Initialize: Some(fn_initialize),
578    C_Finalize: Some(fn_finalize),
579    C_GetInfo: Some(fn_get_info),
580    C_GetFunctionList: Some(fn_get_function_list),
581    C_GetSlotList: Some(fn_get_slot_list),
582    C_GetSlotInfo: Some(fn_get_slot_info),
583    C_GetTokenInfo: Some(fn_get_token_info),
584    C_GetMechanismList: Some(fn_get_mechanism_list),
585    C_GetMechanismInfo: Some(fn_get_mechanism_info),
586    C_InitToken: Some(fn_init_token),
587    C_InitPIN: Some(fn_init_pin),
588    C_SetPIN: Some(fn_set_pin),
589    C_OpenSession: Some(fn_open_session),
590    C_CloseSession: Some(fn_close_session),
591    C_CloseAllSessions: Some(fn_close_all_sessions),
592    C_GetSessionInfo: Some(fn_get_session_info),
593    C_GetOperationState: Some(fn_get_operation_state),
594    C_SetOperationState: Some(fn_set_operation_state),
595    C_Login: Some(fn_login),
596    C_Logout: Some(fn_logout),
597    C_CreateObject: Some(fn_create_object),
598    C_CopyObject: Some(fn_copy_object),
599    C_DestroyObject: Some(fn_destroy_object),
600    C_GetObjectSize: Some(fn_get_object_size),
601    C_GetAttributeValue: Some(fn_get_attribute_value),
602    C_SetAttributeValue: Some(fn_set_attribute_value),
603    C_FindObjectsInit: Some(fn_find_objects_init),
604    C_FindObjects: Some(fn_find_objects),
605    C_FindObjectsFinal: Some(fn_find_objects_final),
606    C_EncryptInit: Some(fn_encrypt_init),
607    C_Encrypt: Some(fn_encrypt),
608    C_EncryptUpdate: Some(fn_encrypt_update),
609    C_EncryptFinal: Some(fn_encrypt_final),
610    C_DecryptInit: Some(fn_decrypt_init),
611    C_Decrypt: Some(fn_decrypt),
612    C_DecryptUpdate: Some(fn_decrypt_update),
613    C_DecryptFinal: Some(fn_decrypt_final),
614    C_DigestInit: Some(fn_digest_init),
615    C_Digest: Some(fn_digest),
616    C_DigestUpdate: Some(fn_digest_update),
617    C_DigestKey: Some(fn_digest_key),
618    C_DigestFinal: Some(fn_digest_final),
619    C_SignInit: Some(fn_sign_init),
620    C_Sign: Some(fn_sign),
621    C_SignUpdate: Some(fn_sign_update),
622    C_SignFinal: Some(fn_sign_final),
623    C_SignRecoverInit: Some(fn_sign_recover_init),
624    C_SignRecover: Some(fn_sign_recover),
625    C_VerifyInit: Some(fn_verify_init),
626    C_Verify: Some(fn_verify),
627    C_VerifyUpdate: Some(fn_verify_update),
628    C_VerifyFinal: Some(fn_verify_final),
629    C_VerifyRecoverInit: Some(fn_verify_recover_init),
630    C_VerifyRecover: Some(fn_verify_recover),
631    C_DigestEncryptUpdate: Some(fn_digest_encrypt_update),
632    C_DecryptDigestUpdate: Some(fn_decrypt_digest_update),
633    C_SignEncryptUpdate: Some(fn_sign_encrypt_update),
634    C_DecryptVerifyUpdate: Some(fn_decrypt_verify_update),
635    C_GenerateKey: Some(fn_generate_key),
636    C_GenerateKeyPair: Some(fn_generate_key_pair),
637    C_WrapKey: Some(fn_wrap_key),
638    C_UnwrapKey: Some(fn_unwrap_key),
639    C_DeriveKey: Some(fn_derive_key),
640    C_SeedRandom: Some(fn_seed_random),
641    C_GenerateRandom: Some(fn_generate_random),
642    C_GetFunctionStatus: Some(fn_get_function_status),
643    C_CancelFunction: Some(fn_cancel_function),
644    C_WaitForSlotEvent: Some(fn_wait_for_slot_event),
645};
646
647/// FFI Compatible structure that holds the PKCS#11 v3.0 functions table
648pub(crate) static FNLIST_300: CK_FUNCTION_LIST_3_0 = CK_FUNCTION_LIST_3_0 {
649    version: CK_VERSION { major: 3, minor: 0 },
650    C_Initialize: Some(fn_initialize),
651    C_Finalize: Some(fn_finalize),
652    C_GetInfo: Some(fn_get_info),
653    C_GetFunctionList: Some(fn_get_function_list),
654    C_GetSlotList: Some(fn_get_slot_list),
655    C_GetSlotInfo: Some(fn_get_slot_info),
656    C_GetTokenInfo: Some(fn_get_token_info),
657    C_GetMechanismList: Some(fn_get_mechanism_list),
658    C_GetMechanismInfo: Some(fn_get_mechanism_info),
659    C_InitToken: Some(fn_init_token),
660    C_InitPIN: Some(fn_init_pin),
661    C_SetPIN: Some(fn_set_pin),
662    C_OpenSession: Some(fn_open_session),
663    C_CloseSession: Some(fn_close_session),
664    C_CloseAllSessions: Some(fn_close_all_sessions),
665    C_GetSessionInfo: Some(fn_get_session_info),
666    C_GetOperationState: Some(fn_get_operation_state),
667    C_SetOperationState: Some(fn_set_operation_state),
668    C_Login: Some(fn_login),
669    C_Logout: Some(fn_logout),
670    C_CreateObject: Some(fn_create_object),
671    C_CopyObject: Some(fn_copy_object),
672    C_DestroyObject: Some(fn_destroy_object),
673    C_GetObjectSize: Some(fn_get_object_size),
674    C_GetAttributeValue: Some(fn_get_attribute_value),
675    C_SetAttributeValue: Some(fn_set_attribute_value),
676    C_FindObjectsInit: Some(fn_find_objects_init),
677    C_FindObjects: Some(fn_find_objects),
678    C_FindObjectsFinal: Some(fn_find_objects_final),
679    C_EncryptInit: Some(fn_encrypt_init),
680    C_Encrypt: Some(fn_encrypt),
681    C_EncryptUpdate: Some(fn_encrypt_update),
682    C_EncryptFinal: Some(fn_encrypt_final),
683    C_DecryptInit: Some(fn_decrypt_init),
684    C_Decrypt: Some(fn_decrypt),
685    C_DecryptUpdate: Some(fn_decrypt_update),
686    C_DecryptFinal: Some(fn_decrypt_final),
687    C_DigestInit: Some(fn_digest_init),
688    C_Digest: Some(fn_digest),
689    C_DigestUpdate: Some(fn_digest_update),
690    C_DigestKey: Some(fn_digest_key),
691    C_DigestFinal: Some(fn_digest_final),
692    C_SignInit: Some(fn_sign_init),
693    C_Sign: Some(fn_sign),
694    C_SignUpdate: Some(fn_sign_update),
695    C_SignFinal: Some(fn_sign_final),
696    C_SignRecoverInit: Some(fn_sign_recover_init),
697    C_SignRecover: Some(fn_sign_recover),
698    C_VerifyInit: Some(fn_verify_init),
699    C_Verify: Some(fn_verify),
700    C_VerifyUpdate: Some(fn_verify_update),
701    C_VerifyFinal: Some(fn_verify_final),
702    C_VerifyRecoverInit: Some(fn_verify_recover_init),
703    C_VerifyRecover: Some(fn_verify_recover),
704    C_DigestEncryptUpdate: Some(fn_digest_encrypt_update),
705    C_DecryptDigestUpdate: Some(fn_decrypt_digest_update),
706    C_SignEncryptUpdate: Some(fn_sign_encrypt_update),
707    C_DecryptVerifyUpdate: Some(fn_decrypt_verify_update),
708    C_GenerateKey: Some(fn_generate_key),
709    C_GenerateKeyPair: Some(fn_generate_key_pair),
710    C_WrapKey: Some(fn_wrap_key),
711    C_UnwrapKey: Some(fn_unwrap_key),
712    C_DeriveKey: Some(fn_derive_key),
713    C_SeedRandom: Some(fn_seed_random),
714    C_GenerateRandom: Some(fn_generate_random),
715    C_GetFunctionStatus: Some(fn_get_function_status),
716    C_CancelFunction: Some(fn_cancel_function),
717    C_WaitForSlotEvent: Some(fn_wait_for_slot_event),
718    C_GetInterfaceList: Some(fn_get_interface_list),
719    C_GetInterface: Some(fn_get_interface),
720    C_LoginUser: Some(fn_login_user),
721    C_SessionCancel: Some(fn_session_cancel),
722    C_MessageEncryptInit: Some(fn_message_encrypt_init),
723    C_EncryptMessage: Some(fn_encrypt_message),
724    C_EncryptMessageBegin: Some(fn_encrypt_message_begin),
725    C_EncryptMessageNext: Some(fn_encrypt_message_next),
726    C_MessageEncryptFinal: Some(fn_message_encrypt_final),
727    C_MessageDecryptInit: Some(fn_message_decrypt_init),
728    C_DecryptMessage: Some(fn_decrypt_message),
729    C_DecryptMessageBegin: Some(fn_decrypt_message_begin),
730    C_DecryptMessageNext: Some(fn_decrypt_message_next),
731    C_MessageDecryptFinal: Some(fn_message_decrypt_final),
732    C_MessageSignInit: Some(fn_message_sign_init),
733    C_SignMessage: Some(fn_sign_message),
734    C_SignMessageBegin: Some(fn_sign_message_begin),
735    C_SignMessageNext: Some(fn_sign_message_next),
736    C_MessageSignFinal: Some(fn_message_sign_final),
737    C_MessageVerifyInit: Some(fn_message_verify_init),
738    C_VerifyMessage: Some(fn_verify_message),
739    C_VerifyMessageBegin: Some(fn_verify_message_begin),
740    C_VerifyMessageNext: Some(fn_verify_message_next),
741    C_MessageVerifyFinal: Some(fn_message_verify_final),
742};
743
744/// FFI Compatible structure that holds the PKCS#11 v3.2 functions table
745static FNLIST_320: CK_FUNCTION_LIST_3_2 = CK_FUNCTION_LIST_3_2 {
746    version: CK_VERSION { major: 3, minor: 2 },
747    C_Initialize: Some(fn_initialize),
748    C_Finalize: Some(fn_finalize),
749    C_GetInfo: Some(fn_get_info),
750    C_GetFunctionList: Some(fn_get_function_list),
751    C_GetSlotList: Some(fn_get_slot_list),
752    C_GetSlotInfo: Some(fn_get_slot_info),
753    C_GetTokenInfo: Some(fn_get_token_info),
754    C_GetMechanismList: Some(fn_get_mechanism_list),
755    C_GetMechanismInfo: Some(fn_get_mechanism_info),
756    C_InitToken: Some(fn_init_token),
757    C_InitPIN: Some(fn_init_pin),
758    C_SetPIN: Some(fn_set_pin),
759    C_OpenSession: Some(fn_open_session),
760    C_CloseSession: Some(fn_close_session),
761    C_CloseAllSessions: Some(fn_close_all_sessions),
762    C_GetSessionInfo: Some(fn_get_session_info),
763    C_GetOperationState: Some(fn_get_operation_state),
764    C_SetOperationState: Some(fn_set_operation_state),
765    C_Login: Some(fn_login),
766    C_Logout: Some(fn_logout),
767    C_CreateObject: Some(fn_create_object),
768    C_CopyObject: Some(fn_copy_object),
769    C_DestroyObject: Some(fn_destroy_object),
770    C_GetObjectSize: Some(fn_get_object_size),
771    C_GetAttributeValue: Some(fn_get_attribute_value),
772    C_SetAttributeValue: Some(fn_set_attribute_value),
773    C_FindObjectsInit: Some(fn_find_objects_init),
774    C_FindObjects: Some(fn_find_objects),
775    C_FindObjectsFinal: Some(fn_find_objects_final),
776    C_EncryptInit: Some(fn_encrypt_init),
777    C_Encrypt: Some(fn_encrypt),
778    C_EncryptUpdate: Some(fn_encrypt_update),
779    C_EncryptFinal: Some(fn_encrypt_final),
780    C_DecryptInit: Some(fn_decrypt_init),
781    C_Decrypt: Some(fn_decrypt),
782    C_DecryptUpdate: Some(fn_decrypt_update),
783    C_DecryptFinal: Some(fn_decrypt_final),
784    C_DigestInit: Some(fn_digest_init),
785    C_Digest: Some(fn_digest),
786    C_DigestUpdate: Some(fn_digest_update),
787    C_DigestKey: Some(fn_digest_key),
788    C_DigestFinal: Some(fn_digest_final),
789    C_SignInit: Some(fn_sign_init),
790    C_Sign: Some(fn_sign),
791    C_SignUpdate: Some(fn_sign_update),
792    C_SignFinal: Some(fn_sign_final),
793    C_SignRecoverInit: Some(fn_sign_recover_init),
794    C_SignRecover: Some(fn_sign_recover),
795    C_VerifyInit: Some(fn_verify_init),
796    C_Verify: Some(fn_verify),
797    C_VerifyUpdate: Some(fn_verify_update),
798    C_VerifyFinal: Some(fn_verify_final),
799    C_VerifyRecoverInit: Some(fn_verify_recover_init),
800    C_VerifyRecover: Some(fn_verify_recover),
801    C_DigestEncryptUpdate: Some(fn_digest_encrypt_update),
802    C_DecryptDigestUpdate: Some(fn_decrypt_digest_update),
803    C_SignEncryptUpdate: Some(fn_sign_encrypt_update),
804    C_DecryptVerifyUpdate: Some(fn_decrypt_verify_update),
805    C_GenerateKey: Some(fn_generate_key),
806    C_GenerateKeyPair: Some(fn_generate_key_pair),
807    C_WrapKey: Some(fn_wrap_key),
808    C_UnwrapKey: Some(fn_unwrap_key),
809    C_DeriveKey: Some(fn_derive_key),
810    C_SeedRandom: Some(fn_seed_random),
811    C_GenerateRandom: Some(fn_generate_random),
812    C_GetFunctionStatus: Some(fn_get_function_status),
813    C_CancelFunction: Some(fn_cancel_function),
814    C_WaitForSlotEvent: Some(fn_wait_for_slot_event),
815    C_GetInterfaceList: Some(fn_get_interface_list),
816    C_GetInterface: Some(fn_get_interface),
817    C_LoginUser: Some(fn_login_user),
818    C_SessionCancel: Some(fn_session_cancel),
819    C_MessageEncryptInit: Some(fn_message_encrypt_init),
820    C_EncryptMessage: Some(fn_encrypt_message),
821    C_EncryptMessageBegin: Some(fn_encrypt_message_begin),
822    C_EncryptMessageNext: Some(fn_encrypt_message_next),
823    C_MessageEncryptFinal: Some(fn_message_encrypt_final),
824    C_MessageDecryptInit: Some(fn_message_decrypt_init),
825    C_DecryptMessage: Some(fn_decrypt_message),
826    C_DecryptMessageBegin: Some(fn_decrypt_message_begin),
827    C_DecryptMessageNext: Some(fn_decrypt_message_next),
828    C_MessageDecryptFinal: Some(fn_message_decrypt_final),
829    C_MessageSignInit: Some(fn_message_sign_init),
830    C_SignMessage: Some(fn_sign_message),
831    C_SignMessageBegin: Some(fn_sign_message_begin),
832    C_SignMessageNext: Some(fn_sign_message_next),
833    C_MessageSignFinal: Some(fn_message_sign_final),
834    C_MessageVerifyInit: Some(fn_message_verify_init),
835    C_VerifyMessage: Some(fn_verify_message),
836    C_VerifyMessageBegin: Some(fn_verify_message_begin),
837    C_VerifyMessageNext: Some(fn_verify_message_next),
838    C_MessageVerifyFinal: Some(fn_message_verify_final),
839    C_EncapsulateKey: Some(fn_encapsulate_key),
840    C_DecapsulateKey: Some(fn_decapsulate_key),
841    C_VerifySignatureInit: Some(fn_verify_signature_init),
842    C_VerifySignature: Some(fn_verify_signature),
843    C_VerifySignatureUpdate: Some(fn_verify_signature_update),
844    C_VerifySignatureFinal: Some(fn_verify_signature_final),
845    C_GetSessionValidationFlags: Some(fn_get_session_validation_flags),
846    C_AsyncComplete: Some(fn_async_complete),
847    C_AsyncGetID: Some(fn_async_get_id),
848    C_AsyncJoin: Some(fn_async_join),
849    C_WrapKeyAuthenticated: Some(fn_wrap_key_authenticated),
850    C_UnwrapKeyAuthenticated: Some(fn_unwrap_key_authenticated),
851};
852
853/// PKCS#11 reserved name for the standard official interfaces
854static INTERFACE_NAME_STD_NUL: &str = "PKCS 11\0";
855
856/// Holds pointers to v2.40 interface
857static INTERFACE_240: CK_INTERFACE = CK_INTERFACE {
858    pInterfaceName: INTERFACE_NAME_STD_NUL.as_ptr() as *mut u8,
859    pFunctionList: &FNLIST_240 as *const _ as *const ::std::os::raw::c_void,
860    flags: 0,
861};
862
863/// Holds pointers to v3.0 interface
864static INTERFACE_300: CK_INTERFACE = CK_INTERFACE {
865    pInterfaceName: INTERFACE_NAME_STD_NUL.as_ptr() as *mut u8,
866    pFunctionList: &FNLIST_300 as *const _ as *const ::std::os::raw::c_void,
867    flags: 0,
868};
869
870/// Holds pointers to v3.2 interface
871static INTERFACE_320: CK_INTERFACE = CK_INTERFACE {
872    pInterfaceName: INTERFACE_NAME_STD_NUL.as_ptr() as *mut u8,
873    pFunctionList: &FNLIST_320 as *const _ as *const ::std::os::raw::c_void,
874    flags: 0,
875};
876
877/// Structure that holds a pointer to the interface structure.
878/// It is used when applications request a specific interface version,
879/// and we need to return the associated structure via FFI.
880
881#[derive(Debug, Copy, Clone)]
882struct InterfaceData {
883    interface: *const CK_INTERFACE,
884    version: CK_VERSION,
885}
886unsafe impl Sync for InterfaceData {}
887unsafe impl Send for InterfaceData {}
888
889/// The set of known interfaces we can return to applications
890
891static INTERFACE_SET: LazyLock<Vec<InterfaceData>> = LazyLock::new(|| {
892    let mut v = Vec::with_capacity(3);
893    v.push(InterfaceData {
894        interface: std::ptr::addr_of!(INTERFACE_320),
895        version: FNLIST_320.version,
896    });
897    v.push(InterfaceData {
898        interface: std::ptr::addr_of!(INTERFACE_300),
899        version: FNLIST_300.version,
900    });
901    v.push(InterfaceData {
902        interface: std::ptr::addr_of!(INTERFACE_240),
903        version: FNLIST_240.version,
904    });
905    v
906});
907
908#[cfg(test)]
909mod tests;