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:
parent
af504452d1
commit
cb26b9ff71
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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, ¶m, 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);
|
||||
|
|
Loading…
Reference in New Issue