pub mod composite;
pub(super) mod ffi;
pub mod hsm_signing;
pub mod key_ops;
pub mod rsa_transport;
pub mod signature;
pub mod signing;
pub mod symmetric;
pub(crate) use composite::{composite_mldsa_signer_from_pkcs8, priv_generate_composite_mldsa};
pub(crate) use hsm_signing::{nss_hsm_signer, priv_load_from_pkcs11_uri_nss};
pub(crate) use rsa_transport::{
nss_rsa_oaep_decrypt, nss_rsa_oaep_encrypt, nss_rsa_pkcs1v15_decrypt, nss_rsa_pkcs1v15_encrypt,
};
pub use signature::{NssSignatureVerifier, NssVerifierError};
pub(crate) use signing::NssUnsupportedSigner;
pub use signing::{NssSigner, NssSignerError};
pub(crate) use symmetric::{
nss_block_cipher_provider, nss_data_hasher, nss_hmac_provider, nss_pbkdf2_provider,
nss_secure_random, nss_streaming_hasher, nss_streaming_hmac_provider,
};
pub use symmetric::{NssDataHasher, NssDataHasherError, NssHmacError, NssHmacProvider};
use std::sync::OnceLock;
pub(crate) fn ensure_nss_init() -> bool {
static NSS_INIT: OnceLock<bool> = OnceLock::new();
*NSS_INIT.get_or_init(|| {
let status = unsafe { nss_sys::NSS_NoDB_Init(std::ptr::null()) };
status == nss_sys::SECSuccess
})
}
use crate::crypto::{ErasedKeyIdHasher, KeyIdHasher, PrivateKeyError};
use crate::oids;
use ffi::{
PK11_HashBuf, SECOidTag, SEC_OID_MD5, SEC_OID_SHA1, SEC_OID_SHA224, SEC_OID_SHA256,
SEC_OID_SHA384, SEC_OID_SHA3_256, SEC_OID_SHA3_384, SEC_OID_SHA3_512, SEC_OID_SHA512,
};
pub(super) fn alg_name_to_hash_tag(algorithm: &str) -> Option<(SECOidTag, usize)> {
match algorithm {
"md5" => Some((SEC_OID_MD5, 16)),
"sha1" => Some((SEC_OID_SHA1, 20)),
"sha224" => Some((SEC_OID_SHA224, 28)),
"sha256" => Some((SEC_OID_SHA256, 32)),
"sha384" => Some((SEC_OID_SHA384, 48)),
"sha512" => Some((SEC_OID_SHA512, 64)),
"sha3-256" => Some((SEC_OID_SHA3_256, 32)),
"sha3-384" => Some((SEC_OID_SHA3_384, 48)),
"sha3-512" => Some((SEC_OID_SHA3_512, 64)),
_ => None,
}
}
pub struct NssKeyIdHasher;
#[derive(Debug)]
pub struct NssKeyIdHasherError(String);
impl std::fmt::Display for NssKeyIdHasherError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
impl std::error::Error for NssKeyIdHasherError {}
impl KeyIdHasher for NssKeyIdHasher {
type Error = NssKeyIdHasherError;
fn hash(&self, algorithm_oid: &[u32], data: &[u8]) -> Result<Vec<u8>, NssKeyIdHasherError> {
if !ensure_nss_init() {
return Err(NssKeyIdHasherError("NSS initialisation failed".to_string()));
}
let (nss_tag, out_len) = if algorithm_oid == oids::ID_SHA1 {
(SEC_OID_SHA1, 20usize)
} else if algorithm_oid == oids::ID_SHA256 {
(SEC_OID_SHA256, 32usize)
} else if algorithm_oid == oids::ID_SHA384 {
(SEC_OID_SHA384, 48usize)
} else if algorithm_oid == oids::ID_SHA512 {
(SEC_OID_SHA512, 64usize)
} else {
return Err(NssKeyIdHasherError(format!(
"unsupported hash algorithm OID: {:?}",
algorithm_oid
)));
};
let mut out = vec![0u8; out_len];
let status = unsafe {
PK11_HashBuf(
nss_tag,
out.as_mut_ptr(),
data.as_ptr(),
data.len() as std::ffi::c_int,
)
};
if status == nss_sys::SECSuccess {
Ok(out)
} else {
Err(NssKeyIdHasherError("PK11_HashBuf failed".to_string()))
}
}
}
impl ErasedKeyIdHasher for NssKeyIdHasher {
fn hash_erased(&self, algorithm_oid: &[u32], data: &[u8]) -> Result<Vec<u8>, PrivateKeyError> {
self.hash(algorithm_oid, data).map_err(PrivateKeyError::new)
}
}
pub(crate) fn nss_signature_verifier() -> Box<dyn crate::crypto::ErasedSignatureVerifier> {
Box::new(NssSignatureVerifier)
}
pub(crate) fn nss_key_id_hasher() -> Box<dyn ErasedKeyIdHasher> {
Box::new(NssKeyIdHasher)
}