Commit cb26b9ff authored by Ingo Franzki's avatar Ingo Franzki Committed by Martin Schwidefsky
Browse files

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: default avatarIngo Franzki <ifranzki@linux.ibm.com>
Reviewed-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Reviewed-by: default avatarHendrik Brueckner <brueckner@linux.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent af504452
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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 */
+9 −0
Original line number Diff line number Diff line
@@ -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 */
+66 −1
Original line number Diff line number Diff line
@@ -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);