use std::ptr;
use crate::crypto::utils::split_alg_id;
use crate::crypto::PrivateKeyError;
use crate::crypto::{ErasedSignatureVerifier, SignatureVerifier};
use crate::oids;
use super::ensure_nss_init;
#[derive(Debug)]
pub struct NssVerifierError(pub(crate) String);
impl std::fmt::Display for NssVerifierError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
impl std::error::Error for NssVerifierError {}
use nss_sys::{SECAlgorithmIDStr, SECItemStr, SECItemType};
use super::ffi::{
PK11_Verify, SECKEY_DecodeDERSubjectPublicKeyInfo, SECKEY_DestroyPublicKey,
SECKEY_DestroySubjectPublicKeyInfo, SECKEY_ExtractPublicKey, VFY_VerifyDataWithAlgorithmID,
};
pub struct NssSignatureVerifier;
fn do_verify_signature(
tbs_der: &[u8],
sig_alg_der: &[u8],
signature_bits: &[u8],
issuer_spki_der: &[u8],
) -> Result<(), NssVerifierError> {
if !ensure_nss_init() {
return Err(NssVerifierError("NSS initialisation failed".to_string()));
}
let (oid, oid_value, params) =
split_alg_id(sig_alg_der, |e| NssVerifierError(format!("{:?}", e)))?;
{
let comps = oid.components();
if comps.starts_with(oids::COMPOSITE_MLDSA_ARC) && comps.len() == 9 {
let sub_arc = comps[8];
return super::composite::verify_composite_mldsa_signature(
tbs_der,
sub_arc,
signature_bits,
issuer_spki_der,
);
}
}
let spki_item = SECItemStr {
type_: SECItemType::siBuffer,
data: issuer_spki_der.as_ptr() as *mut _,
len: issuer_spki_der.len() as u32,
};
let spki_info = unsafe { SECKEY_DecodeDERSubjectPublicKeyInfo(&spki_item) };
if spki_info.is_null() {
return Err(NssVerifierError(
"SECKEY_DecodeDERSubjectPublicKeyInfo failed: could not decode issuer SPKI".to_string(),
));
}
let pub_key = unsafe { SECKEY_ExtractPublicKey(spki_info) };
unsafe { SECKEY_DestroySubjectPublicKeyInfo(spki_info) };
if pub_key.is_null() {
return Err(NssVerifierError(
"SECKEY_ExtractPublicKey failed: could not extract public key from SPKI".to_string(),
));
}
let sig_item = SECItemStr {
type_: SECItemType::siBuffer,
data: signature_bits.as_ptr() as *mut _,
len: signature_bits.len() as u32,
};
let status = if oid.components() == oids::ED25519 {
let msg_item = SECItemStr {
type_: SECItemType::siBuffer,
data: tbs_der.as_ptr() as *mut _,
len: tbs_der.len() as u32,
};
unsafe { PK11_Verify(pub_key, &sig_item, &msg_item, ptr::null_mut()) }
} else {
let alg_id = SECAlgorithmIDStr {
algorithm: SECItemStr {
type_: SECItemType::siDEROID,
data: oid_value.as_ptr() as *mut _,
len: oid_value.len() as u32,
},
parameters: SECItemStr {
type_: SECItemType::siBuffer,
data: if params.is_empty() {
ptr::null_mut()
} else {
params.as_ptr() as *mut _
},
len: params.len() as u32,
},
};
unsafe {
VFY_VerifyDataWithAlgorithmID(
tbs_der.as_ptr(),
tbs_der.len() as std::ffi::c_int,
pub_key,
&sig_item,
&alg_id,
ptr::null(),
ptr::null_mut(),
)
}
};
unsafe { SECKEY_DestroyPublicKey(pub_key) };
if status == nss_sys::SECSuccess {
Ok(())
} else {
Err(NssVerifierError(
"signature verification failed".to_string(),
))
}
}
impl SignatureVerifier for NssSignatureVerifier {
type Error = NssVerifierError;
fn verify_certificate_signature(
&self,
tbs_der: &[u8],
sig_alg_der: &[u8],
signature_bits: &[u8],
issuer_spki_der: &[u8],
) -> Result<(), NssVerifierError> {
do_verify_signature(tbs_der, sig_alg_der, signature_bits, issuer_spki_der)
}
}
impl ErasedSignatureVerifier for NssSignatureVerifier {
fn verify_certificate_signature_erased(
&self,
tbs_der: &[u8],
sig_alg_der: &[u8],
signature_bits: &[u8],
issuer_spki_der: &[u8],
) -> Result<(), PrivateKeyError> {
do_verify_signature(tbs_der, sig_alg_der, signature_bits, issuer_spki_der)
.map_err(PrivateKeyError::new)
}
}