s390/pkey: Introduce new API for random protected key generation
authorIngo Franzki <ifranzki@linux.ibm.com>
Thu, 23 Aug 2018 08:06:26 +0000 (10:06 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Tue, 9 Oct 2018 09:21:38 +0000 (11:21 +0200)
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>
arch/s390/include/asm/pkey.h
arch/s390/include/uapi/asm/pkey.h
drivers/s390/crypto/pkey_api.c

index 053117ba7328ca72322a0122f2b99930e8ea868f..c931818b99213603941d82f214723ad410fc480d 100644 (file)
@@ -109,4 +109,12 @@ int pkey_verifykey(const struct pkey_seckey *seckey,
                   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 */
index 6f84a53c3270eebb1bf4bbb88b1b79595b6a6e2e..10a7bc7c5fa9bd9a03498936582343a02edc5c6c 100644 (file)
@@ -129,4 +129,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 */
index 1b4001e0285fe0a5979558e2e9e2ce8f60e0808e..29028ccdce5b6f420d69d637f3ecb7e22553c4bd 100644 (file)
@@ -16,6 +16,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>
@@ -1051,6 +1052,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
  */
@@ -1167,6 +1208,20 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
                        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;