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

Introduce a new ioctl API and in-kernel API to verify if a
random protected key is still valid. A protected key is
invalid when its wrapping key verification pattern does not
match the verification pattern of the LPAR. Each time an LPAR
is activated, a new LPAR wrapping key is generated and the
wrapping key verification pattern is updated.
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>
This commit is contained in:
Ingo Franzki 2018-08-23 17:49:38 +02:00 committed by Martin Schwidefsky
parent af504452d1
commit cb26b9ff71
3 changed files with 83 additions and 1 deletions

View File

@ -117,4 +117,12 @@ int pkey_verifykey(const struct pkey_seckey *seckey,
*/
int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey);
/*
* In-kernel API: Verify an (AES) protected key.
* @param protkey pointer to buffer containing the protected key to verify
* @return 0 on success, negative errno value on failure. In case the protected
* key is not valid -EKEYREJECTED is returned
*/
int pkey_verifyprotkey(const struct pkey_protkey *protkey);
#endif /* _KAPI_PKEY_H */

View File

@ -139,4 +139,13 @@ struct pkey_genprotk {
#define PKEY_GENPROTK _IOWR(PKEY_IOCTL_MAGIC, 0x08, struct pkey_genprotk)
/*
* Verify an (AES) protected key.
*/
struct pkey_verifyprotk {
struct pkey_protkey protkey; /* in: the protected key to verify */
};
#define PKEY_VERIFYPROTK _IOW(PKEY_IOCTL_MAGIC, 0x09, struct pkey_verifyprotk)
#endif /* _UAPI_PKEY_H */

View File

@ -20,6 +20,7 @@
#include <asm/zcrypt.h>
#include <asm/cpacf.h>
#include <asm/pkey.h>
#include <crypto/aes.h>
#include "zcrypt_api.h"
@ -1113,6 +1114,52 @@ int pkey_genprotkey(__u32 keytype, struct pkey_protkey *protkey)
}
EXPORT_SYMBOL(pkey_genprotkey);
/*
* Verify if a protected key is still valid
*/
int pkey_verifyprotkey(const struct pkey_protkey *protkey)
{
unsigned long fc;
struct {
u8 iv[AES_BLOCK_SIZE];
u8 key[MAXPROTKEYSIZE];
} param;
u8 null_msg[AES_BLOCK_SIZE];
u8 dest_buf[AES_BLOCK_SIZE];
unsigned int k;
switch (protkey->type) {
case PKEY_KEYTYPE_AES_128:
fc = CPACF_KMC_PAES_128;
break;
case PKEY_KEYTYPE_AES_192:
fc = CPACF_KMC_PAES_192;
break;
case PKEY_KEYTYPE_AES_256:
fc = CPACF_KMC_PAES_256;
break;
default:
DEBUG_ERR("%s unknown/unsupported keytype %d\n", __func__,
protkey->type);
return -EINVAL;
}
memset(null_msg, 0, sizeof(null_msg));
memset(param.iv, 0, sizeof(param.iv));
memcpy(param.key, protkey->protkey, sizeof(param.key));
k = cpacf_kmc(fc | CPACF_ENCRYPT, &param, null_msg, dest_buf,
sizeof(null_msg));
if (k != sizeof(null_msg)) {
DEBUG_ERR("%s protected key is not valid\n", __func__);
return -EKEYREJECTED;
}
return 0;
}
EXPORT_SYMBOL(pkey_verifyprotkey);
/*
* File io functions
*/
@ -1243,6 +1290,16 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
return -EFAULT;
break;
}
case PKEY_VERIFYPROTK: {
struct pkey_verifyprotk __user *uvp = (void __user *) arg;
struct pkey_verifyprotk kvp;
if (copy_from_user(&kvp, uvp, sizeof(kvp)))
return -EFAULT;
rc = pkey_verifyprotkey(&kvp.protkey);
DEBUG_DBG("%s pkey_verifyprotkey()=%d\n", __func__, rc);
break;
}
default:
/* unknown/unsupported ioctl cmd */
return -ENOTTY;
@ -1504,7 +1561,7 @@ static struct miscdevice pkey_dev = {
*/
static int __init pkey_init(void)
{
cpacf_mask_t pckmo_functions;
cpacf_mask_t pckmo_functions, kmc_functions;
/* check for pckmo instructions available */
if (!cpacf_query(CPACF_PCKMO, &pckmo_functions))
@ -1514,6 +1571,14 @@ static int __init pkey_init(void)
!cpacf_test_func(&pckmo_functions, CPACF_PCKMO_ENC_AES_256_KEY))
return -EOPNOTSUPP;
/* check for kmc instructions available */
if (!cpacf_query(CPACF_KMC, &kmc_functions))
return -EOPNOTSUPP;
if (!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_128) ||
!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_192) ||
!cpacf_test_func(&kmc_functions, CPACF_KMC_PAES_256))
return -EOPNOTSUPP;
pkey_debug_init();
return misc_register(&pkey_dev);