lib.rs (8018B)
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 log::{debug, error, trace}; 9 use pkcs11_bindings::*; 10 use rsclientcerts::manager::{IsSearchingForClientCerts, Manager}; 11 use rsclientcerts::{ 12 declare_pkcs11_find_functions, declare_pkcs11_informational_functions, 13 declare_pkcs11_session_functions, declare_pkcs11_sign_functions, 14 declare_unsupported_pkcs11_functions, log_with_thread_id, 15 }; 16 use std::sync::Mutex; 17 18 mod backend; 19 20 use backend::Backend; 21 22 static MANAGER: Mutex<Option<Manager<Backend, AlwaysSearchingForClientCerts>>> = Mutex::new(None); 23 24 macro_rules! try_to_get_manager_guard { 25 () => { 26 match MANAGER.lock() { 27 Ok(maybe_manager) => maybe_manager, 28 Err(_) => return CKR_DEVICE_ERROR, 29 } 30 }; 31 } 32 33 macro_rules! manager_guard_to_manager { 34 ($manager_guard:ident) => { 35 match $manager_guard.as_mut() { 36 Some(manager) => manager, 37 None => return CKR_DEVICE_ERROR, 38 } 39 }; 40 } 41 42 struct AlwaysSearchingForClientCerts; 43 44 impl IsSearchingForClientCerts for AlwaysSearchingForClientCerts { 45 fn is_searching_for_client_certs() -> bool { 46 true 47 } 48 } 49 50 extern "C" fn C_Initialize(_pInitArgs: CK_VOID_PTR) -> CK_RV { 51 // This will fail if this has already been called, but this isn't a problem because either way, 52 // logging has been initialized. 53 let _ = env_logger::try_init(); 54 55 let backends = vec![ 56 Backend::new( 57 SLOT_DESCRIPTIONS_BYTES[0], 58 TOKEN_LABELS_BYTES[0], 59 CKF_REMOVABLE_DEVICE, 60 CKF_TOKEN_INITIALIZED, 61 Vec::new(), 62 Vec::new(), 63 ), 64 Backend::new( 65 SLOT_DESCRIPTIONS_BYTES[1], 66 TOKEN_LABELS_BYTES[1], 67 CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE, 68 CKF_PROTECTED_AUTHENTICATION_PATH 69 | CKF_USER_PIN_INITIALIZED 70 | CKF_LOGIN_REQUIRED 71 | CKF_TOKEN_INITIALIZED, 72 vec![ 73 include_str!("client-cert-rsa.pem"), 74 include_str!("client-cert-ecdsa.pem"), 75 ], 76 vec![ 77 include_str!("client-cert-rsa.key"), 78 include_str!("client-cert-ecdsa.key"), 79 ], 80 ), 81 Backend::new( 82 SLOT_DESCRIPTIONS_BYTES[2], 83 TOKEN_LABELS_BYTES[2], 84 CKF_REMOVABLE_DEVICE, 85 CKF_TOKEN_INITIALIZED, 86 Vec::new(), 87 Vec::new(), 88 ), 89 ]; 90 let mut manager_guard = try_to_get_manager_guard!(); 91 let _unexpected_previous_manager = manager_guard.replace(Manager::new(backends)); 92 CKR_OK 93 } 94 95 extern "C" fn C_Finalize(_pReserved: CK_VOID_PTR) -> CK_RV { 96 let mut manager_guard = try_to_get_manager_guard!(); 97 match manager_guard.take() { 98 Some(_) => CKR_OK, 99 None => CKR_CRYPTOKI_NOT_INITIALIZED, 100 } 101 } 102 103 // The specification mandates that these strings be padded with spaces to the appropriate length. 104 // Since the length of fixed-size arrays in rust is part of the type, the compiler enforces that 105 // these byte strings are of the correct length. 106 const MANUFACTURER_ID_BYTES: &[u8; 32] = b"Test PKCS11 Manufacturer ID "; 107 const LIBRARY_DESCRIPTION_BYTES: &[u8; 32] = b"Test PKCS11 Library "; 108 109 const SLOT_DESCRIPTIONS_BYTES: [&'static [u8; 64]; 3] = [ 110 b"Test PKCS11 Slot ", 111 // \xE4\xBA\x8C is the utf-8 encoding of '二' (2) 112 b"Test PKCS11 Slot \xE4\xBA\x8C ", 113 b"Empty PKCS11 Slot ", 114 ]; 115 116 const TOKEN_LABELS_BYTES: [&'static [u8; 32]; 3] = [ 117 // \xC3\xB1 is the utf-8 encoding of 'ñ' 118 b"Test PKCS11 Toke\xC3\xB1 Label ", 119 b"Test PKCS11 Toke\xC3\xB1 2 Label ", 120 b"Test PKCS11 Toke\xC3\xB1 3 Label ", 121 ]; 122 123 declare_pkcs11_informational_functions!(); 124 declare_pkcs11_session_functions!(); 125 declare_pkcs11_find_functions!(); 126 declare_pkcs11_sign_functions!(); 127 declare_unsupported_pkcs11_functions!(); 128 129 /// To be a valid PKCS #11 module, this list of functions must be supported. At least cryptoki 2.2 130 /// must be supported for this module to work in NSS. 131 static FUNCTION_LIST: CK_FUNCTION_LIST = CK_FUNCTION_LIST { 132 version: CK_VERSION { major: 2, minor: 2 }, 133 C_Initialize: Some(C_Initialize), 134 C_Finalize: Some(C_Finalize), 135 C_GetInfo: Some(C_GetInfo), 136 C_GetFunctionList: None, 137 C_GetSlotList: Some(C_GetSlotList), 138 C_GetSlotInfo: Some(C_GetSlotInfo), 139 C_GetTokenInfo: Some(C_GetTokenInfo), 140 C_GetMechanismList: Some(C_GetMechanismList), 141 C_GetMechanismInfo: Some(C_GetMechanismInfo), 142 C_InitToken: Some(C_InitToken), 143 C_InitPIN: Some(C_InitPIN), 144 C_SetPIN: Some(C_SetPIN), 145 C_OpenSession: Some(C_OpenSession), 146 C_CloseSession: Some(C_CloseSession), 147 C_CloseAllSessions: Some(C_CloseAllSessions), 148 C_GetSessionInfo: Some(C_GetSessionInfo), 149 C_GetOperationState: Some(C_GetOperationState), 150 C_SetOperationState: Some(C_SetOperationState), 151 C_Login: Some(C_Login), 152 C_Logout: Some(C_Logout), 153 C_CreateObject: Some(C_CreateObject), 154 C_CopyObject: Some(C_CopyObject), 155 C_DestroyObject: Some(C_DestroyObject), 156 C_GetObjectSize: Some(C_GetObjectSize), 157 C_GetAttributeValue: Some(C_GetAttributeValue), 158 C_SetAttributeValue: Some(C_SetAttributeValue), 159 C_FindObjectsInit: Some(C_FindObjectsInit), 160 C_FindObjects: Some(C_FindObjects), 161 C_FindObjectsFinal: Some(C_FindObjectsFinal), 162 C_EncryptInit: Some(C_EncryptInit), 163 C_Encrypt: Some(C_Encrypt), 164 C_EncryptUpdate: Some(C_EncryptUpdate), 165 C_EncryptFinal: Some(C_EncryptFinal), 166 C_DecryptInit: Some(C_DecryptInit), 167 C_Decrypt: Some(C_Decrypt), 168 C_DecryptUpdate: Some(C_DecryptUpdate), 169 C_DecryptFinal: Some(C_DecryptFinal), 170 C_DigestInit: Some(C_DigestInit), 171 C_Digest: Some(C_Digest), 172 C_DigestUpdate: Some(C_DigestUpdate), 173 C_DigestKey: Some(C_DigestKey), 174 C_DigestFinal: Some(C_DigestFinal), 175 C_SignInit: Some(C_SignInit), 176 C_Sign: Some(C_Sign), 177 C_SignUpdate: Some(C_SignUpdate), 178 C_SignFinal: Some(C_SignFinal), 179 C_SignRecoverInit: Some(C_SignRecoverInit), 180 C_SignRecover: Some(C_SignRecover), 181 C_VerifyInit: Some(C_VerifyInit), 182 C_Verify: Some(C_Verify), 183 C_VerifyUpdate: Some(C_VerifyUpdate), 184 C_VerifyFinal: Some(C_VerifyFinal), 185 C_VerifyRecoverInit: Some(C_VerifyRecoverInit), 186 C_VerifyRecover: Some(C_VerifyRecover), 187 C_DigestEncryptUpdate: Some(C_DigestEncryptUpdate), 188 C_DecryptDigestUpdate: Some(C_DecryptDigestUpdate), 189 C_SignEncryptUpdate: Some(C_SignEncryptUpdate), 190 C_DecryptVerifyUpdate: Some(C_DecryptVerifyUpdate), 191 C_GenerateKey: Some(C_GenerateKey), 192 C_GenerateKeyPair: Some(C_GenerateKeyPair), 193 C_WrapKey: Some(C_WrapKey), 194 C_UnwrapKey: Some(C_UnwrapKey), 195 C_DeriveKey: Some(C_DeriveKey), 196 C_SeedRandom: Some(C_SeedRandom), 197 C_GenerateRandom: Some(C_GenerateRandom), 198 C_GetFunctionStatus: Some(C_GetFunctionStatus), 199 C_CancelFunction: Some(C_CancelFunction), 200 C_WaitForSlotEvent: Some(C_WaitForSlotEvent), 201 }; 202 203 /// # Safety 204 /// 205 /// This is the only function this module exposes. NSS calls it to obtain the list of functions 206 /// comprising this module. 207 /// ppFunctionList must be a valid pointer. 208 #[unsafe(no_mangle)] 209 pub unsafe extern "C" fn PKCS11TestModule_GetFunctionList( 210 ppFunctionList: CK_FUNCTION_LIST_PTR_PTR, 211 ) -> CK_RV { 212 if ppFunctionList.is_null() { 213 return CKR_ARGUMENTS_BAD; 214 } 215 // CK_FUNCTION_LIST_PTR is a *mut CK_FUNCTION_LIST, but as per the 216 // specification, the caller must treat it as *const CK_FUNCTION_LIST. 217 unsafe { *ppFunctionList = std::ptr::addr_of!(FUNCTION_LIST) as CK_FUNCTION_LIST_PTR }; 218 CKR_OK 219 }