1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /** |
3 | * Copyright(c) 2016-20 Intel Corporation. |
4 | * |
5 | * Intel Software Guard Extensions (SGX) support. |
6 | */ |
7 | #ifndef _ASM_X86_SGX_H |
8 | #define _ASM_X86_SGX_H |
9 | |
10 | #include <linux/bits.h> |
11 | #include <linux/types.h> |
12 | |
13 | /* |
14 | * This file contains both data structures defined by SGX architecture and Linux |
15 | * defined software data structures and functions. The two should not be mixed |
16 | * together for better readability. The architectural definitions come first. |
17 | */ |
18 | |
19 | /* The SGX specific CPUID function. */ |
20 | #define SGX_CPUID 0x12 |
21 | /* EPC enumeration. */ |
22 | #define SGX_CPUID_EPC 2 |
23 | /* An invalid EPC section, i.e. the end marker. */ |
24 | #define SGX_CPUID_EPC_INVALID 0x0 |
25 | /* A valid EPC section. */ |
26 | #define SGX_CPUID_EPC_SECTION 0x1 |
27 | /* The bitmask for the EPC section type. */ |
28 | #define SGX_CPUID_EPC_MASK GENMASK(3, 0) |
29 | |
30 | enum sgx_encls_function { |
31 | ECREATE = 0x00, |
32 | EADD = 0x01, |
33 | EINIT = 0x02, |
34 | EREMOVE = 0x03, |
35 | EDGBRD = 0x04, |
36 | EDGBWR = 0x05, |
37 | EEXTEND = 0x06, |
38 | ELDU = 0x08, |
39 | EBLOCK = 0x09, |
40 | EPA = 0x0A, |
41 | EWB = 0x0B, |
42 | ETRACK = 0x0C, |
43 | EAUG = 0x0D, |
44 | EMODPR = 0x0E, |
45 | EMODT = 0x0F, |
46 | }; |
47 | |
48 | /** |
49 | * SGX_ENCLS_FAULT_FLAG - flag signifying an ENCLS return code is a trapnr |
50 | * |
51 | * ENCLS has its own (positive value) error codes and also generates |
52 | * ENCLS specific #GP and #PF faults. And the ENCLS values get munged |
53 | * with system error codes as everything percolates back up the stack. |
54 | * Unfortunately (for us), we need to precisely identify each unique |
55 | * error code, e.g. the action taken if EWB fails varies based on the |
56 | * type of fault and on the exact SGX error code, i.e. we can't simply |
57 | * convert all faults to -EFAULT. |
58 | * |
59 | * To make all three error types coexist, we set bit 30 to identify an |
60 | * ENCLS fault. Bit 31 (technically bits N:31) is used to differentiate |
61 | * between positive (faults and SGX error codes) and negative (system |
62 | * error codes) values. |
63 | */ |
64 | #define SGX_ENCLS_FAULT_FLAG 0x40000000 |
65 | |
66 | /** |
67 | * enum sgx_return_code - The return code type for ENCLS, ENCLU and ENCLV |
68 | * %SGX_EPC_PAGE_CONFLICT: Page is being written by other ENCLS function. |
69 | * %SGX_NOT_TRACKED: Previous ETRACK's shootdown sequence has not |
70 | * been completed yet. |
71 | * %SGX_CHILD_PRESENT SECS has child pages present in the EPC. |
72 | * %SGX_INVALID_EINITTOKEN: EINITTOKEN is invalid and enclave signer's |
73 | * public key does not match IA32_SGXLEPUBKEYHASH. |
74 | * %SGX_PAGE_NOT_MODIFIABLE: The EPC page cannot be modified because it |
75 | * is in the PENDING or MODIFIED state. |
76 | * %SGX_UNMASKED_EVENT: An unmasked event, e.g. INTR, was received |
77 | */ |
78 | enum sgx_return_code { |
79 | SGX_EPC_PAGE_CONFLICT = 7, |
80 | SGX_NOT_TRACKED = 11, |
81 | SGX_CHILD_PRESENT = 13, |
82 | SGX_INVALID_EINITTOKEN = 16, |
83 | SGX_PAGE_NOT_MODIFIABLE = 20, |
84 | SGX_UNMASKED_EVENT = 128, |
85 | }; |
86 | |
87 | /* The modulus size for 3072-bit RSA keys. */ |
88 | #define SGX_MODULUS_SIZE 384 |
89 | |
90 | /** |
91 | * enum sgx_miscselect - additional information to an SSA frame |
92 | * %SGX_MISC_EXINFO: Report #PF or #GP to the SSA frame. |
93 | * |
94 | * Save State Area (SSA) is a stack inside the enclave used to store processor |
95 | * state when an exception or interrupt occurs. This enum defines additional |
96 | * information stored to an SSA frame. |
97 | */ |
98 | enum sgx_miscselect { |
99 | SGX_MISC_EXINFO = BIT(0), |
100 | }; |
101 | |
102 | #define SGX_MISC_RESERVED_MASK GENMASK_ULL(63, 1) |
103 | |
104 | #define SGX_SSA_GPRS_SIZE 184 |
105 | #define SGX_SSA_MISC_EXINFO_SIZE 16 |
106 | |
107 | /** |
108 | * enum sgx_attributes - the attributes field in &struct sgx_secs |
109 | * %SGX_ATTR_INIT: Enclave can be entered (is initialized). |
110 | * %SGX_ATTR_DEBUG: Allow ENCLS(EDBGRD) and ENCLS(EDBGWR). |
111 | * %SGX_ATTR_MODE64BIT: Tell that this a 64-bit enclave. |
112 | * %SGX_ATTR_PROVISIONKEY: Allow to use provisioning keys for remote |
113 | * attestation. |
114 | * %SGX_ATTR_KSS: Allow to use key separation and sharing (KSS). |
115 | * %SGX_ATTR_EINITTOKENKEY: Allow to use token signing key that is used to |
116 | * sign cryptographic tokens that can be passed to |
117 | * EINIT as an authorization to run an enclave. |
118 | * %SGX_ATTR_ASYNC_EXIT_NOTIFY: Allow enclaves to be notified after an |
119 | * asynchronous exit has occurred. |
120 | */ |
121 | enum sgx_attribute { |
122 | SGX_ATTR_INIT = BIT(0), |
123 | SGX_ATTR_DEBUG = BIT(1), |
124 | SGX_ATTR_MODE64BIT = BIT(2), |
125 | /* BIT(3) is reserved */ |
126 | SGX_ATTR_PROVISIONKEY = BIT(4), |
127 | SGX_ATTR_EINITTOKENKEY = BIT(5), |
128 | /* BIT(6) is for CET */ |
129 | SGX_ATTR_KSS = BIT(7), |
130 | /* BIT(8) is reserved */ |
131 | /* BIT(9) is reserved */ |
132 | SGX_ATTR_ASYNC_EXIT_NOTIFY = BIT(10), |
133 | }; |
134 | |
135 | #define SGX_ATTR_RESERVED_MASK (BIT_ULL(3) | \ |
136 | BIT_ULL(6) | \ |
137 | BIT_ULL(8) | \ |
138 | BIT_ULL(9) | \ |
139 | GENMASK_ULL(63, 11)) |
140 | |
141 | #define SGX_ATTR_UNPRIV_MASK (SGX_ATTR_DEBUG | \ |
142 | SGX_ATTR_MODE64BIT | \ |
143 | SGX_ATTR_KSS | \ |
144 | SGX_ATTR_ASYNC_EXIT_NOTIFY) |
145 | |
146 | #define SGX_ATTR_PRIV_MASK (SGX_ATTR_PROVISIONKEY | \ |
147 | SGX_ATTR_EINITTOKENKEY) |
148 | |
149 | /** |
150 | * struct sgx_secs - SGX Enclave Control Structure (SECS) |
151 | * @size: size of the address space |
152 | * @base: base address of the address space |
153 | * @ssa_frame_size: size of an SSA frame |
154 | * @miscselect: additional information stored to an SSA frame |
155 | * @attributes: attributes for enclave |
156 | * @xfrm: XSave-Feature Request Mask (subset of XCR0) |
157 | * @mrenclave: SHA256-hash of the enclave contents |
158 | * @mrsigner: SHA256-hash of the public key used to sign the SIGSTRUCT |
159 | * @config_id: a user-defined value that is used in key derivation |
160 | * @isv_prod_id: a user-defined value that is used in key derivation |
161 | * @isv_svn: a user-defined value that is used in key derivation |
162 | * @config_svn: a user-defined value that is used in key derivation |
163 | * |
164 | * SGX Enclave Control Structure (SECS) is a special enclave page that is not |
165 | * visible in the address space. In fact, this structure defines the address |
166 | * range and other global attributes for the enclave and it is the first EPC |
167 | * page created for any enclave. It is moved from a temporary buffer to an EPC |
168 | * by the means of ENCLS[ECREATE] function. |
169 | */ |
170 | struct sgx_secs { |
171 | u64 size; |
172 | u64 base; |
173 | u32 ssa_frame_size; |
174 | u32 miscselect; |
175 | u8 reserved1[24]; |
176 | u64 attributes; |
177 | u64 xfrm; |
178 | u32 mrenclave[8]; |
179 | u8 reserved2[32]; |
180 | u32 mrsigner[8]; |
181 | u8 reserved3[32]; |
182 | u32 config_id[16]; |
183 | u16 isv_prod_id; |
184 | u16 isv_svn; |
185 | u16 config_svn; |
186 | u8 reserved4[3834]; |
187 | } __packed; |
188 | |
189 | /** |
190 | * enum sgx_tcs_flags - execution flags for TCS |
191 | * %SGX_TCS_DBGOPTIN: If enabled allows single-stepping and breakpoints |
192 | * inside an enclave. It is cleared by EADD but can |
193 | * be set later with EDBGWR. |
194 | */ |
195 | enum sgx_tcs_flags { |
196 | SGX_TCS_DBGOPTIN = 0x01, |
197 | }; |
198 | |
199 | #define SGX_TCS_RESERVED_MASK GENMASK_ULL(63, 1) |
200 | #define SGX_TCS_RESERVED_SIZE 4024 |
201 | |
202 | /** |
203 | * struct sgx_tcs - Thread Control Structure (TCS) |
204 | * @state: used to mark an entered TCS |
205 | * @flags: execution flags (cleared by EADD) |
206 | * @ssa_offset: SSA stack offset relative to the enclave base |
207 | * @ssa_index: the current SSA frame index (cleard by EADD) |
208 | * @nr_ssa_frames: the number of frame in the SSA stack |
209 | * @entry_offset: entry point offset relative to the enclave base |
210 | * @exit_addr: address outside the enclave to exit on an exception or |
211 | * interrupt |
212 | * @fs_offset: offset relative to the enclave base to become FS |
213 | * segment inside the enclave |
214 | * @gs_offset: offset relative to the enclave base to become GS |
215 | * segment inside the enclave |
216 | * @fs_limit: size to become a new FS-limit (only 32-bit enclaves) |
217 | * @gs_limit: size to become a new GS-limit (only 32-bit enclaves) |
218 | * |
219 | * Thread Control Structure (TCS) is an enclave page visible in its address |
220 | * space that defines an entry point inside the enclave. A thread enters inside |
221 | * an enclave by supplying address of TCS to ENCLU(EENTER). A TCS can be entered |
222 | * by only one thread at a time. |
223 | */ |
224 | struct sgx_tcs { |
225 | u64 state; |
226 | u64 flags; |
227 | u64 ssa_offset; |
228 | u32 ssa_index; |
229 | u32 nr_ssa_frames; |
230 | u64 entry_offset; |
231 | u64 exit_addr; |
232 | u64 fs_offset; |
233 | u64 gs_offset; |
234 | u32 fs_limit; |
235 | u32 gs_limit; |
236 | u8 reserved[SGX_TCS_RESERVED_SIZE]; |
237 | } __packed; |
238 | |
239 | /** |
240 | * struct sgx_pageinfo - an enclave page descriptor |
241 | * @addr: address of the enclave page |
242 | * @contents: pointer to the page contents |
243 | * @metadata: pointer either to a SECINFO or PCMD instance |
244 | * @secs: address of the SECS page |
245 | */ |
246 | struct sgx_pageinfo { |
247 | u64 addr; |
248 | u64 contents; |
249 | u64 metadata; |
250 | u64 secs; |
251 | } __packed __aligned(32); |
252 | |
253 | |
254 | /** |
255 | * enum sgx_page_type - bits in the SECINFO flags defining the page type |
256 | * %SGX_PAGE_TYPE_SECS: a SECS page |
257 | * %SGX_PAGE_TYPE_TCS: a TCS page |
258 | * %SGX_PAGE_TYPE_REG: a regular page |
259 | * %SGX_PAGE_TYPE_VA: a VA page |
260 | * %SGX_PAGE_TYPE_TRIM: a page in trimmed state |
261 | * |
262 | * Make sure when making changes to this enum that its values can still fit |
263 | * in the bitfield within &struct sgx_encl_page |
264 | */ |
265 | enum sgx_page_type { |
266 | SGX_PAGE_TYPE_SECS, |
267 | SGX_PAGE_TYPE_TCS, |
268 | SGX_PAGE_TYPE_REG, |
269 | SGX_PAGE_TYPE_VA, |
270 | SGX_PAGE_TYPE_TRIM, |
271 | }; |
272 | |
273 | #define SGX_NR_PAGE_TYPES 5 |
274 | #define SGX_PAGE_TYPE_MASK GENMASK(7, 0) |
275 | |
276 | /** |
277 | * enum sgx_secinfo_flags - the flags field in &struct sgx_secinfo |
278 | * %SGX_SECINFO_R: allow read |
279 | * %SGX_SECINFO_W: allow write |
280 | * %SGX_SECINFO_X: allow execution |
281 | * %SGX_SECINFO_SECS: a SECS page |
282 | * %SGX_SECINFO_TCS: a TCS page |
283 | * %SGX_SECINFO_REG: a regular page |
284 | * %SGX_SECINFO_VA: a VA page |
285 | * %SGX_SECINFO_TRIM: a page in trimmed state |
286 | */ |
287 | enum sgx_secinfo_flags { |
288 | SGX_SECINFO_R = BIT(0), |
289 | SGX_SECINFO_W = BIT(1), |
290 | SGX_SECINFO_X = BIT(2), |
291 | SGX_SECINFO_SECS = (SGX_PAGE_TYPE_SECS << 8), |
292 | SGX_SECINFO_TCS = (SGX_PAGE_TYPE_TCS << 8), |
293 | SGX_SECINFO_REG = (SGX_PAGE_TYPE_REG << 8), |
294 | SGX_SECINFO_VA = (SGX_PAGE_TYPE_VA << 8), |
295 | SGX_SECINFO_TRIM = (SGX_PAGE_TYPE_TRIM << 8), |
296 | }; |
297 | |
298 | #define SGX_SECINFO_PERMISSION_MASK GENMASK_ULL(2, 0) |
299 | #define SGX_SECINFO_PAGE_TYPE_MASK (SGX_PAGE_TYPE_MASK << 8) |
300 | #define SGX_SECINFO_RESERVED_MASK ~(SGX_SECINFO_PERMISSION_MASK | \ |
301 | SGX_SECINFO_PAGE_TYPE_MASK) |
302 | |
303 | /** |
304 | * struct sgx_secinfo - describes attributes of an EPC page |
305 | * @flags: permissions and type |
306 | * |
307 | * Used together with ENCLS leaves that add or modify an EPC page to an |
308 | * enclave to define page permissions and type. |
309 | */ |
310 | struct sgx_secinfo { |
311 | u64 flags; |
312 | u8 reserved[56]; |
313 | } __packed __aligned(64); |
314 | |
315 | #define SGX_PCMD_RESERVED_SIZE 40 |
316 | |
317 | /** |
318 | * struct sgx_pcmd - Paging Crypto Metadata (PCMD) |
319 | * @enclave_id: enclave identifier |
320 | * @mac: MAC over PCMD, page contents and isvsvn |
321 | * |
322 | * PCMD is stored for every swapped page to the regular memory. When ELDU loads |
323 | * the page back it recalculates the MAC by using a isvsvn number stored in a |
324 | * VA page. Together these two structures bring integrity and rollback |
325 | * protection. |
326 | */ |
327 | struct sgx_pcmd { |
328 | struct sgx_secinfo secinfo; |
329 | u64 enclave_id; |
330 | u8 reserved[SGX_PCMD_RESERVED_SIZE]; |
331 | u8 mac[16]; |
332 | } __packed __aligned(128); |
333 | |
334 | #define SGX_SIGSTRUCT_RESERVED1_SIZE 84 |
335 | #define SGX_SIGSTRUCT_RESERVED2_SIZE 20 |
336 | #define SGX_SIGSTRUCT_RESERVED3_SIZE 32 |
337 | #define SGX_SIGSTRUCT_RESERVED4_SIZE 12 |
338 | |
339 | /** |
340 | * struct sgx_sigstruct_header - defines author of the enclave |
341 | * @header1: constant byte string |
342 | * @vendor: must be either 0x0000 or 0x8086 |
343 | * @date: YYYYMMDD in BCD |
344 | * @header2: constant byte string |
345 | * @swdefined: software defined value |
346 | */ |
347 | struct { |
348 | u64 [2]; |
349 | u32 ; |
350 | u32 ; |
351 | u64 [2]; |
352 | u32 ; |
353 | u8 [84]; |
354 | } __packed; |
355 | |
356 | /** |
357 | * struct sgx_sigstruct_body - defines contents of the enclave |
358 | * @miscselect: additional information stored to an SSA frame |
359 | * @misc_mask: required miscselect in SECS |
360 | * @attributes: attributes for enclave |
361 | * @xfrm: XSave-Feature Request Mask (subset of XCR0) |
362 | * @attributes_mask: required attributes in SECS |
363 | * @xfrm_mask: required XFRM in SECS |
364 | * @mrenclave: SHA256-hash of the enclave contents |
365 | * @isvprodid: a user-defined value that is used in key derivation |
366 | * @isvsvn: a user-defined value that is used in key derivation |
367 | */ |
368 | struct sgx_sigstruct_body { |
369 | u32 miscselect; |
370 | u32 misc_mask; |
371 | u8 reserved2[20]; |
372 | u64 attributes; |
373 | u64 xfrm; |
374 | u64 attributes_mask; |
375 | u64 xfrm_mask; |
376 | u8 mrenclave[32]; |
377 | u8 reserved3[32]; |
378 | u16 isvprodid; |
379 | u16 isvsvn; |
380 | } __packed; |
381 | |
382 | /** |
383 | * struct sgx_sigstruct - an enclave signature |
384 | * @header: defines author of the enclave |
385 | * @modulus: the modulus of the public key |
386 | * @exponent: the exponent of the public key |
387 | * @signature: the signature calculated over the fields except modulus, |
388 | * @body: defines contents of the enclave |
389 | * @q1: a value used in RSA signature verification |
390 | * @q2: a value used in RSA signature verification |
391 | * |
392 | * Header and body are the parts that are actual signed. The remaining fields |
393 | * define the signature of the enclave. |
394 | */ |
395 | struct sgx_sigstruct { |
396 | struct sgx_sigstruct_header ; |
397 | u8 modulus[SGX_MODULUS_SIZE]; |
398 | u32 exponent; |
399 | u8 signature[SGX_MODULUS_SIZE]; |
400 | struct sgx_sigstruct_body body; |
401 | u8 reserved4[12]; |
402 | u8 q1[SGX_MODULUS_SIZE]; |
403 | u8 q2[SGX_MODULUS_SIZE]; |
404 | } __packed; |
405 | |
406 | #define SGX_LAUNCH_TOKEN_SIZE 304 |
407 | |
408 | /* |
409 | * Do not put any hardware-defined SGX structure representations below this |
410 | * comment! |
411 | */ |
412 | |
413 | #ifdef CONFIG_X86_SGX_KVM |
414 | int sgx_virt_ecreate(struct sgx_pageinfo *pageinfo, void __user *secs, |
415 | int *trapnr); |
416 | int sgx_virt_einit(void __user *sigstruct, void __user *token, |
417 | void __user *secs, u64 *lepubkeyhash, int *trapnr); |
418 | #endif |
419 | |
420 | int sgx_set_attribute(unsigned long *allowed_attributes, |
421 | unsigned int attribute_fd); |
422 | |
423 | #endif /* _ASM_X86_SGX_H */ |
424 | |