tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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" {}