Line data Source code
1 : //! PE enclave configuration
2 : use std::marker::PhantomData;
3 :
4 : use crate::{common::FromFFI, declare_iterator, to_slice};
5 : use lief_ffi as ffi;
6 :
7 : /// Defines an entry in the array of images that an enclave can import.
8 : pub struct EnclaveConfiguration<'a> {
9 : ptr: cxx::UniquePtr<ffi::PE_EnclaveConfiguration>,
10 : _owner: PhantomData<&'a ffi::PE_LoadConfiguration>,
11 : }
12 :
13 : impl EnclaveConfiguration<'_> {
14 : /// The size of the `IMAGE_ENCLAVE_CONFIG64/IMAGE_ENCLAVE_CONFIG32` structure, in bytes.
15 10 : pub fn size(&self) -> u32 {
16 10 : self.ptr.size()
17 10 : }
18 :
19 : /// The minimum size of the `IMAGE_ENCLAVE_CONFIG(32,64)` structure that the
20 : /// image loader must be able to process in order for the enclave to be usable.
21 : ///
22 : /// This member allows an enclave to inform an earlier version of the image
23 : /// loader that the image loader can safely load the enclave and ignore
24 : /// optional members added to `IMAGE_ENCLAVE_CONFIG(32,64)` for later versions
25 : /// of the enclave. If the size of `IMAGE_ENCLAVE_CONFIG(32,64)` that the image
26 : /// loader can process is less than `MinimumRequiredConfigSize`, the enclave
27 : /// cannot be run securely.
28 : ///
29 : /// If `MinimumRequiredConfigSize` is zero, the minimum size of the
30 : /// `IMAGE_ENCLAVE_CONFIG(32,64)` structure that the image loader must be able
31 : /// to process in order for the enclave to be usable is assumed to be the size
32 : /// of the structure through and including the `MinimumRequiredConfigSize` member.
33 10 : pub fn min_required_config_size(&self) -> u32 {
34 10 : self.ptr.min_required_config_size()
35 10 : }
36 :
37 : /// A flag that indicates whether the enclave permits debugging.
38 10 : pub fn policy_flags(&self) -> u32 {
39 10 : self.ptr.policy_flags()
40 10 : }
41 :
42 : /// Whether this enclave can be debugged
43 10 : pub fn is_debuggable(&self) -> bool {
44 10 : self.ptr.is_debuggable()
45 10 : }
46 :
47 : /// The RVA of the array of images that the enclave image may import, with identity information
48 : /// for each image.
49 10 : pub fn import_list_rva(&self) -> u32 {
50 10 : self.ptr.import_list_rva()
51 10 : }
52 :
53 : /// The size of each image in the array of images that the [`EnclaveConfiguration::import_list_rva`]
54 : /// member points to.
55 10 : pub fn import_entry_size(&self) -> u32 {
56 10 : self.ptr.import_entry_size()
57 10 : }
58 :
59 : /// The number of images in the array of images that the [`EnclaveConfiguration::import_list_rva`]
60 : /// member points to.
61 10 : pub fn nb_imports(&self) -> u32 {
62 10 : self.ptr.nb_imports()
63 10 : }
64 :
65 : /// Return an iterator over the enclave's imports
66 10 : pub fn imports(&self) -> Imports {
67 10 : Imports::new(self.ptr.imports())
68 10 : }
69 :
70 : /// The family identifier that the author of the enclave assigned to the enclave.
71 10 : pub fn family_id(&self) -> &[u8] {
72 10 : to_slice!(self.ptr.family_id());
73 10 : }
74 :
75 : /// The image identifier that the author of the enclave assigned to the enclave.
76 0 : pub fn image_id(&self) -> &[u8] {
77 0 : to_slice!(self.ptr.image_id());
78 0 : }
79 :
80 : /// The version number that the author of the enclave assigned to the enclave.
81 10 : pub fn image_version(&self) -> u32 {
82 10 : self.ptr.image_version()
83 10 : }
84 :
85 : /// The security version number that the author of the enclave assigned to the enclave.
86 10 : pub fn security_version(&self) -> u32 {
87 10 : self.ptr.security_version()
88 10 : }
89 :
90 : /// The expected virtual size of the private address range for the enclave, in bytes.
91 10 : pub fn enclave_size(&self) -> u64 {
92 10 : self.ptr.enclave_size()
93 10 : }
94 :
95 : /// The maximum number of threads that can be created within the enclave.
96 10 : pub fn nb_threads(&self) -> u32 {
97 10 : self.ptr.nb_threads()
98 10 : }
99 :
100 : /// A flag that indicates whether the image is suitable for use as the primary image in the
101 : /// enclave.
102 10 : pub fn enclave_flags(&self) -> u32 {
103 10 : self.ptr.enclave_flags()
104 10 : }
105 : }
106 :
107 : impl std::fmt::Debug for EnclaveConfiguration<'_> {
108 10 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 10 : f.debug_struct("EnclaveConfiguration")
110 10 : .field("size", &self.size())
111 10 : .field("min_required_config_size", &self.min_required_config_size())
112 10 : .field("policy_flags", &self.policy_flags())
113 10 : .field("is_debuggable", &self.is_debuggable())
114 10 : .field("import_list_rva", &self.import_list_rva())
115 10 : .field("import_entry_size", &self.import_entry_size())
116 10 : .field("nb_imports", &self.nb_imports())
117 10 : .field("family_id", &self.family_id())
118 10 : .field("image_version", &self.image_version())
119 10 : .field("security_version", &self.security_version())
120 10 : .field("enclave_size", &self.enclave_size())
121 10 : .field("nb_threads", &self.nb_threads())
122 10 : .field("enclave_flags", &self.enclave_flags())
123 10 : .finish()
124 10 : }
125 : }
126 :
127 : impl std::fmt::Display for EnclaveConfiguration<'_> {
128 10 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
129 10 : write!(f, "{}", self.ptr.to_string())
130 10 : }
131 : }
132 :
133 : impl<'a> FromFFI<ffi::PE_EnclaveConfiguration> for EnclaveConfiguration<'a> {
134 10 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_EnclaveConfiguration>) -> Self {
135 10 : Self {
136 10 : ptr,
137 10 : _owner: PhantomData,
138 10 : }
139 10 : }
140 : }
141 :
142 :
143 : /// This structure represents an entry in the array of images that an enclave can import.
144 : pub struct EnclaveImport<'a> {
145 : ptr: cxx::UniquePtr<ffi::PE_EnclaveImport>,
146 : _owner: PhantomData<&'a ffi::PE_EnclaveConfiguration>,
147 : }
148 :
149 : impl EnclaveImport<'_> {
150 : /// The type of identifier of the image that must match the value in the import record.
151 30 : pub fn get_type(&self) -> Type {
152 30 : Type::from(self.ptr.get_type())
153 30 : }
154 :
155 : /// The minimum enclave security version that each image must have for the
156 : /// image to be imported successfully. The image is rejected unless its enclave
157 : /// security version is equal to or greater than the minimum value in the
158 : /// import record. Set the value in the import record to zero to turn off the
159 : /// security version check.
160 30 : pub fn min_security_version(&self) -> u32 {
161 30 : self.ptr.min_security_version()
162 30 : }
163 :
164 : /// The relative virtual address of a NULL-terminated string that contains the
165 : /// same value found in the import directory for the image.
166 30 : pub fn import_name_rva(&self) -> u32 {
167 30 : self.ptr.import_name_rva()
168 30 : }
169 :
170 : /// Resolved import name
171 30 : pub fn import_name(&self) -> String {
172 30 : self.ptr.import_name().to_string()
173 30 : }
174 :
175 : /// Reserved. Should be 0
176 30 : pub fn reserved(&self) -> u32 {
177 30 : self.ptr.reserved()
178 30 : }
179 :
180 : /// The unique identifier of the primary module for the enclave, if the
181 : /// [`EnclaveImport::get_type`] is [`Type::UNIQUE_ID`]. Otherwise, the author identifier of the
182 : /// primary module for the enclave.
183 30 : pub fn id(&self) -> &[u8] {
184 30 : to_slice!(self.ptr.id());
185 30 : }
186 :
187 : /// The family identifier of the primary module for the enclave.
188 30 : pub fn family_id(&self) -> &[u8] {
189 30 : to_slice!(self.ptr.family_id());
190 30 : }
191 :
192 : /// The image identifier of the primary module for the enclave.
193 30 : pub fn image_id(&self) -> &[u8] {
194 30 : to_slice!(self.ptr.image_id());
195 30 : }
196 : }
197 :
198 : impl std::fmt::Debug for EnclaveImport<'_> {
199 30 : fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
200 30 : f.debug_struct("EnclaveImport")
201 30 : .field("type", &self.get_type())
202 30 : .field("min_security_version", &self.min_security_version())
203 30 : .field("import_name_rva", &self.import_name_rva())
204 30 : .field("import_name", &self.import_name())
205 30 : .field("reserved", &self.reserved())
206 30 : .field("id", &self.id())
207 30 : .field("family_id", &self.family_id())
208 30 : .field("image_id", &self.image_id())
209 30 : .finish()
210 30 : }
211 : }
212 :
213 : impl std::fmt::Display for EnclaveImport<'_> {
214 30 : fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
215 30 : write!(f, "{}", self.ptr.to_string())
216 30 : }
217 : }
218 :
219 : impl<'a> FromFFI<ffi::PE_EnclaveImport> for EnclaveImport<'a> {
220 30 : fn from_ffi(ptr: cxx::UniquePtr<ffi::PE_EnclaveImport>) -> Self {
221 30 : Self {
222 30 : ptr,
223 30 : _owner: PhantomData,
224 30 : }
225 30 : }
226 : }
227 :
228 : #[allow(non_camel_case_types)]
229 30 : #[derive(Debug, Copy, Clone)]
230 : pub enum Type {
231 : /// None of the identifiers of the image need to match the value in the
232 : /// import record.
233 : NONE,
234 :
235 : /// The value of the enclave unique identifier of the image must match the
236 : /// value in the import record. Otherwise, loading of the image fails.
237 : UNIQUE_ID,
238 :
239 : /// The value of the enclave author identifier of the image must match the
240 : /// value in the import record. Otherwise, loading of the image fails. If
241 : /// this flag is set and the import record indicates an author identifier
242 : /// of all zeros, the imported image must be part of the Windows installation.
243 : AUTHOR_ID,
244 :
245 : /// The value of the enclave family identifier of the image must match the
246 : /// value in the import record. Otherwise, loading of the image fails.
247 : FAMILY_ID,
248 :
249 : /// The value of the enclave image identifier of the image must match the
250 : /// value in the import record. Otherwise, loading of the image fails.
251 : IMAGE_ID,
252 : UNKNOWN(u32),
253 : }
254 :
255 : impl From<u32> for Type {
256 30 : fn from(value: u32) -> Self {
257 30 : match value {
258 0 : 0x00000000 => Type::NONE,
259 0 : 0x00000001 => Type::UNIQUE_ID,
260 0 : 0x00000002 => Type::AUTHOR_ID,
261 0 : 0x00000003 => Type::FAMILY_ID,
262 30 : 0x00000004 => Type::IMAGE_ID,
263 0 : _ => Type::UNKNOWN(value),
264 : }
265 30 : }
266 : }
267 :
268 30 : declare_iterator!(
269 30 : Imports,
270 30 : EnclaveImport<'a>,
271 30 : ffi::PE_EnclaveImport,
272 30 : ffi::PE_EnclaveConfiguration,
273 30 : ffi::PE_EnclaveConfiguration_it_imports
274 30 : );
275 :
276 :
|