зеркало из https://github.com/mozilla/gecko-dev.git
bug 1591271 - osclientcerts: support RSA-PSS on Windows r=kjacobs
Differential Revision: https://phabricator.services.mozilla.com/D50662 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
5da49ed3d7
Коммит
06dafb8707
|
@ -250,8 +250,87 @@ impl Deref for NCryptKeyHandle {
|
|||
}
|
||||
}
|
||||
|
||||
// In some cases, the ncrypt API takes a pointer to a null-terminated wide-character string as a way
|
||||
// of specifying an algorithm. The "right" way to do this would be to take the corresponding
|
||||
// &'static str constant provided by the winapi crate, create an OsString from it, encode it as wide
|
||||
// characters, and collect it into a Vec<u16>. However, since the implementation that provides this
|
||||
// functionality isn't constant, we would have to manage the memory this creates and uses. Since
|
||||
// rust structures generally can't be self-referrential, this memory would have to live elsewhere,
|
||||
// and the nice abstractions we've created for this implementation start to break down. It's much
|
||||
// simpler to hard-code the identifiers we support, since there are only four of them.
|
||||
// The following arrays represent the identifiers "SHA1", "SHA256", "SHA384", and "SHA512",
|
||||
// respectively.
|
||||
const SHA1_ALGORITHM_STRING: &[u16] = &[83, 72, 65, 49, 0];
|
||||
const SHA256_ALGORITHM_STRING: &[u16] = &[83, 72, 65, 50, 53, 54, 0];
|
||||
const SHA384_ALGORITHM_STRING: &[u16] = &[83, 72, 65, 51, 56, 52, 0];
|
||||
const SHA512_ALGORITHM_STRING: &[u16] = &[83, 72, 65, 53, 49, 50, 0];
|
||||
|
||||
enum SignParams {
|
||||
EC,
|
||||
RSA_PKCS1(BCRYPT_PKCS1_PADDING_INFO),
|
||||
RSA_PSS(BCRYPT_PSS_PADDING_INFO),
|
||||
}
|
||||
|
||||
impl SignParams {
|
||||
fn new(key_type: KeyType, params: &Option<CK_RSA_PKCS_PSS_PARAMS>) -> Result<SignParams, ()> {
|
||||
// EC is easy, so handle that first.
|
||||
match key_type {
|
||||
KeyType::EC => return Ok(SignParams::EC),
|
||||
KeyType::RSA => {}
|
||||
}
|
||||
// If `params` is `Some`, we're doing RSA-PSS. If it is `None`, we're doing RSA-PKCS1.
|
||||
let pss_params = match params {
|
||||
Some(pss_params) => pss_params,
|
||||
None => {
|
||||
// The hash algorithm should be encoded in the data to be signed, so we don't have to
|
||||
// (and don't want to) specify a particular algorithm here.
|
||||
return Ok(SignParams::RSA_PKCS1(BCRYPT_PKCS1_PADDING_INFO {
|
||||
pszAlgId: std::ptr::null(),
|
||||
}));
|
||||
}
|
||||
};
|
||||
let algorithm_string = match pss_params.hashAlg {
|
||||
CKM_SHA_1 => SHA1_ALGORITHM_STRING,
|
||||
CKM_SHA256 => SHA256_ALGORITHM_STRING,
|
||||
CKM_SHA384 => SHA384_ALGORITHM_STRING,
|
||||
CKM_SHA512 => SHA512_ALGORITHM_STRING,
|
||||
_ => {
|
||||
error!(
|
||||
"unsupported algorithm to use with RSA-PSS: {}",
|
||||
unsafe_packed_field_access!(pss_params.hashAlg)
|
||||
);
|
||||
return Err(());
|
||||
}
|
||||
};
|
||||
Ok(SignParams::RSA_PSS(BCRYPT_PSS_PADDING_INFO {
|
||||
pszAlgId: algorithm_string.as_ptr(),
|
||||
cbSalt: pss_params.sLen,
|
||||
}))
|
||||
}
|
||||
|
||||
fn params_ptr(&mut self) -> *mut std::ffi::c_void {
|
||||
match self {
|
||||
SignParams::EC => std::ptr::null_mut(),
|
||||
SignParams::RSA_PKCS1(params) => {
|
||||
params as *mut BCRYPT_PKCS1_PADDING_INFO as *mut std::ffi::c_void
|
||||
}
|
||||
SignParams::RSA_PSS(params) => {
|
||||
params as *mut BCRYPT_PSS_PADDING_INFO as *mut std::ffi::c_void
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn flags(&self) -> u32 {
|
||||
match self {
|
||||
&SignParams::EC => 0,
|
||||
&SignParams::RSA_PKCS1(_) => NCRYPT_PAD_PKCS1_FLAG,
|
||||
&SignParams::RSA_PSS(_) => NCRYPT_PAD_PSS_FLAG,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper enum to identify a private key's type. We support EC and RSA.
|
||||
#[derive(Debug)]
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum KeyType {
|
||||
EC,
|
||||
RSA,
|
||||
|
@ -405,45 +484,48 @@ impl Key {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_signature_length(&self, data: &[u8]) -> Result<usize, ()> {
|
||||
match self.sign_internal(data, false) {
|
||||
pub fn get_signature_length(
|
||||
&self,
|
||||
data: &[u8],
|
||||
params: &Option<CK_RSA_PKCS_PSS_PARAMS>,
|
||||
) -> Result<usize, ()> {
|
||||
match self.sign_internal(data, params, false) {
|
||||
Ok(dummy_signature_bytes) => Ok(dummy_signature_bytes.len()),
|
||||
Err(()) => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sign(&self, data: &[u8]) -> Result<Vec<u8>, ()> {
|
||||
self.sign_internal(data, true)
|
||||
pub fn sign(
|
||||
&self,
|
||||
data: &[u8],
|
||||
params: &Option<CK_RSA_PKCS_PSS_PARAMS>,
|
||||
) -> Result<Vec<u8>, ()> {
|
||||
self.sign_internal(data, params, true)
|
||||
}
|
||||
|
||||
/// data: the data to sign
|
||||
/// do_signature: if true, actually perform the signature. Otherwise, return a `Vec<u8>` of the
|
||||
/// length the signature would be, if performed.
|
||||
fn sign_internal(&self, data: &[u8], do_signature: bool) -> Result<Vec<u8>, ()> {
|
||||
fn sign_internal(
|
||||
&self,
|
||||
data: &[u8],
|
||||
params: &Option<CK_RSA_PKCS_PSS_PARAMS>,
|
||||
do_signature: bool,
|
||||
) -> Result<Vec<u8>, ()> {
|
||||
// Acquiring a handle on the key can cause the OS to show some UI to the user, so we do this
|
||||
// as late as possible (i.e. here).
|
||||
let key = NCryptKeyHandle::from_cert(&self.cert)?;
|
||||
// This only applies to RSA.
|
||||
let mut padding_info = BCRYPT_PKCS1_PADDING_INFO {
|
||||
// Because the hash algorithm is encoded in `data`, we don't have to (and don't want to)
|
||||
// specify a particular algorithm here.
|
||||
pszAlgId: std::ptr::null(),
|
||||
};
|
||||
let (padding_info_ptr, flags) = match self.key_type_enum {
|
||||
KeyType::EC => (std::ptr::null_mut(), 0),
|
||||
KeyType::RSA => (
|
||||
&mut padding_info as *mut BCRYPT_PKCS1_PADDING_INFO,
|
||||
NCRYPT_PAD_PKCS1_FLAG,
|
||||
),
|
||||
};
|
||||
let mut sign_params = SignParams::new(self.key_type_enum, params)?;
|
||||
let params_ptr = sign_params.params_ptr();
|
||||
let flags = sign_params.flags();
|
||||
let mut data = data.to_vec();
|
||||
let mut signature_len = 0;
|
||||
// We call NCryptSignHash twice: the first time to get the size of the buffer we need to
|
||||
// allocate and then again to actually sign the data.
|
||||
// allocate and then again to actually sign the data, if `do_signature` is `true`.
|
||||
let status = unsafe {
|
||||
NCryptSignHash(
|
||||
*key,
|
||||
padding_info_ptr as *mut std::ffi::c_void,
|
||||
params_ptr,
|
||||
data.as_mut_ptr(),
|
||||
data.len().try_into().map_err(|_| ())?,
|
||||
std::ptr::null_mut(),
|
||||
|
@ -468,7 +550,7 @@ impl Key {
|
|||
let status = unsafe {
|
||||
NCryptSignHash(
|
||||
*key,
|
||||
padding_info_ptr as *mut std::ffi::c_void,
|
||||
params_ptr,
|
||||
data.as_mut_ptr(),
|
||||
data.len().try_into().map_err(|_| ())?,
|
||||
signature.as_mut_ptr(),
|
||||
|
|
|
@ -19,10 +19,11 @@ extern crate winapi;
|
|||
use pkcs11::types::*;
|
||||
use std::sync::Mutex;
|
||||
|
||||
mod manager;
|
||||
#[macro_use]
|
||||
mod util;
|
||||
#[cfg(target_os = "windows")]
|
||||
mod backend_windows;
|
||||
mod manager;
|
||||
mod util;
|
||||
|
||||
use manager::Manager;
|
||||
|
||||
|
@ -167,8 +168,8 @@ extern "C" fn C_GetTokenInfo(slotID: CK_SLOT_ID, pInfo: CK_TOKEN_INFO_PTR) -> CK
|
|||
CKR_OK
|
||||
}
|
||||
|
||||
/// This gets called to determine what mechanisms a slot supports. This implementation does not
|
||||
/// support any mechanisms.
|
||||
/// This gets called to determine what mechanisms a slot supports. This implementation supports
|
||||
/// ECDSA, RSA PKCS, and RSA PSS.
|
||||
extern "C" fn C_GetMechanismList(
|
||||
slotID: CK_SLOT_ID,
|
||||
pMechanismList: CK_MECHANISM_TYPE_PTR,
|
||||
|
@ -178,10 +179,20 @@ extern "C" fn C_GetMechanismList(
|
|||
error!("C_GetMechanismList: CKR_ARGUMENTS_BAD");
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
}
|
||||
if pMechanismList.is_null() {
|
||||
unsafe {
|
||||
*pulCount = 0;
|
||||
let mechanisms = [CKM_ECDSA, CKM_RSA_PKCS, CKM_RSA_PKCS_PSS];
|
||||
if !pMechanismList.is_null() {
|
||||
if unsafe { *pulCount as usize } < mechanisms.len() {
|
||||
error!("C_GetMechanismList: CKR_ARGUMENTS_BAD");
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
}
|
||||
for i in 0..mechanisms.len() {
|
||||
unsafe {
|
||||
*pMechanismList.offset(i as isize) = mechanisms[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
*pulCount = mechanisms.len() as CK_ULONG;
|
||||
}
|
||||
debug!("C_GetMechanismList: CKR_OK");
|
||||
CKR_OK
|
||||
|
@ -618,12 +629,24 @@ extern "C" fn C_SignInit(
|
|||
error!("C_SignInit: CKR_ARGUMENTS_BAD");
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
}
|
||||
// pMechanism generally appears to be empty (just mechanism is set).
|
||||
// Presumably we should validate the mechanism against hKey, but the specification doesn't
|
||||
// actually seem to require this.
|
||||
debug!("C_SignInit: mechanism is {:?}", unsafe { *pMechanism });
|
||||
let mechanism = unsafe { *pMechanism };
|
||||
debug!("C_SignInit: mechanism is {:?}", mechanism);
|
||||
let mechanism_params = if mechanism.mechanism == CKM_RSA_PKCS_PSS {
|
||||
if mechanism.ulParameterLen as usize != std::mem::size_of::<CK_RSA_PKCS_PSS_PARAMS>() {
|
||||
error!(
|
||||
"C_SignInit: bad ulParameterLen for CKM_RSA_PKCS_PSS: {}",
|
||||
unsafe_packed_field_access!(mechanism.ulParameterLen)
|
||||
);
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
}
|
||||
Some(unsafe { *(mechanism.pParameter as *const CK_RSA_PKCS_PSS_PARAMS) })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let mut manager = try_to_get_manager!();
|
||||
match manager.start_sign(hSession, hKey) {
|
||||
match manager.start_sign(hSession, hKey, mechanism_params) {
|
||||
Ok(()) => {}
|
||||
Err(()) => {
|
||||
error!("C_SignInit: CKR_GENERAL_ERROR");
|
||||
|
|
|
@ -18,8 +18,9 @@ pub struct Manager {
|
|||
sessions: BTreeSet<CK_SESSION_HANDLE>,
|
||||
/// A map of searches to PKCS #11 object handles that match those searches.
|
||||
searches: BTreeMap<CK_SESSION_HANDLE, Vec<CK_OBJECT_HANDLE>>,
|
||||
/// A map of sign operations to the object handle being used by each one.
|
||||
signs: BTreeMap<CK_SESSION_HANDLE, CK_OBJECT_HANDLE>,
|
||||
/// A map of sign operations to a pair of the object handle and optionally some params being
|
||||
/// used by each one.
|
||||
signs: BTreeMap<CK_SESSION_HANDLE, (CK_OBJECT_HANDLE, Option<CK_RSA_PKCS_PSS_PARAMS>)>,
|
||||
/// A map of object handles to the underlying objects.
|
||||
objects: BTreeMap<CK_OBJECT_HANDLE, Object>,
|
||||
/// A set of certificate identifiers (not the same as handles).
|
||||
|
@ -177,6 +178,7 @@ impl Manager {
|
|||
&mut self,
|
||||
session: CK_SESSION_HANDLE,
|
||||
key_handle: CK_OBJECT_HANDLE,
|
||||
params: Option<CK_RSA_PKCS_PSS_PARAMS>,
|
||||
) -> Result<(), ()> {
|
||||
if self.signs.contains_key(&session) {
|
||||
return Err(());
|
||||
|
@ -185,7 +187,7 @@ impl Manager {
|
|||
Some(Object::Key(_)) => {}
|
||||
_ => return Err(()),
|
||||
};
|
||||
self.signs.insert(session, key_handle);
|
||||
self.signs.insert(session, (key_handle, params));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -194,28 +196,28 @@ impl Manager {
|
|||
session: CK_SESSION_HANDLE,
|
||||
data: &[u8],
|
||||
) -> Result<usize, ()> {
|
||||
let key_handle = match self.signs.get(&session) {
|
||||
Some(key_handle) => key_handle,
|
||||
let (key_handle, params) = match self.signs.get(&session) {
|
||||
Some((key_handle, params)) => (key_handle, params),
|
||||
None => return Err(()),
|
||||
};
|
||||
let key = match self.objects.get(&key_handle) {
|
||||
Some(Object::Key(key)) => key,
|
||||
_ => return Err(()),
|
||||
};
|
||||
key.get_signature_length(data)
|
||||
key.get_signature_length(data, params)
|
||||
}
|
||||
|
||||
pub fn sign(&mut self, session: CK_SESSION_HANDLE, data: &[u8]) -> Result<Vec<u8>, ()> {
|
||||
// Performing the signature (via C_Sign, which is the only way we support) finishes the sign
|
||||
// operation, so it needs to be removed here.
|
||||
let key_handle = match self.signs.remove(&session) {
|
||||
Some(key_handle) => key_handle,
|
||||
let (key_handle, params) = match self.signs.remove(&session) {
|
||||
Some((key_handle, params)) => (key_handle, params),
|
||||
None => return Err(()),
|
||||
};
|
||||
let key = match self.objects.get(&key_handle) {
|
||||
Some(Object::Key(key)) => key,
|
||||
_ => return Err(()),
|
||||
};
|
||||
key.sign(data)
|
||||
key.sign(data, ¶ms)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,19 @@
|
|||
use byteorder::{BigEndian, NativeEndian, ReadBytesExt, WriteBytesExt};
|
||||
use std::convert::TryInto;
|
||||
|
||||
/// Accessing fields of packed structs is unsafe (it may be undefined behavior if the field isn't
|
||||
/// aligned). Since we're implementing a PKCS#11 module, we already have to trust the caller not to
|
||||
/// give us bad data, so normally we would deal with this by adding an unsafe block. If we do that,
|
||||
/// though, the compiler complains that the unsafe block is unnecessary. Thus, we use this macro to
|
||||
/// annotate the unsafe block to silence the compiler.
|
||||
macro_rules! unsafe_packed_field_access {
|
||||
($e:expr) => {{
|
||||
#[allow(unused_unsafe)]
|
||||
let tmp = unsafe { $e };
|
||||
tmp
|
||||
}};
|
||||
}
|
||||
|
||||
// This is a helper function to take a value and lay it out in memory how
|
||||
// PKCS#11 is expecting it.
|
||||
pub fn serialize_uint<T: TryInto<u64>>(value: T) -> Result<Vec<u8>, ()> {
|
||||
|
|
|
@ -1038,6 +1038,11 @@ function asyncTestCertificateUsages(certdb, cert, expectedUsages) {
|
|||
* Loads the pkcs11testmodule.cpp test PKCS #11 module, and registers a cleanup
|
||||
* function that unloads it once the calling test completes.
|
||||
*
|
||||
* @param {nsIFile} libraryFile
|
||||
* The dynamic library file that implements the module to
|
||||
* load.
|
||||
* @param {String} moduleName
|
||||
* What to call the module.
|
||||
* @param {Boolean} expectModuleUnloadToFail
|
||||
* Should be set to true for tests that manually unload the
|
||||
* test module, so the attempt to auto unload the test module
|
||||
|
@ -1045,18 +1050,15 @@ function asyncTestCertificateUsages(certdb, cert, expectedUsages) {
|
|||
* otherwise, so failure to automatically unload the test
|
||||
* module gets reported.
|
||||
*/
|
||||
function loadPKCS11TestModule(expectModuleUnloadToFail) {
|
||||
let libraryFile = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
|
||||
libraryFile.append("pkcs11testmodule");
|
||||
libraryFile.append(ctypes.libraryName("pkcs11testmodule"));
|
||||
ok(libraryFile.exists(), "The pkcs11testmodule file should exist");
|
||||
function loadPKCS11Module(libraryFile, moduleName, expectModuleUnloadToFail) {
|
||||
ok(libraryFile.exists(), "The PKCS11 module file should exist");
|
||||
|
||||
let pkcs11ModuleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
|
||||
Ci.nsIPKCS11ModuleDB
|
||||
);
|
||||
registerCleanupFunction(() => {
|
||||
try {
|
||||
pkcs11ModuleDB.deleteModule("PKCS11 Test Module");
|
||||
pkcs11ModuleDB.deleteModule(moduleName);
|
||||
} catch (e) {
|
||||
Assert.ok(
|
||||
expectModuleUnloadToFail,
|
||||
|
@ -1064,7 +1066,7 @@ function loadPKCS11TestModule(expectModuleUnloadToFail) {
|
|||
);
|
||||
}
|
||||
});
|
||||
pkcs11ModuleDB.addModule("PKCS11 Test Module", libraryFile.path, 0, 0);
|
||||
pkcs11ModuleDB.addModule(moduleName, libraryFile.path, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1094,3 +1096,70 @@ function writeLinesAndClose(lines, outputStream) {
|
|||
}
|
||||
outputStream.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {String} moduleName
|
||||
* The name of the module that should not be loaded.
|
||||
* @param {String} libraryName
|
||||
* A unique substring of name of the dynamic library file of the module
|
||||
* that should not be loaded.
|
||||
*/
|
||||
function checkPKCS11ModuleNotPresent(moduleName, libraryName) {
|
||||
let moduleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
|
||||
Ci.nsIPKCS11ModuleDB
|
||||
);
|
||||
let modules = moduleDB.listModules();
|
||||
ok(
|
||||
modules.hasMoreElements(),
|
||||
"One or more modules should be present with test module not present"
|
||||
);
|
||||
for (let module of modules) {
|
||||
notEqual(
|
||||
module.name,
|
||||
moduleName,
|
||||
"Non-test module name shouldn't equal 'PKCS11 Test Module'"
|
||||
);
|
||||
ok(
|
||||
!(module.libName && module.libName.includes(libraryName)),
|
||||
`Non-test module lib name should not include '${libraryName}'`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the test module exists in the module list.
|
||||
* Also checks various attributes of the test module for correctness.
|
||||
*
|
||||
* @param {String} moduleName
|
||||
* The name of the module that should be present.
|
||||
* @param {String} libraryName
|
||||
* A unique substring of the name of the dynamic library file
|
||||
* of the module that should be loaded.
|
||||
* @returns {nsIPKCS11Module}
|
||||
* The test module.
|
||||
*/
|
||||
function checkPKCS11ModuleExists(moduleName, libraryName) {
|
||||
let moduleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
|
||||
Ci.nsIPKCS11ModuleDB
|
||||
);
|
||||
let modules = moduleDB.listModules();
|
||||
ok(
|
||||
modules.hasMoreElements(),
|
||||
"One or more modules should be present with test module present"
|
||||
);
|
||||
let testModule = null;
|
||||
for (let module of modules) {
|
||||
if (module.name == moduleName) {
|
||||
testModule = module;
|
||||
break;
|
||||
}
|
||||
}
|
||||
notEqual(testModule, null, "Test module should have been found");
|
||||
notEqual(testModule.libName, 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;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/publicdomain/zero/1.0/
|
||||
"use strict";
|
||||
|
||||
// Tests that the platform can load the osclientcerts module.
|
||||
|
||||
// Ensure that the appropriate initialization has happened.
|
||||
do_get_profile();
|
||||
|
||||
function run_test() {
|
||||
// Check that if we have never added the osclientcerts module, that we don't
|
||||
// find it in the module list.
|
||||
checkPKCS11ModuleNotPresent("OS Client Cert Module", "osclientcerts");
|
||||
|
||||
// Check that adding the osclientcerts module makes it appear in the module
|
||||
// list.
|
||||
let libraryFile = Services.dirsvc.get("GreBinD", Ci.nsIFile);
|
||||
libraryFile.append(ctypes.libraryName("osclientcerts"));
|
||||
loadPKCS11Module(libraryFile, "OS Client Cert Module", true);
|
||||
let testModule = checkPKCS11ModuleExists(
|
||||
"OS Client Cert Module",
|
||||
"osclientcerts"
|
||||
);
|
||||
|
||||
// Check that listing the slots for the osclientcerts module works.
|
||||
let testModuleSlotNames = Array.from(
|
||||
testModule.listSlots(),
|
||||
slot => slot.name
|
||||
);
|
||||
testModuleSlotNames.sort();
|
||||
const expectedSlotNames = ["OS Client Cert Slot"];
|
||||
deepEqual(
|
||||
testModuleSlotNames,
|
||||
expectedSlotNames,
|
||||
"Actual and expected slot names should be equal"
|
||||
);
|
||||
|
||||
// Check that deleting the osclientcerts module makes it disappear from the
|
||||
// module list.
|
||||
let pkcs11ModuleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
|
||||
Ci.nsIPKCS11ModuleDB
|
||||
);
|
||||
pkcs11ModuleDB.deleteModule("OS Client Cert Module");
|
||||
checkPKCS11ModuleNotPresent("OS Client Cert Module", "osclientcerts");
|
||||
}
|
|
@ -13,63 +13,20 @@ const gModuleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
|
|||
Ci.nsIPKCS11ModuleDB
|
||||
);
|
||||
|
||||
function checkTestModuleNotPresent() {
|
||||
let modules = gModuleDB.listModules();
|
||||
ok(
|
||||
modules.hasMoreElements(),
|
||||
"One or more modules should be present with test module not present"
|
||||
);
|
||||
for (let module of modules) {
|
||||
notEqual(
|
||||
module.name,
|
||||
"PKCS11 Test Module",
|
||||
"Non-test module name shouldn't equal 'PKCS11 Test Module'"
|
||||
);
|
||||
ok(
|
||||
!(module.libName && module.libName.includes("pkcs11testmodule")),
|
||||
"Non-test module lib name should not include 'pkcs11testmodule'"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the test module exists in the module list.
|
||||
* Also checks various attributes of the test module for correctness.
|
||||
*
|
||||
* @returns {nsIPKCS11Module}
|
||||
* The test module.
|
||||
*/
|
||||
function checkTestModuleExists() {
|
||||
let modules = gModuleDB.listModules();
|
||||
ok(
|
||||
modules.hasMoreElements(),
|
||||
"One or more modules should be present with test module present"
|
||||
);
|
||||
let testModule = null;
|
||||
for (let module of modules) {
|
||||
if (module.name == "PKCS11 Test Module") {
|
||||
testModule = module;
|
||||
break;
|
||||
}
|
||||
}
|
||||
notEqual(testModule, null, "Test module should have been found");
|
||||
notEqual(testModule.libName, null, "Test module lib name should not be null");
|
||||
ok(
|
||||
testModule.libName.includes(ctypes.libraryName("pkcs11testmodule")),
|
||||
"Test module lib name should include lib name of 'pkcs11testmodule'"
|
||||
);
|
||||
|
||||
return testModule;
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
// Check that if we have never added the test module, that we don't find it
|
||||
// in the module list.
|
||||
checkTestModuleNotPresent();
|
||||
checkPKCS11ModuleNotPresent("PKCS11 Test Module", "pkcs11testmodule");
|
||||
|
||||
// Check that adding the test module makes it appear in the module list.
|
||||
loadPKCS11TestModule(true);
|
||||
let testModule = checkTestModuleExists();
|
||||
let libraryFile = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
|
||||
libraryFile.append("pkcs11testmodule");
|
||||
libraryFile.append(ctypes.libraryName("pkcs11testmodule"));
|
||||
loadPKCS11Module(libraryFile, "PKCS11 Test Module", true);
|
||||
let testModule = checkPKCS11ModuleExists(
|
||||
"PKCS11 Test Module",
|
||||
"pkcs11testmodule"
|
||||
);
|
||||
|
||||
// Check that listing the slots for the test module works.
|
||||
let testModuleSlotNames = Array.from(
|
||||
|
@ -93,7 +50,7 @@ function run_test() {
|
|||
Ci.nsIPKCS11ModuleDB
|
||||
);
|
||||
pkcs11ModuleDB.deleteModule("PKCS11 Test Module");
|
||||
checkTestModuleNotPresent();
|
||||
checkPKCS11ModuleNotPresent("PKCS11 Test Module", "pkcs11testmodule");
|
||||
|
||||
// Check miscellaneous module DB methods and attributes.
|
||||
ok(!gModuleDB.canToggleFIPS, "It should NOT be possible to toggle FIPS");
|
||||
|
|
|
@ -27,7 +27,10 @@ function find_module_by_name(moduleDB, name) {
|
|||
}
|
||||
|
||||
function run_test() {
|
||||
loadPKCS11TestModule(false);
|
||||
let libraryFile = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
|
||||
libraryFile.append("pkcs11testmodule");
|
||||
libraryFile.append(ctypes.libraryName("pkcs11testmodule"));
|
||||
loadPKCS11Module(libraryFile, "PKCS11 Test Module", false);
|
||||
|
||||
let moduleDB = Cc["@mozilla.org/security/pkcs11moduledb;1"].getService(
|
||||
Ci.nsIPKCS11ModuleDB
|
||||
|
|
|
@ -5,6 +5,8 @@ tags = psm
|
|||
skip-if = toolkit == 'android'
|
||||
support-files =
|
||||
|
||||
[test_osclientcerts_module.js]
|
||||
skip-if = os != 'win' || processor == 'aarch64'
|
||||
[test_pkcs11_module.js]
|
||||
[test_pkcs11_moduleDB.js]
|
||||
[test_pkcs11_safe_mode.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче