Blob Blame History Raw
From: Ingo Franzki <ifranzki@linux.ibm.com>
Subject: s390/pkey: Introduce new API for random protected key generation
Git-commit: a45a5c7d36a53646094c2ba4970777a20ec0ec42
Patch-mainline: v4.20-rc1
References: FATE#326366, LTC#169192, bsc#1113523

Summary:     crypto: Add support for randomly generated protected keys
Description: This feature enhances the paes_s390 and the pkey kernel modules
             to allow using randomly generated protected keys. Such randomly
             generated protected keys do not require an CryptoExpress adapter.
             This is mainly useful for encrypted swap disks, or any other
             cases where the keys are ephemeral, that their life time does not
             extend over different boot, machine migrations or suspend/resume.

Upstream-Description:

             s390/pkey: Introduce new API for random protected key generation

             This patch introduces a new ioctl API and in-kernel API to
             generate a random protected key. The protected key is generated
             in a way that the effective clear key is never exposed in clear.
             Both APIs are described in detail in the header files
             arch/s390/include/asm/pkey.h and arch/s390/include/uapi/asm/pkey.h.

             Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
             Reviewed-by: Harald Freudenberger <freude@linux.ibm.com>
             Reviewed-by: Hendrik Brueckner <brueckner@linux.ibm.com>
             Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 arch/s390/include/asm/pkey.h      |    8 +++++
 arch/s390/include/uapi/asm/pkey.h |   10 ++++++
 drivers/s390/crypto/pkey_api.c    |   55 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)

--- a/arch/s390/include/asm/pkey.h
+++ b/arch/s390/include/asm/pkey.h
@@ -108,4 +108,12 @@ int pkey_verifykey(const struct pkey_sec
 		   u16 *pcardnr, u16 *pdomain,
 		   u16 *pkeysize, u32 *pattributes);
 
+/*
+ * In-kernel API: Generate (AES) random protected key.
+ * @param keytype one of the PKEY_KEYTYPE values
+ * @param protkey pointer to buffer receiving the protected key
+ * @return 0 on success, negative errno value on failure
+ */
+int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey);
+
 #endif /* _KAPI_PKEY_H */
--- a/arch/s390/include/uapi/asm/pkey.h
+++ b/arch/s390/include/uapi/asm/pkey.h
@@ -128,4 +128,14 @@ struct pkey_verifykey {
 #define PKEY_VERIFY_ATTR_AES	   0x00000001  /* key is an AES key */
 #define PKEY_VERIFY_ATTR_OLD_MKVP  0x00000100  /* key has old MKVP value */
 
+/*
+ * Generate (AES) random protected key.
+ */
+struct pkey_genprotk {
+	__u32 keytype;			       /* in: key type to generate */
+	struct pkey_protkey protkey;	       /* out: the protected key   */
+};
+
+#define PKEY_GENPROTK _IOWR(PKEY_IOCTL_MAGIC, 0x08, struct pkey_genprotk)
+
 #endif /* _UAPI_PKEY_H */
--- a/drivers/s390/crypto/pkey_api.c
+++ b/drivers/s390/crypto/pkey_api.c
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/kallsyms.h>
 #include <linux/debugfs.h>
+#include <linux/random.h>
 #include <asm/zcrypt.h>
 #include <asm/cpacf.h>
 #include <asm/pkey.h>
@@ -1057,6 +1058,46 @@ out:
 EXPORT_SYMBOL(pkey_verifykey);
 
 /*
+ * Generate a random protected key
+ */
+int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey)
+{
+	struct pkey_clrkey clrkey;
+	int keysize;
+	int rc;
+
+	switch (keytype) {
+	case PKEY_KEYTYPE_AES_128:
+		keysize = 16;
+		break;
+	case PKEY_KEYTYPE_AES_192:
+		keysize = 24;
+		break;
+	case PKEY_KEYTYPE_AES_256:
+		keysize = 32;
+		break;
+	default:
+		DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__,
+			  keytype);
+		return -EINVAL;
+	}
+
+	/* generate a dummy random clear key */
+	get_random_bytes(clrkey.clrkey, keysize);
+
+	/* convert it to a dummy protected key */
+	rc = pkey_clr2protkey(keytype, &clrkey, protkey);
+	if (rc)
+		return rc;
+
+	/* replace the key part of the protected key with random bytes */
+	get_random_bytes(protkey->protkey, keysize);
+
+	return 0;
+}
+EXPORT_SYMBOL(pkey_genprotkey);
+
+/*
  * File io functions
  */
 
@@ -1172,6 +1213,20 @@ static long pkey_unlocked_ioctl(struct f
 			return -EFAULT;
 		break;
 	}
+	case PKEY_GENPROTK: {
+		struct pkey_genprotk __user *ugp = (void __user *) arg;
+		struct pkey_genprotk kgp;
+
+		if (copy_from_user(&kgp, ugp, sizeof(kgp)))
+			return -EFAULT;
+		rc = pkey_genprotkey(kgp.keytype, &kgp.protkey);
+		DEBUG_DBG("%s pkey_genprotkey()=%d\n", __func__, rc);
+		if (rc)
+			break;
+		if (copy_to_user(ugp, &kgp, sizeof(kgp)))
+			return -EFAULT;
+		break;
+	}
 	default:
 		/* unknown/unsupported ioctl cmd */
 		return -ENOTTY;