Line data Source code
1 : use std::marker::PhantomData;
2 :
3 : use lief_ffi as ffi;
4 :
5 : use crate::common::{FromFFI, into_optional};
6 : use crate::to_slice;
7 : use crate::pe::Algorithms;
8 :
9 : pub struct ContentInfo<'a> {
10 : ptr: cxx::UniquePtr<ffi::PE_ContentInfo>,
11 : _owner: PhantomData<&'a ffi::PE_Signature>,
12 : }
13 :
14 : /// ContentInfo as described in the RFC2315 <https://tools.ietf.org/html/rfc2315#section-7>
15 : impl ContentInfo<'_> {
16 : /// Return the OID that describes the content wrapped by this object.
17 : /// It should match `SPC_INDIRECT_DATA_OBJID` (`1.3.6.1.4.1.311.2.1.4`)
18 190 : pub fn content_type(&self) -> String {
19 190 : self.ptr.content_type().to_string()
20 190 : }
21 :
22 190 : pub fn value(&self) -> Option<Content<'_>> {
23 190 : into_optional(self.ptr.value())
24 190 : }
25 :
26 : /// Return the digest (authentihash) if the underlying content type is `SPC_INDIRECT_DATA_OBJID`
27 : /// Otherwise, return an empty vector
28 0 : pub fn digest(&self) -> Vec<u8> {
29 0 : Vec::from(self.ptr.digest().as_slice())
30 0 : }
31 :
32 : /// Return the digest used to hash the file
33 0 : pub fn digest_algorithm(&self) -> Algorithms {
34 0 : Algorithms::from(self.ptr.digest_algorithm())
35 0 : }
36 : }
37 :
38 : impl std::fmt::Debug for ContentInfo<'_> {
39 190 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 190 : f.debug_struct("ContentInfo")
41 190 : .field("content_type", &self.content_type())
42 190 : .finish()
43 190 : }
44 : }
45 :
46 : impl<'a> FromFFI<ffi::PE_ContentInfo> for ContentInfo<'a> {
47 380 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ContentInfo>) -> Self {
48 380 : ContentInfo {
49 380 : ptr,
50 380 : _owner: PhantomData,
51 380 : }
52 380 : }
53 : }
54 :
55 190 : #[derive(Debug)]
56 : pub enum Content<'a> {
57 : SpcIndirectData(SpcIndirectData<'a>),
58 : PKCS9TSTInfo(PKCS9TSTInfo<'a>),
59 : Generic(Generic<'a>),
60 : }
61 :
62 : impl<'a> FromFFI<ffi::PE_ContentInfo_Content> for Content<'a> {
63 190 : fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_ContentInfo_Content>) -> Self {
64 190 : unsafe {
65 190 : let content_ref = ffi_entry.as_ref().unwrap();
66 190 : if ffi::PE_SpcIndirectData::classof(content_ref) {
67 130 : let raw = {
68 130 : type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
69 130 : type To = cxx::UniquePtr<ffi::PE_SpcIndirectData>;
70 130 : std::mem::transmute::<From, To>(ffi_entry)
71 130 : };
72 130 : Content::SpcIndirectData(SpcIndirectData::from_ffi(raw))
73 : }
74 60 : else if ffi::PE_PKCS9TSTInfo::classof(content_ref) {
75 60 : let raw = {
76 60 : type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
77 60 : type To = cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>;
78 60 : std::mem::transmute::<From, To>(ffi_entry)
79 60 : };
80 60 : Content::PKCS9TSTInfo(PKCS9TSTInfo::from_ffi(raw))
81 : } else {
82 0 : let raw = {
83 0 : type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
84 0 : type To = cxx::UniquePtr<ffi::PE_GenericContent>;
85 0 : std::mem::transmute::<From, To>(ffi_entry)
86 0 : };
87 0 : Content::Generic(Generic::from_ffi(raw))
88 : }
89 : }
90 190 : }
91 : }
92 :
93 : pub trait ContentTrait {
94 : #[doc(hidden)]
95 : fn as_generic(&self) -> &ffi::PE_ContentInfo_Content;
96 :
97 : /// Return the OID that describes this content info.
98 : /// In the case of the PE authenticode, it should return `SPC_INDIRECT_DATA_OBJID (1.3.6.1.4.1.311.2.1.4)`
99 0 : fn content_type(&self) -> String {
100 0 : self.as_generic().content_type().to_string()
101 0 : }
102 : }
103 :
104 : pub struct SpcIndirectData<'a> {
105 : ptr: cxx::UniquePtr<ffi::PE_SpcIndirectData>,
106 : _owner: PhantomData<&'a ffi::PE_ContentInfo>,
107 : }
108 :
109 : impl SpcIndirectData<'_> {
110 260 : pub fn file(&self) -> String {
111 260 : self.ptr.file().to_string()
112 260 : }
113 : /// PE's authentihash
114 : ///
115 : /// See: [`crate::pe::Binary::authentihash`]
116 130 : pub fn digest(&self) -> &[u8] {
117 130 : to_slice!(self.ptr.digest());
118 130 : }
119 :
120 : /// Digest used to hash the file
121 260 : pub fn digest_algorithm(&self) -> Algorithms {
122 260 : Algorithms::from(self.ptr.digest_algorithm())
123 260 : }
124 : }
125 :
126 : impl std::fmt::Debug for SpcIndirectData<'_> {
127 260 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128 260 : f.debug_struct("SpcIndirectData")
129 260 : .field("file", &self.file())
130 260 : .field("digest_algorithm", &self.digest_algorithm())
131 260 : .finish()
132 260 : }
133 : }
134 :
135 : impl FromFFI<ffi::PE_SpcIndirectData> for SpcIndirectData<'_> {
136 130 : fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_SpcIndirectData>) -> Self {
137 130 : Self {
138 130 : ptr: cmd,
139 130 : _owner: PhantomData,
140 130 : }
141 130 : }
142 : }
143 :
144 : impl ContentTrait for SpcIndirectData<'_> {
145 0 : fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
146 0 : self.ptr.as_ref().unwrap().as_ref()
147 0 : }
148 : }
149 :
150 : pub struct PKCS9TSTInfo<'a> {
151 : ptr: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>,
152 : _owner: PhantomData<&'a ffi::PE_ContentInfo>,
153 : }
154 :
155 : impl PKCS9TSTInfo<'_> {
156 : // TODO(romain): Add API
157 : }
158 :
159 : impl std::fmt::Debug for PKCS9TSTInfo<'_> {
160 60 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 60 : f.debug_struct("PKCS9TSTInfo")
162 60 : .finish()
163 60 : }
164 : }
165 :
166 : impl FromFFI<ffi::PE_PKCS9TSTInfo> for PKCS9TSTInfo<'_> {
167 60 : fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>) -> Self {
168 60 : Self {
169 60 : ptr: cmd,
170 60 : _owner: PhantomData,
171 60 : }
172 60 : }
173 : }
174 :
175 : impl ContentTrait for PKCS9TSTInfo<'_> {
176 0 : fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
177 0 : self.ptr.as_ref().unwrap().as_ref()
178 0 : }
179 : }
180 :
181 :
182 : pub struct Generic<'a> {
183 : ptr: cxx::UniquePtr<ffi::PE_GenericContent>,
184 : _owner: PhantomData<&'a ffi::PE_ContentInfo>,
185 : }
186 :
187 : impl Generic<'_> {
188 0 : pub fn raw(&self) -> &[u8] {
189 0 : to_slice!(self.ptr.raw());
190 0 : }
191 :
192 0 : pub fn oid(&self) -> String {
193 0 : self.ptr.oid().to_string()
194 0 : }
195 :
196 : }
197 :
198 : impl std::fmt::Debug for Generic<'_> {
199 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 0 : f.debug_struct("Generic").finish()
201 0 : }
202 : }
203 :
204 : impl FromFFI<ffi::PE_GenericContent> for Generic<'_> {
205 0 : fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_GenericContent>) -> Self {
206 0 : Self {
207 0 : ptr: cmd,
208 0 : _owner: PhantomData,
209 0 : }
210 0 : }
211 : }
212 :
213 : impl ContentTrait for Generic<'_> {
214 0 : fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
215 0 : self.ptr.as_ref().unwrap().as_ref()
216 0 : }
217 : }
218 :
|