diff --git a/Cargo.lock b/Cargo.lock index f2757c00fb51..53e9387e7dc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -579,6 +579,7 @@ name = "builtins-static" version = "0.1.0" dependencies = [ "bindgen 0.69.4", + "mozbuild", "mozilla-central-workspace-hack", "nom", "pkcs11-bindings", @@ -5679,6 +5680,18 @@ dependencies = [ name = "terminal_size" version = "0.3.999" +[[package]] +name = "test-builtins-static" +version = "0.1.0" +dependencies = [ + "bindgen 0.69.4", + "mozbuild", + "mozilla-central-workspace-hack", + "nom", + "pkcs11-bindings", + "smallvec", +] + [[package]] name = "textwrap" version = "0.16.1" diff --git a/Cargo.toml b/Cargo.toml index 02206bafdfeb..de45b8f9eea9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ members = [ "js/src/rust", "netwerk/test/http3server", "security/manager/ssl/builtins", + "security/manager/ssl/tests/unit/test_builtins", "security/manager/ssl/ipcclientcerts", "security/manager/ssl/osclientcerts", "testing/geckodriver", diff --git a/build/workspace-hack/Cargo.toml b/build/workspace-hack/Cargo.toml index 56a46eb68d53..afc9c78f8afa 100644 --- a/build/workspace-hack/Cargo.toml +++ b/build/workspace-hack/Cargo.toml @@ -224,3 +224,4 @@ jsrust = ["dep:arrayvec", "dep:cc", "dep:env_logger", "dep:getrandom", "dep:hash mozwer_s = ["dep:getrandom", "dep:hashbrown", "dep:indexmap", "dep:log", "dep:once_cell", "dep:serde_json", "dep:uuid", "dep:windows-sys"] nmhproxy = ["dep:bitflags", "dep:hashbrown", "dep:indexmap", "dep:once_cell", "dep:serde_json", "dep:smallvec", "dep:unicode-bidi", "dep:url", "dep:windows-sys"] osclientcerts-static = ["dep:bindgen", "dep:bitflags", "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"] diff --git a/security/manager/ssl/builtins/Cargo.toml b/security/manager/ssl/builtins/Cargo.toml index b3f2e9c7b8cb..0f182b127781 100644 --- a/security/manager/ssl/builtins/Cargo.toml +++ b/security/manager/ssl/builtins/Cargo.toml @@ -12,6 +12,7 @@ mozilla-central-workspace-hack = { version = "0.1", features = ["builtins-static [build-dependencies] bindgen = { default-features = false, features = ["runtime"], version = "0.69" } +mozbuild = "0.1" nom = "7.1.1" [lib] diff --git a/security/manager/ssl/builtins/build.rs b/security/manager/ssl/builtins/build.rs index 81afe1449b82..439f407fcfa8 100644 --- a/security/manager/ssl/builtins/build.rs +++ b/security/manager/ssl/builtins/build.rs @@ -9,6 +9,8 @@ extern crate nom; use bindgen::callbacks::*; use bindgen::*; +use mozbuild::TOPSRCDIR; + use nom::branch::alt; use nom::bytes::complete::{tag, take_until}; use nom::character::complete::{ @@ -314,11 +316,16 @@ macro_rules! emit_build_error { } fn main() -> std::io::Result<()> { - println!("cargo:rerun-if-changed=../../../nss/lib/ckfw/builtins/certdata.txt"); - println!("cargo:rerun-if-changed=../../../nss/lib/ckfw/builtins/nssckbi.h"); + let testlib_certdata = + TOPSRCDIR.join("security/manager/ssl/tests/unit/test_builtins/certdata.txt"); + let mozilla_certdata = TOPSRCDIR.join("security/nss/lib/ckfw/builtins/certdata.txt"); + let nssckbi_header = TOPSRCDIR.join("security/nss/lib/ckfw/builtins/nssckbi.h"); + println!("cargo:rerun-if-changed={}", testlib_certdata.display()); + println!("cargo:rerun-if-changed={}", mozilla_certdata.display()); + println!("cargo:rerun-if-changed={}", nssckbi_header.display()); let bindings = Builder::default() - .header("../../../nss/lib/ckfw/builtins/nssckbi.h") + .header(nssckbi_header.display().to_string()) .allowlist_var("NSS_BUILTINS_CRYPTOKI_VERSION_MAJOR") .allowlist_var("NSS_BUILTINS_CRYPTOKI_VERSION_MINOR") .allowlist_var("NSS_BUILTINS_LIBRARY_VERSION_MAJOR") @@ -340,8 +347,15 @@ fn main() -> std::io::Result<()> { File::create(out_path.join("builtins.rs")).expect("Could not write builtins.rs."), ); - let mut input: String = std::fs::read_to_string("../../../nss/lib/ckfw/builtins/certdata.txt") - .expect("Unable to read certdata.txt."); + // If we are building the test module, use the certdata.txt in the test directory. + #[cfg(feature = "testlib")] + let mut input = + std::fs::read_to_string(testlib_certdata).expect("Unable to read certdata.txt."); + + // Otherwise, use the official certdata.txt for the Mozilla root store. + #[cfg(not(feature = "testlib"))] + let mut input = + std::fs::read_to_string(mozilla_certdata).expect("Unable to read certdata.txt."); // Add a trailing newline to simplify parsing. input.push('\n'); diff --git a/security/manager/ssl/builtins/src/lib.rs b/security/manager/ssl/builtins/src/lib.rs index 17b05b454d66..fb8b9b0e0c86 100644 --- a/security/manager/ssl/builtins/src/lib.rs +++ b/security/manager/ssl/builtins/src/lib.rs @@ -3,6 +3,8 @@ * 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/. */ +// certdata may include dead code depending on the contents of certdata.txt +#[allow(dead_code)] mod certdata; mod internal; mod pkcs11; diff --git a/security/manager/ssl/tests/unit/moz.build b/security/manager/ssl/tests/unit/moz.build index 561502dd5156..87686a61116a 100644 --- a/security/manager/ssl/tests/unit/moz.build +++ b/security/manager/ssl/tests/unit/moz.build @@ -4,7 +4,7 @@ # 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 += ["tlsserver", "test_signed_apps"] +DIRS += ["tlsserver", "test_builtins", "test_signed_apps"] if not CONFIG["MOZ_NO_SMART_CARDS"]: DIRS += ["pkcs11testmodule"] diff --git a/security/manager/ssl/tests/unit/test_builtins.js b/security/manager/ssl/tests/unit/test_builtins.js new file mode 100644 index 000000000000..916783a70e7d --- /dev/null +++ b/security/manager/ssl/tests/unit/test_builtins.js @@ -0,0 +1,34 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/publicdomain/zero/1.0/ +"use strict"; + +// Tests that use a mock builtins module. + +// Ensure that the appropriate initialization has happened. +do_get_profile(); + +add_setup(function load_nssckbi_testlib() { + let moduleName = "Mock Builtins"; + let libraryName = "test_builtins"; + + checkPKCS11ModuleNotPresent(moduleName, libraryName); + + let libraryFile = Services.dirsvc.get("CurWorkD", Ci.nsIFile); + libraryFile.append("test_builtins"); + libraryFile.append(ctypes.libraryName(libraryName)); + loadPKCS11Module(libraryFile, moduleName, true); + let testModule = checkPKCS11ModuleExists(moduleName, libraryName); + + // Check that listing the slots for the test module works. + let testModuleSlotNames = Array.from( + testModule.listSlots(), + slot => slot.name + ); + testModuleSlotNames.sort(); + const expectedSlotNames = ["NSS Builtin Objects"]; + deepEqual( + testModuleSlotNames, + expectedSlotNames, + "Actual and expected slot names should be equal" + ); +}); diff --git a/security/manager/ssl/tests/unit/test_builtins/Cargo.toml b/security/manager/ssl/tests/unit/test_builtins/Cargo.toml new file mode 100644 index 000000000000..b2c4e842eba1 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_builtins/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "test-builtins-static" +version = "0.1.0" +authors = ["John Schanck "] +edition = "2021" +license = "MPL-2.0" +build = "../../../builtins/build.rs" + +[features] +default = ["testlib"] +testlib = [] + +[dependencies] +pkcs11-bindings = "0.1.1" +smallvec = { version = "1.9.0", features = ["const_new"] } +mozilla-central-workspace-hack = { version = "0.1", features = ["test-builtins-static"], optional = true } + +[build-dependencies] +bindgen = { default-features = false, features = ["runtime"], version = "0.69" } +mozbuild = "0.1" +nom = "7.1.1" + +[lib] +crate-type = ["staticlib"] +path = "../../../builtins/src/lib.rs" diff --git a/security/manager/ssl/tests/unit/test_builtins/certdata.txt b/security/manager/ssl/tests/unit/test_builtins/certdata.txt new file mode 100644 index 000000000000..b62c83293d67 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_builtins/certdata.txt @@ -0,0 +1,11 @@ +# +# 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/. + +BEGINDATA +CKA_CLASS CK_OBJECT_CLASS CKO_NSS_BUILTIN_ROOT_LIST +CKA_TOKEN CK_BBOOL CK_TRUE +CKA_PRIVATE CK_BBOOL CK_FALSE +CKA_MODIFIABLE CK_BBOOL CK_FALSE +CKA_LABEL UTF8 "Test Roots" diff --git a/security/manager/ssl/tests/unit/test_builtins/dynamic-library/builtins.symbols b/security/manager/ssl/tests/unit/test_builtins/dynamic-library/builtins.symbols new file mode 100644 index 000000000000..562ecea21d43 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_builtins/dynamic-library/builtins.symbols @@ -0,0 +1 @@ +C_GetFunctionList diff --git a/security/manager/ssl/tests/unit/test_builtins/dynamic-library/moz.build b/security/manager/ssl/tests/unit/test_builtins/dynamic-library/moz.build new file mode 100644 index 000000000000..439d0c556929 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_builtins/dynamic-library/moz.build @@ -0,0 +1,46 @@ +# -*- 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/. + +FINAL_TARGET = "_tests/xpcshell/security/manager/ssl/tests/unit/test_builtins" + +USE_LIBS += ["test-builtins-static"] + +# see notes in ipcclientcerts/dynamic-library/moz.build + +if CONFIG["OS_ARCH"] == "Linux" and CONFIG["OS_TARGET"] != "Android": + SOURCES += [ + "stub.cpp", + ] +else: + SOURCES += [ + "stub.c", + ] + +if CONFIG["OS_TARGET"] == "Android": + OS_LIBS += ["m"] + +if CONFIG["OS_ARCH"] == "WINNT": + OS_LIBS += [ + "advapi32", + "userenv", + "ws2_32", + ] + OS_LIBS += [ + "bcrypt", + "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", + ] + +SharedLibrary("test_builtins") + +NoVisibilityFlags() +SYMBOLS_FILE = "builtins.symbols" diff --git a/security/manager/ssl/tests/unit/test_builtins/dynamic-library/stub.c b/security/manager/ssl/tests/unit/test_builtins/dynamic-library/stub.c new file mode 100644 index 000000000000..75139c48bf37 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_builtins/dynamic-library/stub.c @@ -0,0 +1,27 @@ +/* -*- 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/. */ + +#include "pkcs11.h" + +// see notes in ipcclientcerts/dynamic-library/stub.c + +CK_RV BUILTINSC_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); + +CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) { + return BUILTINSC_GetFunctionList(ppFunctionList); +} + +#ifdef __MINGW32__ +# include "mozilla/Assertions.h" +void _Unwind_Resume() { MOZ_CRASH("Unexpected call to _Unwind_*"); } +void _Unwind_GetDataRelBase() { _Unwind_Resume(); } +void _Unwind_GetTextRelBase() { _Unwind_Resume(); } +void _Unwind_GetLanguageSpecificData() { _Unwind_Resume(); } +void _Unwind_GetIPInfo() { _Unwind_Resume(); } +void _Unwind_GetRegionStart() { _Unwind_Resume(); } +void _Unwind_SetGR() { _Unwind_Resume(); } +void _Unwind_SetIP() { _Unwind_Resume(); } +void _GCC_specific_handler() { _Unwind_Resume(); } +#endif diff --git a/security/manager/ssl/tests/unit/test_builtins/dynamic-library/stub.cpp b/security/manager/ssl/tests/unit/test_builtins/dynamic-library/stub.cpp new file mode 100644 index 000000000000..414f5a68c188 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_builtins/dynamic-library/stub.cpp @@ -0,0 +1,17 @@ +/* -*- 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/. */ + +#include "pkcs11.h" + +// see notes in ipcclientcerts/dynamic-library/stub.cpp + +extern "C" { + +CK_RV BUILTINSC_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); + +CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) { + return BUILTINSC_GetFunctionList(ppFunctionList); +} +} diff --git a/security/manager/ssl/tests/unit/test_builtins/moz.build b/security/manager/ssl/tests/unit/test_builtins/moz.build new file mode 100644 index 000000000000..1f6d2cf47e87 --- /dev/null +++ b/security/manager/ssl/tests/unit/test_builtins/moz.build @@ -0,0 +1,11 @@ +# -*- 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"] + +OS_LIBS += CONFIG["DL_LIBS"] + +RustLibrary("test-builtins-static") diff --git a/security/manager/ssl/tests/unit/xpcshell.toml b/security/manager/ssl/tests/unit/xpcshell.toml index 82abfcb85857..4fa0383b9c54 100644 --- a/security/manager/ssl/tests/unit/xpcshell.toml +++ b/security/manager/ssl/tests/unit/xpcshell.toml @@ -9,6 +9,7 @@ support-files = [ "ocsp_certs/**", "test_baseline_requirements/**", "test_broken_fips/**", + "test_builtins/**", "test_cert_eku/**", "test_cert_embedded_null/**", "test_cert_keyUsage/**", @@ -71,6 +72,8 @@ skip-if = [ "os == 'linux'" ] +["test_builtins.js"] + ["test_certDB_export_pkcs12.js"] ["test_certDB_export_pkcs12_with_primary_password.js"]