#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(all(
any(feature = "std", feature = "kernel-verify"),
feature = "backend-mbedtls",
feature = "backend-rustcrypto"
))]
compile_error!("features `backend-mbedtls` and `backend-rustcrypto` are mutually exclusive");
#[cfg(all(
any(feature = "std", feature = "kernel-verify"),
not(any(feature = "backend-mbedtls", feature = "backend-rustcrypto"))
))]
compile_error!("enable exactly one of `backend-mbedtls` or `backend-rustcrypto`");
#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;
#[cfg(any(feature = "backend-mbedtls", feature = "backend-rustcrypto"))]
pub mod crypto;
#[cfg(any(feature = "backend-mbedtls", feature = "backend-rustcrypto"))]
pub mod x509;
#[cfg(any(feature = "std", feature = "kernel-verify"))]
use log::{debug, info};
#[cfg(all(feature = "std", feature = "bjca"))]
pub mod bjca;
pub mod cms;
#[cfg(feature = "std")]
pub mod cert;
#[cfg(feature = "std")]
pub mod elf;
pub mod error;
#[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;
#[cfg(feature = "std")]
pub use cms::{
extract_cms_detached_parts, sign_gmssl_cms_attached_native, sign_sm2_cms, CmsSignAlgorithm,
SignInputs,
};
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 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,
};
pub use error::Error;
#[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())?;
let pkcs7 = ta_signature_section_bytes_with_limits(elf_bytes, limits).map_err(|e| {
Error::at_verify_stage("提取 `.ta_signature`(PKCS#7 DER)", e)
})?;
limits.check_cms_der_len(pkcs7.len())?;
let plain = plain_bytes_from_signed_elf_with_limits(elf_bytes, limits).map_err(|e| {
Error::at_verify_stage("重算签名原数据 plain", e)
})?;
limits.check_plain_buffer_len(plain.len())?;
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::at_verify_stage("CMS/PKCS#7 验签", 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())?;
limits.check_cms_der_len(signature_der.len())?;
verify_cms_signature_with_ca_opt_and_limits(signature_der, plain_elf_sections, ca_pem, limits)
.map_err(|e| Error::at_verify_stage("CMS/PKCS#7 验签(分离式)", 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:?}"),
}
}
}