1 /* -*- Mode: rust; rust-indent-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #![allow(non_snake_case)]
8 use pkcs11_bindings::*;
11 use std::collections::btree_map::Entry;
12 use std::collections::{BTreeMap, BTreeSet};
13 use std::sync::atomic::{AtomicU32, Ordering};
14 use std::sync::{Mutex, MutexGuard};
16 use crate::internal::{get_attribute, search};
17 use crate::internal::{ObjectHandle, Query, SearchResult};
19 use crate::version::*;
21 const BUILTINS_VERSION: CK_VERSION = CK_VERSION {
22 major: NSS_BUILTINS_LIBRARY_VERSION_MAJOR,
23 minor: NSS_BUILTINS_LIBRARY_VERSION_MINOR,
26 const FIRMWARE_VERSION: CK_VERSION = CK_VERSION {
27 major: NSS_BUILTINS_FIRMWARE_VERSION_MAJOR,
28 minor: NSS_BUILTINS_FIRMWARE_VERSION_MINOR,
31 const CRYPTOKI_VERSION: CK_VERSION = CK_VERSION {
32 major: NSS_BUILTINS_CRYPTOKI_VERSION_MAJOR,
33 minor: NSS_BUILTINS_CRYPTOKI_VERSION_MINOR,
35 const HARDWARE_VERSION: CK_VERSION = CK_VERSION {
36 major: NSS_BUILTINS_HARDWARE_VERSION_MAJOR,
37 minor: NSS_BUILTINS_HARDWARE_VERSION_MINOR,
40 const MANUFACTURER_ID_BYTES: &[u8; 32] = b"Mozilla Foundation ";
41 const LIBRARY_DESCRIPTION_BYTES: &[u8; 32] = b"NSS Builtin Object Cryptoki Modu";
43 const SLOT_COUNT: CK_ULONG = 1;
44 const SLOT_ID_ROOTS: CK_SLOT_ID = 1;
45 const SLOT_DESCRIPTION_ROOTS_BYTES: &[u8; 64] =
46 b"NSS Builtin Objects ";
48 const TOKEN_LABEL_ROOTS_BYTES: &[u8; 32] = b"Builtin Object Token ";
49 const TOKEN_MODEL_BYTES: &[u8; 16] = b"1 ";
50 const TOKEN_SERIAL_NUMBER_BYTES: &[u8; 16] = b"1 ";
51 const TOKEN_UTC_TIME: &[u8; 16] = b" ";
54 struct PK11Error(CK_RV);
56 // The token assigns session handles using a counter. It would make sense to use a 64 bit counter,
57 // as there would then be no risk of exhausting the session handle space. However,
58 // CK_SESSION_HANDLE is defined as a C unsigned long, which is a u32 on some platforms.
60 // We start the counter at 1 since PKCS#11 reserves 0 to signal an invalid handle
62 type SessionHandle = u32;
63 static NEXT_HANDLE: AtomicU32 = AtomicU32::new(1);
65 // The token needs to keep track of which sessions are open.
67 type SessionSet = BTreeSet<SessionHandle>;
68 static OPEN_SESSIONS: Mutex<Option<SessionSet>> = Mutex::new(None);
70 // Helper functions for accessing OPEN_SESSIONS
72 type SessionSetGuard = MutexGuard<'static, Option<SessionSet>>;
74 fn get_open_sessions_guard() -> Result<SessionSetGuard, PK11Error> {
77 .map_err(|_| PK11Error(CKR_DEVICE_ERROR))
80 fn get_open_sessions(guard: &mut SessionSetGuard) -> Result<&mut SessionSet, PK11Error> {
83 .ok_or(PK11Error(CKR_CRYPTOKI_NOT_INITIALIZED))?;
87 // The token needs to cache search results until the client reads them or closes the session.
89 type SearchCache = BTreeMap<SessionHandle, SearchResult>;
90 static SEARCHES: Mutex<Option<SearchCache>> = Mutex::new(None);
92 // Helper functions for accessing SEARCHES
94 type SearchCacheGuard = MutexGuard<'static, Option<SearchCache>>;
96 fn get_search_cache_guard() -> Result<SearchCacheGuard, PK11Error> {
97 SEARCHES.lock().map_err(|_| PK11Error(CKR_DEVICE_ERROR))
100 fn get_search_cache(guard: &mut SearchCacheGuard) -> Result<&mut SearchCache, PK11Error> {
103 .ok_or(PK11Error(CKR_CRYPTOKI_NOT_INITIALIZED))?;
107 fn validate_session(handle: SessionHandle) -> Result<(), PK11Error> {
108 let mut guard = get_open_sessions_guard()?;
109 let sessions = get_open_sessions(&mut guard)?;
110 if sessions.contains(&handle) {
113 if handle < NEXT_HANDLE.load(Ordering::SeqCst) {
114 Err(PK11Error(CKR_SESSION_CLOSED))
116 // Possible that NEXT_HANDLE wrapped and we should return CKR_SESSION_CLOSED.
117 // But this is best-effort.
118 Err(PK11Error(CKR_SESSION_HANDLE_INVALID))
122 // The internal implementation of C_Initialize
123 fn initialize() -> Result<(), PK11Error> {
125 let mut search_cache_guard = get_search_cache_guard()?;
126 if (*search_cache_guard).is_some() {
127 return Err(PK11Error(CKR_CRYPTOKI_ALREADY_INITIALIZED));
129 *search_cache_guard = Some(SearchCache::default());
133 let mut session_guard = get_open_sessions_guard()?;
134 if (*session_guard).is_some() {
135 return Err(PK11Error(CKR_CRYPTOKI_ALREADY_INITIALIZED));
137 *session_guard = Some(SessionSet::default());
143 // The internal implementation of C_Finalize
144 fn finalize() -> Result<(), PK11Error> {
146 let mut guard = get_search_cache_guard()?;
147 // Try to access the search cache to ensure we're initialized.
148 // Returns CKR_CRYPTOKI_NOT_INITIALIZED if we're not.
149 let _ = get_search_cache(&mut guard)?;
153 let mut guard = get_open_sessions_guard()?;
154 let _ = get_open_sessions(&mut guard)?;
160 // Internal implementation of C_OpenSession
161 fn open_session() -> Result<SessionHandle, PK11Error> {
162 let mut handle = NEXT_HANDLE.fetch_add(1, Ordering::SeqCst);
164 // skip handle 0 if the addition wraps
165 handle = NEXT_HANDLE.fetch_add(1, Ordering::SeqCst);
168 let mut guard = get_open_sessions_guard()?;
169 let sessions = get_open_sessions(&mut guard)?;
170 while !sessions.insert(handle) {
171 // this only executes if NEXT_HANDLE wraps while sessions with
172 // small handles are still open.
173 handle = NEXT_HANDLE.fetch_add(1, Ordering::SeqCst);
179 // Internal implementation of C_CloseSession
180 fn close_session(session: SessionHandle) -> Result<(), PK11Error> {
182 let mut guard = get_search_cache_guard()?;
183 let searches = get_search_cache(&mut guard)?;
184 searches.remove(&session);
188 let mut guard = get_open_sessions_guard()?;
189 let sessions = get_open_sessions(&mut guard)?;
190 if sessions.remove(&session) {
192 } else if session < NEXT_HANDLE.load(Ordering::SeqCst) {
193 Err(PK11Error(CKR_SESSION_CLOSED))
195 Err(PK11Error(CKR_SESSION_HANDLE_INVALID))
200 // Internal implementation of C_CloseAllSessions
201 fn close_all_sessions() -> Result<(), PK11Error> {
203 let mut guard = get_search_cache_guard()?;
204 let searches = get_search_cache(&mut guard)?;
209 let mut guard = get_open_sessions_guard()?;
210 let sessions = get_open_sessions(&mut guard)?;
217 // Internal implementation of C_FindObjectsInit
218 fn find_objects_init(session: SessionHandle, query: &Query) -> Result<usize, PK11Error> {
219 validate_session(session)?;
221 let results = search(query);
222 let count = results.len();
224 let mut guard = get_search_cache_guard()?;
225 let searches = get_search_cache(&mut guard)?;
226 match searches.entry(session) {
227 Entry::Occupied(_) => Err(PK11Error(CKR_OPERATION_ACTIVE)),
228 Entry::Vacant(v) => {
235 // Internal implementation of C_FindObjects
236 fn find_objects(session: SessionHandle, out: &mut [CK_OBJECT_HANDLE]) -> Result<usize, PK11Error> {
237 validate_session(session)?;
239 let mut guard = get_search_cache_guard()?;
240 let searches = get_search_cache(&mut guard)?;
241 if let Some(objects) = searches.get_mut(&session) {
242 for (i, out_i) in out.iter_mut().enumerate() {
243 match objects.pop() {
244 Some(object) => *out_i = object.into(),
245 None => return Ok(i),
254 // Internal implementation of C_FindObjectsFinal
255 fn find_objects_final(session: SessionHandle) -> Result<(), PK11Error> {
256 validate_session(session)?;
258 let mut guard = get_search_cache_guard()?;
259 let searches = get_search_cache(&mut guard)?;
260 searches.remove(&session);
264 extern "C" fn C_Initialize(_pInitArgs: CK_VOID_PTR) -> CK_RV {
267 Err(PK11Error(e)) => e,
271 extern "C" fn C_Finalize(pReserved: CK_VOID_PTR) -> CK_RV {
272 if !pReserved.is_null() {
273 return CKR_ARGUMENTS_BAD;
277 Err(PK11Error(e)) => e,
281 extern "C" fn C_GetInfo(pInfo: CK_INFO_PTR) -> CK_RV {
283 return CKR_ARGUMENTS_BAD;
287 cryptokiVersion: CRYPTOKI_VERSION,
288 manufacturerID: *MANUFACTURER_ID_BYTES,
290 libraryDescription: *LIBRARY_DESCRIPTION_BYTES,
291 libraryVersion: BUILTINS_VERSION,
297 extern "C" fn C_GetSlotList(
298 _tokenPresent: CK_BBOOL,
299 pSlotList: CK_SLOT_ID_PTR,
300 pulCount: CK_ULONG_PTR,
302 if pulCount.is_null() {
303 return CKR_ARGUMENTS_BAD;
305 if !pSlotList.is_null() {
306 if unsafe { *pulCount } < SLOT_COUNT {
307 return CKR_BUFFER_TOO_SMALL;
310 *pSlotList = SLOT_ID_ROOTS;
314 *pulCount = SLOT_COUNT;
319 extern "C" fn C_GetSlotInfo(slotID: CK_SLOT_ID, pInfo: CK_SLOT_INFO_PTR) -> CK_RV {
320 if (slotID != SLOT_ID_ROOTS) || pInfo.is_null() {
321 return CKR_ARGUMENTS_BAD;
324 *pInfo = CK_SLOT_INFO {
325 slotDescription: *SLOT_DESCRIPTION_ROOTS_BYTES,
326 manufacturerID: *MANUFACTURER_ID_BYTES,
327 flags: CKF_TOKEN_PRESENT,
328 hardwareVersion: HARDWARE_VERSION,
329 firmwareVersion: FIRMWARE_VERSION,
335 extern "C" fn C_GetTokenInfo(slotID: CK_SLOT_ID, pInfo: CK_TOKEN_INFO_PTR) -> CK_RV {
336 if (slotID != SLOT_ID_ROOTS) || pInfo.is_null() {
337 return CKR_ARGUMENTS_BAD;
340 *pInfo = CK_TOKEN_INFO {
341 label: *TOKEN_LABEL_ROOTS_BYTES,
342 manufacturerID: *MANUFACTURER_ID_BYTES,
343 model: *TOKEN_MODEL_BYTES,
344 serialNumber: *TOKEN_SERIAL_NUMBER_BYTES,
345 flags: CKF_WRITE_PROTECTED,
346 ulMaxSessionCount: CK_UNAVAILABLE_INFORMATION,
348 ulMaxRwSessionCount: CK_UNAVAILABLE_INFORMATION,
350 ulMaxPinLen: CK_UNAVAILABLE_INFORMATION,
351 ulMinPinLen: CK_UNAVAILABLE_INFORMATION,
352 ulTotalPublicMemory: CK_UNAVAILABLE_INFORMATION,
353 ulFreePublicMemory: CK_UNAVAILABLE_INFORMATION,
354 ulTotalPrivateMemory: CK_UNAVAILABLE_INFORMATION,
355 ulFreePrivateMemory: CK_UNAVAILABLE_INFORMATION,
356 hardwareVersion: HARDWARE_VERSION,
357 firmwareVersion: FIRMWARE_VERSION,
358 utcTime: *TOKEN_UTC_TIME,
364 extern "C" fn C_GetMechanismList(
366 _pMechanismList: CK_MECHANISM_TYPE_PTR,
367 pulCount: CK_ULONG_PTR,
369 if slotID != SLOT_ID_ROOTS || pulCount.is_null() {
370 return CKR_ARGUMENTS_BAD;
378 extern "C" fn C_GetMechanismInfo(
380 _type: CK_MECHANISM_TYPE,
381 _pInfo: CK_MECHANISM_INFO_PTR,
383 CKR_FUNCTION_NOT_SUPPORTED
386 extern "C" fn C_InitToken(
388 _pPin: CK_UTF8CHAR_PTR,
390 _pLabel: CK_UTF8CHAR_PTR,
392 CKR_FUNCTION_NOT_SUPPORTED
395 extern "C" fn C_InitPIN(
396 _hSession: CK_SESSION_HANDLE,
397 _pPin: CK_UTF8CHAR_PTR,
400 CKR_FUNCTION_NOT_SUPPORTED
403 extern "C" fn C_SetPIN(
404 _hSession: CK_SESSION_HANDLE,
405 _pOldPin: CK_UTF8CHAR_PTR,
407 _pNewPin: CK_UTF8CHAR_PTR,
410 CKR_FUNCTION_NOT_SUPPORTED
413 extern "C" fn C_OpenSession(
416 _pApplication: CK_VOID_PTR,
418 phSession: CK_SESSION_HANDLE_PTR,
420 if slotID != SLOT_ID_ROOTS || phSession.is_null() {
421 return CKR_ARGUMENTS_BAD;
423 // [pkcs11-base-v3.0, Section 5.6.1]
424 // For legacy reasons, the CKF_SERIAL_SESSION bit MUST always be set; if a call to
425 // C_OpenSession does not have this bit set, the call should return unsuccessfully with the
426 // error code CKR_SESSION_PARALLEL_NOT_SUPPORTED.
427 if flags & CKF_SERIAL_SESSION == 0 {
428 return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
430 let session_id = match open_session() {
431 Ok(session_id) => session_id as CK_SESSION_HANDLE,
432 Err(PK11Error(e)) => return e,
434 unsafe { *phSession = session_id };
438 extern "C" fn C_CloseSession(hSession: CK_SESSION_HANDLE) -> CK_RV {
439 let session: SessionHandle = match hSession.try_into() {
440 Ok(session) => session,
441 Err(_) => return CKR_SESSION_HANDLE_INVALID,
443 match close_session(session) {
445 Err(PK11Error(e)) => e,
449 extern "C" fn C_CloseAllSessions(slotID: CK_SLOT_ID) -> CK_RV {
450 if slotID != SLOT_ID_ROOTS {
451 return CKR_ARGUMENTS_BAD;
453 match close_all_sessions() {
455 Err(PK11Error(e)) => e,
459 extern "C" fn C_GetSessionInfo(_hSession: CK_SESSION_HANDLE, _pInfo: CK_SESSION_INFO_PTR) -> CK_RV {
460 CKR_FUNCTION_NOT_SUPPORTED
463 extern "C" fn C_GetOperationState(
464 _hSession: CK_SESSION_HANDLE,
465 _pOperationState: CK_BYTE_PTR,
466 _pulOperationStateLen: CK_ULONG_PTR,
468 CKR_FUNCTION_NOT_SUPPORTED
471 extern "C" fn C_SetOperationState(
472 _hSession: CK_SESSION_HANDLE,
473 _pOperationState: CK_BYTE_PTR,
474 _ulOperationStateLen: CK_ULONG,
475 _hEncryptionKey: CK_OBJECT_HANDLE,
476 _hAuthenticationKey: CK_OBJECT_HANDLE,
478 CKR_FUNCTION_NOT_SUPPORTED
481 extern "C" fn C_Login(
482 _hSession: CK_SESSION_HANDLE,
483 _userType: CK_USER_TYPE,
484 _pPin: CK_UTF8CHAR_PTR,
487 CKR_FUNCTION_NOT_SUPPORTED
490 extern "C" fn C_Logout(_hSession: CK_SESSION_HANDLE) -> CK_RV {
494 extern "C" fn C_CreateObject(
495 _hSession: CK_SESSION_HANDLE,
496 _pTemplate: CK_ATTRIBUTE_PTR,
498 _phObject: CK_OBJECT_HANDLE_PTR,
500 CKR_FUNCTION_NOT_SUPPORTED
503 extern "C" fn C_CopyObject(
504 _hSession: CK_SESSION_HANDLE,
505 _hObject: CK_OBJECT_HANDLE,
506 _pTemplate: CK_ATTRIBUTE_PTR,
508 _phNewObject: CK_OBJECT_HANDLE_PTR,
510 CKR_FUNCTION_NOT_SUPPORTED
513 extern "C" fn C_DestroyObject(_hSession: CK_SESSION_HANDLE, _hObject: CK_OBJECT_HANDLE) -> CK_RV {
514 CKR_FUNCTION_NOT_SUPPORTED
517 extern "C" fn C_GetObjectSize(
518 _hSession: CK_SESSION_HANDLE,
519 _hObject: CK_OBJECT_HANDLE,
520 _pulSize: CK_ULONG_PTR,
522 CKR_FUNCTION_NOT_SUPPORTED
525 extern "C" fn C_GetAttributeValue(
526 _hSession: CK_SESSION_HANDLE,
527 hObject: CK_OBJECT_HANDLE,
528 pTemplate: CK_ATTRIBUTE_PTR,
531 if pTemplate.is_null() {
532 return CKR_ARGUMENTS_BAD;
535 let count: usize = match ulCount.try_into() {
537 Err(_) => return CKR_ARGUMENTS_BAD,
540 // C_GetAttributeValue has a session handle parameter because PKCS#11 objects can have
541 // session-bound lifetimes and access controls. We don't have any session objects, and all of
542 // our token objects are public. So there's no good reason to validate the session handle.
544 //let session: SessionHandle = match hSession.try_into() {
545 // Ok(session) => session,
546 // Err(_) => return CKR_SESSION_HANDLE_INVALID,
549 //if let Err(PK11Error(e)) = validate_session(session) {
553 let handle: ObjectHandle = match hObject.try_into() {
554 Ok(handle) => handle,
555 Err(_) => return CKR_OBJECT_HANDLE_INVALID,
558 let attrs: &mut [CK_ATTRIBUTE] = unsafe { slice::from_raw_parts_mut(pTemplate, count) };
562 // Handle requests with null pValue fields
563 for attr in attrs.iter_mut().filter(|x| x.pValue.is_null()) {
564 attr.ulValueLen = match get_attribute(attr.type_, &handle) {
566 // [pkcs11-base-v3.0, Section 5.7.5]
567 // 2. [...] if the specified value for the object is invalid (the object does not possess
568 // such an attribute), then the ulValueLen field in that triple is modified to hold the
569 // value CK_UNAVAILABLE_INFORMATION.
570 rv = CKR_ATTRIBUTE_TYPE_INVALID;
571 CK_UNAVAILABLE_INFORMATION
574 // [pkcs11-base-v3.0, Section 5.7.5]
575 // 3. [...] if the pValue field has the value NULL_PTR, then the ulValueLen field is modified
576 // to hold the exact length of the specified attribute for the object.
577 attr.len() as CK_ULONG
582 // Handle requests with non-null pValue fields
583 for attr in attrs.iter_mut().filter(|x| !x.pValue.is_null()) {
584 let dst_len: usize = match attr.ulValueLen.try_into() {
585 Ok(dst_len) => dst_len,
586 Err(_) => return CKR_ARGUMENTS_BAD,
588 attr.ulValueLen = match get_attribute(attr.type_, &handle) {
590 // [pkcs11-base-v3.0, Section 5.7.5]
591 // 2. [...] if the specified value for the object is invalid (the object does not possess
592 // such an attribute), then the ulValueLen field in that triple is modified to hold the
593 // value CK_UNAVAILABLE_INFORMATION.
594 rv = CKR_ATTRIBUTE_TYPE_INVALID;
595 CK_UNAVAILABLE_INFORMATION
597 Some(src) if dst_len >= src.len() => {
598 // [pkcs11-base-v3.0, Section 5.7.5]
599 // 4. [...] if the length specified in ulValueLen is large enough to hold the value
600 // of the specified attribute for the object, then that attribute is copied into
601 // the buffer located at pValue, and the ulValueLen field is modified to hold
602 // the exact length of the attribute.
604 unsafe { slice::from_raw_parts_mut(attr.pValue as *mut u8, dst_len) };
605 dst[..src.len()].copy_from_slice(src);
606 src.len() as CK_ULONG
609 // [pkcs11-base-v3.0, Section 5.7.5]
610 // 5. Otherwise, the ulValueLen field is modified to hold the value
611 // CK_UNAVAILABLE_INFORMATION.
612 rv = CKR_BUFFER_TOO_SMALL;
613 CK_UNAVAILABLE_INFORMATION
618 // [pkcs11-base-v3.0, Section 5.7.5]
619 // If case 2 applies to any of the requested attributes, then the call should return the value
620 // CKR_ATTRIBUTE_TYPE_INVALID. If case 5 applies to any of the requested attributes, then the
621 // call should return the value CKR_BUFFER_TOO_SMALL. As usual, if more than one of these
622 // error codes is applicable, Cryptoki may return any of them. Only if none of them applies to
623 // any of the requested attributes will CKR_OK be returned.
627 extern "C" fn C_SetAttributeValue(
628 _hSession: CK_SESSION_HANDLE,
629 _hObject: CK_OBJECT_HANDLE,
630 _pTemplate: CK_ATTRIBUTE_PTR,
633 CKR_FUNCTION_NOT_SUPPORTED
636 extern "C" fn C_FindObjectsInit(
637 hSession: CK_SESSION_HANDLE,
638 pTemplate: CK_ATTRIBUTE_PTR,
641 if pTemplate.is_null() {
642 return CKR_ARGUMENTS_BAD;
644 let count: usize = match ulCount.try_into() {
646 Err(_) => return CKR_ARGUMENTS_BAD,
648 let session: SessionHandle = match hSession.try_into() {
649 Ok(session) => session,
650 Err(_) => return CKR_SESSION_HANDLE_INVALID,
653 let raw_attrs: &[CK_ATTRIBUTE] = unsafe { slice::from_raw_parts_mut(pTemplate, count) };
655 let mut query: Vec<(CK_ATTRIBUTE_TYPE, &[u8])> = Vec::with_capacity(raw_attrs.len());
656 for attr in raw_attrs {
657 match usize::try_from(attr.ulValueLen) {
658 Ok(len) => query.push((attr.type_, unsafe {
659 slice::from_raw_parts_mut(attr.pValue as *mut u8, len)
661 Err(_) => return CKR_ARGUMENTS_BAD,
665 match find_objects_init(session, &query) {
667 Err(PK11Error(e)) => e,
671 extern "C" fn C_FindObjects(
672 hSession: CK_SESSION_HANDLE,
673 phObject: CK_OBJECT_HANDLE_PTR,
674 ulMaxObjectCount: CK_ULONG,
675 pulObjectCount: CK_ULONG_PTR,
677 if phObject.is_null() || pulObjectCount.is_null() {
678 return CKR_ARGUMENTS_BAD;
680 let max_object_count: usize = match ulMaxObjectCount.try_into() {
681 Ok(max_object_count) => max_object_count,
682 Err(_) => return CKR_ARGUMENTS_BAD,
684 let session: SessionHandle = match hSession.try_into() {
685 Ok(session) => session,
686 Err(_) => return CKR_SESSION_HANDLE_INVALID,
688 let out: &mut [CK_OBJECT_HANDLE] =
689 unsafe { slice::from_raw_parts_mut(phObject, max_object_count) };
690 match find_objects(session, out) {
692 unsafe { *pulObjectCount = num_found as CK_ULONG };
695 Err(PK11Error(e)) => e,
699 extern "C" fn C_FindObjectsFinal(hSession: CK_SESSION_HANDLE) -> CK_RV {
700 let session: SessionHandle = match hSession.try_into() {
701 Ok(session) => session,
702 Err(_) => return CKR_SESSION_HANDLE_INVALID,
704 match find_objects_final(session) {
706 Err(PK11Error(e)) => e,
710 extern "C" fn C_EncryptInit(
711 _hSession: CK_SESSION_HANDLE,
712 _pMechanism: CK_MECHANISM_PTR,
713 _hKey: CK_OBJECT_HANDLE,
715 CKR_FUNCTION_NOT_SUPPORTED
718 extern "C" fn C_Encrypt(
719 _hSession: CK_SESSION_HANDLE,
721 _ulDataLen: CK_ULONG,
722 _pEncryptedData: CK_BYTE_PTR,
723 _pulEncryptedDataLen: CK_ULONG_PTR,
725 CKR_FUNCTION_NOT_SUPPORTED
728 extern "C" fn C_EncryptUpdate(
729 _hSession: CK_SESSION_HANDLE,
731 _ulPartLen: CK_ULONG,
732 _pEncryptedPart: CK_BYTE_PTR,
733 _pulEncryptedPartLen: CK_ULONG_PTR,
735 CKR_FUNCTION_NOT_SUPPORTED
738 extern "C" fn C_EncryptFinal(
739 _hSession: CK_SESSION_HANDLE,
740 _pLastEncryptedPart: CK_BYTE_PTR,
741 _pulLastEncryptedPartLen: CK_ULONG_PTR,
743 CKR_FUNCTION_NOT_SUPPORTED
746 extern "C" fn C_DecryptInit(
747 _hSession: CK_SESSION_HANDLE,
748 _pMechanism: CK_MECHANISM_PTR,
749 _hKey: CK_OBJECT_HANDLE,
751 CKR_FUNCTION_NOT_SUPPORTED
754 extern "C" fn C_Decrypt(
755 _hSession: CK_SESSION_HANDLE,
756 _pEncryptedData: CK_BYTE_PTR,
757 _ulEncryptedDataLen: CK_ULONG,
759 _pulDataLen: CK_ULONG_PTR,
761 CKR_FUNCTION_NOT_SUPPORTED
764 extern "C" fn C_DecryptUpdate(
765 _hSession: CK_SESSION_HANDLE,
766 _pEncryptedPart: CK_BYTE_PTR,
767 _ulEncryptedPartLen: CK_ULONG,
769 _pulPartLen: CK_ULONG_PTR,
771 CKR_FUNCTION_NOT_SUPPORTED
774 extern "C" fn C_DecryptFinal(
775 _hSession: CK_SESSION_HANDLE,
776 _pLastPart: CK_BYTE_PTR,
777 _pulLastPartLen: CK_ULONG_PTR,
779 CKR_FUNCTION_NOT_SUPPORTED
782 extern "C" fn C_DigestInit(_hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR) -> CK_RV {
783 CKR_FUNCTION_NOT_SUPPORTED
786 extern "C" fn C_Digest(
787 _hSession: CK_SESSION_HANDLE,
789 _ulDataLen: CK_ULONG,
790 _pDigest: CK_BYTE_PTR,
791 _pulDigestLen: CK_ULONG_PTR,
793 CKR_FUNCTION_NOT_SUPPORTED
796 extern "C" fn C_DigestUpdate(
797 _hSession: CK_SESSION_HANDLE,
799 _ulPartLen: CK_ULONG,
801 CKR_FUNCTION_NOT_SUPPORTED
804 extern "C" fn C_DigestKey(_hSession: CK_SESSION_HANDLE, _hKey: CK_OBJECT_HANDLE) -> CK_RV {
805 CKR_FUNCTION_NOT_SUPPORTED
808 extern "C" fn C_DigestFinal(
809 _hSession: CK_SESSION_HANDLE,
810 _pDigest: CK_BYTE_PTR,
811 _pulDigestLen: CK_ULONG_PTR,
813 CKR_FUNCTION_NOT_SUPPORTED
816 extern "C" fn C_SignInit(
817 _hSession: CK_SESSION_HANDLE,
818 _pMechanism: CK_MECHANISM_PTR,
819 _hKey: CK_OBJECT_HANDLE,
821 CKR_FUNCTION_NOT_SUPPORTED
824 extern "C" fn C_Sign(
825 _hSession: CK_SESSION_HANDLE,
827 _ulDataLen: CK_ULONG,
828 _pSignature: CK_BYTE_PTR,
829 _pulSignatureLen: CK_ULONG_PTR,
831 CKR_FUNCTION_NOT_SUPPORTED
834 extern "C" fn C_SignUpdate(
835 _hSession: CK_SESSION_HANDLE,
837 _ulPartLen: CK_ULONG,
839 CKR_FUNCTION_NOT_SUPPORTED
842 extern "C" fn C_SignFinal(
843 _hSession: CK_SESSION_HANDLE,
844 _pSignature: CK_BYTE_PTR,
845 _pulSignatureLen: CK_ULONG_PTR,
847 CKR_FUNCTION_NOT_SUPPORTED
850 extern "C" fn C_SignRecoverInit(
851 _hSession: CK_SESSION_HANDLE,
852 _pMechanism: CK_MECHANISM_PTR,
853 _hKey: CK_OBJECT_HANDLE,
855 CKR_FUNCTION_NOT_SUPPORTED
858 extern "C" fn C_SignRecover(
859 _hSession: CK_SESSION_HANDLE,
861 _ulDataLen: CK_ULONG,
862 _pSignature: CK_BYTE_PTR,
863 _pulSignatureLen: CK_ULONG_PTR,
865 CKR_FUNCTION_NOT_SUPPORTED
868 extern "C" fn C_VerifyInit(
869 _hSession: CK_SESSION_HANDLE,
870 _pMechanism: CK_MECHANISM_PTR,
871 _hKey: CK_OBJECT_HANDLE,
873 CKR_FUNCTION_NOT_SUPPORTED
876 extern "C" fn C_Verify(
877 _hSession: CK_SESSION_HANDLE,
879 _ulDataLen: CK_ULONG,
880 _pSignature: CK_BYTE_PTR,
881 _ulSignatureLen: CK_ULONG,
883 CKR_FUNCTION_NOT_SUPPORTED
886 extern "C" fn C_VerifyUpdate(
887 _hSession: CK_SESSION_HANDLE,
889 _ulPartLen: CK_ULONG,
891 CKR_FUNCTION_NOT_SUPPORTED
894 extern "C" fn C_VerifyFinal(
895 _hSession: CK_SESSION_HANDLE,
896 _pSignature: CK_BYTE_PTR,
897 _ulSignatureLen: CK_ULONG,
899 CKR_FUNCTION_NOT_SUPPORTED
902 extern "C" fn C_VerifyRecoverInit(
903 _hSession: CK_SESSION_HANDLE,
904 _pMechanism: CK_MECHANISM_PTR,
905 _hKey: CK_OBJECT_HANDLE,
907 CKR_FUNCTION_NOT_SUPPORTED
910 extern "C" fn C_VerifyRecover(
911 _hSession: CK_SESSION_HANDLE,
912 _pSignature: CK_BYTE_PTR,
913 _ulSignatureLen: CK_ULONG,
915 _pulDataLen: CK_ULONG_PTR,
917 CKR_FUNCTION_NOT_SUPPORTED
920 extern "C" fn C_DigestEncryptUpdate(
921 _hSession: CK_SESSION_HANDLE,
923 _ulPartLen: CK_ULONG,
924 _pEncryptedPart: CK_BYTE_PTR,
925 _pulEncryptedPartLen: CK_ULONG_PTR,
927 CKR_FUNCTION_NOT_SUPPORTED
930 extern "C" fn C_DecryptDigestUpdate(
931 _hSession: CK_SESSION_HANDLE,
932 _pEncryptedPart: CK_BYTE_PTR,
933 _ulEncryptedPartLen: CK_ULONG,
935 _pulPartLen: CK_ULONG_PTR,
937 CKR_FUNCTION_NOT_SUPPORTED
940 extern "C" fn C_SignEncryptUpdate(
941 _hSession: CK_SESSION_HANDLE,
943 _ulPartLen: CK_ULONG,
944 _pEncryptedPart: CK_BYTE_PTR,
945 _pulEncryptedPartLen: CK_ULONG_PTR,
947 CKR_FUNCTION_NOT_SUPPORTED
950 extern "C" fn C_DecryptVerifyUpdate(
951 _hSession: CK_SESSION_HANDLE,
952 _pEncryptedPart: CK_BYTE_PTR,
953 _ulEncryptedPartLen: CK_ULONG,
955 _pulPartLen: CK_ULONG_PTR,
957 CKR_FUNCTION_NOT_SUPPORTED
960 extern "C" fn C_GenerateKey(
961 _hSession: CK_SESSION_HANDLE,
962 _pMechanism: CK_MECHANISM_PTR,
963 _pTemplate: CK_ATTRIBUTE_PTR,
965 _phKey: CK_OBJECT_HANDLE_PTR,
967 CKR_FUNCTION_NOT_SUPPORTED
970 extern "C" fn C_GenerateKeyPair(
971 _hSession: CK_SESSION_HANDLE,
972 _pMechanism: CK_MECHANISM_PTR,
973 _pPublicKeyTemplate: CK_ATTRIBUTE_PTR,
974 _ulPublicKeyAttributeCount: CK_ULONG,
975 _pPrivateKeyTemplate: CK_ATTRIBUTE_PTR,
976 _ulPrivateKeyAttributeCount: CK_ULONG,
977 _phPublicKey: CK_OBJECT_HANDLE_PTR,
978 _phPrivateKey: CK_OBJECT_HANDLE_PTR,
980 CKR_FUNCTION_NOT_SUPPORTED
983 extern "C" fn C_WrapKey(
984 _hSession: CK_SESSION_HANDLE,
985 _pMechanism: CK_MECHANISM_PTR,
986 _hWrappingKey: CK_OBJECT_HANDLE,
987 _hKey: CK_OBJECT_HANDLE,
988 _pWrappedKey: CK_BYTE_PTR,
989 _pulWrappedKeyLen: CK_ULONG_PTR,
991 CKR_FUNCTION_NOT_SUPPORTED
994 extern "C" fn C_UnwrapKey(
995 _hSession: CK_SESSION_HANDLE,
996 _pMechanism: CK_MECHANISM_PTR,
997 _hUnwrappingKey: CK_OBJECT_HANDLE,
998 _pWrappedKey: CK_BYTE_PTR,
999 _ulWrappedKeyLen: CK_ULONG,
1000 _pTemplate: CK_ATTRIBUTE_PTR,
1001 _ulAttributeCount: CK_ULONG,
1002 _phKey: CK_OBJECT_HANDLE_PTR,
1004 CKR_FUNCTION_NOT_SUPPORTED
1007 extern "C" fn C_DeriveKey(
1008 _hSession: CK_SESSION_HANDLE,
1009 _pMechanism: CK_MECHANISM_PTR,
1010 _hBaseKey: CK_OBJECT_HANDLE,
1011 _pTemplate: CK_ATTRIBUTE_PTR,
1012 _ulAttributeCount: CK_ULONG,
1013 _phKey: CK_OBJECT_HANDLE_PTR,
1015 CKR_FUNCTION_NOT_SUPPORTED
1018 extern "C" fn C_SeedRandom(
1019 _hSession: CK_SESSION_HANDLE,
1020 _pSeed: CK_BYTE_PTR,
1021 _ulSeedLen: CK_ULONG,
1023 CKR_FUNCTION_NOT_SUPPORTED
1026 extern "C" fn C_GenerateRandom(
1027 _hSession: CK_SESSION_HANDLE,
1028 _RandomData: CK_BYTE_PTR,
1029 _ulRandomLen: CK_ULONG,
1031 CKR_FUNCTION_NOT_SUPPORTED
1034 extern "C" fn C_GetFunctionStatus(_hSession: CK_SESSION_HANDLE) -> CK_RV {
1035 CKR_FUNCTION_NOT_SUPPORTED
1038 extern "C" fn C_CancelFunction(_hSession: CK_SESSION_HANDLE) -> CK_RV {
1039 CKR_FUNCTION_NOT_SUPPORTED
1042 extern "C" fn C_WaitForSlotEvent(
1044 _pSlot: CK_SLOT_ID_PTR,
1045 _pRserved: CK_VOID_PTR,
1047 CKR_FUNCTION_NOT_SUPPORTED
1050 pub static FUNCTION_LIST: CK_FUNCTION_LIST = CK_FUNCTION_LIST {
1051 version: CRYPTOKI_VERSION,
1052 C_Initialize: Some(C_Initialize),
1053 C_Finalize: Some(C_Finalize),
1054 C_GetInfo: Some(C_GetInfo),
1055 C_GetFunctionList: None,
1056 C_GetSlotList: Some(C_GetSlotList),
1057 C_GetSlotInfo: Some(C_GetSlotInfo),
1058 C_GetTokenInfo: Some(C_GetTokenInfo),
1059 C_GetMechanismList: Some(C_GetMechanismList),
1060 C_GetMechanismInfo: Some(C_GetMechanismInfo),
1061 C_InitToken: Some(C_InitToken),
1062 C_InitPIN: Some(C_InitPIN),
1063 C_SetPIN: Some(C_SetPIN),
1064 C_OpenSession: Some(C_OpenSession),
1065 C_CloseSession: Some(C_CloseSession),
1066 C_CloseAllSessions: Some(C_CloseAllSessions),
1067 C_GetSessionInfo: Some(C_GetSessionInfo),
1068 C_GetOperationState: Some(C_GetOperationState),
1069 C_SetOperationState: Some(C_SetOperationState),
1070 C_Login: Some(C_Login),
1071 C_Logout: Some(C_Logout),
1072 C_CreateObject: Some(C_CreateObject),
1073 C_CopyObject: Some(C_CopyObject),
1074 C_DestroyObject: Some(C_DestroyObject),
1075 C_GetObjectSize: Some(C_GetObjectSize),
1076 C_GetAttributeValue: Some(C_GetAttributeValue),
1077 C_SetAttributeValue: Some(C_SetAttributeValue),
1078 C_FindObjectsInit: Some(C_FindObjectsInit),
1079 C_FindObjects: Some(C_FindObjects),
1080 C_FindObjectsFinal: Some(C_FindObjectsFinal),
1081 C_EncryptInit: Some(C_EncryptInit),
1082 C_Encrypt: Some(C_Encrypt),
1083 C_EncryptUpdate: Some(C_EncryptUpdate),
1084 C_EncryptFinal: Some(C_EncryptFinal),
1085 C_DecryptInit: Some(C_DecryptInit),
1086 C_Decrypt: Some(C_Decrypt),
1087 C_DecryptUpdate: Some(C_DecryptUpdate),
1088 C_DecryptFinal: Some(C_DecryptFinal),
1089 C_DigestInit: Some(C_DigestInit),
1090 C_Digest: Some(C_Digest),
1091 C_DigestUpdate: Some(C_DigestUpdate),
1092 C_DigestKey: Some(C_DigestKey),
1093 C_DigestFinal: Some(C_DigestFinal),
1094 C_SignInit: Some(C_SignInit),
1095 C_Sign: Some(C_Sign),
1096 C_SignUpdate: Some(C_SignUpdate),
1097 C_SignFinal: Some(C_SignFinal),
1098 C_SignRecoverInit: Some(C_SignRecoverInit),
1099 C_SignRecover: Some(C_SignRecover),
1100 C_VerifyInit: Some(C_VerifyInit),
1101 C_Verify: Some(C_Verify),
1102 C_VerifyUpdate: Some(C_VerifyUpdate),
1103 C_VerifyFinal: Some(C_VerifyFinal),
1104 C_VerifyRecoverInit: Some(C_VerifyRecoverInit),
1105 C_VerifyRecover: Some(C_VerifyRecover),
1106 C_DigestEncryptUpdate: Some(C_DigestEncryptUpdate),
1107 C_DecryptDigestUpdate: Some(C_DecryptDigestUpdate),
1108 C_SignEncryptUpdate: Some(C_SignEncryptUpdate),
1109 C_DecryptVerifyUpdate: Some(C_DecryptVerifyUpdate),
1110 C_GenerateKey: Some(C_GenerateKey),
1111 C_GenerateKeyPair: Some(C_GenerateKeyPair),
1112 C_WrapKey: Some(C_WrapKey),
1113 C_UnwrapKey: Some(C_UnwrapKey),
1114 C_DeriveKey: Some(C_DeriveKey),
1115 C_SeedRandom: Some(C_SeedRandom),
1116 C_GenerateRandom: Some(C_GenerateRandom),
1117 C_GetFunctionStatus: Some(C_GetFunctionStatus),
1118 C_CancelFunction: Some(C_CancelFunction),
1119 C_WaitForSlotEvent: Some(C_WaitForSlotEvent),
1123 pub unsafe fn BUILTINSC_GetFunctionList(ppFunctionList: CK_FUNCTION_LIST_PTR_PTR) -> CK_RV {
1124 if ppFunctionList.is_null() {
1125 return CKR_ARGUMENTS_BAD;
1127 // CK_FUNCTION_LIST_PTR is a *mut CK_FUNCTION_LIST, but as per the
1128 // specification, the caller must treat it as *const CK_FUNCTION_LIST.
1129 *ppFunctionList = std::ptr::addr_of!(FUNCTION_LIST) as CK_FUNCTION_LIST_PTR;
1135 use crate::certdata::*;
1136 use crate::internal::*;
1137 use crate::pkcs11::*;
1141 // We need to run tests serially because of C_Initialize / C_Finalize calls.
1143 test_c_get_function_list();
1144 test_c_get_attribute();
1148 let query = &[(CKA_CLASS, CKO_CERTIFICATE_BYTES)];
1149 initialize().expect("initialize should not fail.");
1150 let hSession = open_session().expect("open_session should not fail.");
1151 let count = find_objects_init(hSession, query).expect("find_objects_init should not fail.");
1152 assert_eq!(count, BUILTINS.len());
1153 let mut results: [CK_OBJECT_HANDLE; 10] = [0; 10];
1155 find_objects(hSession, &mut results).expect("find_objects_init should not fail.");
1156 assert_eq!(n_read, 10);
1157 finalize().expect("finalize should not fail.");
1160 fn test_c_get_function_list() {
1161 let c_null = 0 as *mut std::ffi::c_void;
1162 let mut pFunctionList: CK_FUNCTION_LIST_PTR = c_null as CK_FUNCTION_LIST_PTR;
1163 let rv = unsafe { crate::pkcs11::BUILTINSC_GetFunctionList(&mut pFunctionList) };
1164 assert_eq!(CKR_OK, rv);
1165 if let Some(pC_Initialize) = unsafe { (*pFunctionList).C_Initialize } {
1166 let rv = unsafe { pC_Initialize(c_null) };
1167 assert_eq!(CKR_OK, rv);
1172 if let Some(pC_Finalize) = unsafe { (*pFunctionList).C_Finalize } {
1173 let rv = unsafe { pC_Finalize(c_null) };
1174 assert_eq!(CKR_OK, rv);
1180 fn test_c_get_attribute() {
1181 let c_null = 0 as *mut std::ffi::c_void;
1182 let template: &mut [CK_ATTRIBUTE] = &mut [CK_ATTRIBUTE {
1187 let template_ptr = &mut template[0] as CK_ATTRIBUTE_PTR;
1188 let object: CK_OBJECT_HANDLE = 2;
1189 let mut session: CK_SESSION_HANDLE = 0;
1190 assert_eq!(CKR_OK, C_Initialize(c_null));
1198 &mut session as *mut CK_SESSION_HANDLE
1203 C_GetAttributeValue(session, object, template_ptr, 1)
1205 let len = template[0].ulValueLen as usize;
1206 assert_eq!(len, BUILTINS[0].der_name.len());
1208 let value: &mut [u8] = &mut vec![0; 1];
1209 let value_ptr: *mut u8 = &mut value[0] as *mut u8;
1210 template[0].pValue = value_ptr as *mut std::ffi::c_void;
1211 template[0].ulValueLen = 1;
1213 CKR_BUFFER_TOO_SMALL,
1214 C_GetAttributeValue(session, object, template_ptr, 1)
1216 assert_eq!(template[0].ulValueLen, CK_UNAVAILABLE_INFORMATION);
1218 let value: &mut [u8] = &mut vec![0; len];
1219 let value_ptr: *mut u8 = &mut value[0] as *mut u8;
1220 template[0].pValue = value_ptr as *mut std::ffi::c_void;
1221 template[0].ulValueLen = len as CK_ULONG;
1224 C_GetAttributeValue(session, object, template_ptr, 1)
1226 assert_eq!(value, BUILTINS[0].der_name);
1227 assert_eq!(CKR_OK, C_Finalize(c_null));