pelite/
security.rs

1/*!
2Security Directory.
3
4The security directory contains the digital signature if the module is signed.
5The security directory is only available on disk images and isn't mapped to memory.
6
7# Examples
8
9```
10# #![allow(unused_variables)]
11use pelite::pe64::{Pe, PeFile};
12
13# #[allow(dead_code)]
14fn example(file: PeFile<'_>) -> pelite::Result<()> {
15	// Access the security directory
16	let security = file.security()?;
17
18	// The raw certificate data bytes
19	let certificate_data = security.certificate_data();
20
21	Ok(())
22}
23```
24*/
25
26use std::{fmt, mem};
27use crate::image::WIN_CERTIFICATE;
28use crate::util::AlignTo;
29
30/// Security Directory.
31///
32/// For more information see the [module-level documentation](index.html).
33#[derive(Copy, Clone)]
34pub struct Security<'a> {
35	image: &'a [u8], // unsafe: MUST BE DWORD ALIGNED!
36}
37impl<'a> Security<'a> {
38	pub(crate) unsafe fn new(image: &'a [u8]) -> Security<'a> {
39		debug_assert!(image.as_ptr().aligned_to(mem::align_of::<WIN_CERTIFICATE>()));
40		debug_assert!(image.len() >= 8);
41		Security { image }
42	}
43	/// Returns the underlying security directory image.
44	pub fn image(&self) -> &'a WIN_CERTIFICATE {
45		// Safety checked by new
46		unsafe {
47			&*(self.image.as_ptr() as *const _)
48		}
49	}
50	/// Gets the type of the certificate.
51	///
52	/// List of known certificate types:
53	///
54	/// * [X.509: `WIN_CERT_TYPE_X509`](../../image/constant.WIN_CERT_TYPE_X509.html)
55	/// * [PKCS SignedData: `WIN_CERT_TYPE_PKCS_SIGNED_DATA`](../../image/constant.WIN_CERT_TYPE_PKCS_SIGNED_DATA.html)
56	/// * [PKCS1_MODULE_SIGN: `WIN_CERT_TYPE_PKCS1_SIGN`](../../image/constant.WIN_CERT_TYPE_PKCS1_SIGN.html)
57	pub fn certificate_type(&self) -> u16 {
58		self.image().wCertificateType
59	}
60	/// Gets the raw certificate data bytes.
61	///
62	/// The interpretation of this data depends the type of the certificate.
63	/// No further introspection is provided.
64	///
65	/// External tools such as _OpenSSL_ can be used to further disect and analyze this data.
66	/// Eg. for `WIN_CERT_TYPE_PKCS_SIGNED_DATA` the following can be used to decode the bytes:
67	///
68	/// ```sh
69	/// openssl pkcs7 -inform DER -print_certs -text -in pe_certificate
70	/// ```
71	pub fn certificate_data(&self) -> &'a [u8] {
72		// Safety checked by new
73		unsafe {
74			self.image.get_unchecked(8..)
75		}
76	}
77}
78impl<'a> fmt::Debug for Security<'a> {
79	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80		f.debug_struct("Security")
81			.field("certificate_type", &self.certificate_type())
82			.field("certificate_data.len", &self.certificate_data().len())
83			.finish()
84	}
85}
86
87#[cfg(feature = "serde")]
88mod serde {
89	use crate::util::serde_helper::*;
90	use super::Security;
91
92	impl<'a> Serialize for Security<'a> {
93		fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
94			let is_human_readable = serializer.is_human_readable();
95			let mut state = serializer.serialize_struct("Security", 2)?;
96			state.serialize_field("certificate_type", &self.certificate_type())?;
97			if cfg!(feature = "data-encoding") && is_human_readable {
98				#[cfg(feature = "data-encoding")]
99				state.serialize_field("certificate_data",
100					&data_encoding::BASE64.encode(self.certificate_data()))?;
101			}
102			else {
103				state.serialize_field("certificate_data", &self.certificate_data())?;
104			}
105			state.end()
106		}
107	}
108}