1// SPDX-License-Identifier: GPL-2.0 2/* Copyright(c) 2016-20 Intel Corporation. */ 3 4#include <stddef.h> 5#include "defines.h" 6 7/* 8 * Data buffer spanning two pages that will be placed first in the .data 9 * segment via the linker script. Even if not used internally the second page 10 * is needed by external test manipulating page permissions, so mark 11 * encl_buffer as "used" to make sure it is entirely preserved by the compiler. 12 */ 13static uint8_t __used __section(".data.encl_buffer") encl_buffer[8192] = { 1 }; 14 15enum sgx_enclu_function { 16 EACCEPT = 0x5, 17 EMODPE = 0x6, 18}; 19 20static void do_encl_emodpe(void *_op) 21{ 22 struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; 23 struct encl_op_emodpe *op = _op; 24 25 secinfo.flags = op->flags; 26 27 asm volatile(".byte 0x0f, 0x01, 0xd7" 28 : /* no outputs */ 29 : "a" (EMODPE), 30 "b" (&secinfo), 31 "c" (op->epc_addr) 32 : "memory" /* read from secinfo pointer */); 33} 34 35static void do_encl_eaccept(void *_op) 36{ 37 struct sgx_secinfo secinfo __aligned(sizeof(struct sgx_secinfo)) = {0}; 38 struct encl_op_eaccept *op = _op; 39 int rax; 40 41 secinfo.flags = op->flags; 42 43 asm volatile(".byte 0x0f, 0x01, 0xd7" 44 : "=a" (rax) 45 : "a" (EACCEPT), 46 "b" (&secinfo), 47 "c" (op->epc_addr) 48 : "memory" /* read from secinfo pointer */); 49 50 op->ret = rax; 51} 52 53static void *memcpy(void *dest, const void *src, size_t n) 54{ 55 size_t i; 56 57 for (i = 0; i < n; i++) 58 ((char *)dest)[i] = ((char *)src)[i]; 59 60 return dest; 61} 62 63static void *memset(void *dest, int c, size_t n) 64{ 65 size_t i; 66 67 for (i = 0; i < n; i++) 68 ((char *)dest)[i] = c; 69 70 return dest; 71} 72 73static void do_encl_init_tcs_page(void *_op) 74{ 75 struct encl_op_init_tcs_page *op = _op; 76 void *tcs = (void *)op->tcs_page; 77 uint32_t val_32; 78 79 memset(tcs, 0, 16); /* STATE and FLAGS */ 80 memcpy(tcs + 16, &op->ssa, 8); /* OSSA */ 81 memset(tcs + 24, 0, 4); /* CSSA */ 82 val_32 = 1; 83 memcpy(tcs + 28, &val_32, 4); /* NSSA */ 84 memcpy(tcs + 32, &op->entry, 8); /* OENTRY */ 85 memset(tcs + 40, 0, 24); /* AEP, OFSBASE, OGSBASE */ 86 val_32 = 0xFFFFFFFF; 87 memcpy(tcs + 64, &val_32, 4); /* FSLIMIT */ 88 memcpy(tcs + 68, &val_32, 4); /* GSLIMIT */ 89 memset(tcs + 72, 0, 4024); /* Reserved */ 90} 91 92static void do_encl_op_put_to_buf(void *op) 93{ 94 struct encl_op_put_to_buf *op2 = op; 95 96 memcpy(&encl_buffer[0], &op2->value, 8); 97} 98 99static void do_encl_op_get_from_buf(void *op) 100{ 101 struct encl_op_get_from_buf *op2 = op; 102 103 memcpy(&op2->value, &encl_buffer[0], 8); 104} 105 106static void do_encl_op_put_to_addr(void *_op) 107{ 108 struct encl_op_put_to_addr *op = _op; 109 110 memcpy((void *)op->addr, &op->value, 8); 111} 112 113static void do_encl_op_get_from_addr(void *_op) 114{ 115 struct encl_op_get_from_addr *op = _op; 116 117 memcpy(&op->value, (void *)op->addr, 8); 118} 119 120static void do_encl_op_nop(void *_op) 121{ 122 123} 124 125/* 126 * Symbol placed at the start of the enclave image by the linker script. 127 * Declare this extern symbol with visibility "hidden" to ensure the compiler 128 * does not access it through the GOT and generates position-independent 129 * addressing as __encl_base(%rip), so we can get the actual enclave base 130 * during runtime. 131 */ 132extern const uint8_t __attribute__((visibility("hidden"))) __encl_base; 133 134typedef void (*encl_op_t)(void *); 135static const encl_op_t encl_op_array[ENCL_OP_MAX] = { 136 do_encl_op_put_to_buf, 137 do_encl_op_get_from_buf, 138 do_encl_op_put_to_addr, 139 do_encl_op_get_from_addr, 140 do_encl_op_nop, 141 do_encl_eaccept, 142 do_encl_emodpe, 143 do_encl_init_tcs_page, 144}; 145 146void encl_body(void *rdi, void *rsi) 147{ 148 struct encl_op_header *header = (struct encl_op_header *)rdi; 149 encl_op_t op; 150 151 if (header->type >= ENCL_OP_MAX) 152 return; 153 154 /* 155 * The enclave base address needs to be added, as this call site 156 * *cannot be* made rip-relative by the compiler, or fixed up by 157 * any other possible means. 158 */ 159 op = ((uint64_t)&__encl_base) + encl_op_array[header->type]; 160 161 (*op)(header); 162} 163