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