tor-browser

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

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 }