linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RESEND 1/3] x86/sgx: Adding eextend ioctl
       [not found] <cover.1617194795.git.raoul.strackx@fortanix.com>
@ 2021-03-31 12:51 ` Raoul Strackx
  2021-03-31 12:51 ` [PATCH RESEND 2/3] x86/sgx: Fix compatibility issue with OPENSSL < 1.1.0 Raoul Strackx
  2021-03-31 12:51 ` [PATCH RESEND 3/3] x86/sgx: eextend ioctl selftest Raoul Strackx
  2 siblings, 0 replies; 3+ messages in thread
From: Raoul Strackx @ 2021-03-31 12:51 UTC (permalink / raw)
  To: Jarkko Sakkinen, Dave Hansen, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, x86, H. Peter Anvin, linux-sgx, linux-kernel

The current sgx driver can only launch enclaves that always measure 4K pages. That may not necessarily be the case. This patch adds an ioctl to enable users to add the enclave measurement per 256 byte.

Signed-off-by: Raoul Strackx <raoul.strackx@fortanix.com>
---
 arch/x86/include/uapi/asm/sgx.h | 11 ++++++
 arch/x86/kernel/cpu/sgx/ioctl.c | 81 +++++++++++++++++++++++++++++++++++------
 2 files changed, 81 insertions(+), 11 deletions(-)

diff --git a/arch/x86/include/uapi/asm/sgx.h b/arch/x86/include/uapi/asm/sgx.h
index 9034f30..121ca5f 100644
--- a/arch/x86/include/uapi/asm/sgx.h
+++ b/arch/x86/include/uapi/asm/sgx.h
@@ -27,6 +27,8 @@ enum sgx_page_flags {
 	_IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init)
 #define SGX_IOC_ENCLAVE_PROVISION \
 	_IOW(SGX_MAGIC, 0x03, struct sgx_enclave_provision)
+#define SGX_IOC_ENCLAVE_EXTEND \
+	_IOW(SGX_MAGIC, 0x04, struct sgx_enclave_extend)
 
 /**
  * struct sgx_enclave_create - parameter structure for the
@@ -57,6 +59,15 @@ struct sgx_enclave_add_pages {
 };
 
 /**
+ * struct sgx_enclave_extend - parameter structure for the
+ *                             %SGX_IOC_ENCLAVE_MEASURE ioctl
+ * @offset:	offset of the data from the start address for the data
+ */
+struct sgx_enclave_extend {
+	__u64 offset;
+};
+
+/**
  * struct sgx_enclave_init - parameter structure for the
  *                           %SGX_IOC_ENCLAVE_INIT ioctl
  * @sigstruct:	address for the SIGSTRUCT data
diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
index 90a5caf..a21d3e7 100644
--- a/arch/x86/kernel/cpu/sgx/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/ioctl.c
@@ -261,20 +261,21 @@ static int __sgx_encl_add_page(struct sgx_encl *encl,
 	return ret ? -EIO : 0;
 }
 
-/*
- * If the caller requires measurement of the page as a proof for the content,
- * use EEXTEND to add a measurement for 256 bytes of the page. Repeat this
- * operation until the entire page is measured."
- */
-static int __sgx_encl_extend(struct sgx_encl *encl,
-			     struct sgx_epc_page *epc_page)
+static int __sgx_encl_extend_chunk(struct sgx_encl *encl,
+				   void *chunk, unsigned long size)
 {
 	unsigned long offset;
 	int ret;
+	void *secs_addr;
 
-	for (offset = 0; offset < PAGE_SIZE; offset += SGX_EEXTEND_BLOCK_SIZE) {
-		ret = __eextend(sgx_get_epc_virt_addr(encl->secs.epc_page),
-				sgx_get_epc_virt_addr(epc_page) + offset);
+	if (!size || !IS_ALIGNED(size, SGX_EEXTEND_BLOCK_SIZE)) {
+		return -EINVAL;
+	}
+
+	secs_addr = sgx_get_epc_virt_addr(encl->secs.epc_page);
+	for (offset = 0; offset < size; offset += SGX_EEXTEND_BLOCK_SIZE) {
+		ret = __eextend(secs_addr,
+				chunk + offset);
 		if (ret) {
 			if (encls_failed(ret))
 				ENCLS_WARN(ret, "EEXTEND");
@@ -286,6 +287,18 @@ static int __sgx_encl_extend(struct sgx_encl *encl,
 	return 0;
 }
 
+/*
+ * If the caller requires measurement of the page as a proof for the content,
+ * use EEXTEND to add a measurement for 256 bytes of the page. Repeat this
+ * operation until the entire page is measured."
+ */
+static int __sgx_encl_extend_page(struct sgx_encl *encl,
+			     struct sgx_epc_page *epc_page)
+{
+	void *chunk = sgx_get_epc_virt_addr(epc_page);
+	return __sgx_encl_extend_chunk(encl, chunk, PAGE_SIZE);
+}
+
 static int sgx_encl_add_page(struct sgx_encl *encl, unsigned long src,
 			     unsigned long offset, struct sgx_secinfo *secinfo,
 			     unsigned long flags)
@@ -346,7 +359,7 @@ static int sgx_encl_add_page(struct sgx_encl *encl, unsigned long src,
 	encl->secs_child_cnt++;
 
 	if (flags & SGX_PAGE_MEASURE) {
-		ret = __sgx_encl_extend(encl, epc_page);
+		ret = __sgx_encl_extend_page(encl, epc_page);
 		if (ret)
 			goto err_out;
 	}
@@ -466,6 +479,49 @@ static long sgx_ioc_enclave_add_pages(struct sgx_encl *encl, void __user *arg)
 	return ret;
 }
 
+static long sgx_ioc_enclave_extend(struct sgx_encl *encl, void __user *user_arg)
+{
+	struct sgx_enclave_extend arg;
+	struct sgx_encl_page *encl_page;
+	void *chunk;
+	long ret = 0;
+
+	if (!test_bit(SGX_ENCL_CREATED, &encl->flags) ||
+	    test_bit(SGX_ENCL_INITIALIZED, &encl->flags))
+		return -EINVAL;
+
+	if (copy_from_user(&arg, user_arg, sizeof(arg)))
+		return -EFAULT;
+
+	if (!arg.offset || !IS_ALIGNED(arg.offset, SGX_EEXTEND_BLOCK_SIZE)) {
+		pr_info("offset not a multiple of 256: %llu\n", arg.offset);
+		return -EINVAL;
+	}
+
+	encl_page = xa_load(&encl->page_array, PFN_DOWN(encl->base + arg.offset));
+
+	if (!encl_page) {
+		pr_info("enc page not found\n");
+		return -EFAULT;
+	}
+
+	mmap_read_lock(current->mm);
+	mutex_lock(&encl->lock);
+	sgx_unmark_page_reclaimable(encl_page->epc_page);
+
+	chunk = sgx_get_epc_virt_addr(encl_page->epc_page) + (arg.offset & (PAGE_SIZE - 1));
+
+	if (__sgx_encl_extend_chunk(encl, chunk, SGX_EEXTEND_BLOCK_SIZE)) {
+		pr_info("extend returned an error\n");
+		ret = -EFAULT;
+	}
+
+	sgx_mark_page_reclaimable(encl_page->epc_page);
+	mutex_unlock(&encl->lock);
+	mmap_read_unlock(current->mm);
+	return ret;
+}
+
 static int __sgx_get_key_hash(struct crypto_shash *tfm, const void *modulus,
 			      void *hash)
 {
@@ -706,6 +762,9 @@ long sgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 	case SGX_IOC_ENCLAVE_PROVISION:
 		ret = sgx_ioc_enclave_provision(encl, (void __user *)arg);
 		break;
+	case SGX_IOC_ENCLAVE_EXTEND:
+		ret = sgx_ioc_enclave_extend(encl, (void __user *)arg);
+		break;
 	default:
 		ret = -ENOIOCTLCMD;
 		break;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH RESEND 2/3] x86/sgx: Fix compatibility issue with OPENSSL < 1.1.0
       [not found] <cover.1617194795.git.raoul.strackx@fortanix.com>
  2021-03-31 12:51 ` [PATCH RESEND 1/3] x86/sgx: Adding eextend ioctl Raoul Strackx
@ 2021-03-31 12:51 ` Raoul Strackx
  2021-03-31 12:51 ` [PATCH RESEND 3/3] x86/sgx: eextend ioctl selftest Raoul Strackx
  2 siblings, 0 replies; 3+ messages in thread
From: Raoul Strackx @ 2021-03-31 12:51 UTC (permalink / raw)
  To: Jarkko Sakkinen, Dave Hansen, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, x86, H. Peter Anvin, linux-sgx, linux-kernel

The `RSA_get0_key` function only got introduced in OpenSSL 1.1.0. This makes compilation fail with older versions.

Signed-off-by: Raoul Strackx <raoul.strackx@fortanix.com>
---
 tools/testing/selftests/sgx/sigstruct.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/sgx/sigstruct.c b/tools/testing/selftests/sgx/sigstruct.c
index dee7a3d..aac9cbc 100644
--- a/tools/testing/selftests/sgx/sigstruct.c
+++ b/tools/testing/selftests/sgx/sigstruct.c
@@ -128,8 +128,11 @@ static bool check_crypto_errors(void)
 static inline const BIGNUM *get_modulus(RSA *key)
 {
 	const BIGNUM *n;
-
+#if OPENSSL_VERSION_NUMBER >= 0x10100000L
 	RSA_get0_key(key, &n, NULL, NULL);
+#else
+	n = key->n;
+#endif
 	return n;
 }
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH RESEND 3/3] x86/sgx: eextend ioctl selftest
       [not found] <cover.1617194795.git.raoul.strackx@fortanix.com>
  2021-03-31 12:51 ` [PATCH RESEND 1/3] x86/sgx: Adding eextend ioctl Raoul Strackx
  2021-03-31 12:51 ` [PATCH RESEND 2/3] x86/sgx: Fix compatibility issue with OPENSSL < 1.1.0 Raoul Strackx
@ 2021-03-31 12:51 ` Raoul Strackx
  2 siblings, 0 replies; 3+ messages in thread
From: Raoul Strackx @ 2021-03-31 12:51 UTC (permalink / raw)
  To: Jarkko Sakkinen, Dave Hansen, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, x86, H. Peter Anvin, linux-sgx, linux-kernel

In order to test the new eextend ioctl, the SGX selftest is modified to only partially measure the last page of segments. Most segments are larger than 4k, so the MEASURE flag for SGX_IOC_ENCLAVE_ADD_PAGE is still being tested.

Signed-off-by: Raoul Strackx <raoul.strackx@fortanix.com>
---
 tools/testing/selftests/sgx/defines.h   |  1 +
 tools/testing/selftests/sgx/load.c      | 55 ++++++++++++++++++++++++++++-----
 tools/testing/selftests/sgx/main.h      |  1 +
 tools/testing/selftests/sgx/sigstruct.c | 38 +++++++++++------------
 4 files changed, 67 insertions(+), 28 deletions(-)

diff --git a/tools/testing/selftests/sgx/defines.h b/tools/testing/selftests/sgx/defines.h
index 592c1cc..c09550d 100644
--- a/tools/testing/selftests/sgx/defines.h
+++ b/tools/testing/selftests/sgx/defines.h
@@ -10,6 +10,7 @@
 
 #define PAGE_SIZE 4096
 #define PAGE_MASK (~(PAGE_SIZE - 1))
+#define SGX_EEXTEND_BLOCK_SIZE 256
 
 #define __aligned(x) __attribute__((__aligned__(x)))
 #define __packed __attribute__((packed))
diff --git a/tools/testing/selftests/sgx/load.c b/tools/testing/selftests/sgx/load.c
index 9d43b75..52f0569 100644
--- a/tools/testing/selftests/sgx/load.c
+++ b/tools/testing/selftests/sgx/load.c
@@ -102,28 +102,67 @@ static bool encl_ioc_create(struct encl *encl)
 static bool encl_ioc_add_pages(struct encl *encl, struct encl_segment *seg)
 {
 	struct sgx_enclave_add_pages ioc;
+	struct sgx_enclave_extend ioc_extend;
 	struct sgx_secinfo secinfo;
+	uint64_t size_full_pages;
+	uint64_t size;
+	uint64_t chunk_offset;
 	int rc;
 
+	size_full_pages = size_fit(seg->size, SGX_EEXTEND_BLOCK_SIZE) & PAGE_MASK;
+	size = size_fit(seg->size, SGX_EEXTEND_BLOCK_SIZE);
+
 	memset(&secinfo, 0, sizeof(secinfo));
 	secinfo.flags = seg->flags;
 
+	// Add and extend full pages
 	ioc.src = (uint64_t)encl->src + seg->offset;
 	ioc.offset = seg->offset;
-	ioc.length = seg->size;
 	ioc.secinfo = (unsigned long)&secinfo;
+	ioc.length = size_full_pages;
 	ioc.flags = SGX_PAGE_MEASURE;
 
-	rc = ioctl(encl->fd, SGX_IOC_ENCLAVE_ADD_PAGES, &ioc);
-	if (rc < 0) {
-		fprintf(stderr, "SGX_IOC_ENCLAVE_ADD_PAGES failed: errno=%d.\n",
-			errno);
-		return false;
+	if (0 < ioc.length) {
+		rc = ioctl(encl->fd, SGX_IOC_ENCLAVE_ADD_PAGES, &ioc);
+		if (rc < 0) {
+			fprintf(stderr, "SGX_IOC_ENCLAVE_ADD_PAGES failed: errno=%d.\n",
+				errno);
+			return false;
+		}
+	}
+
+	if (size_full_pages < size) {
+		// Add last, partly measured page
+		ioc.offset = seg->offset + size_full_pages;
+		ioc.length = 0x1000;
+		ioc.flags = 0;
+
+		rc = ioctl(encl->fd, SGX_IOC_ENCLAVE_ADD_PAGES, &ioc);
+		if (rc < 0) {
+			fprintf(stderr, "SGX_IOC_ENCLAVE_ADD_PAGES failed: errno=%d.\n",
+				errno);
+			return false;
+		}
+
+		// extend chunks
+		for (chunk_offset = 0; chunk_offset < size - size_full_pages; chunk_offset += SGX_EEXTEND_BLOCK_SIZE) {
+			ioc_extend.offset = seg->offset + size_full_pages + chunk_offset;
+			rc = ioctl(encl->fd, SGX_IOC_ENCLAVE_EXTEND, &ioc_extend);
+			if (rc < 0) {
+				fprintf(stderr, "SGX_IOC_ENCLAVE_EXTEND failed: errno=%d.\n",
+					errno);
+				return false;
+			}
+		}
 	}
 
 	return true;
 }
 
+uint64_t size_fit(uint64_t size_in_bytes, uint64_t block_size) {
+	return (size_in_bytes + block_size - 1) & (~(block_size - 1));
+}
+
 bool encl_load(const char *path, struct encl *encl)
 {
 	Elf64_Phdr *phdr_tbl;
@@ -197,7 +236,7 @@ bool encl_load(const char *path, struct encl *encl)
 		}
 
 		seg->offset = (phdr->p_offset & PAGE_MASK) - src_offset;
-		seg->size = (phdr->p_filesz + PAGE_SIZE - 1) & PAGE_MASK;
+		seg->size = phdr->p_filesz;
 
 		printf("0x%016lx 0x%016lx 0x%02x\n", seg->offset, seg->size,
 		       seg->prot);
@@ -209,7 +248,7 @@ bool encl_load(const char *path, struct encl *encl)
 
 	encl->src = encl->bin + src_offset;
 	encl->src_size = encl->segment_tbl[j - 1].offset +
-			 encl->segment_tbl[j - 1].size;
+			 size_fit(encl->segment_tbl[j - 1].size, PAGE_SIZE);
 
 	for (encl->encl_size = 4096; encl->encl_size < encl->src_size; )
 		encl->encl_size <<= 1;
diff --git a/tools/testing/selftests/sgx/main.h b/tools/testing/selftests/sgx/main.h
index 67211a7..9d63bda 100644
--- a/tools/testing/selftests/sgx/main.h
+++ b/tools/testing/selftests/sgx/main.h
@@ -34,6 +34,7 @@ void encl_delete(struct encl *ctx);
 bool encl_load(const char *path, struct encl *encl);
 bool encl_measure(struct encl *encl);
 bool encl_build(struct encl *encl);
+uint64_t size_fit(uint64_t size_in_bytes, uint64_t block_size);
 
 int sgx_call_vdso(void *rdi, void *rsi, long rdx, u32 function, void *r8, void *r9,
 		  struct sgx_enclave_run *run);
diff --git a/tools/testing/selftests/sgx/sigstruct.c b/tools/testing/selftests/sgx/sigstruct.c
index aac9cbc..eba7c86 100644
--- a/tools/testing/selftests/sgx/sigstruct.c
+++ b/tools/testing/selftests/sgx/sigstruct.c
@@ -260,28 +260,25 @@ static bool mrenclave_eextend(EVP_MD_CTX *ctx, uint64_t offset,
 			      const uint8_t *data)
 {
 	struct mreextend mreextend;
-	int i;
 
-	for (i = 0; i < 0x1000; i += 0x100) {
-		memset(&mreextend, 0, sizeof(mreextend));
-		mreextend.tag = MREEXTEND;
-		mreextend.offset = offset + i;
+	memset(&mreextend, 0, sizeof(mreextend));
+	mreextend.tag = MREEXTEND;
+	mreextend.offset = offset;
 
-		if (!mrenclave_update(ctx, &mreextend))
-			return false;
+	if (!mrenclave_update(ctx, &mreextend))
+		return false;
 
-		if (!mrenclave_update(ctx, &data[i + 0x00]))
-			return false;
+	if (!mrenclave_update(ctx, &data[0x00]))
+		return false;
 
-		if (!mrenclave_update(ctx, &data[i + 0x40]))
-			return false;
+	if (!mrenclave_update(ctx, &data[0x40]))
+		return false;
 
-		if (!mrenclave_update(ctx, &data[i + 0x80]))
-			return false;
+	if (!mrenclave_update(ctx, &data[0x80]))
+		return false;
 
-		if (!mrenclave_update(ctx, &data[i + 0xC0]))
-			return false;
-	}
+	if (!mrenclave_update(ctx, &data[0xC0]))
+		return false;
 
 	return true;
 }
@@ -289,12 +286,13 @@ static bool mrenclave_eextend(EVP_MD_CTX *ctx, uint64_t offset,
 static bool mrenclave_segment(EVP_MD_CTX *ctx, struct encl *encl,
 			      struct encl_segment *seg)
 {
-	uint64_t end = seg->offset + seg->size;
+	uint64_t end = seg->offset + size_fit(seg->size, SGX_EEXTEND_BLOCK_SIZE);
 	uint64_t offset;
 
-	for (offset = seg->offset; offset < end; offset += PAGE_SIZE) {
-		if (!mrenclave_eadd(ctx, offset, seg->flags))
-			return false;
+	for (offset = seg->offset; offset < end; offset += SGX_EEXTEND_BLOCK_SIZE) {
+		if (offset % PAGE_SIZE == 0)
+			if (!mrenclave_eadd(ctx, offset, seg->flags))
+				return false;
 
 		if (!mrenclave_eextend(ctx, offset, encl->src + offset))
 			return false;
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-03-31 12:52 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <cover.1617194795.git.raoul.strackx@fortanix.com>
2021-03-31 12:51 ` [PATCH RESEND 1/3] x86/sgx: Adding eextend ioctl Raoul Strackx
2021-03-31 12:51 ` [PATCH RESEND 2/3] x86/sgx: Fix compatibility issue with OPENSSL < 1.1.0 Raoul Strackx
2021-03-31 12:51 ` [PATCH RESEND 3/3] x86/sgx: eextend ioctl selftest Raoul Strackx

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).