"use strict"; ChromeUtils.defineESModuleGetters(this, { MockRegistry: "resource://testing-common/MockRegistry.sys.mjs", ctypes: "resource://gre/modules/ctypes.sys.mjs", }); do_get_profile(); let tmpDir; let baseDir; let slug = AppConstants.platform === "linux" ? "pkcs11-modules" : "PKCS11Modules"; add_task(async function setupTest() { tmpDir = await IOUtils.createUniqueDirectory( Services.dirsvc.get("TmpD", Ci.nsIFile).path, "PKCS11" ); baseDir = PathUtils.join(tmpDir, slug); await IOUtils.makeDirectory(baseDir); }); registerCleanupFunction(async () => { await IOUtils.remove(tmpDir, { recursive: true }); }); const testmodule = PathUtils.join( PathUtils.parent(Services.dirsvc.get("CurWorkD", Ci.nsIFile).path, 5), "security", "manager", "ssl", "tests", "unit", "pkcs11testmodule", ctypes.libraryName("pkcs11testmodule") ); // This function was inspired by the native messaging test under // toolkit/components/extensions async function setupManifests(modules) { async function writeManifest(module) { let manifest = { name: module.name, description: module.description, path: module.path, type: "pkcs11", allowed_extensions: [module.id], }; let manifestPath = PathUtils.join(baseDir, `${module.name}.json`); await IOUtils.writeJSON(manifestPath, manifest); return manifestPath; } switch (AppConstants.platform) { case "macosx": case "linux": let dirProvider = { getFile(property) { if ( property == "XREUserNativeManifests" || property == "XRESysNativeManifests" ) { return new FileUtils.File(tmpDir); } return null; }, }; Services.dirsvc.registerProvider(dirProvider); registerCleanupFunction(() => { Services.dirsvc.unregisterProvider(dirProvider); }); for (let module of modules) { await writeManifest(module); } break; case "win": const REGKEY = String.raw`Software\Mozilla\PKCS11Modules`; let registry = new MockRegistry(); registerCleanupFunction(() => { registry.shutdown(); }); for (let module of modules) { let manifestPath = await writeManifest(module); registry.setValue( Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER, `${REGKEY}\\${module.name}`, "", manifestPath ); } break; default: ok( false, `Loading of PKCS#11 modules is not supported on ${AppConstants.platform}` ); } } add_task(async function test_pkcs11() { async function background() { try { const { os } = await browser.runtime.getPlatformInfo(); if (os !== "win") { // Expect this call to not throw (explicitly cover regression fixed in Bug 1759162). let isInstalledNonAbsolute = await browser.pkcs11.isModuleInstalled( "testmoduleNonAbsolutePath" ); browser.test.assertFalse( isInstalledNonAbsolute, "PKCS#11 module with non absolute path expected to not be installed" ); } let isInstalled = await browser.pkcs11.isModuleInstalled("testmodule"); browser.test.assertFalse( isInstalled, "PKCS#11 module is not installed before we install it" ); await browser.pkcs11.installModule("testmodule", 0); isInstalled = await browser.pkcs11.isModuleInstalled("testmodule"); browser.test.assertTrue( isInstalled, "PKCS#11 module is installed after we install it" ); let slots = await browser.pkcs11.getModuleSlots("testmodule"); browser.test.assertEq( "Test PKCS11 Slot", slots[0].name, "The first slot name matches the expected name" ); browser.test.assertEq( "Test PKCS11 Slot 二", slots[1].name, "The second slot name matches the expected name" ); browser.test.assertTrue(slots[1].token, "The second slot has a token"); browser.test.assertFalse(slots[2].token, "The third slot has no token"); browser.test.assertEq( "Test PKCS11 Tokeñ 2 Label", slots[1].token.name, "The token name matches the expected name" ); browser.test.assertEq( "Test PKCS11 Manufacturer ID", slots[1].token.manufacturer, "The token manufacturer matches the expected manufacturer" ); browser.test.assertEq( "0.0", slots[1].token.HWVersion, "The token hardware version matches the expected version" ); browser.test.assertEq( "0.0", slots[1].token.FWVersion, "The token firmware version matches the expected version" ); browser.test.assertEq( "", slots[1].token.serial, "The token has no serial number" ); browser.test.assertFalse( slots[1].token.isLoggedIn, "The token is not logged in" ); await browser.pkcs11.uninstallModule("testmodule"); isInstalled = await browser.pkcs11.isModuleInstalled("testmodule"); browser.test.assertFalse( isInstalled, "PKCS#11 module is no longer installed after we uninstall it" ); await browser.pkcs11.installModule("testmodule"); isInstalled = await browser.pkcs11.isModuleInstalled("testmodule"); browser.test.assertTrue( isInstalled, "Installing the PKCS#11 module without flags parameter succeeds" ); await browser.pkcs11.uninstallModule("testmodule"); await browser.test.assertRejects( browser.pkcs11.isModuleInstalled("nonexistingmodule"), /No such PKCS#11 module nonexistingmodule/, "We cannot access modules if no JSON file exists" ); await browser.test.assertRejects( browser.pkcs11.isModuleInstalled("othermodule"), /No such PKCS#11 module othermodule/, "We cannot access modules if we're not listed in the module's manifest file's allowed_extensions key" ); await browser.test.assertRejects( browser.pkcs11.uninstallModule("internalmodule"), /No such PKCS#11 module internalmodule/, "We cannot uninstall the NSS Builtin Roots Module" ); await browser.test.assertRejects( browser.pkcs11.installModule("osclientcerts", 0), /No such PKCS#11 module osclientcerts/, "installModule should not work on the built-in osclientcerts module" ); await browser.test.assertRejects( browser.pkcs11.uninstallModule("osclientcerts"), /No such PKCS#11 module osclientcerts/, "uninstallModule should not work on the built-in osclientcerts module" ); await browser.test.assertRejects( browser.pkcs11.isModuleInstalled("osclientcerts"), /No such PKCS#11 module osclientcerts/, "isModuleLoaded should not work on the built-in osclientcerts module" ); await browser.test.assertRejects( browser.pkcs11.getModuleSlots("osclientcerts"), /No such PKCS#11 module osclientcerts/, "getModuleSlots should not work on the built-in osclientcerts module" ); await browser.test.assertRejects( browser.pkcs11.installModule("ipcclientcerts", 0), /No such PKCS#11 module ipcclientcerts/, "installModule should not work on the built-in ipcclientcerts module" ); await browser.test.assertRejects( browser.pkcs11.uninstallModule("ipcclientcerts"), /No such PKCS#11 module ipcclientcerts/, "uninstallModule should not work on the built-in ipcclientcerts module" ); await browser.test.assertRejects( browser.pkcs11.isModuleInstalled("ipcclientcerts"), /No such PKCS#11 module ipcclientcerts/, "isModuleLoaded should not work on the built-in ipcclientcerts module" ); await browser.test.assertRejects( browser.pkcs11.getModuleSlots("ipcclientcerts"), /No such PKCS#11 module ipcclientcerts/, "getModuleSlots should not work on the built-in ipcclientcerts module" ); browser.test.notifyPass("pkcs11"); } catch (e) { browser.test.fail(`Error: ${String(e)} :: ${e.stack}`); browser.test.notifyFail("pkcs11 failed"); } } let libDir = FileUtils.getDir("GreBinD", []); await setupManifests([ { name: "testmodule", description: "PKCS#11 Test Module", path: testmodule, id: "pkcs11@tests.mozilla.org", }, { name: "testmoduleNonAbsolutePath", description: "PKCS#11 Test Module", path: ctypes.libraryName("pkcs11testmodule"), id: "pkcs11@tests.mozilla.org", }, { name: "othermodule", description: "PKCS#11 Test Module", path: testmodule, id: "other@tests.mozilla.org", }, { name: "internalmodule", description: "Builtin Roots Module", path: PathUtils.join( Services.dirsvc.get("CurWorkD", Ci.nsIFile).path, ctypes.libraryName("nssckbi") ), id: "pkcs11@tests.mozilla.org", }, { name: "osclientcerts", description: "OS Client Cert Module", path: PathUtils.join(libDir.path, ctypes.libraryName("osclientcerts")), id: "pkcs11@tests.mozilla.org", }, ]); let extension = ExtensionTestUtils.loadExtension({ manifest: { permissions: ["pkcs11"], browser_specific_settings: { gecko: { id: "pkcs11@tests.mozilla.org" } }, }, background: background, }); await extension.startup(); await extension.awaitFinish("pkcs11"); await extension.unload(); });