liberpal-skeleton.c 6.2 KB
Newer Older
1 2 3 4
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
// Copyright(c) 2016-18 Intel Corporation.

#include <elf.h>
5
#include <errno.h>
6
#include <fcntl.h>
7
#include <stdbool.h>
8 9 10 11 12 13 14 15 16 17 18 19
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include "defines.h"
#include "sgx_call.h"
20

21
#define PAGE_SIZE  4096
22

23 24
#define SGX_REG_PAGE_FLAGS \
	(SGX_SECINFO_REG | SGX_SECINFO_R | SGX_SECINFO_W | SGX_SECINFO_X)
25

26 27 28
#define IMAGE		"encl.bin"
#define SIGSTRUCT	"encl.ss"
#define TOKEN		"encl.token"
29

30 31 32 33 34 35
static const uint64_t MAGIC = 0x1122334455667788ULL;
static struct sgx_secs secs;
static bool initialized = false;

static bool encl_create(int dev_fd, unsigned long bin_size,
			struct sgx_secs *secs)
36
{
37 38 39 40 41 42 43 44
	struct sgx_enclave_create ioc;
	void *area;
	int rc;

	memset(secs, 0, sizeof(*secs));
	secs->ssa_frame_size = 1;
	secs->attributes = SGX_ATTR_MODE64BIT | SGX_ATTR_DEBUG;
	secs->xfrm = 7;
45

46 47 48 49 50 51 52
	for (secs->size = PAGE_SIZE; secs->size < bin_size; )
		secs->size <<= 1;

	area = mmap(NULL, secs->size * 2, PROT_NONE, MAP_SHARED, dev_fd, 0);
	if (area == MAP_FAILED) {
		perror("mmap");
		return false;
53 54
	}

55 56 57 58
	secs->base = ((uint64_t)area + secs->size - 1) & ~(secs->size - 1);
	munmap(area, secs->base - (uint64_t)area);
	munmap((void *)(secs->base + secs->size),
	       (uint64_t)area + secs->size - secs->base);
59

60 61 62 63 64 65 66 67 68 69 70 71 72 73
	if (mprotect((void *)secs->base, secs->size, PROT_READ | PROT_WRITE | PROT_EXEC)) {
		perror("mprotect");
		return false;
	}

	ioc.src = (unsigned long)secs;
	rc = ioctl(dev_fd, SGX_IOC_ENCLAVE_CREATE, &ioc);
	if (rc) {
		fprintf(stderr, "ECREATE failed rc=%d, err=%d.\n", rc, errno);
		munmap((void *)secs->base, secs->size);
		return false;
	}

	return true;
74 75
}

76 77
static bool encl_add_pages(int dev_fd, unsigned long addr, void *data,
			   unsigned long length, uint64_t flags)
78
{
79 80 81
	struct sgx_enclave_add_page ioc;
	struct sgx_secinfo secinfo;
	int rc;
82

83 84
	memset(&secinfo, 0, sizeof(secinfo));
	secinfo.flags = flags;
85

86 87 88 89
	ioc.src = (uint64_t)data;
	ioc.addr = addr;
	ioc.secinfo = (unsigned long)&secinfo;
	ioc.mrmask = (__u16)-1;
90

91 92 93 94 95 96
	uint64_t added_size = 0;
	while (added_size < length) {
		rc = ioctl(dev_fd, SGX_IOC_ENCLAVE_ADD_PAGE, &ioc);
		if (rc) {
			fprintf(stderr, "EADD failed rc=%d.\n", rc);
			return false;
97
		}
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

		ioc.addr += PAGE_SIZE;
		ioc.src += PAGE_SIZE;
		added_size += PAGE_SIZE;
	}

	return true;
}

static bool encl_build(struct sgx_secs *secs, void *bin, unsigned long bin_size, 
			struct sgx_sigstruct *sigstruct,struct sgx_einittoken *token)
{
	struct sgx_enclave_init ioc;
	int dev_fd;
	int rc;

	dev_fd = open("/dev/isgx", O_RDWR);
	if (dev_fd < 0) {
		fprintf(stderr, "Unable to open /dev/sgx\n");
		return false;
118 119
	}

120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
	if (!encl_create(dev_fd, bin_size, secs))
		goto out_dev_fd;

	if (!encl_add_pages(dev_fd, secs->base + 0, bin, PAGE_SIZE, SGX_SECINFO_TCS))
		goto out_dev_fd;

	if (!encl_add_pages(dev_fd, secs->base + PAGE_SIZE, bin + PAGE_SIZE,
			    bin_size - PAGE_SIZE, SGX_REG_PAGE_FLAGS))
		goto out_dev_fd;

	ioc.addr = secs->base;
	ioc.sigstruct = (uint64_t)sigstruct;
	ioc.einittoken = (uint64_t)token;
	rc = ioctl(dev_fd, SGX_IOC_ENCLAVE_INIT, &ioc);
	if (rc) {
		printf("EINIT failed rc=%d\n", rc);
		goto out_map;
	}

	close(dev_fd);
	return true;
out_map:
	munmap((void *)secs->base, secs->size);
out_dev_fd:
	close(dev_fd);
	return false;
}

148
static bool get_file_size(const char *path, off_t *bin_size)
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
{
	struct stat sb;
	int ret;

	ret = stat(path, &sb);
	if (ret) {
		perror("stat");
		return false;
	}

	if (!sb.st_size || sb.st_size & 0xfff) {
		fprintf(stderr, "Invalid blob size %lu\n", sb.st_size);
		return false;
	}

	*bin_size = sb.st_size;
	return true;
}

168
static bool encl_data_map(const char *path, void **bin, off_t *bin_size)
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
{
	int fd;

	fd = open(path, O_RDONLY);
	if (fd == -1)  {
		fprintf(stderr, "open() %s failed, errno=%d.\n", path, errno);
		return false;
	}

	if (!get_file_size(path, bin_size))
		goto err_out;

	*bin = mmap(NULL, *bin_size, PROT_READ, MAP_PRIVATE, fd, 0);
	if (*bin == MAP_FAILED) {
		fprintf(stderr, "mmap() %s failed, errno=%d.\n", path, errno);
		goto err_out;
	}

	close(fd);
	return true;

err_out:
	close(fd);
	return false;
}

195
static bool load_sigstruct(const char *path, void *sigstruct)
196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
{
	int fd;

	fd = open(path, O_RDONLY);
	if (fd == -1)  {
		fprintf(stderr, "open() %s failed, errno=%d.\n", path, errno);
		return false;
	}

	if (read(fd, sigstruct, sizeof(struct sgx_sigstruct)) !=
	    sizeof(struct sgx_sigstruct)) {
		fprintf(stderr, "read() %s failed, errno=%d.\n", path, errno);
		close(fd);
		return false;
	}

	close(fd);
	return true;
}

216
static bool load_token(const char *path, void *token)
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
{
	int fd;

	fd = open(path, O_RDONLY);
	if (fd == -1)  {
		fprintf(stderr, "open() %s failed, errno=%d.\n", path, errno);
		return false;
	}

	if (read(fd, token, sizeof(struct sgx_einittoken)) !=
		sizeof(struct sgx_einittoken)) {
		fprintf(stderr, "read() %s failed, errno=%d.\n", path, errno);
		close(fd);
		return false;
	}

	close(fd);
	return true;
}

237 238 239 240 241 242
int pal_get_version(void)
{
	return 1;
}

int pal_init(const char *args, const char *log_level)
243 244 245 246 247 248 249
{
	struct sgx_sigstruct sigstruct;
	struct sgx_einittoken token;
	off_t bin_size;
	void *bin;

	if (!encl_data_map(IMAGE, &bin, &bin_size))
250
		return -ENOENT;
251 252

	if (!load_sigstruct(SIGSTRUCT, &sigstruct))
253
		return -ENOENT;
254 255

	if (!load_token(TOKEN, &token))
256
		return -ENOENT;
257 258

	if (!encl_build(&secs, bin, bin_size, &sigstruct, &token))
259
		return -EINVAL;
260 261

	initialized = true;	
262

263 264 265
	return 0;
}

266 267
int pal_exec(char *path, char *argv[], const char *envp[],
	     int *exit_code, int stdin, int stdout, int stderr)
268
{
269 270 271 272 273 274 275 276 277
        FILE *fp = fdopen(stderr, "w");
        if (!fp)
                return -1;

	if (!initialized) {
	        fprintf(fp, "enclave runtime skeleton uninitialized yet!\n");
		fclose(fp);
	        return -1;
	}
278

279 280 281 282
	uint64_t result = 0;

	sgx_call_eenter((void *)&MAGIC, &result, (void *)secs.base);
	if (result != MAGIC) {
283 284
		fprintf(fp, "0x%lx != 0x%lx\n", result, MAGIC);
		fclose(fp);
285 286 287
		return -1;
	}

288 289
	fprintf(fp, "copy MAGIC with enclave sucess.\n");
	fclose(fp);
290

291
	*exit_code = 0;
292

293 294 295
	return 0;
}

296
int pal_destroy(void)
297 298 299 300 301 302 303
{
	if (!initialized) {
		fprintf(stderr, "enclave runtime skeleton uninitialized yet!\n");
		return -1;
	}
	return 0;
}