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 250 : pub fn content_type(&self) -> String {
19 250 : self.ptr.content_type().to_string()
20 250 : }
21 :
22 250 : pub fn value(&self) -> Option<Content<'_>> {
23 250 : into_optional(self.ptr.value())
24 250 : }
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 250 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
40 250 : f.debug_struct("ContentInfo")
41 250 : .field("content_type", &self.content_type())
42 250 : .finish()
43 250 : }
44 : }
45 :
46 : impl<'a> FromFFI<ffi::PE_ContentInfo> for ContentInfo<'a> {
47 500 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_ContentInfo>) -> Self {
48 500 : ContentInfo {
49 500 : ptr,
50 500 : _owner: PhantomData,
51 500 : }
52 500 : }
53 : }
54 :
55 250 : #[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 250 : fn from_ffi(ffi_entry: cxx::UniquePtr<ffi::PE_ContentInfo_Content>) -> Self {
64 250 : unsafe {
65 250 : let content_ref = ffi_entry.as_ref().unwrap();
66 250 : if ffi::PE_SpcIndirectData::classof(content_ref) {
67 160 : let raw = {
68 160 : type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
69 160 : type To = cxx::UniquePtr<ffi::PE_SpcIndirectData>;
70 160 : std::mem::transmute::<From, To>(ffi_entry)
71 160 : };
72 160 : Content::SpcIndirectData(SpcIndirectData::from_ffi(raw))
73 : }
74 90 : else if ffi::PE_PKCS9TSTInfo::classof(content_ref) {
75 90 : let raw = {
76 90 : type From = cxx::UniquePtr<ffi::PE_ContentInfo_Content>;
77 90 : type To = cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>;
78 90 : std::mem::transmute::<From, To>(ffi_entry)
79 90 : };
80 90 : 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 250 : }
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 320 : pub fn file(&self) -> String {
111 320 : self.ptr.file().to_string()
112 320 : }
113 :
114 320 : pub fn url(&self) -> String {
115 320 : self.ptr.url().to_string()
116 320 : }
117 :
118 : /// PE's authentihash
119 : ///
120 : /// See: [`crate::pe::Binary::authentihash`]
121 160 : pub fn digest(&self) -> &[u8] {
122 160 : to_slice!(self.ptr.digest());
123 160 : }
124 :
125 : /// Digest used to hash the file
126 320 : pub fn digest_algorithm(&self) -> Algorithms {
127 320 : Algorithms::from(self.ptr.digest_algorithm())
128 320 : }
129 : }
130 :
131 : impl std::fmt::Debug for SpcIndirectData<'_> {
132 320 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 320 : f.debug_struct("SpcIndirectData")
134 320 : .field("file", &self.file())
135 320 : .field("url", &self.url())
136 320 : .field("digest_algorithm", &self.digest_algorithm())
137 320 : .finish()
138 320 : }
139 : }
140 :
141 : impl FromFFI<ffi::PE_SpcIndirectData> for SpcIndirectData<'_> {
142 160 : fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_SpcIndirectData>) -> Self {
143 160 : Self {
144 160 : ptr: cmd,
145 160 : _owner: PhantomData,
146 160 : }
147 160 : }
148 : }
149 :
150 : impl ContentTrait for SpcIndirectData<'_> {
151 0 : fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
152 0 : self.ptr.as_ref().unwrap().as_ref()
153 0 : }
154 : }
155 :
156 : pub struct PKCS9TSTInfo<'a> {
157 : ptr: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>,
158 : _owner: PhantomData<&'a ffi::PE_ContentInfo>,
159 : }
160 :
161 : impl PKCS9TSTInfo<'_> {
162 : // TODO(romain): Add API
163 : }
164 :
165 : impl std::fmt::Debug for PKCS9TSTInfo<'_> {
166 90 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
167 90 : f.debug_struct("PKCS9TSTInfo")
168 90 : .finish()
169 90 : }
170 : }
171 :
172 : impl FromFFI<ffi::PE_PKCS9TSTInfo> for PKCS9TSTInfo<'_> {
173 90 : fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_PKCS9TSTInfo>) -> Self {
174 90 : Self {
175 90 : ptr: cmd,
176 90 : _owner: PhantomData,
177 90 : }
178 90 : }
179 : }
180 :
181 : impl ContentTrait for PKCS9TSTInfo<'_> {
182 0 : fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
183 0 : self.ptr.as_ref().unwrap().as_ref()
184 0 : }
185 : }
186 :
187 :
188 : pub struct Generic<'a> {
189 : ptr: cxx::UniquePtr<ffi::PE_GenericContent>,
190 : _owner: PhantomData<&'a ffi::PE_ContentInfo>,
191 : }
192 :
193 : impl Generic<'_> {
194 0 : pub fn raw(&self) -> &[u8] {
195 0 : to_slice!(self.ptr.raw());
196 0 : }
197 :
198 0 : pub fn oid(&self) -> String {
199 0 : self.ptr.oid().to_string()
200 0 : }
201 :
202 : }
203 :
204 : impl std::fmt::Debug for Generic<'_> {
205 0 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
206 0 : f.debug_struct("Generic").finish()
207 0 : }
208 : }
209 :
210 : impl FromFFI<ffi::PE_GenericContent> for Generic<'_> {
211 0 : fn from_ffi(cmd: cxx::UniquePtr<ffi::PE_GenericContent>) -> Self {
212 0 : Self {
213 0 : ptr: cmd,
214 0 : _owner: PhantomData,
215 0 : }
216 0 : }
217 : }
218 :
219 : impl ContentTrait for Generic<'_> {
220 0 : fn as_generic(&self) -> &ffi::PE_ContentInfo_Content {
221 0 : self.ptr.as_ref().unwrap().as_ref()
222 0 : }
223 : }
224 :
|