1use super::{
2 CertificateInfo, CryptoError, CryptoResult, SignatureVerificationResult, TimestampInfo,
3};
4use crate::crypto::timestamp;
5
6#[cfg(feature = "crypto")]
7use openssl::{
8 pkcs7::Pkcs7,
9 pkey::PKey,
10 x509::{X509Ref, X509},
11};
12
13#[cfg(feature = "crypto")]
14use x509_parser::prelude::*;
15
16#[cfg(not(feature = "crypto"))]
17use sha1::Sha1;
18#[cfg(not(feature = "crypto"))]
19use sha2::{Digest, Sha256, Sha384, Sha512};
20
21pub struct Pkcs7Handler;
23pub type PKCS7Parser = Pkcs7Handler;
24
25pub struct SignedData {
26 pub content_info: ContentInfo,
27 pub certificates: Vec<Vec<u8>>,
28 pub crls: Vec<Vec<u8>>,
29 pub signers: Vec<SignerInfo>,
30}
31
32#[allow(dead_code)]
33impl Default for Pkcs7Handler {
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39impl Pkcs7Handler {
40 pub fn new() -> Self {
41 Self
42 }
43
44 pub fn verify_pkcs7(
46 &self,
47 pkcs7_data: &[u8],
48 signed_data: &[u8],
49 ) -> CryptoResult<SignatureVerificationResult> {
50 let pkcs7_info = self.parse_pkcs7_structure(pkcs7_data)?;
52
53 #[cfg(feature = "crypto")]
55 {
56 self.verify_with_openssl(&pkcs7_info, signed_data)
57 }
58 #[cfg(not(feature = "crypto"))]
59 {
60 self.verify_simple(&pkcs7_info, signed_data)
61 }
62 }
63
64 fn parse_pkcs7_structure(&self, data: &[u8]) -> CryptoResult<Pkcs7Info> {
66 if data.len() < 20 {
67 return Err(CryptoError::InvalidSignatureFormat(
68 "PKCS#7 data too short".to_string(),
69 ));
70 }
71
72 if data[0] != 0x30 {
74 return Err(CryptoError::InvalidSignatureFormat(
75 "Invalid PKCS#7 ASN.1 structure".to_string(),
76 ));
77 }
78
79 let (content_start, total_length) = self.parse_asn1_length(&data[1..])?;
81
82 if data.len() < content_start + 1 + total_length {
83 return Err(CryptoError::InvalidSignatureFormat(
84 "PKCS#7 data truncated".to_string(),
85 ));
86 }
87
88 let signed_data_oid = &[
90 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02,
91 ];
92
93 if !self.contains_sequence(data, signed_data_oid) {
94 return Err(CryptoError::InvalidSignatureFormat(
95 "Not a SignedData PKCS#7 structure".to_string(),
96 ));
97 }
98
99 let pkcs7_info = Pkcs7Info {
101 version: self.extract_version(data)?,
102 digest_algorithms: self.extract_digest_algorithms(data)?,
103 content_info: self.extract_content_info(data)?,
104 certificates: self.extract_certificates(data)?,
105 signer_infos: self.extract_signer_infos(data)?,
106 raw_data: data.to_vec(),
107 };
108
109 Ok(pkcs7_info)
110 }
111
112 fn parse_asn1_length(&self, data: &[u8]) -> CryptoResult<(usize, usize)> {
114 if data.is_empty() {
115 return Err(CryptoError::InvalidSignatureFormat(
116 "Empty ASN.1 length field".to_string(),
117 ));
118 }
119
120 let first_byte = data[0];
121
122 if first_byte & 0x80 == 0 {
123 Ok((1, first_byte as usize))
125 } else {
126 let length_octets = (first_byte & 0x7F) as usize;
128 if length_octets == 0 || length_octets > 4 || data.len() < 1 + length_octets {
129 return Err(CryptoError::InvalidSignatureFormat(
130 "Invalid ASN.1 long form length".to_string(),
131 ));
132 }
133
134 let mut length = 0usize;
135 for i in 0..length_octets {
136 length = (length << 8) | data[1 + i] as usize;
137 }
138
139 Ok((1 + length_octets, length))
140 }
141 }
142
143 fn contains_sequence(&self, data: &[u8], sequence: &[u8]) -> bool {
145 data.windows(sequence.len())
146 .any(|window| window == sequence)
147 }
148
149 fn extract_version(&self, data: &[u8]) -> CryptoResult<u32> {
151 for i in 0..data.len().min(50) {
153 if data[i] == 0x02 && i + 2 < data.len() && data[i + 1] == 0x01 {
154 return Ok(data[i + 2] as u32);
155 }
156 }
157 Ok(1) }
159
160 fn extract_digest_algorithms(&self, data: &[u8]) -> CryptoResult<Vec<String>> {
162 #[cfg(feature = "crypto")]
163 {
164 self.extract_digest_algorithms_asn1(data)
165 }
166 #[cfg(not(feature = "crypto"))]
167 {
168 Ok(vec!["SHA-256".to_string()])
170 }
171 }
172
173 #[cfg(feature = "crypto")]
175 fn extract_digest_algorithms_asn1(&self, data: &[u8]) -> CryptoResult<Vec<String>> {
176 use der_parser::der::*;
177
178 let mut algorithms = Vec::new();
179
180 match parse_der(data) {
182 Ok((_remaining, obj)) => {
183 if let DerObjectContent::Sequence(seq) = obj.content {
184 for item in seq {
186 if let DerObjectContent::Set(set) = item.content {
187 for alg_item in set {
189 if let DerObjectContent::Sequence(alg_seq) = alg_item.content {
190 if let Some(first) = alg_seq.first() {
191 if let DerObjectContent::OID(oid) = &first.content {
192 let algorithm_name = match oid.to_string().as_str() {
193 "1.3.14.3.2.26" => "SHA-1".to_string(),
194 "2.16.840.1.101.3.4.2.1" => "SHA-256".to_string(),
195 "2.16.840.1.101.3.4.2.2" => "SHA-384".to_string(),
196 "2.16.840.1.101.3.4.2.3" => "SHA-512".to_string(),
197 _ => format!("Unknown ({})", oid),
198 };
199 algorithms.push(algorithm_name);
200 }
201 }
202 }
203 }
204 }
205 }
206 }
207 }
208 Err(_) => {
209 algorithms.push("SHA-256".to_string());
211 }
212 }
213
214 if algorithms.is_empty() {
215 algorithms.push("SHA-256".to_string()); }
217
218 Ok(algorithms)
219 }
220
221 fn extract_content_info(&self, _data: &[u8]) -> CryptoResult<ContentInfo> {
223 Ok(ContentInfo {
224 content_type: "data".to_string(),
225 content: None,
226 })
227 }
228
229 fn extract_certificates(&self, data: &[u8]) -> CryptoResult<Vec<Vec<u8>>> {
231 let mut certificates = Vec::new();
233
234 let mut i = 0;
235 while i < data.len().saturating_sub(10) {
236 if data[i] == 0xA0 {
237 let (len_start, certs_length) = self.parse_asn1_length(&data[i + 1..])?;
239 let certs_start = i + 1 + len_start;
240 let certs_end = certs_start + certs_length;
241
242 if certs_end <= data.len() {
243 let certs_data = &data[certs_start..certs_end];
245 let extracted = self.extract_individual_certificates(certs_data)?;
246 certificates.extend(extracted);
247 }
248 break;
249 }
250 i += 1;
251 }
252
253 Ok(certificates)
254 }
255
256 fn extract_individual_certificates(&self, certs_data: &[u8]) -> CryptoResult<Vec<Vec<u8>>> {
258 let mut certificates = Vec::new();
259 let mut i = 0;
260
261 while i < certs_data.len().saturating_sub(10) {
262 if certs_data[i] == 0x30 && certs_data[i + 1] == 0x82 {
263 let cert_length =
265 ((certs_data[i + 2] as usize) << 8) | (certs_data[i + 3] as usize);
266 let total_length = cert_length + 4;
267
268 if i + total_length <= certs_data.len() {
269 certificates.push(certs_data[i..i + total_length].to_vec());
270 i += total_length;
271 } else {
272 break;
273 }
274 } else {
275 i += 1;
276 }
277 }
278
279 Ok(certificates)
280 }
281
282 fn extract_signer_infos(&self, data: &[u8]) -> CryptoResult<Vec<SignerInfo>> {
284 #[cfg(feature = "crypto")]
285 {
286 self.extract_signer_infos_asn1(data)
287 }
288 #[cfg(not(feature = "crypto"))]
289 {
290 Ok(vec![SignerInfo {
292 version: 1,
293 issuer_and_serial: IssuerAndSerial {
294 issuer: "CN=Unknown".to_string(),
295 serial_number: vec![1],
296 },
297 digest_algorithm: "SHA-256".to_string(),
298 signature_algorithm: "RSA".to_string(),
299 signature: vec![0; 256], authenticated_attributes: Vec::new(),
301 unauthenticated_attributes: Vec::new(),
302 }])
303 }
304 }
305
306 #[cfg(feature = "crypto")]
308 fn extract_signer_infos_asn1(&self, data: &[u8]) -> CryptoResult<Vec<SignerInfo>> {
309 use der_parser::der::*;
310
311 let mut signer_infos = Vec::new();
312
313 match parse_der(data) {
315 Ok((_remaining, obj)) => {
316 if let DerObjectContent::Sequence(seq) = obj.content {
317 for item in seq {
321 if let DerObjectContent::Set(set) = item.content {
322 for signer_item in set {
324 if let DerObjectContent::Sequence(signer_seq) = signer_item.content
325 {
326 let mut version = 1u32;
328 let digest_algorithm = "SHA-256".to_string();
329 let signature_algorithm = "RSA".to_string();
330 let signature = vec![0; 256];
331
332 if let Some(first) = signer_seq.first() {
334 if let DerObjectContent::Integer(int_bytes) = &first.content
335 {
336 if !int_bytes.is_empty() {
337 version = int_bytes[0] as u32;
338 }
339 }
340 }
341
342 signer_infos.push(SignerInfo {
343 version,
344 issuer_and_serial: IssuerAndSerial {
345 issuer: "CN=PKCS#7 Signer".to_string(),
346 serial_number: vec![1, 2, 3, 4],
347 },
348 digest_algorithm,
349 signature_algorithm,
350 signature,
351 authenticated_attributes: Vec::new(),
352 unauthenticated_attributes: Vec::new(),
353 });
354 }
355 }
356 }
357 }
358 }
359 }
360 Err(_) => {
361 signer_infos.push(SignerInfo {
363 version: 1,
364 issuer_and_serial: IssuerAndSerial {
365 issuer: "CN=Unknown".to_string(),
366 serial_number: vec![1],
367 },
368 digest_algorithm: "SHA-256".to_string(),
369 signature_algorithm: "RSA".to_string(),
370 signature: vec![0; 256],
371 authenticated_attributes: Vec::new(),
372 unauthenticated_attributes: Vec::new(),
373 });
374 }
375 }
376
377 if signer_infos.is_empty() {
378 signer_infos.push(SignerInfo {
380 version: 1,
381 issuer_and_serial: IssuerAndSerial {
382 issuer: "CN=Default Signer".to_string(),
383 serial_number: vec![1],
384 },
385 digest_algorithm: "SHA-256".to_string(),
386 signature_algorithm: "RSA".to_string(),
387 signature: vec![0; 256],
388 authenticated_attributes: Vec::new(),
389 unauthenticated_attributes: Vec::new(),
390 });
391 }
392
393 Ok(signer_infos)
394 }
395
396 #[cfg(feature = "crypto")]
398 fn verify_with_openssl(
399 &self,
400 pkcs7_info: &Pkcs7Info,
401 signed_data: &[u8],
402 ) -> CryptoResult<SignatureVerificationResult> {
403 use openssl::pkcs7::Pkcs7Flags;
404 use openssl::stack::Stack;
405 use openssl::x509::store::X509StoreBuilder;
406
407 let pkcs7 = match Pkcs7::from_der(&pkcs7_info.raw_data) {
408 Ok(p7) => p7,
409 Err(e) => {
410 return Ok(SignatureVerificationResult {
411 is_valid: false,
412 signer_certificate: None,
413 signing_time: None,
414 algorithm: "PKCS#7".to_string(),
415 error_message: Some(format!("Failed to parse PKCS#7: {}", e)),
416 certificate_chain: Vec::new(),
417 timestamp_info: None,
418 });
419 }
420 };
421
422 let empty_certs = Stack::new().unwrap();
423 let certs = pkcs7
424 .signed()
425 .and_then(|s| s.certificates())
426 .unwrap_or(&empty_certs);
427
428 let mut cert_chain = Vec::new();
429 for cert in certs.iter() {
430 if let Ok(info) = self.parse_x509_certificate_openssl(cert) {
431 cert_chain.push(info);
432 }
433 }
434
435 let mut store_builder = X509StoreBuilder::new()
436 .map_err(|e| CryptoError::OpenSsl(format!("Failed to create store builder: {}", e)))?;
437 store_builder.set_default_paths().map_err(|e| {
438 CryptoError::OpenSsl(format!("Failed to load system trust store: {}", e))
439 })?;
440 let store = store_builder.build();
441
442 let mut output = Vec::new();
443 let verify_result = pkcs7.verify(
444 certs,
445 &store,
446 if signed_data.is_empty() {
447 None
448 } else {
449 Some(signed_data)
450 },
451 Some(&mut output),
452 Pkcs7Flags::empty(),
453 );
454
455 let is_valid = verify_result.is_ok();
456 let error_message = verify_result
457 .err()
458 .map(|e| format!("PKCS#7 verification failed: {}", e));
459
460 let signer_cert_info = pkcs7
461 .signers(certs, Pkcs7Flags::empty())
462 .ok()
463 .and_then(|stack| {
464 let cert = stack.iter().next()?;
465 self.parse_x509_certificate_openssl(cert).ok()
466 });
467
468 let signing_time = self.extract_signing_time(pkcs7_info);
469 let timestamp_info = self.extract_timestamp_info(pkcs7_info);
470
471 Ok(SignatureVerificationResult {
472 is_valid,
473 signer_certificate: signer_cert_info,
474 signing_time,
475 algorithm: "PKCS#7".to_string(),
476 error_message,
477 certificate_chain: cert_chain,
478 timestamp_info,
479 })
480 }
481
482 #[cfg(not(feature = "crypto"))]
484 fn verify_simple(
485 &self,
486 pkcs7_info: &Pkcs7Info,
487 signed_data: &[u8],
488 ) -> CryptoResult<SignatureVerificationResult> {
489 let signer_cert = if !pkcs7_info.certificates.is_empty() {
491 self.parse_certificate_simple(&pkcs7_info.certificates[0])
492 .ok()
493 } else {
494 None
495 };
496
497 Ok(SignatureVerificationResult {
499 is_valid: false,
500 signer_certificate: signer_cert,
501 signing_time: self.extract_signing_time(pkcs7_info),
502 algorithm: "PKCS#7".to_string(),
503 error_message: Some("Full PKCS#7 verification requires crypto features".to_string()),
504 certificate_chain: self.parse_certificate_chain(&pkcs7_info.certificates),
505 timestamp_info: self.extract_timestamp_info(pkcs7_info),
506 })
507 }
508
509 #[cfg(feature = "crypto")]
511 fn parse_x509_certificate_openssl(&self, cert: &X509Ref) -> CryptoResult<CertificateInfo> {
512 let der = cert
513 .to_der()
514 .map_err(|e| CryptoError::CertificateError(format!("X509 DER encode error: {}", e)))?;
515
516 let (_, parsed) = X509Certificate::from_der(&der).map_err(|e| {
517 CryptoError::CertificateError(format!("Failed to parse certificate: {}", e))
518 })?;
519
520 let subject = parsed.subject().to_string();
521 let issuer = parsed.issuer().to_string();
522 let serial_number = parsed.tbs_certificate.raw_serial_as_string();
523
524 let not_before = self
525 .asn1_time_to_chrono_x509(&parsed.validity().not_before)
526 .unwrap_or_else(super::chrono::Utc::now);
527 let not_after = self
528 .asn1_time_to_chrono_x509(&parsed.validity().not_after)
529 .unwrap_or_else(super::chrono::Utc::now);
530
531 let public_key_algorithm = parsed.public_key().algorithm.algorithm.to_string();
532 let signature_algorithm = parsed.signature_algorithm.algorithm.to_string();
533
534 let fingerprint_sha256 = self
535 .compute_sha256(&der)
536 .map(|hash| hash.iter().map(|byte| format!("{:02x}", byte)).collect())
537 .unwrap_or_else(|_| "unknown".to_string());
538
539 let key_usage = parse_key_usage_from_x509(&parsed);
540 let extended_key_usage = parse_extended_key_usage_from_x509(&parsed);
541 let is_ca = parse_is_ca_from_x509(&parsed);
542
543 Ok(CertificateInfo {
544 subject,
545 issuer,
546 serial_number,
547 der,
548 not_before,
549 not_after,
550 public_key_algorithm,
551 signature_algorithm,
552 key_usage,
553 extended_key_usage,
554 is_ca,
555 fingerprint_sha256,
556 })
557 }
558
559 #[allow(dead_code)]
561 fn parse_certificate_simple(&self, cert_data: &[u8]) -> CryptoResult<CertificateInfo> {
562 #[cfg(feature = "crypto")]
563 {
564 self.parse_certificate_with_x509_parser(cert_data)
565 }
566 #[cfg(not(feature = "crypto"))]
567 {
568 self.parse_certificate_basic(cert_data)
569 }
570 }
571
572 #[cfg(feature = "crypto")]
574 #[allow(dead_code)]
575 fn parse_certificate_with_x509_parser(
576 &self,
577 cert_data: &[u8],
578 ) -> CryptoResult<CertificateInfo> {
579 let (_, cert) = X509Certificate::from_der(cert_data).map_err(|e| {
581 CryptoError::CertificateError(format!("Failed to parse certificate: {}", e))
582 })?;
583
584 let subject = cert.subject().to_string();
585 let issuer = cert.issuer().to_string();
586 let serial_number = cert.tbs_certificate.raw_serial_as_string();
587
588 let not_before = self
589 .asn1_time_to_chrono_x509(&cert.validity().not_before)
590 .unwrap_or_else(super::chrono::Utc::now);
591 let not_after = self
592 .asn1_time_to_chrono_x509(&cert.validity().not_after)
593 .unwrap_or_else(super::chrono::Utc::now);
594
595 let public_key_algorithm = cert.public_key().algorithm.algorithm.to_string();
596 let signature_algorithm = cert.signature_algorithm.algorithm.to_string();
597
598 let fingerprint_sha256 = self
599 .compute_sha256(cert_data)
600 .map(|hash| hash.iter().map(|byte| format!("{:02x}", byte)).collect())
601 .unwrap_or_else(|_| "unknown".to_string());
602
603 let key_usage = parse_key_usage_from_x509(&cert);
604 let extended_key_usage = parse_extended_key_usage_from_x509(&cert);
605 let is_ca = parse_is_ca_from_x509(&cert);
606
607 Ok(CertificateInfo {
608 subject,
609 issuer,
610 serial_number,
611 der: cert_data.to_vec(),
612 not_before,
613 not_after,
614 public_key_algorithm,
615 signature_algorithm,
616 key_usage,
617 extended_key_usage,
618 is_ca,
619 fingerprint_sha256,
620 })
621 }
622
623 #[cfg(feature = "crypto")]
625 #[allow(dead_code)]
626 fn asn1_time_to_chrono_x509(
627 &self,
628 _asn1_time: &ASN1Time,
629 ) -> Option<super::chrono::DateTime<super::chrono::Utc>> {
630 let time = _asn1_time.to_datetime();
631 Some(super::chrono::DateTime::from_timestamp(
632 time.unix_timestamp(),
633 ))
634 }
635
636 #[cfg(not(feature = "crypto"))]
638 fn parse_certificate_basic(&self, cert_data: &[u8]) -> CryptoResult<CertificateInfo> {
639 if cert_data.len() < 100 {
640 return Err(CryptoError::CertificateError(
641 "Certificate too short".to_string(),
642 ));
643 }
644
645 Ok(CertificateInfo {
647 subject: "CN=PKCS#7 Signer".to_string(),
648 issuer: "CN=Unknown CA".to_string(),
649 serial_number: "123456".to_string(),
650 der: cert_data.to_vec(),
651 not_before: super::chrono::Utc::now(),
652 not_after: super::chrono::Utc::now(),
653 public_key_algorithm: "RSA".to_string(),
654 signature_algorithm: "SHA256withRSA".to_string(),
655 key_usage: vec!["Digital Signature".to_string()],
656 extended_key_usage: vec!["Code Signing".to_string()],
657 is_ca: false,
658 fingerprint_sha256: "basic_cert_fingerprint".to_string(),
659 })
660 }
661
662 #[allow(dead_code)]
664 fn parse_certificate_chain(&self, cert_data_list: &[Vec<u8>]) -> Vec<CertificateInfo> {
665 cert_data_list
666 .iter()
667 .filter_map(|cert_data| self.parse_certificate_simple(cert_data).ok())
668 .collect()
669 }
670
671 fn extract_signing_time(
673 &self,
674 pkcs7_info: &Pkcs7Info,
675 ) -> Option<super::chrono::DateTime<super::chrono::Utc>> {
676 for signer_info in &pkcs7_info.signer_infos {
678 for attr in &signer_info.authenticated_attributes {
679 if attr.oid == "1.2.840.113549.1.9.5" {
680 return Some(super::chrono::Utc::now()); }
684 }
685 }
686 None
687 }
688
689 fn extract_timestamp_info(&self, pkcs7_info: &Pkcs7Info) -> Option<TimestampInfo> {
691 for signer_info in &pkcs7_info.signer_infos {
693 for attr in &signer_info.unauthenticated_attributes {
694 if attr.oid == "1.2.840.113549.1.9.16.2.14" {
695 if let Some(value) = attr.values.first() {
697 if let Ok(parsed) = timestamp::parse_timestamp_token(value) {
698 let hash_algorithm = parsed
699 .hash_algorithm
700 .unwrap_or_else(|| "Unknown".to_string());
701 let timestamp_authority = parsed
702 .tsa_certificate_der
703 .as_deref()
704 .and_then(Self::extract_cert_subject)
705 .or(parsed.policy_oid)
706 .unwrap_or_else(|| "Unknown TSA".to_string());
707 let error_message = if parsed.message_imprint.is_some() {
708 Some(
709 "Timestamp parsed; digest verification requires document bytes"
710 .to_string(),
711 )
712 } else {
713 Some("Timestamp missing message imprint".to_string())
714 };
715 return Some(TimestampInfo {
716 timestamp: parsed.time,
717 timestamp_authority,
718 hash_algorithm,
719 is_valid: false,
720 error_message,
721 });
722 }
723 }
724 }
725 }
726 }
727 None
728 }
729
730 #[cfg(feature = "crypto")]
731 fn extract_cert_subject(cert_der: &[u8]) -> Option<String> {
732 use openssl::x509::X509;
733
734 let cert = X509::from_der(cert_der).ok()?;
735 let subject = cert.subject_name();
736 subject
737 .entries()
738 .next()
739 .and_then(|entry| entry.data().as_utf8().ok().map(|s| s.to_string()))
740 }
741
742 #[cfg(not(feature = "crypto"))]
743 fn extract_cert_subject(_cert_der: &[u8]) -> Option<String> {
744 None
745 }
746
747 pub fn compute_digest(&self, data: &[u8], algorithm: &str) -> CryptoResult<Vec<u8>> {
749 match algorithm {
750 "SHA-1" => self.compute_sha1(data),
751 "SHA-256" => self.compute_sha256(data),
752 "SHA-384" => self.compute_sha384(data),
753 "SHA-512" => self.compute_sha512(data),
754 _ => Err(CryptoError::UnsupportedAlgorithm(format!(
755 "Unsupported digest algorithm: {}",
756 algorithm
757 ))),
758 }
759 }
760
761 #[cfg(feature = "crypto")]
762 fn compute_sha1(&self, data: &[u8]) -> CryptoResult<Vec<u8>> {
763 use openssl::hash::{hash, MessageDigest};
764
765 hash(MessageDigest::sha1(), data)
766 .map(|digest| digest.to_vec())
767 .map_err(|e| {
768 CryptoError::UnsupportedAlgorithm(format!("SHA-1 computation failed: {}", e))
769 })
770 }
771
772 #[cfg(feature = "crypto")]
773 fn compute_sha256(&self, data: &[u8]) -> CryptoResult<Vec<u8>> {
774 use openssl::hash::{hash, MessageDigest};
775
776 hash(MessageDigest::sha256(), data)
777 .map(|digest| digest.to_vec())
778 .map_err(|e| {
779 CryptoError::UnsupportedAlgorithm(format!("SHA-256 computation failed: {}", e))
780 })
781 }
782
783 #[cfg(feature = "crypto")]
784 fn compute_sha384(&self, data: &[u8]) -> CryptoResult<Vec<u8>> {
785 use openssl::hash::{hash, MessageDigest};
786
787 hash(MessageDigest::sha384(), data)
788 .map(|digest| digest.to_vec())
789 .map_err(|e| {
790 CryptoError::UnsupportedAlgorithm(format!("SHA-384 computation failed: {}", e))
791 })
792 }
793
794 #[cfg(feature = "crypto")]
795 fn compute_sha512(&self, data: &[u8]) -> CryptoResult<Vec<u8>> {
796 use openssl::hash::{hash, MessageDigest};
797
798 hash(MessageDigest::sha512(), data)
799 .map(|digest| digest.to_vec())
800 .map_err(|e| {
801 CryptoError::UnsupportedAlgorithm(format!("SHA-512 computation failed: {}", e))
802 })
803 }
804
805 #[cfg(not(feature = "crypto"))]
806 fn compute_sha1(&self, data: &[u8]) -> CryptoResult<Vec<u8>> {
807 let mut hasher = Sha1::new();
808 hasher.update(data);
809 Ok(hasher.finalize().to_vec())
810 }
811
812 #[cfg(not(feature = "crypto"))]
813 fn compute_sha256(&self, data: &[u8]) -> CryptoResult<Vec<u8>> {
814 let mut hasher = Sha256::new();
815 hasher.update(data);
816 Ok(hasher.finalize().to_vec())
817 }
818
819 #[cfg(not(feature = "crypto"))]
820 fn compute_sha384(&self, data: &[u8]) -> CryptoResult<Vec<u8>> {
821 let mut hasher = Sha384::new();
822 hasher.update(data);
823 Ok(hasher.finalize().to_vec())
824 }
825
826 #[cfg(not(feature = "crypto"))]
827 fn compute_sha512(&self, data: &[u8]) -> CryptoResult<Vec<u8>> {
828 let mut hasher = Sha512::new();
829 hasher.update(data);
830 Ok(hasher.finalize().to_vec())
831 }
832
833 pub fn parse_signed_data(&self, contents: &[u8]) -> CryptoResult<SignedData> {
835 Ok(SignedData {
838 content_info: ContentInfo {
839 content_type: "1.2.840.113549.1.7.1".to_string(), content: Some(contents.to_vec()),
841 },
842 certificates: Vec::new(),
843 crls: Vec::new(),
844 signers: Vec::new(),
845 })
846 }
847}
848
849#[cfg(feature = "crypto")]
850fn parse_key_usage_from_x509(cert: &X509Certificate) -> Vec<String> {
851 use x509_parser::extensions::ParsedExtension;
852 for ext in cert.extensions() {
853 if let ParsedExtension::KeyUsage(ku) = &ext.parsed_extension() {
854 let mut out = Vec::new();
855 if ku.digital_signature() {
856 out.push("Digital Signature".to_string());
857 }
858 if ku.non_repudiation() {
859 out.push("Non Repudiation".to_string());
860 }
861 if ku.key_encipherment() {
862 out.push("Key Encipherment".to_string());
863 }
864 if ku.data_encipherment() {
865 out.push("Data Encipherment".to_string());
866 }
867 if ku.key_agreement() {
868 out.push("Key Agreement".to_string());
869 }
870 if ku.key_cert_sign() {
871 out.push("Certificate Signing".to_string());
872 }
873 if ku.crl_sign() {
874 out.push("CRL Signing".to_string());
875 }
876 if ku.encipher_only() {
877 out.push("Encipher Only".to_string());
878 }
879 if ku.decipher_only() {
880 out.push("Decipher Only".to_string());
881 }
882 return out;
883 }
884 }
885 Vec::new()
886}
887
888#[cfg(feature = "crypto")]
889fn parse_extended_key_usage_from_x509(cert: &X509Certificate) -> Vec<String> {
890 use x509_parser::extensions::ParsedExtension;
891 for ext in cert.extensions() {
892 if let ParsedExtension::ExtendedKeyUsage(eku) = &ext.parsed_extension() {
893 let mut out = Vec::new();
894 if eku.any {
895 out.push("Any".to_string());
896 }
897 if eku.server_auth {
898 out.push("Server Auth".to_string());
899 }
900 if eku.client_auth {
901 out.push("Client Auth".to_string());
902 }
903 if eku.code_signing {
904 out.push("Code Signing".to_string());
905 }
906 if eku.email_protection {
907 out.push("Email Protection".to_string());
908 }
909 if eku.time_stamping {
910 out.push("Time Stamping".to_string());
911 }
912 if eku.ocsp_signing {
913 out.push("OCSP Signing".to_string());
914 }
915 for oid in &eku.other {
916 out.push(oid.to_string());
917 }
918 return out;
919 }
920 }
921 Vec::new()
922}
923
924#[cfg(feature = "crypto")]
925fn parse_is_ca_from_x509(cert: &X509Certificate) -> bool {
926 use x509_parser::extensions::ParsedExtension;
927 for ext in cert.extensions() {
928 if let ParsedExtension::BasicConstraints(bc) = &ext.parsed_extension() {
929 return bc.ca;
930 }
931 }
932 false
933}
934
935#[derive(Debug, Clone)]
936pub struct Pkcs7Info {
937 pub version: u32,
938 pub digest_algorithms: Vec<String>,
939 pub content_info: ContentInfo,
940 pub certificates: Vec<Vec<u8>>,
941 pub signer_infos: Vec<SignerInfo>,
942 pub raw_data: Vec<u8>,
943}
944
945#[derive(Debug, Clone)]
946pub struct ContentInfo {
947 pub content_type: String,
948 pub content: Option<Vec<u8>>,
949}
950
951#[derive(Debug, Clone)]
952pub struct SignerInfo {
953 pub version: u32,
954 pub issuer_and_serial: IssuerAndSerial,
955 pub digest_algorithm: String,
956 pub signature_algorithm: String,
957 pub signature: Vec<u8>,
958 pub authenticated_attributes: Vec<Attribute>,
959 pub unauthenticated_attributes: Vec<Attribute>,
960}
961
962#[derive(Debug, Clone)]
963pub struct IssuerAndSerial {
964 pub issuer: String,
965 pub serial_number: Vec<u8>,
966}
967
968#[derive(Debug, Clone)]
969pub struct Attribute {
970 pub oid: String,
971 pub values: Vec<Vec<u8>>,
972}
973
974pub struct Pkcs7Builder {
976 content: Option<Vec<u8>>,
977 certificates: Vec<Vec<u8>>,
978 signers: Vec<SignerConfig>,
979 detached: bool,
980}
981
982impl Default for Pkcs7Builder {
983 fn default() -> Self {
984 Self::new()
985 }
986}
987
988impl Pkcs7Builder {
989 pub fn new() -> Self {
990 Self {
991 content: None,
992 certificates: Vec::new(),
993 signers: Vec::new(),
994 detached: false,
995 }
996 }
997
998 pub fn with_content(mut self, content: Vec<u8>) -> Self {
999 self.content = Some(content);
1000 self
1001 }
1002
1003 pub fn add_certificate(mut self, cert: Vec<u8>) -> Self {
1004 self.certificates.push(cert);
1005 self
1006 }
1007
1008 pub fn add_signer(mut self, signer: SignerConfig) -> Self {
1009 self.signers.push(signer);
1010 self
1011 }
1012
1013 pub fn detached(mut self, detached: bool) -> Self {
1014 self.detached = detached;
1015 self
1016 }
1017
1018 pub fn build(self) -> CryptoResult<Vec<u8>> {
1019 #[cfg(feature = "crypto")]
1020 {
1021 self.build_with_openssl()
1022 }
1023 #[cfg(not(feature = "crypto"))]
1024 {
1025 Err(CryptoError::UnsupportedAlgorithm(
1026 "PKCS#7 building requires crypto feature".to_string(),
1027 ))
1028 }
1029 }
1030
1031 #[cfg(feature = "crypto")]
1033 fn build_with_openssl(self) -> CryptoResult<Vec<u8>> {
1034 use openssl::{
1035 pkcs7::{Pkcs7, Pkcs7Flags},
1036 stack::Stack,
1037 };
1038
1039 if self.signers.is_empty() {
1040 return Err(CryptoError::InvalidSignatureFormat(
1041 "No signers provided".to_string(),
1042 ));
1043 }
1044
1045 let mut signer_certs = Stack::new().map_err(|e| {
1047 CryptoError::InvalidSignatureFormat(format!(
1048 "Failed to create certificate stack: {}",
1049 e
1050 ))
1051 })?;
1052 let mut signer_keys = Vec::new();
1053
1054 for signer in &self.signers {
1055 let cert = X509::from_der(&signer.certificate).map_err(|e| {
1057 CryptoError::CertificateError(format!("Failed to parse signer certificate: {}", e))
1058 })?;
1059 signer_certs.push(cert).map_err(|e| {
1060 CryptoError::InvalidSignatureFormat(format!(
1061 "Failed to add certificate to stack: {}",
1062 e
1063 ))
1064 })?;
1065
1066 let key = PKey::private_key_from_der(&signer.private_key)
1068 .or_else(|_| PKey::private_key_from_pem(&signer.private_key))
1069 .map_err(|e| {
1070 CryptoError::InvalidKey(format!("Failed to parse private key: {}", e))
1071 })?;
1072 signer_keys.push(key);
1073 }
1074
1075 let mut certs = Stack::new().map_err(|e| {
1077 CryptoError::InvalidSignatureFormat(format!(
1078 "Failed to create certificate stack: {}",
1079 e
1080 ))
1081 })?;
1082 for cert_data in &self.certificates {
1083 let cert = X509::from_der(cert_data).map_err(|e| {
1084 CryptoError::CertificateError(format!("Failed to parse certificate: {}", e))
1085 })?;
1086 certs.push(cert).map_err(|e| {
1087 CryptoError::InvalidSignatureFormat(format!(
1088 "Failed to add certificate to stack: {}",
1089 e
1090 ))
1091 })?;
1092 }
1093
1094 let content_bytes;
1096 let content_slice = if let Some(content_data) = &self.content {
1097 content_bytes = content_data.as_slice();
1098 Some(content_bytes)
1099 } else {
1100 None
1101 };
1102
1103 let flags = if self.detached {
1104 Pkcs7Flags::DETACHED
1105 } else {
1106 Pkcs7Flags::empty()
1107 };
1108
1109 if let (Some(first_signer_cert), Some(first_signer_key)) =
1111 (signer_certs.get(0), signer_keys.first())
1112 {
1113 let content_for_signing = content_slice.unwrap_or(&[]);
1114
1115 let pkcs7 = Pkcs7::sign(
1116 first_signer_cert,
1117 first_signer_key,
1118 &certs,
1119 content_for_signing,
1120 flags,
1121 )
1122 .map_err(|e| {
1123 CryptoError::InvalidSignatureFormat(format!("Failed to create PKCS#7: {}", e))
1124 })?;
1125
1126 pkcs7.to_der().map_err(|e| {
1128 CryptoError::InvalidSignatureFormat(format!("Failed to serialize PKCS#7: {}", e))
1129 })
1130 } else {
1131 Err(CryptoError::InvalidSignatureFormat(
1132 "No valid signers available".to_string(),
1133 ))
1134 }
1135 }
1136}
1137
1138#[derive(Debug, Clone)]
1139pub struct SignerConfig {
1140 pub certificate: Vec<u8>,
1141 pub private_key: Vec<u8>,
1142 pub digest_algorithm: String,
1143 pub signature_algorithm: String,
1144}
1145
1146#[cfg(test)]
1147mod tests {
1148 use super::*;
1149
1150 #[test]
1151 fn test_pkcs7_handler_creation() {
1152 let handler = Pkcs7Handler::new();
1153 assert_eq!(std::mem::size_of_val(&handler), 0); }
1156
1157 #[test]
1158 fn test_asn1_length_parsing() {
1159 let handler = Pkcs7Handler::new();
1160
1161 let short_data = [0x05]; let (start, length) = handler.parse_asn1_length(&short_data).unwrap();
1164 assert_eq!(start, 1);
1165 assert_eq!(length, 5);
1166
1167 let long_data = [0x81, 0xFF]; let (start, length) = handler.parse_asn1_length(&long_data).unwrap();
1170 assert_eq!(start, 2);
1171 assert_eq!(length, 255);
1172 }
1173
1174 #[test]
1175 fn test_sequence_detection() {
1176 let handler = Pkcs7Handler::new();
1177 let data = [0x01, 0x02, 0x03, 0x04, 0x05];
1178 let sequence = [0x03, 0x04];
1179
1180 assert!(handler.contains_sequence(&data, &sequence));
1181
1182 let not_found = [0x06, 0x07];
1183 assert!(!handler.contains_sequence(&data, ¬_found));
1184 }
1185
1186 #[test]
1187 fn test_pkcs7_structure_validation() {
1188 let handler = Pkcs7Handler::new();
1189
1190 let invalid_data = [0x00, 0x01, 0x02];
1192 assert!(handler.parse_pkcs7_structure(&invalid_data).is_err());
1193
1194 let sequence_data = [0x30, 0x82, 0x01, 0x00]; assert!(handler.parse_pkcs7_structure(&sequence_data).is_err());
1198 }
1199
1200 #[test]
1201 fn test_pkcs7_builder() {
1202 let builder = Pkcs7Builder::new()
1203 .with_content(b"Hello, World!".to_vec())
1204 .detached(false);
1205
1206 let result = builder.build();
1208 assert!(result.is_err());
1209 }
1210
1211 #[test]
1212 fn test_hash_functions() {
1213 let handler = Pkcs7Handler::new();
1214 let test_data = b"test data";
1215
1216 let sha256_result = handler.compute_sha256(test_data);
1218 assert!(sha256_result.is_ok());
1219 assert_eq!(sha256_result.unwrap().len(), 32); let sha1_result = handler.compute_sha1(test_data);
1223 assert!(sha1_result.is_ok());
1224 assert_eq!(sha1_result.unwrap().len(), 20); let sha384_result = handler.compute_sha384(test_data);
1228 assert!(sha384_result.is_ok());
1229 assert_eq!(sha384_result.unwrap().len(), 48); let sha512_result = handler.compute_sha512(test_data);
1233 assert!(sha512_result.is_ok());
1234 assert_eq!(sha512_result.unwrap().len(), 64); }
1236
1237 #[test]
1238 fn test_certificate_parsing_basic() {
1239 let handler = Pkcs7Handler::new();
1240
1241 let invalid_cert_data = vec![0x30, 0x82, 0x01, 0x00]; let mut cert_data_extended = invalid_cert_data;
1246 cert_data_extended.resize(200, 0); let result = handler.parse_certificate_simple(&cert_data_extended);
1249
1250 match result {
1254 Ok(_) => {
1255 let cert_info = result.unwrap();
1257 assert!(!cert_info.subject.is_empty());
1258 assert!(!cert_info.issuer.is_empty());
1259 }
1260 Err(e) => {
1261 assert!(matches!(e, CryptoError::CertificateError(_)));
1263 if let CryptoError::CertificateError(msg) = e {
1264 assert!(msg.contains("Failed to parse certificate"));
1265 }
1266 }
1267 }
1268
1269 let too_short = vec![0x30, 0x01];
1271 let result_short = handler.parse_certificate_simple(&too_short);
1272 assert!(result_short.is_err());
1273 }
1274}