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}