4
4
* License, v. 2.0. If a copy of the MPL was not distributed with this
5
5
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
6
7
+ use std:: arch:: x86_64:: { self , CpuidResult } ;
7
8
use std:: fs:: File ;
8
9
use std:: io:: { Error as IoError , ErrorKind , Read , Result as IoResult } ;
9
10
use std:: ops:: RangeInclusive ;
@@ -21,6 +22,7 @@ use openssl::{
21
22
} ;
22
23
23
24
use sgx_isa:: { Attributes , AttributesFlags , Miscselect , Sigstruct } ;
25
+ use sgxs:: sgxs:: PageReader ;
24
26
use sgxs:: crypto:: { SgxHashOps , SgxRsaOps } ;
25
27
use sgxs:: loader:: { Load , MappingInfo , Tcs } ;
26
28
use sgxs:: sigstruct:: { self , EnclaveHash , Signer } ;
@@ -163,11 +165,67 @@ impl<'a> EnclaveBuilder<'a> {
163
165
ret
164
166
}
165
167
166
- fn generate_dummy_signature ( & mut self ) -> Result < Sigstruct , anyhow:: Error > {
168
+ fn cpuid ( eax : u32 , ecx : u32 ) -> Option < CpuidResult > {
169
+ unsafe {
170
+ if eax <= x86_64:: __get_cpuid_max ( 0 ) . 0 {
171
+ Some ( x86_64:: __cpuid_count ( eax, ecx) )
172
+ } else {
173
+ None
174
+ }
175
+ }
176
+ }
177
+
178
+ fn generate_xfrm ( max_ssaframesize_in_pages : u32 ) -> u64 {
167
179
fn xgetbv0 ( ) -> u64 {
168
180
unsafe { arch:: x86_64:: _xgetbv ( 0 ) }
169
181
}
170
182
183
+ debug_assert ! ( 0 < max_ssaframesize_in_pages) ;
184
+ let xcr0 = xgetbv0 ( ) ;
185
+
186
+ // See allorithm of Intel dev manual Chpt 40.7.2.2
187
+ let xfrm = ( 0 ..64 )
188
+ . map ( |bit| {
189
+ let select = 0x1 << bit;
190
+ match bit {
191
+ 0 | 1 => select, // Bit 0 and 1 always need to be set
192
+ _ => {
193
+ if xcr0 & select == 0 {
194
+ return 0 ;
195
+ }
196
+
197
+ let ( base, size) = {
198
+ let cpuid = Self :: cpuid ( 0x0d , bit) ;
199
+ let base = cpuid. map_or ( 0 , |c| c. ebx ) ;
200
+ let size = cpuid. map_or ( 0 , |c| c. eax ) ;
201
+ ( base, size)
202
+ } ;
203
+ if max_ssaframesize_in_pages * 0x1000 <= base + size {
204
+ return 0 ;
205
+ }
206
+
207
+ select
208
+ }
209
+ }
210
+ } )
211
+ . fold ( 0 , |xfrm, b| xfrm | b) ;
212
+
213
+ // Intel x86 manual Vol 3 Chpt 13.3:
214
+ // "Executing the XSETBV instruction causes a general-protection fault (#GP) if ECX = 0
215
+ // and EAX[17] ≠ EAX[18] (TILECFG and TILEDATA must be enabled together). This implies
216
+ // that the value of XCR0[18:17] is always either 00b or 11b."
217
+ // The enclave entry code executes xrstor, and we may have just cleared bit 18, so we
218
+ // need to correct the invariant
219
+ if ( xfrm & ( 0x1 << 17 ) ) != ( xfrm & ( 0x1 << 18 ) ) {
220
+ xfrm & !( 0x11 << 17 )
221
+ } else {
222
+ xfrm
223
+ }
224
+ }
225
+
226
+ fn generate_dummy_signature ( & mut self ) -> Result < Sigstruct , anyhow:: Error > {
227
+ let mut enclave = self . enclave . try_clone ( ) . unwrap ( ) ;
228
+ let create_info = PageReader :: new ( & mut enclave) ?;
171
229
let mut enclave = self . enclave . try_clone ( ) . unwrap ( ) ;
172
230
let hash = match self . hash_enclave . take ( ) {
173
231
Some ( f) => f ( & mut enclave) ?,
@@ -177,7 +235,7 @@ impl<'a> EnclaveBuilder<'a> {
177
235
178
236
let attributes = self . attributes . unwrap_or_else ( || Attributes {
179
237
flags : AttributesFlags :: DEBUG | AttributesFlags :: MODE64BIT ,
180
- xfrm : xgetbv0 ( ) ,
238
+ xfrm : Self :: generate_xfrm ( create_info . 0 . ecreate . ssaframesize ) ,
181
239
} ) ;
182
240
signer
183
241
. attributes_flags ( attributes. flags , !0 )
0 commit comments