Bug 1937808 - Export OSClientCerts in libxul instead of shared library r=keeler,glandium

Differential Revision: https://phabricator.services.mozilla.com/D230412
This commit is contained in:
Anna Weine
2025-01-15 19:46:29 +00:00
parent 5e051b9062
commit d010e93c00
20 changed files with 128 additions and 178 deletions

5
Cargo.lock generated
View File

@@ -2457,6 +2457,7 @@ dependencies = [
"nsstring", "nsstring",
"oblivious_http", "oblivious_http",
"origin-trials-ffi", "origin-trials-ffi",
"osclientcerts",
"oxilangtag", "oxilangtag",
"oxilangtag-ffi", "oxilangtag-ffi",
"prefs_parser", "prefs_parser",
@@ -4839,7 +4840,7 @@ dependencies = [
] ]
[[package]] [[package]]
name = "osclientcerts-static" name = "osclientcerts"
version = "0.1.4" version = "0.1.4"
dependencies = [ dependencies = [
"byteorder", "byteorder",
@@ -4848,10 +4849,10 @@ dependencies = [
"lazy_static", "lazy_static",
"libloading", "libloading",
"log", "log",
"mozilla-central-workspace-hack",
"pkcs11-bindings", "pkcs11-bindings",
"rsclientcerts", "rsclientcerts",
"sha2", "sha2",
"static_prefs",
"winapi", "winapi",
] ]

View File

@@ -359,14 +359,6 @@ bin/libfreebl_64int_3.so
@RESPATH@/chrome/pippki@JAREXT@ @RESPATH@/chrome/pippki@JAREXT@
@RESPATH@/chrome/pippki.manifest @RESPATH@/chrome/pippki.manifest
; preprocessor.py doesn't handle parentheses, so while the following could be
; expressed in a single line, it's more clear to break them up.
#if defined(XP_WIN) || defined(XP_MACOSX)
#if !defined(_ARM64_)
@BINPATH@/@DLL_PREFIX@osclientcerts@DLL_SUFFIX@
#endif
#endif
@BINPATH@/@DLL_PREFIX@ipcclientcerts@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@ipcclientcerts@DLL_SUFFIX@
; For process sandboxing ; For process sandboxing

View File

@@ -274,5 +274,4 @@ jsrust = ["dep:allocator-api2", "dep:arrayvec", "dep:byteorder", "dep:cc", "dep:
minidump-analyzer-export = ["dep:allocator-api2", "dep:arrayvec", "dep:bitflags", "dep:byteorder", "dep:clap", "dep:env_logger", "dep:futures-channel", "dep:futures-core", "dep:futures-executor", "dep:futures-sink", "dep:futures-util", "dep:getrandom", "dep:hashbrown", "dep:hex", "dep:indexmap", "dep:log", "dep:memchr", "dep:nom", "dep:num-traits", "dep:object", "dep:once_cell", "dep:scroll", "dep:serde_json", "dep:time", "dep:time-macros", "dep:tracing", "dep:uuid", "dep:windows-sys", "dep:zerocopy"] minidump-analyzer-export = ["dep:allocator-api2", "dep:arrayvec", "dep:bitflags", "dep:byteorder", "dep:clap", "dep:env_logger", "dep:futures-channel", "dep:futures-core", "dep:futures-executor", "dep:futures-sink", "dep:futures-util", "dep:getrandom", "dep:hashbrown", "dep:hex", "dep:indexmap", "dep:log", "dep:memchr", "dep:nom", "dep:num-traits", "dep:object", "dep:once_cell", "dep:scroll", "dep:serde_json", "dep:time", "dep:time-macros", "dep:tracing", "dep:uuid", "dep:windows-sys", "dep:zerocopy"]
mozwer_s = ["dep:allocator-api2", "dep:byteorder", "dep:getrandom", "dep:hashbrown", "dep:indexmap", "dep:log", "dep:once_cell", "dep:scroll", "dep:serde_json", "dep:uuid", "dep:windows-sys", "dep:zerocopy"] mozwer_s = ["dep:allocator-api2", "dep:byteorder", "dep:getrandom", "dep:hashbrown", "dep:indexmap", "dep:log", "dep:once_cell", "dep:scroll", "dep:serde_json", "dep:uuid", "dep:windows-sys", "dep:zerocopy"]
nmhproxy = ["dep:allocator-api2", "dep:bitflags", "dep:byteorder", "dep:form_urlencoded", "dep:hashbrown", "dep:icu_locid", "dep:icu_properties", "dep:idna", "dep:indexmap", "dep:once_cell", "dep:percent-encoding", "dep:serde_json", "dep:smallvec", "dep:stable_deref_trait", "dep:tinystr", "dep:unicode-bidi", "dep:url", "dep:windows-sys", "dep:yoke", "dep:zerocopy", "dep:zerofrom", "dep:zerovec"] nmhproxy = ["dep:allocator-api2", "dep:bitflags", "dep:byteorder", "dep:form_urlencoded", "dep:hashbrown", "dep:icu_locid", "dep:icu_properties", "dep:idna", "dep:indexmap", "dep:once_cell", "dep:percent-encoding", "dep:serde_json", "dep:smallvec", "dep:stable_deref_trait", "dep:tinystr", "dep:unicode-bidi", "dep:url", "dep:windows-sys", "dep:yoke", "dep:zerocopy", "dep:zerofrom", "dep:zerovec"]
osclientcerts-static = ["dep:bindgen", "dep:bitflags", "dep:byteorder", "dep:core-foundation-sys", "dep:env_logger", "dep:itertools", "dep:log", "dep:memchr", "dep:nom", "dep:regex"]
test-builtins-static = ["dep:bindgen", "dep:bitflags", "dep:itertools", "dep:memchr", "dep:nom", "dep:regex", "dep:smallvec"] test-builtins-static = ["dep:bindgen", "dep:bitflags", "dep:itertools", "dep:memchr", "dep:nom", "dep:regex", "dep:smallvec"]

View File

@@ -16094,6 +16094,7 @@
type: RelaxedAtomicBool type: RelaxedAtomicBool
value: true value: true
mirror: always mirror: always
rust: true
- name: security.pki.cert_short_lifetime_in_days - name: security.pki.cert_short_lifetime_in_days
type: RelaxedAtomicUint32 type: RelaxedAtomicUint32

View File

@@ -1789,6 +1789,27 @@ bool LoadUserModuleAt(const char* moduleName, const char* libraryName,
return true; return true;
} }
bool LoadUserModuleFromXul(const char* moduleName,
CK_C_GetFunctionList fentry) {
// If a module exists with the same name, make a best effort attempt to delete
// it. Note that it isn't possible to delete the internal module, so checking
// the return value would be detrimental in that case.
int unusedModType;
Unused << SECMOD_DeleteModule(moduleName, &unusedModType);
UniqueSECMODModule userModule(
SECMOD_LoadUserModuleWithFunction(moduleName, fentry));
if (!userModule) {
return false;
}
if (!userModule->loaded) {
return false;
}
return true;
}
bool LoadIPCClientCertsModule(const nsCString& dir) { bool LoadIPCClientCertsModule(const nsCString& dir) {
// The IPC client certs module needs to be able to call back into gecko to be // The IPC client certs module needs to be able to call back into gecko to be
// able to communicate with the parent process over IPC. This is achieved by // able to communicate with the parent process over IPC. This is achieved by
@@ -1812,13 +1833,24 @@ bool LoadIPCClientCertsModule(const nsCString& dir) {
return true; return true;
} }
bool LoadOSClientCertsModule(const nsCString& dir) { extern "C" {
nsLiteralCString params = // Extern function to call osclientcerts module C_GetFunctionList.
StaticPrefs::security_osclientcerts_assume_rsa_pss_support() // NSS calls it to obtain the list of functions comprising this module.
? "RSA-PSS"_ns // ppFunctionList must be a valid pointer.
: ""_ns; CK_RV OSClientCerts_C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList);
return LoadUserModuleAt(kOSClientCertsModuleName.get(), "osclientcerts", dir, } // extern "C"
params.get());
bool LoadOSClientCertsModule() {
// Corresponds to Rust cfg(any(
// target_os = "macos",
// target_os = "ios",
// all(target_os = "windows", not(target_arch = "aarch64"))))]
#if defined(__APPLE__) || (defined WIN32 && !defined(__aarch64__))
return LoadUserModuleFromXul(kOSClientCertsModuleName.get(),
OSClientCerts_C_GetFunctionList);
#else
return false;
#endif
} }
bool LoadLoadableRoots(const nsCString& dir) { bool LoadLoadableRoots(const nsCString& dir) {

View File

@@ -80,12 +80,9 @@ bool LoadLoadableRoots(const nsCString& dir);
/** /**
* Loads the OS client certs module. * Loads the OS client certs module.
* *
* @param dir
* The path to the directory containing the module. This should be the
* same as where all of the other gecko libraries live.
* @return true if the module was successfully loaded, false otherwise. * @return true if the module was successfully loaded, false otherwise.
*/ */
bool LoadOSClientCertsModule(const nsCString& dir); bool LoadOSClientCertsModule();
/** /**
* Loads the IPC client certs module. * Loads the IPC client certs module.

View File

@@ -4,14 +4,6 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
# osclientcerts is currently only implemented for Windows
# osclientcerts transitively depends on winapi 0.2.8, which doesn't work with
# AArch64
if (CONFIG["OS_ARCH"] == "WINNT" and CONFIG["TARGET_CPU"] != "aarch64") or CONFIG[
"OS_ARCH"
] == "Darwin":
DIRS += ["osclientcerts"]
DIRS += ["ipcclientcerts"] DIRS += ["ipcclientcerts"]
DIRS += ["builtins"] DIRS += ["builtins"]
@@ -177,16 +169,11 @@ if CONFIG["TARGET_KERNEL"] == "Darwin":
"OSReauthenticatorDarwin.mm", "OSReauthenticatorDarwin.mm",
] ]
OS_LIBS += [ OS_LIBS += [
"-framework CoreFoundation",
"-framework LocalAuthentication", "-framework LocalAuthentication",
"-framework Security", "-framework Security",
] ]
if CONFIG["OS_ARCH"] == "WINNT":
OS_LIBS += ["credui"]
UNIFIED_SOURCES += [
"CredentialManagerSecret.cpp",
]
IPDL_SOURCES += [ IPDL_SOURCES += [
"PIPCClientCerts.ipdl", "PIPCClientCerts.ipdl",
"PSelectTLSClientAuthCert.ipdl", "PSelectTLSClientAuthCert.ipdl",
@@ -194,6 +181,31 @@ IPDL_SOURCES += [
"PVerifySSLServerCert.ipdl", "PVerifySSLServerCert.ipdl",
] ]
# Required by OSClientCerts and CredentialManagerSecret.
if CONFIG["OS_ARCH"] == "WINNT":
OS_LIBS += [
"advapi32",
"credui",
"crypt32",
"kernel32",
"ncrypt",
"userenv",
"ws2_32",
"ntdll",
]
UNIFIED_SOURCES += [
"CredentialManagerSecret.cpp",
]
# Version string comparison is generally wrong, but by the time it would
# actually matter, either bug 1489995 would be fixed, or the build would
# require version >= 1.78.
if CONFIG["RUSTC_VERSION"] and CONFIG["RUSTC_VERSION"] >= "1.78.0":
OS_LIBS += [
"synchronization",
]
FINAL_LIBRARY = "xul" FINAL_LIBRARY = "xul"
LOCAL_INCLUDES += [ LOCAL_INCLUDES += [

View File

@@ -482,14 +482,12 @@ class LoadLoadableCertsTask final : public Runnable {
public: public:
LoadLoadableCertsTask(nsNSSComponent* nssComponent, LoadLoadableCertsTask(nsNSSComponent* nssComponent,
bool importEnterpriseRoots, bool importEnterpriseRoots,
Vector<nsCString>&& possibleLoadableRootsLocations, Vector<nsCString>&& possibleLoadableRootsLocations)
Maybe<nsCString>&& osClientCertsModuleLocation)
: Runnable("LoadLoadableCertsTask"), : Runnable("LoadLoadableCertsTask"),
mNSSComponent(nssComponent), mNSSComponent(nssComponent),
mImportEnterpriseRoots(importEnterpriseRoots), mImportEnterpriseRoots(importEnterpriseRoots),
mPossibleLoadableRootsLocations( mPossibleLoadableRootsLocations(
std::move(possibleLoadableRootsLocations)), std::move(possibleLoadableRootsLocations)) {
mOSClientCertsModuleLocation(std::move(osClientCertsModuleLocation)) {
MOZ_ASSERT(nssComponent); MOZ_ASSERT(nssComponent);
} }
@@ -503,7 +501,6 @@ class LoadLoadableCertsTask final : public Runnable {
RefPtr<nsNSSComponent> mNSSComponent; RefPtr<nsNSSComponent> mNSSComponent;
bool mImportEnterpriseRoots; bool mImportEnterpriseRoots;
Vector<nsCString> mPossibleLoadableRootsLocations; // encoded in UTF-8 Vector<nsCString> mPossibleLoadableRootsLocations; // encoded in UTF-8
Maybe<nsCString> mOSClientCertsModuleLocation; // encoded in UTF-8
}; };
nsresult LoadLoadableCertsTask::Dispatch() { nsresult LoadLoadableCertsTask::Dispatch() {
@@ -545,12 +542,14 @@ LoadLoadableCertsTask::Run() {
mNSSComponent->ImportEnterpriseRoots(); mNSSComponent->ImportEnterpriseRoots();
mNSSComponent->UpdateCertVerifierWithEnterpriseRoots(); mNSSComponent->UpdateCertVerifierWithEnterpriseRoots();
} }
if (mOSClientCertsModuleLocation.isSome()) {
bool success = LoadOSClientCertsModule(*mOSClientCertsModuleLocation); if (StaticPrefs::security_osclientcerts_autoload()) {
bool success = LoadOSClientCertsModule();
MOZ_LOG(gPIPNSSLog, LogLevel::Debug, MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
("loading OS client certs module %s", ("loading OS client certs module %s",
success ? "succeeded" : "failed")); success ? "succeeded" : "failed"));
} }
{ {
MonitorAutoLock rootsLoadedLock(mNSSComponent->mLoadableCertsLoadedMonitor); MonitorAutoLock rootsLoadedLock(mNSSComponent->mLoadableCertsLoadedMonitor);
mNSSComponent->mLoadableCertsLoaded = true; mNSSComponent->mLoadableCertsLoaded = true;
@@ -590,12 +589,11 @@ static nsresult GetDirectoryPath(const char* directoryKey, nsCString& result) {
class BackgroundLoadOSClientCertsModuleTask final : public CryptoTask { class BackgroundLoadOSClientCertsModuleTask final : public CryptoTask {
public: public:
explicit BackgroundLoadOSClientCertsModuleTask(const nsCString&& libraryDir) explicit BackgroundLoadOSClientCertsModuleTask() {}
: mLibraryDir(std::move(libraryDir)) {}
private: private:
virtual nsresult CalculateResult() override { virtual nsresult CalculateResult() override {
bool success = LoadOSClientCertsModule(mLibraryDir); bool success = LoadOSClientCertsModule();
return success ? NS_OK : NS_ERROR_FAILURE; return success ? NS_OK : NS_ERROR_FAILURE;
} }
@@ -610,19 +608,12 @@ class BackgroundLoadOSClientCertsModuleTask final : public CryptoTask {
nullptr, "psm:load-os-client-certs-module-task-ran", nullptr); nullptr, "psm:load-os-client-certs-module-task-ran", nullptr);
} }
} }
nsCString mLibraryDir;
}; };
void AsyncLoadOrUnloadOSClientCertsModule(bool load) { void AsyncLoadOrUnloadOSClientCertsModule(bool load) {
if (load) { if (load) {
nsCString libraryDir;
nsresult rv = GetDirectoryPath(NS_GRE_BIN_DIR, libraryDir);
if (NS_FAILED(rv)) {
return;
}
RefPtr<BackgroundLoadOSClientCertsModuleTask> task = RefPtr<BackgroundLoadOSClientCertsModuleTask> task =
new BackgroundLoadOSClientCertsModuleTask(std::move(libraryDir)); new BackgroundLoadOSClientCertsModuleTask();
Unused << task->Dispatch(); Unused << task->Dispatch();
} else { } else {
UniqueSECMODModule osClientCertsModule( UniqueSECMODModule osClientCertsModule(
@@ -1660,19 +1651,9 @@ nsresult nsNSSComponent::InitializeNSS() {
return rv; return rv;
} }
bool loadOSClientCertsModule =
StaticPrefs::security_osclientcerts_autoload();
Maybe<nsCString> maybeOSClientCertsModuleLocation;
if (loadOSClientCertsModule) {
nsAutoCString libraryDir;
if (NS_SUCCEEDED(GetDirectoryPath(NS_GRE_BIN_DIR, libraryDir))) {
maybeOSClientCertsModuleLocation.emplace(libraryDir);
}
}
RefPtr<LoadLoadableCertsTask> loadLoadableCertsTask( RefPtr<LoadLoadableCertsTask> loadLoadableCertsTask(
new LoadLoadableCertsTask(this, importEnterpriseRoots, new LoadLoadableCertsTask(this, importEnterpriseRoots,
std::move(possibleLoadableRootsLocations), std::move(possibleLoadableRootsLocations)));
std::move(maybeOSClientCertsModuleLocation)));
rv = loadLoadableCertsTask->Dispatch(); rv = loadLoadableCertsTask->Dispatch();
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {

View File

@@ -1,10 +1,9 @@
[package] [package]
name = "osclientcerts-static" name = "osclientcerts"
version = "0.1.4" version = "0.1.4"
authors = ["Dana Keeler <dkeeler@mozilla.com>"] authors = ["Dana Keeler <dkeeler@mozilla.com>"]
edition = "2018" edition = "2018"
description = "Platform-specific support for client authentication certificates in Firefox" description = "Platform-specific support for client authentication certificates in Firefox"
repository = "https://github.com/mozkeeler/osclientcerts"
license = "MPL-2.0" license = "MPL-2.0"
[dependencies] [dependencies]
@@ -12,11 +11,11 @@ byteorder = "1.3"
env_logger = {version = "0.10", default-features = false } # disable `regex` to reduce code size env_logger = {version = "0.10", default-features = false } # disable `regex` to reduce code size
lazy_static = "1" lazy_static = "1"
log = "0.4" log = "0.4"
mozilla-central-workspace-hack = { version = "0.1", features = ["osclientcerts-static"], optional = true }
pkcs11-bindings = "0.1" pkcs11-bindings = "0.1"
rsclientcerts = { path = "../rsclientcerts" } rsclientcerts = { path = "../rsclientcerts" }
sha2 = "0.10.2" sha2 = "0.10.2"
static_prefs = { path = "../../../../modules/libpref/init/static_prefs"}
[target."cfg(any(target_os = \"macos\", target_os = \"ios\"))".dependencies.core-foundation] [target."cfg(any(target_os = \"macos\", target_os = \"ios\"))".dependencies.core-foundation]
version = "0.9" version = "0.9"
@@ -27,6 +26,3 @@ version = "0.8"
[target."cfg(target_os = \"windows\")".dependencies.winapi] [target."cfg(target_os = \"windows\")".dependencies.winapi]
version = "0.3" version = "0.3"
features = ["errhandlingapi", "wincrypt"] features = ["errhandlingapi", "wincrypt"]
[lib]
crate-type = ["staticlib"]

View File

@@ -1,40 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
USE_LIBS += ["osclientcerts-static"]
UNIFIED_SOURCES += [
"stub.cpp",
]
if CONFIG["OS_ARCH"] == "WINNT":
OS_LIBS += [
"advapi32",
"crypt32",
"kernel32",
"ncrypt",
"userenv",
"ws2_32",
"ntdll",
]
# Version string comparison is generally wrong, but by the time it would
# actually matter, either bug 1489995 would be fixed, or the build would
# require version >= 1.78.
if CONFIG["RUSTC_VERSION"] and CONFIG["RUSTC_VERSION"] >= "1.78.0":
OS_LIBS += [
"synchronization",
]
if CONFIG["OS_ARCH"] == "Darwin":
OS_LIBS += [
"-framework CoreFoundation",
"-framework Security",
]
SharedLibrary("osclientcerts")
NoVisibilityFlags()
SYMBOLS_FILE = "osclientcerts.symbols"

View File

@@ -1,8 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// This is an intentionally empty file. It is necessary for the build system to
// successfully convert a static rust library into a dynamic library on
// Windows.

View File

@@ -1,9 +0,0 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
DIRS += ["dynamic-library"]
RustLibrary("osclientcerts-static")

View File

@@ -21,23 +21,22 @@ extern crate pkcs11_bindings;
#[macro_use] #[macro_use]
extern crate rsclientcerts; extern crate rsclientcerts;
extern crate sha2; extern crate sha2;
#[cfg(target_os = "windows")] #[cfg(all(target_os = "windows", not(target_arch = "aarch64")))]
extern crate winapi; extern crate winapi;
use pkcs11_bindings::*; use pkcs11_bindings::*;
use rsclientcerts::manager::{ManagerProxy, SlotType}; use rsclientcerts::manager::{ManagerProxy, SlotType};
use std::ffi::CStr;
use std::sync::Mutex; use std::sync::Mutex;
use std::thread; use std::thread;
#[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg(any(target_os = "macos", target_os = "ios"))]
mod backend_macos; mod backend_macos;
#[cfg(target_os = "windows")] #[cfg(all(target_os = "windows", not(target_arch = "aarch64")))]
mod backend_windows; mod backend_windows;
#[cfg(any(target_os = "macos", target_os = "ios"))] #[cfg(any(target_os = "macos", target_os = "ios"))]
use crate::backend_macos::Backend; use crate::backend_macos::Backend;
#[cfg(target_os = "windows")] #[cfg(all(target_os = "windows", not(target_arch = "aarch64")))]
use crate::backend_windows::Backend; use crate::backend_windows::Backend;
struct ModuleState { struct ModuleState {
@@ -108,24 +107,12 @@ macro_rules! log_with_thread_id {
/// This gets called to initialize the module. For this implementation, this consists of /// This gets called to initialize the module. For this implementation, this consists of
/// instantiating the `ManagerProxy`. /// instantiating the `ManagerProxy`.
extern "C" fn C_Initialize(pInitArgs: CK_VOID_PTR) -> CK_RV { extern "C" fn C_Initialize(_pInitArgs: CK_VOID_PTR) -> CK_RV {
// This will fail if this has already been called, but this isn't a problem because either way, // This will fail if this has already been called, but this isn't a problem because either way,
// logging has been initialized. // logging has been initialized.
let _ = env_logger::try_init(); let _ = env_logger::try_init();
if pInitArgs.is_null() { let mechanisms = if static_prefs::pref!("security.osclientcerts.assume_rsa_pss_support") {
return CKR_DEVICE_ERROR;
}
let init_args_ptr = unsafe { (*(pInitArgs as CK_C_INITIALIZE_ARGS_PTR)).pReserved };
if init_args_ptr.is_null() {
return CKR_DEVICE_ERROR;
}
let init_args_cstr = unsafe { CStr::from_ptr(init_args_ptr as *mut std::os::raw::c_char) };
let init_args = match init_args_cstr.to_str() {
Ok(init_args) => init_args,
Err(_) => return CKR_DEVICE_ERROR,
};
let mechanisms = if init_args == "RSA-PSS" {
vec![CKM_ECDSA, CKM_RSA_PKCS, CKM_RSA_PKCS_PSS] vec![CKM_ECDSA, CKM_RSA_PKCS, CKM_RSA_PKCS_PSS]
} else { } else {
vec![CKM_ECDSA, CKM_RSA_PKCS] vec![CKM_ECDSA, CKM_RSA_PKCS]
@@ -143,17 +130,10 @@ extern "C" fn C_Initialize(pInitArgs: CK_VOID_PTR) -> CK_RV {
mechanisms, mechanisms,
}) { }) {
Some(_unexpected_previous_module_state) => { Some(_unexpected_previous_module_state) => {
#[cfg(any(target_os = "macos", target_os = "ios"))] log_with_thread_id!(
{ warn,
log_with_thread_id!(info, "C_Initialize: module state previously set (this is expected on macOS - replacing it)"); "C_Initialize: replacing previously set module state (this is expected on macOS but not on Windows)"
} );
#[cfg(target_os = "windows")]
{
log_with_thread_id!(
warn,
"C_Initialize: module state unexpectedly previously set (replacing it)"
);
}
} }
None => {} None => {}
} }
@@ -1247,7 +1227,9 @@ static FUNCTION_LIST: CK_FUNCTION_LIST = CK_FUNCTION_LIST {
/// comprising this module. /// comprising this module.
/// ppFunctionList must be a valid pointer. /// ppFunctionList must be a valid pointer.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn C_GetFunctionList(ppFunctionList: CK_FUNCTION_LIST_PTR_PTR) -> CK_RV { pub unsafe extern "C" fn OSClientCerts_C_GetFunctionList(
ppFunctionList: CK_FUNCTION_LIST_PTR_PTR,
) -> CK_RV {
if ppFunctionList.is_null() { if ppFunctionList.is_null() {
return CKR_ARGUMENTS_BAD; return CKR_ARGUMENTS_BAD;
} }

View File

@@ -1108,7 +1108,7 @@ function writeLinesAndClose(lines, outputStream) {
* A unique substring of name of the dynamic library file of the module * A unique substring of name of the dynamic library file of the module
* that should not be loaded. * that should not be loaded.
*/ */
function checkPKCS11ModuleNotPresent(moduleName, libraryName) { function checkPKCS11ModuleNotPresent(moduleName, libraryName = "undefined") {
let moduleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService( let moduleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
Ci.nsIPKCS11ModuleDB Ci.nsIPKCS11ModuleDB
); );
@@ -1123,10 +1123,12 @@ function checkPKCS11ModuleNotPresent(moduleName, libraryName) {
moduleName, moduleName,
`Non-test module name shouldn't equal '${moduleName}'` `Non-test module name shouldn't equal '${moduleName}'`
); );
ok( if (libraryName != "undefined") {
!(module.libName && module.libName.includes(libraryName)), ok(
`Non-test module lib name should not include '${libraryName}'` !(module.libName && module.libName.includes(libraryName)),
); `Non-test module lib name should not include '${libraryName}'`
);
}
} }
} }
@@ -1142,7 +1144,7 @@ function checkPKCS11ModuleNotPresent(moduleName, libraryName) {
* @returns {nsIPKCS11Module} * @returns {nsIPKCS11Module}
* The test module. * The test module.
*/ */
function checkPKCS11ModuleExists(moduleName, libraryName) { function checkPKCS11ModuleExists(moduleName, libraryName = "undefined") {
let moduleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService( let moduleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
Ci.nsIPKCS11ModuleDB Ci.nsIPKCS11ModuleDB
); );
@@ -1159,11 +1161,17 @@ function checkPKCS11ModuleExists(moduleName, libraryName) {
} }
} }
notEqual(testModule, null, "Test module should have been found"); notEqual(testModule, null, "Test module should have been found");
notEqual(testModule.libName, null, "Test module lib name should not be null"); if (libraryName != "undefined") {
ok( notEqual(
testModule.libName.includes(ctypes.libraryName(libraryName)), testModule.libName,
`Test module lib name should include lib name of '${libraryName}'` null,
); "Test module lib name should not be null"
);
ok(
testModule.libName.includes(ctypes.libraryName(libraryName)),
`Test module lib name should include lib name of '${libraryName}'`
);
}
return testModule; return testModule;
} }

View File

@@ -16,10 +16,7 @@ const { TestUtils } = ChromeUtils.importESModule(
async function check_osclientcerts_module_loaded() { async function check_osclientcerts_module_loaded() {
// Loading happens asynchronously, so we have to wait for the notification. // Loading happens asynchronously, so we have to wait for the notification.
await TestUtils.topicObserved("psm:load-os-client-certs-module-task-ran"); await TestUtils.topicObserved("psm:load-os-client-certs-module-task-ran");
let testModule = checkPKCS11ModuleExists( let testModule = checkPKCS11ModuleExists("OS Client Cert Module");
"OS Client Cert Module",
"osclientcerts"
);
// Check that listing the slots for the osclientcerts module works. // Check that listing the slots for the osclientcerts module works.
let testModuleSlotNames = Array.from( let testModuleSlotNames = Array.from(
@@ -38,7 +35,7 @@ async function check_osclientcerts_module_loaded() {
add_task(async function run_test() { add_task(async function run_test() {
// Check that if we haven't loaded the osclientcerts module, we don't find it // Check that if we haven't loaded the osclientcerts module, we don't find it
// in the module list. // in the module list.
checkPKCS11ModuleNotPresent("OS Client Cert Module", "osclientcerts"); checkPKCS11ModuleNotPresent("OS Client Cert Module");
// Check that enabling the pref that loads the osclientcerts module makes it // Check that enabling the pref that loads the osclientcerts module makes it
// appear in the module list. // appear in the module list.
@@ -48,7 +45,7 @@ add_task(async function run_test() {
// Check that disabling the pref that loads the osclientcerts module (thus // Check that disabling the pref that loads the osclientcerts module (thus
// unloading the module) makes it disappear from the module list. // unloading the module) makes it disappear from the module list.
Services.prefs.setBoolPref("security.osclientcerts.autoload", false); Services.prefs.setBoolPref("security.osclientcerts.autoload", false);
checkPKCS11ModuleNotPresent("OS Client Cert Module", "osclientcerts"); checkPKCS11ModuleNotPresent("OS Client Cert Module");
// Check that loading the module again succeeds. // Check that loading the module again succeeds.
Services.prefs.setBoolPref("security.osclientcerts.autoload", true); Services.prefs.setBoolPref("security.osclientcerts.autoload", true);
@@ -56,5 +53,5 @@ add_task(async function run_test() {
// And once more check that unloading succeeds. // And once more check that unloading succeeds.
Services.prefs.setBoolPref("security.osclientcerts.autoload", false); Services.prefs.setBoolPref("security.osclientcerts.autoload", false);
checkPKCS11ModuleNotPresent("OS Client Cert Module", "osclientcerts"); checkPKCS11ModuleNotPresent("OS Client Cert Module");
}); });

View File

@@ -6,7 +6,7 @@ skip-if = ["os == 'android'"]
["test_osclientcerts_module.js"] ["test_osclientcerts_module.js"]
skip-if = [ skip-if = [
"os == 'linux'", "os == 'linux'",
"os == 'android'", "os == 'android'"
] ]
["test_pkcs11_module.js"] ["test_pkcs11_module.js"]

View File

@@ -582,6 +582,7 @@ SECMOD_GetReadLock
SECMOD_InternaltoPubMechFlags SECMOD_InternaltoPubMechFlags
SECMOD_LoadModule SECMOD_LoadModule
SECMOD_LoadUserModule SECMOD_LoadUserModule
SECMOD_LoadUserModuleWithFunction
SECMOD_LockedModuleHasRemovableSlots SECMOD_LockedModuleHasRemovableSlots
SECMOD_OpenUserDB SECMOD_OpenUserDB
SECMOD_PubCipherFlagstoInternal SECMOD_PubCipherFlagstoInternal

View File

@@ -109,6 +109,9 @@ fallible_collections = { version = "0.4", features = ["rust_1_57"] }
libz-rs-sys = { git = "https://github.com/memorysafety/zlib-rs", rev = "4aa430ccb77537d0d60dab8db993ca51bb1194c5", features = ["custom-prefix"], optional = true } libz-rs-sys = { git = "https://github.com/memorysafety/zlib-rs", rev = "4aa430ccb77537d0d60dab8db993ca51bb1194c5", features = ["custom-prefix"], optional = true }
[target.'cfg(any(target_os = "macos",target_os = "ios", all(target_os = "windows", not(target_arch = "aarch64"))))'.dependencies]
osclientcerts = { path = "../../../../security/manager/ssl/osclientcerts" }
[target.'cfg(not(target_os = "android"))'.dependencies] [target.'cfg(not(target_os = "android"))'.dependencies]
gkrust-uniffi-components = { path = "../../../components/uniffi-bindgen-gecko-js/components/", features = ["xpcom"] } gkrust-uniffi-components = { path = "../../../components/uniffi-bindgen-gecko-js/components/", features = ["xpcom"] }
gkrust-uniffi-fixtures = { path = "../../../components/uniffi-bindgen-gecko-js/fixtures/", features = ["xpcom"], optional = true } gkrust-uniffi-fixtures = { path = "../../../components/uniffi-bindgen-gecko-js/fixtures/", features = ["xpcom"], optional = true }

View File

@@ -85,6 +85,12 @@ extern crate fluent_fallback;
extern crate l10nregistry_ffi; extern crate l10nregistry_ffi;
extern crate localization_ffi; extern crate localization_ffi;
#[cfg(any(
target_os = "macos",
target_os = "ios",
all(target_os = "windows", not(target_arch = "aarch64"))))]
extern crate osclientcerts;
#[cfg(not(target_os = "android"))] #[cfg(not(target_os = "android"))]
extern crate gkrust_uniffi_components; extern crate gkrust_uniffi_components;