lib.rs (7454B)
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::convert::TryInto; 17 use std::sync::Mutex; 18 19 mod backend; 20 21 use backend::Backend; 22 23 /// The singleton `Manager` that handles state with respect to PKCS #11. Only one thread 24 /// may use it at a time, but there is no restriction on which threads may use it. 25 static MANAGER: Mutex<Option<Manager<Backend, IsGeckoSearchingForClientCerts>>> = Mutex::new(None); 26 27 // Obtaining a handle on the manager is a two-step process. First the mutex must be locked, which 28 // (if successful), results in a mutex guard object. We must then get a mutable refence to the 29 // underlying manager (if set - otherwise we return an error). This can't happen all in one macro 30 // without dropping a reference that needs to live long enough for this to be safe. In 31 // practice, this looks like: 32 // let mut manager_guard = try_to_get_manager_guard!(); 33 // let manager = manager_guard_to_manager!(manager_guard); 34 macro_rules! try_to_get_manager_guard { 35 () => { 36 match MANAGER.lock() { 37 Ok(maybe_manager) => maybe_manager, 38 Err(_) => return CKR_DEVICE_ERROR, 39 } 40 }; 41 } 42 43 macro_rules! manager_guard_to_manager { 44 ($manager_guard:ident) => { 45 match $manager_guard.as_mut() { 46 Some(manager) => manager, 47 None => return CKR_DEVICE_ERROR, 48 } 49 }; 50 } 51 52 extern "C" { 53 fn IsGeckoSearchingForClientAuthCertificates() -> bool; 54 } 55 56 struct IsGeckoSearchingForClientCerts; 57 58 impl IsSearchingForClientCerts for IsGeckoSearchingForClientCerts { 59 fn is_searching_for_client_certs() -> bool { 60 unsafe { IsGeckoSearchingForClientAuthCertificates() } 61 } 62 } 63 64 /// This gets called to initialize the module. For this implementation, this consists of 65 /// instantiating the `Manager`. 66 extern "C" fn C_Initialize(_pInitArgs: CK_VOID_PTR) -> CK_RV { 67 let mut manager_guard = try_to_get_manager_guard!(); 68 let _unexpected_previous_manager = manager_guard.replace(Manager::new(vec![Backend::new()])); 69 CKR_OK 70 } 71 72 extern "C" fn C_Finalize(_pReserved: CK_VOID_PTR) -> CK_RV { 73 // Drop the manager. When C_Finalize is called, there should be only one 74 // reference to this module (which is going away), so there shouldn't be 75 // any concurrency issues. 76 let mut manager_guard = try_to_get_manager_guard!(); 77 match manager_guard.take() { 78 Some(_) => CKR_OK, 79 None => CKR_CRYPTOKI_NOT_INITIALIZED, 80 } 81 } 82 83 // The specification mandates that these strings be padded with spaces to the appropriate length. 84 // Since the length of fixed-size arrays in rust is part of the type, the compiler enforces that 85 // these byte strings are of the correct length. 86 const MANUFACTURER_ID_BYTES: &[u8; 32] = b"Mozilla Corporation "; 87 const LIBRARY_DESCRIPTION_BYTES: &[u8; 32] = b"IPC Client Cert Module "; 88 89 declare_pkcs11_informational_functions!(); 90 declare_pkcs11_session_functions!(); 91 declare_pkcs11_find_functions!(); 92 declare_pkcs11_sign_functions!(); 93 declare_unsupported_pkcs11_functions!(); 94 95 /// To be a valid PKCS #11 module, this list of functions must be supported. At least cryptoki 2.2 96 /// must be supported for this module to work in NSS. 97 static FUNCTION_LIST: CK_FUNCTION_LIST = CK_FUNCTION_LIST { 98 version: CK_VERSION { major: 2, minor: 2 }, 99 C_Initialize: Some(C_Initialize), 100 C_Finalize: Some(C_Finalize), 101 C_GetInfo: Some(C_GetInfo), 102 C_GetFunctionList: None, 103 C_GetSlotList: Some(C_GetSlotList), 104 C_GetSlotInfo: Some(C_GetSlotInfo), 105 C_GetTokenInfo: Some(C_GetTokenInfo), 106 C_GetMechanismList: Some(C_GetMechanismList), 107 C_GetMechanismInfo: Some(C_GetMechanismInfo), 108 C_InitToken: Some(C_InitToken), 109 C_InitPIN: Some(C_InitPIN), 110 C_SetPIN: Some(C_SetPIN), 111 C_OpenSession: Some(C_OpenSession), 112 C_CloseSession: Some(C_CloseSession), 113 C_CloseAllSessions: Some(C_CloseAllSessions), 114 C_GetSessionInfo: Some(C_GetSessionInfo), 115 C_GetOperationState: Some(C_GetOperationState), 116 C_SetOperationState: Some(C_SetOperationState), 117 C_Login: Some(C_Login), 118 C_Logout: Some(C_Logout), 119 C_CreateObject: Some(C_CreateObject), 120 C_CopyObject: Some(C_CopyObject), 121 C_DestroyObject: Some(C_DestroyObject), 122 C_GetObjectSize: Some(C_GetObjectSize), 123 C_GetAttributeValue: Some(C_GetAttributeValue), 124 C_SetAttributeValue: Some(C_SetAttributeValue), 125 C_FindObjectsInit: Some(C_FindObjectsInit), 126 C_FindObjects: Some(C_FindObjects), 127 C_FindObjectsFinal: Some(C_FindObjectsFinal), 128 C_EncryptInit: Some(C_EncryptInit), 129 C_Encrypt: Some(C_Encrypt), 130 C_EncryptUpdate: Some(C_EncryptUpdate), 131 C_EncryptFinal: Some(C_EncryptFinal), 132 C_DecryptInit: Some(C_DecryptInit), 133 C_Decrypt: Some(C_Decrypt), 134 C_DecryptUpdate: Some(C_DecryptUpdate), 135 C_DecryptFinal: Some(C_DecryptFinal), 136 C_DigestInit: Some(C_DigestInit), 137 C_Digest: Some(C_Digest), 138 C_DigestUpdate: Some(C_DigestUpdate), 139 C_DigestKey: Some(C_DigestKey), 140 C_DigestFinal: Some(C_DigestFinal), 141 C_SignInit: Some(C_SignInit), 142 C_Sign: Some(C_Sign), 143 C_SignUpdate: Some(C_SignUpdate), 144 C_SignFinal: Some(C_SignFinal), 145 C_SignRecoverInit: Some(C_SignRecoverInit), 146 C_SignRecover: Some(C_SignRecover), 147 C_VerifyInit: Some(C_VerifyInit), 148 C_Verify: Some(C_Verify), 149 C_VerifyUpdate: Some(C_VerifyUpdate), 150 C_VerifyFinal: Some(C_VerifyFinal), 151 C_VerifyRecoverInit: Some(C_VerifyRecoverInit), 152 C_VerifyRecover: Some(C_VerifyRecover), 153 C_DigestEncryptUpdate: Some(C_DigestEncryptUpdate), 154 C_DecryptDigestUpdate: Some(C_DecryptDigestUpdate), 155 C_SignEncryptUpdate: Some(C_SignEncryptUpdate), 156 C_DecryptVerifyUpdate: Some(C_DecryptVerifyUpdate), 157 C_GenerateKey: Some(C_GenerateKey), 158 C_GenerateKeyPair: Some(C_GenerateKeyPair), 159 C_WrapKey: Some(C_WrapKey), 160 C_UnwrapKey: Some(C_UnwrapKey), 161 C_DeriveKey: Some(C_DeriveKey), 162 C_SeedRandom: Some(C_SeedRandom), 163 C_GenerateRandom: Some(C_GenerateRandom), 164 C_GetFunctionStatus: Some(C_GetFunctionStatus), 165 C_CancelFunction: Some(C_CancelFunction), 166 C_WaitForSlotEvent: Some(C_WaitForSlotEvent), 167 }; 168 169 /// This is the only function this module exposes. The C stub calls it when NSS 170 /// calls its exposed C_GetFunctionList function to obtain the list of functions 171 /// comprising this module. 172 #[no_mangle] 173 pub extern "C" fn IPCCC_GetFunctionList(ppFunctionList: CK_FUNCTION_LIST_PTR_PTR) -> CK_RV { 174 if ppFunctionList.is_null() { 175 return CKR_ARGUMENTS_BAD; 176 } 177 unsafe { 178 // CK_FUNCTION_LIST_PTR is a *mut CK_FUNCTION_LIST, but as per the 179 // specification, the caller must treat it as *const CK_FUNCTION_LIST. 180 *ppFunctionList = std::ptr::addr_of!(FUNCTION_LIST) as CK_FUNCTION_LIST_PTR; 181 } 182 CKR_OK 183 } 184 185 #[cfg_attr( 186 any(target_os = "macos", target_os = "ios"), 187 link(name = "Security", kind = "framework") 188 )] 189 extern "C" {}