#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(any(feature = "std", feature = "kernel-verify"))]
use log::{debug, error, info};
pub mod cms;
#[cfg(feature = "std")]
pub mod elf;
pub mod error;
#[cfg(feature = "std")]
mod gmssl_pkcs8_decrypt;
#[cfg(feature = "std")]
pub mod gmssl_cli;
#[cfg(feature = "std")]
pub mod key;
#[cfg(any(feature = "std", feature = "kernel-verify"))]
pub mod limits;
#[cfg(any(feature = "std", feature = "kernel-verify"))]
pub mod plain;
pub use cms::{
verify_cms_signature_with_ca_opt, verify_cms_signature_with_ca_opt_and_limits, verify_sm2_cms,
verify_sm2_cms_with_ca_opt, verify_sm2_cms_with_ca_pem,
};
#[cfg(feature = "std")]
pub use cms::{
extract_cms_detached_parts, sign_gmssl_cms_attached_native, sign_sm2_cms,
CmsSignAlgorithm, SignInputs,
};
pub use error::Error;
#[cfg(feature = "std")]
pub use elf::{
append_ta_signature, append_ta_signature_bytes, append_ta_signature_objcopy,
append_ta_signature_object, normalize_relocatable_elf_bytes,
strip_ta_signature_relocatable_bytes, write_outputs,
};
#[cfg(feature = "std")]
pub use gmssl_cli::{find_gmssl_in_path, resolve_gmssl_path, DEFAULT_GMSSL};
#[cfg(any(feature = "std", feature = "kernel-verify"))]
pub use limits::{LimitsError, VerifyLimits};
#[cfg(any(feature = "std", feature = "kernel-verify"))]
pub use plain::{
build_plain_bin, build_plain_bin_with_limits, has_ta_signature_section,
plain_bytes_from_signed_elf, plain_bytes_from_signed_elf_with_limits,
ta_signature_section_bytes, ta_signature_section_bytes_with_limits, PlainError,
TA_SIGNATURE_SECTION,
};
#[cfg(any(feature = "std", feature = "kernel-verify"))]
pub type TasignError = PlainError;
#[cfg(any(feature = "std", feature = "kernel-verify"))]
pub fn verify_elf_signature(elf_bytes: &[u8], ca_pem: Option<&[u8]>) -> Result<(), Error> {
verify_elf_signature_with_limits(elf_bytes, ca_pem, &VerifyLimits::default())
}
#[cfg(any(feature = "std", feature = "kernel-verify"))]
pub fn verify_elf_signature_with_limits(
elf_bytes: &[u8],
ca_pem: Option<&[u8]>,
limits: &VerifyLimits,
) -> Result<(), Error> {
info!(
target: "tasign",
"verify_elf_signature_with_limits: elf_bytes.len: {}",
elf_bytes.len()
);
limits.check_elf_input_len(elf_bytes.len()).map_err(|e| {
error!(target: "tasign", "verify_elf: ELF 输入长度超过上限: {e}");
Error::from(e)
})?;
let pkcs7 = ta_signature_section_bytes_with_limits(elf_bytes, limits).map_err(|e| {
error!(
target: "tasign",
"verify_elf: 提取 `.ta_signature`(PKCS#7 DER)失败: {e}"
);
Error::Plain(e)
})?;
limits.check_cms_der_len(pkcs7.len()).map_err(|e| {
error!(target: "tasign", "verify_elf: `.ta_signature` DER 长度超过上限: {e}");
Error::from(e)
})?;
let plain = plain_bytes_from_signed_elf_with_limits(elf_bytes, limits).map_err(|e| {
error!(
target: "tasign",
"verify_elf: 重算签名原数据 plain 失败: {e}"
);
Error::Plain(e)
})?;
limits.check_plain_buffer_len(plain.len()).map_err(|e| {
error!(target: "tasign", "verify_elf: plain 输出长度超过上限: {e}");
Error::from(e)
})?;
debug!(target: "tasign", "verify: cms_der.len={}, plain.len={}", pkcs7.len(), plain.len());
verify_cms_signature_with_ca_opt_and_limits(pkcs7, &plain, ca_pem, limits).map_err(|e| {
error!(
target: "tasign",
"verify_elf: CMS/PKCS#7 验签失败: {e}"
);
e
})
}
#[cfg(any(feature = "std", feature = "kernel-verify"))]
pub fn verify_elf_signature_from_parts(
plain_elf_sections: &[u8],
signature_der: &[u8],
ca_pem: Option<&[u8]>,
) -> Result<(), Error> {
verify_elf_signature_from_parts_with_limits(plain_elf_sections, signature_der, ca_pem, &VerifyLimits::default())
}
#[cfg(any(feature = "std", feature = "kernel-verify"))]
pub fn verify_elf_signature_from_parts_with_limits(
plain_elf_sections: &[u8],
signature_der: &[u8],
ca_pem: Option<&[u8]>,
limits: &VerifyLimits,
) -> Result<(), Error> {
limits
.check_plain_buffer_len(plain_elf_sections.len())
.map_err(|e| {
error!(target: "tasign", "verify_elf_from_parts: plain 长度超过上限: {e}");
Error::from(e)
})?;
limits.check_cms_der_len(signature_der.len()).map_err(|e| {
error!(target: "tasign", "verify_elf_from_parts: PKCS#7 DER 长度超过上限: {e}");
Error::from(e)
})?;
verify_cms_signature_with_ca_opt_and_limits(
signature_der,
plain_elf_sections,
ca_pem,
limits,
)
.map_err(|e| {
error!(
target: "tasign",
"verify_elf_from_parts: CMS/PKCS#7 验签失败(plain 与签名不匹配等): {e}"
);
e
})
}
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
fn init_log() {
let _ = env_logger::builder().is_test(true).try_init();
}
#[test]
fn plain_ok_without_ta_signature_fixture() {
init_log();
static ELF: &[u8] = include_bytes!("../tests/fixtures/trivial_elf64.o");
let p = build_plain_bin(ELF).expect("fixture has no .ta_signature");
assert!(!p.is_empty());
}
#[test]
fn rejects_when_ta_signature_present_fixture() {
init_log();
static ELF: &[u8] = include_bytes!("../tests/fixtures/trivial_with_ta_sig.o");
let err = build_plain_bin(ELF).unwrap_err();
match err {
PlainError::TaSignatureSectionExists(_) => {}
e => panic!("unexpected: {e:?}"),
}
}
}