[RFC v2 01/13] x86/mktme: Document the MKTME APIs
Alison Schofield
alison.schofield at intel.com
Tue Dec 4 07:39:48 UTC 2018
This includes an overview, a section on each API: MTKME Keys and
system call encrypt_mprotect(), and a demonstration program.
(Some of this info is destined for man pages.)
Change-Id: I34dc9ff1a1308c057ec4bb3e652c4d7ce6995606
Signed-off-by: Alison Schofield <alison.schofield at intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov at linux.intel.com>
---
Documentation/x86/mktme/index.rst | 11 +++
Documentation/x86/mktme/mktme_demo.rst | 53 ++++++++++++++
Documentation/x86/mktme/mktme_encrypt.rst | 58 +++++++++++++++
Documentation/x86/mktme/mktme_keys.rst | 109 +++++++++++++++++++++++++++++
Documentation/x86/mktme/mktme_overview.rst | 60 ++++++++++++++++
5 files changed, 291 insertions(+)
create mode 100644 Documentation/x86/mktme/index.rst
create mode 100644 Documentation/x86/mktme/mktme_demo.rst
create mode 100644 Documentation/x86/mktme/mktme_encrypt.rst
create mode 100644 Documentation/x86/mktme/mktme_keys.rst
create mode 100644 Documentation/x86/mktme/mktme_overview.rst
diff --git a/Documentation/x86/mktme/index.rst b/Documentation/x86/mktme/index.rst
new file mode 100644
index 000000000000..8c556d04cbc4
--- /dev/null
+++ b/Documentation/x86/mktme/index.rst
@@ -0,0 +1,11 @@
+
+=============================================
+Multi-Key Total Memory Encryption (MKTME) API
+=============================================
+
+.. toctree::
+
+ mktme_overview
+ mktme_keys
+ mktme_encrypt
+ mktme_demo
diff --git a/Documentation/x86/mktme/mktme_demo.rst b/Documentation/x86/mktme/mktme_demo.rst
new file mode 100644
index 000000000000..afd50772e65d
--- /dev/null
+++ b/Documentation/x86/mktme/mktme_demo.rst
@@ -0,0 +1,53 @@
+Demonstration Program using MKTME API's
+=======================================
+
+/* Compile with the keyutils library: cc -o mdemo mdemo.c -lkeyutils */
+
+#include <sys/mman.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <keyutils.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define PAGE_SIZE sysconf(_SC_PAGE_SIZE)
+#define sys_encrypt_mprotect 335
+
+void main(void)
+{
+ char *options_CPU = "algorithm=aes-xts-128 type=cpu";
+ long size = PAGE_SIZE;
+ key_serial_t key;
+ void *ptra;
+ int ret;
+
+ /* Allocate an MKTME Key */
+ key = add_key("mktme", "testkey", options_CPU, strlen(options_CPU),
+ KEY_SPEC_THREAD_KEYRING);
+
+ if (key == -1) {
+ printf("addkey FAILED\n");
+ return;
+ }
+ /* Map a page of ANONYMOUS memory */
+ ptra = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ if (!ptra) {
+ printf("failed to mmap");
+ goto inval_key;
+ }
+ /* Encrypt that page of memory with the MKTME Key */
+ ret = syscall(sys_encrypt_mprotect, ptra, size, PROT_NONE, key);
+ if (ret)
+ printf("mprotect error [%d]\n", ret);
+
+ /* Enjoy that page of encrypted memory */
+
+ /* Free the memory */
+ ret = munmap(ptra, size);
+
+inval_key:
+ /* Free the Key */
+ if (keyctl(KEYCTL_INVALIDATE, key) == -1)
+ printf("invalidate failed on key [%d]\n", key);
+}
diff --git a/Documentation/x86/mktme/mktme_encrypt.rst b/Documentation/x86/mktme/mktme_encrypt.rst
new file mode 100644
index 000000000000..ede5237183fc
--- /dev/null
+++ b/Documentation/x86/mktme/mktme_encrypt.rst
@@ -0,0 +1,58 @@
+MKTME API: system call encrypt_mprotect()
+=========================================
+
+Synopsis
+--------
+int encrypt_mprotect(void \*addr, size_t len, int prot, key_serial_t serial);
+
+Where *key_serial_t serial* is the serial number of a key allocated
+using the MKTME Key Service.
+
+Description
+-----------
+ encrypt_mprotect() encrypts the memory pages containing any part
+ of the address range in the interval specified by addr and len.
+
+ encrypt_mprotect() supports the legacy mprotect() behavior plus
+ the enabling of memory encryption. That means that in addition
+ to encrypting the memory, the protection flags will be updated
+ as requested in the call.
+
+ The *addr* and *len* must be aligned to a page boundary.
+
+ The caller must have *KEY_NEED_VIEW* permission on the key.
+
+ The range of memory that is to be protected must be mapped as
+ *ANONYMOUS*.
+
+Errors
+------
+ In addition to the Errors returned from legacy mprotect()
+ encrypt_mprotect will return:
+
+ ENOKEY *serial* parameter does not represent a valid key.
+
+ EINVAL *len* parameter is not page aligned.
+
+ EACCES Caller does not have *KEY_NEED_VIEW* permission on the key.
+
+EXAMPLE
+--------
+ Allocate an MKTME Key::
+ serial = add_key("mktme", "name", "type=cpu algorithm=aes-xts-128" @u
+
+ Map ANONYMOUS memory::
+ ptr = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+
+ Protect memory::
+ ret = syscall(SYS_encrypt_mprotect, ptr, size, PROT_READ|PROT_WRITE,
+ serial);
+
+ Use the encrypted memory
+
+ Free memory::
+ ret = munmap(ptr, size);
+
+ Free the key resource::
+ ret = keyctl(KEYCTL_INVALIDATE, serial);
+
diff --git a/Documentation/x86/mktme/mktme_keys.rst b/Documentation/x86/mktme/mktme_keys.rst
new file mode 100644
index 000000000000..5837909b2c54
--- /dev/null
+++ b/Documentation/x86/mktme/mktme_keys.rst
@@ -0,0 +1,109 @@
+MKTME Key Service API
+=====================
+MKTME is a new key service type added to the Linux Kernel Key Service.
+
+The MKTME Key Service type is available when CONFIG_X86_INTEL_MKTME is
+turned on in Intel platforms that support the MKTME feature.
+
+The MKTME Key Service type manages the allocation of hardware encryption
+keys. Users can request an MKTME type key and then use that key to
+encrypt memory with the encrypt_mprotect() system call.
+
+Usage
+-----
+ When using the Kernel Key Service to request an *mktme* key,
+ specify the *payload* as follows:
+
+ type=
+ *user* User will supply the encryption key data. Use this
+ type to directly program a hardware encryption key.
+
+ *cpu* User requests a CPU generated encryption key.
+ The CPU generates and assigns an ephemeral key.
+
+ *clear* User requests that a hardware encryption key be
+ cleared. This will clear the encryption key from
+ the hardware. On execution this hardware key gets
+ TME behavior.
+
+ *no-encrypt*
+ User requests that hardware does not encrypt
+ memory when this key is in use.
+
+ algorithm=
+ When type=user or type=cpu the algorithm field must be
+ *aes-xts-128*
+
+ When type=clear or type=no-encrypt the algorithm field
+ must not be present in the payload.
+
+ key=
+ When type=user the user must supply a 128 bit encryption
+ key as exactly 32 ASCII hexadecimal characters.
+
+ When type=cpu the user may optionally supply 128 bits of
+ entropy for the CPU generated encryption key in this field.
+ It must be exactly 32 ASCII hexadecimal characters.
+
+ When type=clear or type=no-encrypt this key field must
+ not be present in the payload.
+
+ tweak=
+ When type=user the user must supply a 128 bit tweak key
+ as exactly 32 ASCII hexadecimal characters.
+
+ When type=cpu the user may optionally supply 128 bits of
+ entropy for the CPU generated tweak key in this field. It
+ must be exactly 32 ASCII hexadecimal characters.
+
+ When type=clear or type=no-encrypt the tweak field must
+ not be present in the payload.
+
+ERRORS
+------
+ In addition to the Errors returned from the Kernel Key Service,
+ add_key(2) or keyctl(1) commands, the MKTME Key Service type may
+ return the following errors:
+
+ EINVAL for any payload specification that does not match the
+ MKTME type payload as defined above.
+ EACCES for access denied. MKTME key type uses capabilities to
+ restrict the allocation of keys. CAP_SYS_RESOURCE is
+ required, but it will accept the broader capability of
+ CAP_SYS_ADMIN. See capabilities(7).
+
+ ENOKEY if a hardware key cannot be allocated. Additional error
+ messages will describe the hardware programming errors.
+
+EXAMPLES
+--------
+ Add a 'user' type key::
+
+ char \*options_USER = "type=user
+ algorithm=aes-xts-128
+ key=12345678912345671234567891234567
+ tweak=12345678912345671234567891234567";
+
+ key = add_key("mktme", "name", options_USER, strlen(options_USER),
+ KEY_SPEC_THREAD_KEYRING);
+
+ Add a 'cpu' type key::
+
+ char \*options_USER = "type=cpu algorithm=aes-xts-128";
+
+ key = add_key("mktme", "name", options_CPU, strlen(options_CPU),
+ KEY_SPEC_THREAD_KEYRING);
+
+ Update a key to 'Clear' type::
+
+ Note: This has the effect of clearing out the previously programmed
+ encryption data in the hardware. Use this to clear the hardware slot
+ prior to invalidating the key.
+
+ ret = keyctl(KEYCTL_UPDATE, key, "type=clear", strlen(options_CLEAR);
+
+ Add a "no-encrypt' type key::
+
+ key = add_key("mktme", "name", "no-encrypt", strlen(options_CPU),
+ KEY_SPEC_THREAD_KEYRING);
+
diff --git a/Documentation/x86/mktme/mktme_overview.rst b/Documentation/x86/mktme/mktme_overview.rst
new file mode 100644
index 000000000000..cc2c4a8320e7
--- /dev/null
+++ b/Documentation/x86/mktme/mktme_overview.rst
@@ -0,0 +1,60 @@
+Overview
+========
+MKTME (Multi-Key Total Memory Encryption) is a technology that allows
+memory encryption on Intel platforms. The main use case for the feature
+is virtual machine isolation. The API should apply to a wide range of
+use cases.
+
+Find the Intel Architecture Specification for MKTME here:
+https://software.intel.com/sites/default/files/managed/a5/16/Multi-Key-Total-Memory-Encryption-Spec.pdf
+
+The Encryption Process
+----------------------
+Userspace will see MKTME encryption as a Step Process.
+
+Step 1: Use the MKTME Key Service API to allocate an encryption key.
+
+Step 2: Use the encrypt_mprotect() system call to protect memory
+ with the encryption key obtained in Step 1.
+
+Definitions
+-----------
+Keys: References to Keys in this document are to Userspace Keys.
+ These keys are requested by users and jointly managed by the
+ MKTME Key Service Type, and more broadly by the Kernel Key
+ Service of which MKTME is a part.
+
+ This document does not intend to document KKS, but only the
+ MKTME type of the KKS. The options of the KKS can be grouped
+ into 2 classes for purposes of understanding how MKTME operates
+ within the broader KKS.
+
+KeyIDs: References to KeyIDs in this document are to the hardware KeyID
+ slots that are available on Intel Platforms. A KeyID is a
+ numerical index into a software programmable slot in the Intel
+ hardware. Refer to the Intel specification linked above for
+ details on the implementation of MKTME in Intel platforms.
+
+Key<-->KeyID Mapping:
+ The MKTME Key Service maintains a mapping between Keys and KeyIDS.
+ This mapping is known only to the kernel. Userspace does not need
+ to know which hardware KeyID slot it's Userspace Key has been
+ assigned.
+
+Configuration
+-------------
+
+CONFIG_X86_INTEL_MKTME
+ MKTME is enabled by selecting CONFIG_X86_INTEL_MKTME on Intel
+ platforms supporting the MKTME feature.
+
+mktme_savekeys
+ mktme_savekeys is a kernel cmdline parameter.
+
+ This parameter allows the kernel to save the user specified
+ MKTME key payload. Saving this payload means that the MKTME
+ Key Service can always allow the addition of new physical
+ packages. If the mktme_savekeys parameter is not present,
+ users key data will not be saved, and new physical packages
+ may only be added to the system if no user type MKTME keys
+ are in use.
--
2.14.1
More information about the Linux-security-module-archive
mailing list