pkcs11.rs (37112B)
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/. */ 5 6 #![allow(non_snake_case)] 7 8 use pkcs11_bindings::*; 9 use std::slice; 10 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}; 15 16 use crate::internal::{get_attribute, search}; 17 use crate::internal::{ObjectHandle, Query, SearchResult}; 18 19 use crate::version::*; 20 21 const BUILTINS_VERSION: CK_VERSION = CK_VERSION { 22 major: NSS_BUILTINS_LIBRARY_VERSION_MAJOR, 23 minor: NSS_BUILTINS_LIBRARY_VERSION_MINOR, 24 }; 25 26 const FIRMWARE_VERSION: CK_VERSION = CK_VERSION { 27 major: NSS_BUILTINS_FIRMWARE_VERSION_MAJOR, 28 minor: NSS_BUILTINS_FIRMWARE_VERSION_MINOR, 29 }; 30 31 const CRYPTOKI_VERSION: CK_VERSION = CK_VERSION { 32 major: NSS_BUILTINS_CRYPTOKI_VERSION_MAJOR, 33 minor: NSS_BUILTINS_CRYPTOKI_VERSION_MINOR, 34 }; 35 const HARDWARE_VERSION: CK_VERSION = CK_VERSION { 36 major: NSS_BUILTINS_HARDWARE_VERSION_MAJOR, 37 minor: NSS_BUILTINS_HARDWARE_VERSION_MINOR, 38 }; 39 40 const MANUFACTURER_ID_BYTES: &[u8; 32] = b"Mozilla Foundation "; 41 const LIBRARY_DESCRIPTION_BYTES: &[u8; 32] = b"NSS Builtin Object Cryptoki Modu"; 42 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 "; 47 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" "; 52 53 #[derive(Debug)] 54 struct PK11Error(CK_RV); 55 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. 59 // 60 // We start the counter at 1 since PKCS#11 reserves 0 to signal an invalid handle 61 // 62 type SessionHandle = u32; 63 static NEXT_HANDLE: AtomicU32 = AtomicU32::new(1); 64 65 // The token needs to keep track of which sessions are open. 66 // 67 type SessionSet = BTreeSet<SessionHandle>; 68 static OPEN_SESSIONS: Mutex<Option<SessionSet>> = Mutex::new(None); 69 70 // Helper functions for accessing OPEN_SESSIONS 71 // 72 type SessionSetGuard = MutexGuard<'static, Option<SessionSet>>; 73 74 fn get_open_sessions_guard() -> Result<SessionSetGuard, PK11Error> { 75 OPEN_SESSIONS 76 .lock() 77 .map_err(|_| PK11Error(CKR_DEVICE_ERROR)) 78 } 79 80 fn get_open_sessions(guard: &mut SessionSetGuard) -> Result<&mut SessionSet, PK11Error> { 81 let sessions = guard 82 .as_mut() 83 .ok_or(PK11Error(CKR_CRYPTOKI_NOT_INITIALIZED))?; 84 Ok(sessions) 85 } 86 87 // The token needs to cache search results until the client reads them or closes the session. 88 // 89 type SearchCache = BTreeMap<SessionHandle, SearchResult>; 90 static SEARCHES: Mutex<Option<SearchCache>> = Mutex::new(None); 91 92 // Helper functions for accessing SEARCHES 93 // 94 type SearchCacheGuard = MutexGuard<'static, Option<SearchCache>>; 95 96 fn get_search_cache_guard() -> Result<SearchCacheGuard, PK11Error> { 97 SEARCHES.lock().map_err(|_| PK11Error(CKR_DEVICE_ERROR)) 98 } 99 100 fn get_search_cache(guard: &mut SearchCacheGuard) -> Result<&mut SearchCache, PK11Error> { 101 let searches = guard 102 .as_mut() 103 .ok_or(PK11Error(CKR_CRYPTOKI_NOT_INITIALIZED))?; 104 Ok(searches) 105 } 106 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) { 111 return Ok(()); 112 } 113 if handle < NEXT_HANDLE.load(Ordering::SeqCst) { 114 Err(PK11Error(CKR_SESSION_CLOSED)) 115 } else { 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)) 119 } 120 } 121 122 // The internal implementation of C_Initialize 123 fn initialize() -> Result<(), PK11Error> { 124 { 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)); 128 } 129 *search_cache_guard = Some(SearchCache::default()); 130 } 131 132 { 133 let mut session_guard = get_open_sessions_guard()?; 134 if (*session_guard).is_some() { 135 return Err(PK11Error(CKR_CRYPTOKI_ALREADY_INITIALIZED)); 136 } 137 *session_guard = Some(SessionSet::default()); 138 } 139 140 Ok(()) 141 } 142 143 // The internal implementation of C_Finalize 144 fn finalize() -> Result<(), PK11Error> { 145 { 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)?; 150 *guard = None; 151 } 152 153 let mut guard = get_open_sessions_guard()?; 154 let _ = get_open_sessions(&mut guard)?; 155 *guard = None; 156 157 Ok(()) 158 } 159 160 // Internal implementation of C_OpenSession 161 fn open_session() -> Result<SessionHandle, PK11Error> { 162 let mut handle = NEXT_HANDLE.fetch_add(1, Ordering::SeqCst); 163 if handle == 0 { 164 // skip handle 0 if the addition wraps 165 handle = NEXT_HANDLE.fetch_add(1, Ordering::SeqCst); 166 } 167 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); 174 } 175 176 Ok(handle) 177 } 178 179 // Internal implementation of C_CloseSession 180 fn close_session(session: SessionHandle) -> Result<(), PK11Error> { 181 { 182 let mut guard = get_search_cache_guard()?; 183 let searches = get_search_cache(&mut guard)?; 184 searches.remove(&session); 185 } 186 187 { 188 let mut guard = get_open_sessions_guard()?; 189 let sessions = get_open_sessions(&mut guard)?; 190 if sessions.remove(&session) { 191 Ok(()) 192 } else if session < NEXT_HANDLE.load(Ordering::SeqCst) { 193 Err(PK11Error(CKR_SESSION_CLOSED)) 194 } else { 195 Err(PK11Error(CKR_SESSION_HANDLE_INVALID)) 196 } 197 } 198 } 199 200 // Internal implementation of C_CloseAllSessions 201 fn close_all_sessions() -> Result<(), PK11Error> { 202 { 203 let mut guard = get_search_cache_guard()?; 204 let searches = get_search_cache(&mut guard)?; 205 searches.clear(); 206 } 207 208 { 209 let mut guard = get_open_sessions_guard()?; 210 let sessions = get_open_sessions(&mut guard)?; 211 sessions.clear(); 212 } 213 214 Ok(()) 215 } 216 217 // Internal implementation of C_FindObjectsInit 218 fn find_objects_init(session: SessionHandle, query: &Query) -> Result<usize, PK11Error> { 219 validate_session(session)?; 220 221 let results = search(query); 222 let count = results.len(); 223 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) => { 229 v.insert(results); 230 Ok(count) 231 } 232 } 233 } 234 235 // Internal implementation of C_FindObjects 236 fn find_objects(session: SessionHandle, out: &mut [CK_OBJECT_HANDLE]) -> Result<usize, PK11Error> { 237 validate_session(session)?; 238 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), 246 } 247 } 248 Ok(out.len()) 249 } else { 250 Ok(0) 251 } 252 } 253 254 // Internal implementation of C_FindObjectsFinal 255 fn find_objects_final(session: SessionHandle) -> Result<(), PK11Error> { 256 validate_session(session)?; 257 258 let mut guard = get_search_cache_guard()?; 259 let searches = get_search_cache(&mut guard)?; 260 searches.remove(&session); 261 Ok(()) 262 } 263 264 extern "C" fn C_Initialize(_pInitArgs: CK_VOID_PTR) -> CK_RV { 265 match initialize() { 266 Ok(_) => CKR_OK, 267 Err(PK11Error(e)) => e, 268 } 269 } 270 271 extern "C" fn C_Finalize(pReserved: CK_VOID_PTR) -> CK_RV { 272 if !pReserved.is_null() { 273 return CKR_ARGUMENTS_BAD; 274 } 275 match finalize() { 276 Ok(_) => CKR_OK, 277 Err(PK11Error(e)) => e, 278 } 279 } 280 281 extern "C" fn C_GetInfo(pInfo: CK_INFO_PTR) -> CK_RV { 282 if pInfo.is_null() { 283 return CKR_ARGUMENTS_BAD; 284 } 285 unsafe { 286 *pInfo = CK_INFO { 287 cryptokiVersion: CRYPTOKI_VERSION, 288 manufacturerID: *MANUFACTURER_ID_BYTES, 289 flags: 0, 290 libraryDescription: *LIBRARY_DESCRIPTION_BYTES, 291 libraryVersion: BUILTINS_VERSION, 292 }; 293 } 294 CKR_OK 295 } 296 297 extern "C" fn C_GetSlotList( 298 _tokenPresent: CK_BBOOL, 299 pSlotList: CK_SLOT_ID_PTR, 300 pulCount: CK_ULONG_PTR, 301 ) -> CK_RV { 302 if pulCount.is_null() { 303 return CKR_ARGUMENTS_BAD; 304 } 305 if !pSlotList.is_null() { 306 if unsafe { *pulCount } < SLOT_COUNT { 307 return CKR_BUFFER_TOO_SMALL; 308 } 309 unsafe { 310 *pSlotList = SLOT_ID_ROOTS; 311 } 312 } 313 unsafe { 314 *pulCount = SLOT_COUNT; 315 } 316 CKR_OK 317 } 318 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; 322 } 323 unsafe { 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, 330 }; 331 } 332 CKR_OK 333 } 334 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; 338 } 339 unsafe { 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, 347 ulSessionCount: 0, 348 ulMaxRwSessionCount: CK_UNAVAILABLE_INFORMATION, 349 ulRwSessionCount: 0, 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, 359 }; 360 } 361 CKR_OK 362 } 363 364 extern "C" fn C_GetMechanismList( 365 slotID: CK_SLOT_ID, 366 _pMechanismList: CK_MECHANISM_TYPE_PTR, 367 pulCount: CK_ULONG_PTR, 368 ) -> CK_RV { 369 if slotID != SLOT_ID_ROOTS || pulCount.is_null() { 370 return CKR_ARGUMENTS_BAD; 371 } 372 unsafe { 373 *pulCount = 0; 374 } 375 CKR_OK 376 } 377 378 extern "C" fn C_GetMechanismInfo( 379 _slotID: CK_SLOT_ID, 380 _type: CK_MECHANISM_TYPE, 381 _pInfo: CK_MECHANISM_INFO_PTR, 382 ) -> CK_RV { 383 CKR_FUNCTION_NOT_SUPPORTED 384 } 385 386 extern "C" fn C_InitToken( 387 _slotID: CK_SLOT_ID, 388 _pPin: CK_UTF8CHAR_PTR, 389 _ulPinLen: CK_ULONG, 390 _pLabel: CK_UTF8CHAR_PTR, 391 ) -> CK_RV { 392 CKR_FUNCTION_NOT_SUPPORTED 393 } 394 395 extern "C" fn C_InitPIN( 396 _hSession: CK_SESSION_HANDLE, 397 _pPin: CK_UTF8CHAR_PTR, 398 _ulPinLen: CK_ULONG, 399 ) -> CK_RV { 400 CKR_FUNCTION_NOT_SUPPORTED 401 } 402 403 extern "C" fn C_SetPIN( 404 _hSession: CK_SESSION_HANDLE, 405 _pOldPin: CK_UTF8CHAR_PTR, 406 _ulOldLen: CK_ULONG, 407 _pNewPin: CK_UTF8CHAR_PTR, 408 _ulNewLen: CK_ULONG, 409 ) -> CK_RV { 410 CKR_FUNCTION_NOT_SUPPORTED 411 } 412 413 extern "C" fn C_OpenSession( 414 slotID: CK_SLOT_ID, 415 flags: CK_FLAGS, 416 _pApplication: CK_VOID_PTR, 417 _Notify: CK_NOTIFY, 418 phSession: CK_SESSION_HANDLE_PTR, 419 ) -> CK_RV { 420 if slotID != SLOT_ID_ROOTS || phSession.is_null() { 421 return CKR_ARGUMENTS_BAD; 422 } 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; 429 } 430 let session_id = match open_session() { 431 Ok(session_id) => session_id as CK_SESSION_HANDLE, 432 Err(PK11Error(e)) => return e, 433 }; 434 unsafe { *phSession = session_id }; 435 CKR_OK 436 } 437 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, 442 }; 443 match close_session(session) { 444 Ok(_) => CKR_OK, 445 Err(PK11Error(e)) => e, 446 } 447 } 448 449 extern "C" fn C_CloseAllSessions(slotID: CK_SLOT_ID) -> CK_RV { 450 if slotID != SLOT_ID_ROOTS { 451 return CKR_ARGUMENTS_BAD; 452 } 453 match close_all_sessions() { 454 Ok(_) => CKR_OK, 455 Err(PK11Error(e)) => e, 456 } 457 } 458 459 extern "C" fn C_GetSessionInfo(_hSession: CK_SESSION_HANDLE, _pInfo: CK_SESSION_INFO_PTR) -> CK_RV { 460 CKR_FUNCTION_NOT_SUPPORTED 461 } 462 463 extern "C" fn C_GetOperationState( 464 _hSession: CK_SESSION_HANDLE, 465 _pOperationState: CK_BYTE_PTR, 466 _pulOperationStateLen: CK_ULONG_PTR, 467 ) -> CK_RV { 468 CKR_FUNCTION_NOT_SUPPORTED 469 } 470 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, 477 ) -> CK_RV { 478 CKR_FUNCTION_NOT_SUPPORTED 479 } 480 481 extern "C" fn C_Login( 482 _hSession: CK_SESSION_HANDLE, 483 _userType: CK_USER_TYPE, 484 _pPin: CK_UTF8CHAR_PTR, 485 _ulPinLen: CK_ULONG, 486 ) -> CK_RV { 487 CKR_FUNCTION_NOT_SUPPORTED 488 } 489 490 extern "C" fn C_Logout(_hSession: CK_SESSION_HANDLE) -> CK_RV { 491 CKR_OK 492 } 493 494 extern "C" fn C_CreateObject( 495 _hSession: CK_SESSION_HANDLE, 496 _pTemplate: CK_ATTRIBUTE_PTR, 497 _ulCount: CK_ULONG, 498 _phObject: CK_OBJECT_HANDLE_PTR, 499 ) -> CK_RV { 500 CKR_FUNCTION_NOT_SUPPORTED 501 } 502 503 extern "C" fn C_CopyObject( 504 _hSession: CK_SESSION_HANDLE, 505 _hObject: CK_OBJECT_HANDLE, 506 _pTemplate: CK_ATTRIBUTE_PTR, 507 _ulCount: CK_ULONG, 508 _phNewObject: CK_OBJECT_HANDLE_PTR, 509 ) -> CK_RV { 510 CKR_FUNCTION_NOT_SUPPORTED 511 } 512 513 extern "C" fn C_DestroyObject(_hSession: CK_SESSION_HANDLE, _hObject: CK_OBJECT_HANDLE) -> CK_RV { 514 CKR_FUNCTION_NOT_SUPPORTED 515 } 516 517 extern "C" fn C_GetObjectSize( 518 _hSession: CK_SESSION_HANDLE, 519 _hObject: CK_OBJECT_HANDLE, 520 _pulSize: CK_ULONG_PTR, 521 ) -> CK_RV { 522 CKR_FUNCTION_NOT_SUPPORTED 523 } 524 525 extern "C" fn C_GetAttributeValue( 526 _hSession: CK_SESSION_HANDLE, 527 hObject: CK_OBJECT_HANDLE, 528 pTemplate: CK_ATTRIBUTE_PTR, 529 ulCount: CK_ULONG, 530 ) -> CK_RV { 531 if pTemplate.is_null() { 532 return CKR_ARGUMENTS_BAD; 533 } 534 535 let count: usize = match ulCount.try_into() { 536 Ok(count) => count, 537 Err(_) => return CKR_ARGUMENTS_BAD, 538 }; 539 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. 543 // 544 //let session: SessionHandle = match hSession.try_into() { 545 // Ok(session) => session, 546 // Err(_) => return CKR_SESSION_HANDLE_INVALID, 547 //}; 548 // 549 //if let Err(PK11Error(e)) = validate_session(session) { 550 // return e; 551 //} 552 553 let handle: ObjectHandle = match hObject.try_into() { 554 Ok(handle) => handle, 555 Err(_) => return CKR_OBJECT_HANDLE_INVALID, 556 }; 557 558 let attrs: &mut [CK_ATTRIBUTE] = unsafe { slice::from_raw_parts_mut(pTemplate, count) }; 559 560 let mut rv = CKR_OK; 561 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) { 565 None => { 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 572 } 573 Some(attr) => { 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 578 } 579 } 580 } 581 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, 587 }; 588 attr.ulValueLen = match get_attribute(attr.type_, &handle) { 589 None => { 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 596 } 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. 603 let dst: &mut [u8] = 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 607 } 608 _ => { 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 614 } 615 }; 616 } 617 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. 624 rv 625 } 626 627 extern "C" fn C_SetAttributeValue( 628 _hSession: CK_SESSION_HANDLE, 629 _hObject: CK_OBJECT_HANDLE, 630 _pTemplate: CK_ATTRIBUTE_PTR, 631 _ulCount: CK_ULONG, 632 ) -> CK_RV { 633 CKR_FUNCTION_NOT_SUPPORTED 634 } 635 636 extern "C" fn C_FindObjectsInit( 637 hSession: CK_SESSION_HANDLE, 638 pTemplate: CK_ATTRIBUTE_PTR, 639 ulCount: CK_ULONG, 640 ) -> CK_RV { 641 if pTemplate.is_null() { 642 return CKR_ARGUMENTS_BAD; 643 } 644 let count: usize = match ulCount.try_into() { 645 Ok(count) => count, 646 Err(_) => return CKR_ARGUMENTS_BAD, 647 }; 648 let session: SessionHandle = match hSession.try_into() { 649 Ok(session) => session, 650 Err(_) => return CKR_SESSION_HANDLE_INVALID, 651 }; 652 653 let raw_attrs: &[CK_ATTRIBUTE] = unsafe { slice::from_raw_parts_mut(pTemplate, count) }; 654 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) 660 })), 661 Err(_) => return CKR_ARGUMENTS_BAD, 662 } 663 } 664 665 match find_objects_init(session, &query) { 666 Ok(_) => CKR_OK, 667 Err(PK11Error(e)) => e, 668 } 669 } 670 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, 676 ) -> CK_RV { 677 if phObject.is_null() || pulObjectCount.is_null() { 678 return CKR_ARGUMENTS_BAD; 679 } 680 let max_object_count: usize = match ulMaxObjectCount.try_into() { 681 Ok(max_object_count) => max_object_count, 682 Err(_) => return CKR_ARGUMENTS_BAD, 683 }; 684 let session: SessionHandle = match hSession.try_into() { 685 Ok(session) => session, 686 Err(_) => return CKR_SESSION_HANDLE_INVALID, 687 }; 688 let out: &mut [CK_OBJECT_HANDLE] = 689 unsafe { slice::from_raw_parts_mut(phObject, max_object_count) }; 690 match find_objects(session, out) { 691 Ok(num_found) => { 692 unsafe { *pulObjectCount = num_found as CK_ULONG }; 693 CKR_OK 694 } 695 Err(PK11Error(e)) => e, 696 } 697 } 698 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, 703 }; 704 match find_objects_final(session) { 705 Ok(()) => CKR_OK, 706 Err(PK11Error(e)) => e, 707 } 708 } 709 710 extern "C" fn C_EncryptInit( 711 _hSession: CK_SESSION_HANDLE, 712 _pMechanism: CK_MECHANISM_PTR, 713 _hKey: CK_OBJECT_HANDLE, 714 ) -> CK_RV { 715 CKR_FUNCTION_NOT_SUPPORTED 716 } 717 718 extern "C" fn C_Encrypt( 719 _hSession: CK_SESSION_HANDLE, 720 _pData: CK_BYTE_PTR, 721 _ulDataLen: CK_ULONG, 722 _pEncryptedData: CK_BYTE_PTR, 723 _pulEncryptedDataLen: CK_ULONG_PTR, 724 ) -> CK_RV { 725 CKR_FUNCTION_NOT_SUPPORTED 726 } 727 728 extern "C" fn C_EncryptUpdate( 729 _hSession: CK_SESSION_HANDLE, 730 _pPart: CK_BYTE_PTR, 731 _ulPartLen: CK_ULONG, 732 _pEncryptedPart: CK_BYTE_PTR, 733 _pulEncryptedPartLen: CK_ULONG_PTR, 734 ) -> CK_RV { 735 CKR_FUNCTION_NOT_SUPPORTED 736 } 737 738 extern "C" fn C_EncryptFinal( 739 _hSession: CK_SESSION_HANDLE, 740 _pLastEncryptedPart: CK_BYTE_PTR, 741 _pulLastEncryptedPartLen: CK_ULONG_PTR, 742 ) -> CK_RV { 743 CKR_FUNCTION_NOT_SUPPORTED 744 } 745 746 extern "C" fn C_DecryptInit( 747 _hSession: CK_SESSION_HANDLE, 748 _pMechanism: CK_MECHANISM_PTR, 749 _hKey: CK_OBJECT_HANDLE, 750 ) -> CK_RV { 751 CKR_FUNCTION_NOT_SUPPORTED 752 } 753 754 extern "C" fn C_Decrypt( 755 _hSession: CK_SESSION_HANDLE, 756 _pEncryptedData: CK_BYTE_PTR, 757 _ulEncryptedDataLen: CK_ULONG, 758 _pData: CK_BYTE_PTR, 759 _pulDataLen: CK_ULONG_PTR, 760 ) -> CK_RV { 761 CKR_FUNCTION_NOT_SUPPORTED 762 } 763 764 extern "C" fn C_DecryptUpdate( 765 _hSession: CK_SESSION_HANDLE, 766 _pEncryptedPart: CK_BYTE_PTR, 767 _ulEncryptedPartLen: CK_ULONG, 768 _pPart: CK_BYTE_PTR, 769 _pulPartLen: CK_ULONG_PTR, 770 ) -> CK_RV { 771 CKR_FUNCTION_NOT_SUPPORTED 772 } 773 774 extern "C" fn C_DecryptFinal( 775 _hSession: CK_SESSION_HANDLE, 776 _pLastPart: CK_BYTE_PTR, 777 _pulLastPartLen: CK_ULONG_PTR, 778 ) -> CK_RV { 779 CKR_FUNCTION_NOT_SUPPORTED 780 } 781 782 extern "C" fn C_DigestInit(_hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR) -> CK_RV { 783 CKR_FUNCTION_NOT_SUPPORTED 784 } 785 786 extern "C" fn C_Digest( 787 _hSession: CK_SESSION_HANDLE, 788 _pData: CK_BYTE_PTR, 789 _ulDataLen: CK_ULONG, 790 _pDigest: CK_BYTE_PTR, 791 _pulDigestLen: CK_ULONG_PTR, 792 ) -> CK_RV { 793 CKR_FUNCTION_NOT_SUPPORTED 794 } 795 796 extern "C" fn C_DigestUpdate( 797 _hSession: CK_SESSION_HANDLE, 798 _pPart: CK_BYTE_PTR, 799 _ulPartLen: CK_ULONG, 800 ) -> CK_RV { 801 CKR_FUNCTION_NOT_SUPPORTED 802 } 803 804 extern "C" fn C_DigestKey(_hSession: CK_SESSION_HANDLE, _hKey: CK_OBJECT_HANDLE) -> CK_RV { 805 CKR_FUNCTION_NOT_SUPPORTED 806 } 807 808 extern "C" fn C_DigestFinal( 809 _hSession: CK_SESSION_HANDLE, 810 _pDigest: CK_BYTE_PTR, 811 _pulDigestLen: CK_ULONG_PTR, 812 ) -> CK_RV { 813 CKR_FUNCTION_NOT_SUPPORTED 814 } 815 816 extern "C" fn C_SignInit( 817 _hSession: CK_SESSION_HANDLE, 818 _pMechanism: CK_MECHANISM_PTR, 819 _hKey: CK_OBJECT_HANDLE, 820 ) -> CK_RV { 821 CKR_FUNCTION_NOT_SUPPORTED 822 } 823 824 extern "C" fn C_Sign( 825 _hSession: CK_SESSION_HANDLE, 826 _pData: CK_BYTE_PTR, 827 _ulDataLen: CK_ULONG, 828 _pSignature: CK_BYTE_PTR, 829 _pulSignatureLen: CK_ULONG_PTR, 830 ) -> CK_RV { 831 CKR_FUNCTION_NOT_SUPPORTED 832 } 833 834 extern "C" fn C_SignUpdate( 835 _hSession: CK_SESSION_HANDLE, 836 _pPart: CK_BYTE_PTR, 837 _ulPartLen: CK_ULONG, 838 ) -> CK_RV { 839 CKR_FUNCTION_NOT_SUPPORTED 840 } 841 842 extern "C" fn C_SignFinal( 843 _hSession: CK_SESSION_HANDLE, 844 _pSignature: CK_BYTE_PTR, 845 _pulSignatureLen: CK_ULONG_PTR, 846 ) -> CK_RV { 847 CKR_FUNCTION_NOT_SUPPORTED 848 } 849 850 extern "C" fn C_SignRecoverInit( 851 _hSession: CK_SESSION_HANDLE, 852 _pMechanism: CK_MECHANISM_PTR, 853 _hKey: CK_OBJECT_HANDLE, 854 ) -> CK_RV { 855 CKR_FUNCTION_NOT_SUPPORTED 856 } 857 858 extern "C" fn C_SignRecover( 859 _hSession: CK_SESSION_HANDLE, 860 _pData: CK_BYTE_PTR, 861 _ulDataLen: CK_ULONG, 862 _pSignature: CK_BYTE_PTR, 863 _pulSignatureLen: CK_ULONG_PTR, 864 ) -> CK_RV { 865 CKR_FUNCTION_NOT_SUPPORTED 866 } 867 868 extern "C" fn C_VerifyInit( 869 _hSession: CK_SESSION_HANDLE, 870 _pMechanism: CK_MECHANISM_PTR, 871 _hKey: CK_OBJECT_HANDLE, 872 ) -> CK_RV { 873 CKR_FUNCTION_NOT_SUPPORTED 874 } 875 876 extern "C" fn C_Verify( 877 _hSession: CK_SESSION_HANDLE, 878 _pData: CK_BYTE_PTR, 879 _ulDataLen: CK_ULONG, 880 _pSignature: CK_BYTE_PTR, 881 _ulSignatureLen: CK_ULONG, 882 ) -> CK_RV { 883 CKR_FUNCTION_NOT_SUPPORTED 884 } 885 886 extern "C" fn C_VerifyUpdate( 887 _hSession: CK_SESSION_HANDLE, 888 _pPart: CK_BYTE_PTR, 889 _ulPartLen: CK_ULONG, 890 ) -> CK_RV { 891 CKR_FUNCTION_NOT_SUPPORTED 892 } 893 894 extern "C" fn C_VerifyFinal( 895 _hSession: CK_SESSION_HANDLE, 896 _pSignature: CK_BYTE_PTR, 897 _ulSignatureLen: CK_ULONG, 898 ) -> CK_RV { 899 CKR_FUNCTION_NOT_SUPPORTED 900 } 901 902 extern "C" fn C_VerifyRecoverInit( 903 _hSession: CK_SESSION_HANDLE, 904 _pMechanism: CK_MECHANISM_PTR, 905 _hKey: CK_OBJECT_HANDLE, 906 ) -> CK_RV { 907 CKR_FUNCTION_NOT_SUPPORTED 908 } 909 910 extern "C" fn C_VerifyRecover( 911 _hSession: CK_SESSION_HANDLE, 912 _pSignature: CK_BYTE_PTR, 913 _ulSignatureLen: CK_ULONG, 914 _pData: CK_BYTE_PTR, 915 _pulDataLen: CK_ULONG_PTR, 916 ) -> CK_RV { 917 CKR_FUNCTION_NOT_SUPPORTED 918 } 919 920 extern "C" fn C_DigestEncryptUpdate( 921 _hSession: CK_SESSION_HANDLE, 922 _pPart: CK_BYTE_PTR, 923 _ulPartLen: CK_ULONG, 924 _pEncryptedPart: CK_BYTE_PTR, 925 _pulEncryptedPartLen: CK_ULONG_PTR, 926 ) -> CK_RV { 927 CKR_FUNCTION_NOT_SUPPORTED 928 } 929 930 extern "C" fn C_DecryptDigestUpdate( 931 _hSession: CK_SESSION_HANDLE, 932 _pEncryptedPart: CK_BYTE_PTR, 933 _ulEncryptedPartLen: CK_ULONG, 934 _pPart: CK_BYTE_PTR, 935 _pulPartLen: CK_ULONG_PTR, 936 ) -> CK_RV { 937 CKR_FUNCTION_NOT_SUPPORTED 938 } 939 940 extern "C" fn C_SignEncryptUpdate( 941 _hSession: CK_SESSION_HANDLE, 942 _pPart: CK_BYTE_PTR, 943 _ulPartLen: CK_ULONG, 944 _pEncryptedPart: CK_BYTE_PTR, 945 _pulEncryptedPartLen: CK_ULONG_PTR, 946 ) -> CK_RV { 947 CKR_FUNCTION_NOT_SUPPORTED 948 } 949 950 extern "C" fn C_DecryptVerifyUpdate( 951 _hSession: CK_SESSION_HANDLE, 952 _pEncryptedPart: CK_BYTE_PTR, 953 _ulEncryptedPartLen: CK_ULONG, 954 _pPart: CK_BYTE_PTR, 955 _pulPartLen: CK_ULONG_PTR, 956 ) -> CK_RV { 957 CKR_FUNCTION_NOT_SUPPORTED 958 } 959 960 extern "C" fn C_GenerateKey( 961 _hSession: CK_SESSION_HANDLE, 962 _pMechanism: CK_MECHANISM_PTR, 963 _pTemplate: CK_ATTRIBUTE_PTR, 964 _ulCount: CK_ULONG, 965 _phKey: CK_OBJECT_HANDLE_PTR, 966 ) -> CK_RV { 967 CKR_FUNCTION_NOT_SUPPORTED 968 } 969 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, 979 ) -> CK_RV { 980 CKR_FUNCTION_NOT_SUPPORTED 981 } 982 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, 990 ) -> CK_RV { 991 CKR_FUNCTION_NOT_SUPPORTED 992 } 993 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, 1003 ) -> CK_RV { 1004 CKR_FUNCTION_NOT_SUPPORTED 1005 } 1006 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, 1014 ) -> CK_RV { 1015 CKR_FUNCTION_NOT_SUPPORTED 1016 } 1017 1018 extern "C" fn C_SeedRandom( 1019 _hSession: CK_SESSION_HANDLE, 1020 _pSeed: CK_BYTE_PTR, 1021 _ulSeedLen: CK_ULONG, 1022 ) -> CK_RV { 1023 CKR_FUNCTION_NOT_SUPPORTED 1024 } 1025 1026 extern "C" fn C_GenerateRandom( 1027 _hSession: CK_SESSION_HANDLE, 1028 _RandomData: CK_BYTE_PTR, 1029 _ulRandomLen: CK_ULONG, 1030 ) -> CK_RV { 1031 CKR_FUNCTION_NOT_SUPPORTED 1032 } 1033 1034 extern "C" fn C_GetFunctionStatus(_hSession: CK_SESSION_HANDLE) -> CK_RV { 1035 CKR_FUNCTION_NOT_SUPPORTED 1036 } 1037 1038 extern "C" fn C_CancelFunction(_hSession: CK_SESSION_HANDLE) -> CK_RV { 1039 CKR_FUNCTION_NOT_SUPPORTED 1040 } 1041 1042 extern "C" fn C_WaitForSlotEvent( 1043 _flags: CK_FLAGS, 1044 _pSlot: CK_SLOT_ID_PTR, 1045 _pRserved: CK_VOID_PTR, 1046 ) -> CK_RV { 1047 CKR_FUNCTION_NOT_SUPPORTED 1048 } 1049 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), 1120 }; 1121 1122 #[no_mangle] 1123 pub unsafe fn TRUST_ANCHORS_GetFunctionList(ppFunctionList: CK_FUNCTION_LIST_PTR_PTR) -> CK_RV { 1124 if ppFunctionList.is_null() { 1125 return CKR_ARGUMENTS_BAD; 1126 } 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; 1130 CKR_OK 1131 } 1132 1133 #[cfg(test)] 1134 mod pkcs11_tests { 1135 use crate::certdata::*; 1136 use crate::internal::*; 1137 use crate::pkcs11::*; 1138 1139 #[test] 1140 fn test_main() { 1141 // We need to run tests serially because of C_Initialize / C_Finalize calls. 1142 test_simple(); 1143 test_c_get_function_list(); 1144 test_c_get_attribute(); 1145 } 1146 1147 fn test_simple() { 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]; 1154 let n_read = 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."); 1158 } 1159 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::TRUST_ANCHORS_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); 1168 } else { 1169 assert!(false); 1170 } 1171 1172 if let Some(pC_Finalize) = unsafe { (*pFunctionList).C_Finalize } { 1173 let rv = unsafe { pC_Finalize(c_null) }; 1174 assert_eq!(CKR_OK, rv); 1175 } else { 1176 assert!(false); 1177 } 1178 } 1179 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 { 1183 type_: CKA_SUBJECT, 1184 pValue: c_null, 1185 ulValueLen: 0, 1186 }]; 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)); 1191 assert_eq!( 1192 CKR_OK, 1193 C_OpenSession( 1194 SLOT_ID_ROOTS, 1195 CKF_SERIAL_SESSION, 1196 c_null, 1197 None, 1198 &mut session as *mut CK_SESSION_HANDLE 1199 ) 1200 ); 1201 assert_eq!( 1202 CKR_OK, 1203 C_GetAttributeValue(session, object, template_ptr, 1) 1204 ); 1205 let len = template[0].ulValueLen as usize; 1206 assert_eq!(len, BUILTINS[0].der_name.len()); 1207 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; 1212 assert_eq!( 1213 CKR_BUFFER_TOO_SMALL, 1214 C_GetAttributeValue(session, object, template_ptr, 1) 1215 ); 1216 assert_eq!(template[0].ulValueLen, CK_UNAVAILABLE_INFORMATION); 1217 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; 1222 assert_eq!( 1223 CKR_OK, 1224 C_GetAttributeValue(session, object, template_ptr, 1) 1225 ); 1226 assert_eq!(value, BUILTINS[0].der_name); 1227 assert_eq!(CKR_OK, C_Finalize(c_null)); 1228 } 1229 }