1#![cfg_attr(not(feature = "std"), no_std)]
20#[cfg(not(feature = "std"))]
21extern crate alloc;
22
23#[cfg(any(feature = "std", feature = "kernel-verify"))]
24use log::{debug, error, info};
25
26pub mod cms;
27#[cfg(feature = "std")]
28pub mod elf;
29pub mod error;
30#[cfg(feature = "std")]
31mod gmssl_pkcs8_decrypt;
32#[cfg(feature = "std")]
33pub mod gmssl_cli;
34#[cfg(feature = "std")]
35pub mod key;
36#[cfg(any(feature = "std", feature = "kernel-verify"))]
37pub mod limits;
38#[cfg(any(feature = "std", feature = "kernel-verify"))]
39pub mod plain;
40
41pub use cms::{
42 verify_cms_signature_with_ca_opt, verify_cms_signature_with_ca_opt_and_limits, verify_sm2_cms,
43 verify_sm2_cms_with_ca_opt, verify_sm2_cms_with_ca_pem,
44};
45#[cfg(feature = "std")]
46pub use cms::{
47 extract_cms_detached_parts, sign_gmssl_cms_attached_native, sign_sm2_cms,
48 CmsSignAlgorithm, SignInputs,
49};
50pub use error::Error;
51#[cfg(feature = "std")]
52pub use elf::{
53 append_ta_signature, append_ta_signature_bytes, append_ta_signature_objcopy,
54 append_ta_signature_object, normalize_relocatable_elf_bytes,
55 strip_ta_signature_relocatable_bytes, write_outputs,
56};
57#[cfg(feature = "std")]
58pub use gmssl_cli::{find_gmssl_in_path, resolve_gmssl_path, DEFAULT_GMSSL};
59#[cfg(any(feature = "std", feature = "kernel-verify"))]
60pub use limits::{LimitsError, VerifyLimits};
61#[cfg(any(feature = "std", feature = "kernel-verify"))]
62pub use plain::{
63 build_plain_bin, build_plain_bin_with_limits, has_ta_signature_section,
64 plain_bytes_from_signed_elf, plain_bytes_from_signed_elf_with_limits,
65 ta_signature_section_bytes, ta_signature_section_bytes_with_limits, PlainError,
66 TA_SIGNATURE_SECTION,
67};
68
69#[cfg(any(feature = "std", feature = "kernel-verify"))]
71pub type TasignError = PlainError;
72
73#[cfg(any(feature = "std", feature = "kernel-verify"))]
87pub fn verify_elf_signature(elf_bytes: &[u8], ca_pem: Option<&[u8]>) -> Result<(), Error> {
88 verify_elf_signature_with_limits(elf_bytes, ca_pem, &VerifyLimits::default())
89}
90
91#[cfg(any(feature = "std", feature = "kernel-verify"))]
93pub fn verify_elf_signature_with_limits(
94 elf_bytes: &[u8],
95 ca_pem: Option<&[u8]>,
96 limits: &VerifyLimits,
97) -> Result<(), Error> {
98 info!(
99 target: "tasign",
100 "verify_elf_signature_with_limits: elf_bytes.len: {}",
101 elf_bytes.len()
102 );
103 limits.check_elf_input_len(elf_bytes.len()).map_err(|e| {
104 error!(target: "tasign", "verify_elf: ELF 输入长度超过上限: {e}");
105 Error::from(e)
106 })?;
107 let pkcs7 = ta_signature_section_bytes_with_limits(elf_bytes, limits).map_err(|e| {
108 error!(
109 target: "tasign",
110 "verify_elf: 提取 `.ta_signature`(PKCS#7 DER)失败: {e}"
111 );
112 Error::Plain(e)
113 })?;
114 limits.check_cms_der_len(pkcs7.len()).map_err(|e| {
115 error!(target: "tasign", "verify_elf: `.ta_signature` DER 长度超过上限: {e}");
116 Error::from(e)
117 })?;
118 let plain = plain_bytes_from_signed_elf_with_limits(elf_bytes, limits).map_err(|e| {
119 error!(
120 target: "tasign",
121 "verify_elf: 重算签名原数据 plain 失败: {e}"
122 );
123 Error::Plain(e)
124 })?;
125 limits.check_plain_buffer_len(plain.len()).map_err(|e| {
126 error!(target: "tasign", "verify_elf: plain 输出长度超过上限: {e}");
127 Error::from(e)
128 })?;
129 debug!(target: "tasign", "verify: cms_der.len={}, plain.len={}", pkcs7.len(), plain.len());
130 verify_cms_signature_with_ca_opt_and_limits(pkcs7, &plain, ca_pem, limits).map_err(|e| {
131 error!(
132 target: "tasign",
133 "verify_elf: CMS/PKCS#7 验签失败: {e}"
134 );
135 e
136 })
137}
138
139#[cfg(any(feature = "std", feature = "kernel-verify"))]
147pub fn verify_elf_signature_from_parts(
148 plain_elf_sections: &[u8],
149 signature_der: &[u8],
150 ca_pem: Option<&[u8]>,
151) -> Result<(), Error> {
152 verify_elf_signature_from_parts_with_limits(plain_elf_sections, signature_der, ca_pem, &VerifyLimits::default())
153}
154
155#[cfg(any(feature = "std", feature = "kernel-verify"))]
157pub fn verify_elf_signature_from_parts_with_limits(
158 plain_elf_sections: &[u8],
159 signature_der: &[u8],
160 ca_pem: Option<&[u8]>,
161 limits: &VerifyLimits,
162) -> Result<(), Error> {
163 limits
164 .check_plain_buffer_len(plain_elf_sections.len())
165 .map_err(|e| {
166 error!(target: "tasign", "verify_elf_from_parts: plain 长度超过上限: {e}");
167 Error::from(e)
168 })?;
169 limits.check_cms_der_len(signature_der.len()).map_err(|e| {
170 error!(target: "tasign", "verify_elf_from_parts: PKCS#7 DER 长度超过上限: {e}");
171 Error::from(e)
172 })?;
173 verify_cms_signature_with_ca_opt_and_limits(
174 signature_der,
175 plain_elf_sections,
176 ca_pem,
177 limits,
178 )
179 .map_err(|e| {
180 error!(
181 target: "tasign",
182 "verify_elf_from_parts: CMS/PKCS#7 验签失败(plain 与签名不匹配等): {e}"
183 );
184 e
185 })
186}
187
188#[cfg(all(test, feature = "std"))]
189mod tests {
190 use super::*;
191
192 fn init_log() {
193 let _ = env_logger::builder().is_test(true).try_init();
194 }
195
196 #[test]
197 fn plain_ok_without_ta_signature_fixture() {
198 init_log();
199 static ELF: &[u8] = include_bytes!("../tests/fixtures/trivial_elf64.o");
200 let p = build_plain_bin(ELF).expect("fixture has no .ta_signature");
201 assert!(!p.is_empty());
202 }
203
204 #[test]
205 fn rejects_when_ta_signature_present_fixture() {
206 init_log();
207 static ELF: &[u8] = include_bytes!("../tests/fixtures/trivial_with_ta_sig.o");
208 let err = build_plain_bin(ELF).unwrap_err();
209 match err {
210 PlainError::TaSignatureSectionExists(_) => {}
211 e => panic!("unexpected: {e:?}"),
212 }
213 }
214}