// SPDX-License-Identifier: GPL-2.0
/*
 *  pkey ep11 specific code
 *
 *  Copyright IBM Corp. 2024
 */

#define pr_fmt(fmt) "pkey: " fmt

#include <linux/init.h>
#include <linux/module.h>
#include <linux/cpufeature.h>

#include "zcrypt_ccamisc.h"
#include "zcrypt_ep11misc.h"
#include "pkey_base.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("IBM Corporation");
MODULE_DESCRIPTION("s390 protected key EP11 handler");

#if IS_MODULE(CONFIG_PKEY_EP11)
static struct ap_device_id pkey_ep11_card_ids[] = {
	{ .dev_type = AP_DEVICE_TYPE_CEX4 },
	{ .dev_type = AP_DEVICE_TYPE_CEX5 },
	{ .dev_type = AP_DEVICE_TYPE_CEX6 },
	{ .dev_type = AP_DEVICE_TYPE_CEX7 },
	{ .dev_type = AP_DEVICE_TYPE_CEX8 },
	{ /* end of list */ },
};
MODULE_DEVICE_TABLE(ap, pkey_ep11_card_ids);
#endif

/*
 * Check key blob for known and supported EP11 key.
 */
static bool is_ep11_key(const u8 *key, u32 keylen)
{
	struct keytoken_header *hdr = (struct keytoken_header *)key;

	if (keylen < sizeof(*hdr))
		return false;

	switch (hdr->type) {
	case TOKTYPE_NON_CCA:
		switch (hdr->version) {
		case TOKVER_EP11_AES:
		case TOKVER_EP11_AES_WITH_HEADER:
		case TOKVER_EP11_ECC_WITH_HEADER:
			return true;
		default:
			return false;
		}
	default:
		return false;
	}
}

static bool is_ep11_keytype(enum pkey_key_type key_type)
{
	switch (key_type) {
	case PKEY_TYPE_EP11:
	case PKEY_TYPE_EP11_AES:
	case PKEY_TYPE_EP11_ECC:
		return true;
	default:
		return false;
	}
}

static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags,
			  struct pkey_apqn *apqns, size_t *nr_apqns, u32 pflags)
{
	struct keytoken_header *hdr = (struct keytoken_header *)key;
	u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
	u32 xflags;
	int rc;

	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;

	if (!flags)
		flags = PKEY_FLAGS_MATCH_CUR_MKVP;

	if (keylen < sizeof(struct keytoken_header) || flags == 0)
		return -EINVAL;

	zcrypt_wait_api_operational();

	if (hdr->type == TOKTYPE_NON_CCA &&
	    (hdr->version == TOKVER_EP11_AES_WITH_HEADER ||
	     hdr->version == TOKVER_EP11_ECC_WITH_HEADER) &&
	    is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
		struct ep11keyblob *kb = (struct ep11keyblob *)
			(key + sizeof(struct ep11kblob_header));
		int minhwtype = 0, api = 0;

		if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)
			return -EINVAL;
		if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {
			minhwtype = ZCRYPT_CEX7;
			api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
		}
		rc = ep11_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
				    minhwtype, api, kb->wkvp, xflags);
		if (rc)
			goto out;

	} else if (hdr->type == TOKTYPE_NON_CCA &&
		   hdr->version == TOKVER_EP11_AES &&
		   is_ep11_keyblob(key)) {
		struct ep11keyblob *kb = (struct ep11keyblob *)key;
		int minhwtype = 0, api = 0;

		if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)
			return -EINVAL;
		if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {
			minhwtype = ZCRYPT_CEX7;
			api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
		}
		rc = ep11_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
				    minhwtype, api, kb->wkvp, xflags);
		if (rc)
			goto out;

	} else {
		PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",
			     __func__, hdr->type, hdr->version);
		return -EINVAL;
	}

	if (apqns) {
		if (*nr_apqns < _nr_apqns)
			rc = -ENOSPC;
		else
			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
	}
	*nr_apqns = _nr_apqns;

out:
	pr_debug("rc=%d\n", rc);
	return rc;
}

static int ep11_apqns4type(enum pkey_key_type ktype,
			   u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
			   struct pkey_apqn *apqns, size_t *nr_apqns, u32 pflags)
{
	u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
	u32 xflags;
	int rc;

	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;

	zcrypt_wait_api_operational();

	if (ktype == PKEY_TYPE_EP11 ||
	    ktype == PKEY_TYPE_EP11_AES ||
	    ktype == PKEY_TYPE_EP11_ECC) {
		u8 *wkvp = NULL;
		int api;

		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
			wkvp = cur_mkvp;
		api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
		rc = ep11_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
				    ZCRYPT_CEX7, api, wkvp, xflags);
		if (rc)
			goto out;

	} else {
		PKEY_DBF_ERR("%s unknown/unsupported key type %d\n",
			     __func__, (int)ktype);
		return -EINVAL;
	}

	if (apqns) {
		if (*nr_apqns < _nr_apqns)
			rc = -ENOSPC;
		else
			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
	}
	*nr_apqns = _nr_apqns;

out:
	pr_debug("rc=%d\n", rc);
	return rc;
}

static int ep11_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
			    const u8 *key, u32 keylen,
			    u8 *protkey, u32 *protkeylen, u32 *protkeytype,
			    u32 pflags)
{
	struct keytoken_header *hdr = (struct keytoken_header *)key;
	struct pkey_apqn _apqns[MAXAPQNSINLIST];
	u32 xflags;
	int i, rc;

	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;

	if (keylen < sizeof(*hdr))
		return -EINVAL;

	if (hdr->type == TOKTYPE_NON_CCA &&
	    hdr->version == TOKVER_EP11_AES_WITH_HEADER &&
	    is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
		/* EP11 AES key blob with header */
		if (ep11_check_aes_key_with_hdr(pkey_dbf_info,
						3, key, keylen, 1))
			return -EINVAL;
	} else if (hdr->type == TOKTYPE_NON_CCA &&
		   hdr->version == TOKVER_EP11_ECC_WITH_HEADER &&
		   is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
		/* EP11 ECC key blob with header */
		if (ep11_check_ecc_key_with_hdr(pkey_dbf_info,
						3, key, keylen, 1))
			return -EINVAL;
	} else if (hdr->type == TOKTYPE_NON_CCA &&
		   hdr->version == TOKVER_EP11_AES &&
		   is_ep11_keyblob(key)) {
		/* EP11 AES key blob with header in session field */
		if (ep11_check_aes_key(pkey_dbf_info, 3, key, keylen, 1))
			return -EINVAL;
	} else {
		PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",
			     __func__, hdr->type, hdr->version);
		return -EINVAL;
	}

	zcrypt_wait_api_operational();

	if (!apqns || (nr_apqns == 1 &&
		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
		nr_apqns = MAXAPQNSINLIST;
		rc = ep11_apqns4key(key, keylen, 0, _apqns, &nr_apqns, pflags);
		if (rc)
			goto out;
		apqns = _apqns;
	}

	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
		if (hdr->type == TOKTYPE_NON_CCA &&
		    hdr->version == TOKVER_EP11_AES_WITH_HEADER &&
		    is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
			rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain,
						key, hdr->len, protkey,
						protkeylen, protkeytype, xflags);
		} else if (hdr->type == TOKTYPE_NON_CCA &&
			   hdr->version == TOKVER_EP11_ECC_WITH_HEADER &&
			   is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {
			rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain,
						key, hdr->len, protkey,
						protkeylen, protkeytype, xflags);
		} else if (hdr->type == TOKTYPE_NON_CCA &&
			   hdr->version == TOKVER_EP11_AES &&
			   is_ep11_keyblob(key)) {
			rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain,
						key, hdr->len, protkey,
						protkeylen, protkeytype, xflags);
		} else {
			rc = -EINVAL;
			break;
		}
	}

out:
	pr_debug("rc=%d\n", rc);
	return rc;
}

/*
 * Generate EP11 secure key.
 * As of now only EP11 AES secure keys are supported.
 * keytype is one of the PKEY_KEYTYPE_* constants,
 * subtype may be PKEY_TYPE_EP11 or PKEY_TYPE_EP11_AES
 * or 0 (results in subtype PKEY_TYPE_EP11_AES),
 * keybitsize is the bit size of the key (may be 0 for
 * keytype PKEY_KEYTYPE_AES_*).
 */
static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
			u32 keytype, u32 subtype,
			u32 keybitsize, u32 flags,
			u8 *keybuf, u32 *keybuflen, u32 *_keyinfo, u32 pflags)
{
	struct pkey_apqn _apqns[MAXAPQNSINLIST];
	int i, len, rc;
	u32 xflags;

	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;

	/* check keytype, subtype, keybitsize */
	switch (keytype) {
	case PKEY_KEYTYPE_AES_128:
	case PKEY_KEYTYPE_AES_192:
	case PKEY_KEYTYPE_AES_256:
		len = pkey_keytype_aes_to_size(keytype);
		if (keybitsize && keybitsize != 8 * len) {
			PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
				     __func__, keybitsize);
			return -EINVAL;
		}
		keybitsize = 8 * len;
		switch (subtype) {
		case PKEY_TYPE_EP11:
		case PKEY_TYPE_EP11_AES:
			break;
		default:
			PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
				     __func__, subtype);
			return -EINVAL;
		}
		break;
	default:
		PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
			     __func__, keytype);
		return -EINVAL;
	}

	zcrypt_wait_api_operational();

	if (!apqns || (nr_apqns == 1 &&
		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
		nr_apqns = MAXAPQNSINLIST;
		rc = ep11_apqns4type(subtype, NULL, NULL, 0,
				     _apqns, &nr_apqns, pflags);
		if (rc)
			goto out;
		apqns = _apqns;
	}

	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
		rc = ep11_genaeskey(apqns[i].card, apqns[i].domain,
				    keybitsize, flags,
				    keybuf, keybuflen, subtype, xflags);
	}

out:
	pr_debug("rc=%d\n", rc);
	return rc;
}

/*
 * Generate EP11 secure key with given clear key value.
 * As of now only EP11 AES secure keys are supported.
 * keytype is one of the PKEY_KEYTYPE_* constants,
 * subtype may be PKEY_TYPE_EP11 or PKEY_TYPE_EP11_AES
 * or 0 (assumes PKEY_TYPE_EP11_AES then).
 * keybitsize is the bit size of the key (may be 0 for
 * keytype PKEY_KEYTYPE_AES_*).
 */
static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
			u32 keytype, u32 subtype,
			u32 keybitsize, u32 flags,
			const u8 *clrkey, u32 clrkeylen,
			u8 *keybuf, u32 *keybuflen, u32 *_keyinfo, u32 pflags)
{
	struct pkey_apqn _apqns[MAXAPQNSINLIST];
	int i, len, rc;
	u32 xflags;

	if (pflags & PKEY_XFLAG_NOCLEARKEY) {
		PKEY_DBF_ERR("%s clear key but xflag NOCLEARKEY\n", __func__);
		return -EINVAL;
	}

	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;

	/* check keytype, subtype, clrkeylen, keybitsize */
	switch (keytype) {
	case PKEY_KEYTYPE_AES_128:
	case PKEY_KEYTYPE_AES_192:
	case PKEY_KEYTYPE_AES_256:
		len = pkey_keytype_aes_to_size(keytype);
		if (keybitsize && keybitsize != 8 * len) {
			PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
				     __func__, keybitsize);
			return -EINVAL;
		}
		keybitsize = 8 * len;
		if (clrkeylen != len) {
			PKEY_DBF_ERR("%s invalid clear key len %d != %d\n",
				     __func__, clrkeylen, len);
			return -EINVAL;
		}
		switch (subtype) {
		case PKEY_TYPE_EP11:
		case PKEY_TYPE_EP11_AES:
			break;
		default:
			PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
				     __func__, subtype);
			return -EINVAL;
		}
		break;
	default:
		PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
			     __func__, keytype);
		return -EINVAL;
	}

	zcrypt_wait_api_operational();

	if (!apqns || (nr_apqns == 1 &&
		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
		nr_apqns = MAXAPQNSINLIST;
		rc = ep11_apqns4type(subtype, NULL, NULL, 0,
				     _apqns, &nr_apqns, pflags);
		if (rc)
			goto out;
		apqns = _apqns;
	}

	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
		rc = ep11_clr2keyblob(apqns[i].card, apqns[i].domain,
				      keybitsize, flags, clrkey,
				      keybuf, keybuflen, subtype, xflags);
	}

out:
	pr_debug("rc=%d\n", rc);
	return rc;
}

static int ep11_verifykey(const u8 *key, u32 keylen,
			  u16 *card, u16 *dom,
			  u32 *keytype, u32 *keybitsize, u32 *flags, u32 pflags)
{
	struct keytoken_header *hdr = (struct keytoken_header *)key;
	u32 apqns[MAXAPQNSINLIST], nr_apqns = ARRAY_SIZE(apqns);
	u32 xflags;
	int rc;

	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;

	if (keylen < sizeof(*hdr))
		return -EINVAL;

	zcrypt_wait_api_operational();

	if (hdr->type == TOKTYPE_NON_CCA &&
	    hdr->version == TOKVER_EP11_AES) {
		struct ep11keyblob *kb = (struct ep11keyblob *)key;
		int api;

		rc = ep11_check_aes_key(pkey_dbf_info, 3, key, keylen, 1);
		if (rc)
			goto out;
		*keytype = PKEY_TYPE_EP11;
		*keybitsize = kb->head.bitlen;

		api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
		rc = ep11_findcard2(apqns, &nr_apqns, *card, *dom,
				    ZCRYPT_CEX7, api,
				    ep11_kb_wkvp(key, keylen), xflags);
		if (rc)
			goto out;

		*flags = PKEY_FLAGS_MATCH_CUR_MKVP;

		*card = ((struct pkey_apqn *)apqns)->card;
		*dom = ((struct pkey_apqn *)apqns)->domain;

	} else if (hdr->type == TOKTYPE_NON_CCA &&
		   hdr->version == TOKVER_EP11_AES_WITH_HEADER) {
		struct ep11kblob_header *kh = (struct ep11kblob_header *)key;
		int api;

		rc = ep11_check_aes_key_with_hdr(pkey_dbf_info,
						 3, key, keylen, 1);
		if (rc)
			goto out;
		*keytype = PKEY_TYPE_EP11_AES;
		*keybitsize = kh->bitlen;

		api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;
		rc = ep11_findcard2(apqns, &nr_apqns, *card, *dom,
				    ZCRYPT_CEX7, api,
				    ep11_kb_wkvp(key, keylen), xflags);
		if (rc)
			goto out;

		*flags = PKEY_FLAGS_MATCH_CUR_MKVP;

		*card = ((struct pkey_apqn *)apqns)->card;
		*dom = ((struct pkey_apqn *)apqns)->domain;

	} else {
		/* unknown/unsupported key blob */
		rc = -EINVAL;
	}

out:
	pr_debug("rc=%d\n", rc);
	return rc;
}

/*
 * This function provides an alternate but usually slow way
 * to convert a 'clear key token' with AES key material into
 * a protected key. That is done via an intermediate step
 * which creates an EP11 AES secure key first and then derives
 * the protected key from this secure key.
 */
static int ep11_slowpath_key2protkey(const struct pkey_apqn *apqns,
				     size_t nr_apqns,
				     const u8 *key, u32 keylen,
				     u8 *protkey, u32 *protkeylen,
				     u32 *protkeytype, u32 pflags)
{
	const struct keytoken_header *hdr = (const struct keytoken_header *)key;
	const struct clearkeytoken *t = (const struct clearkeytoken *)key;
	u8 tmpbuf[MAXEP11AESKEYBLOBSIZE]; /* 336 bytes */
	u32 tmplen, keysize = 0;
	int i, rc;

	if (keylen < sizeof(*hdr))
		return -EINVAL;

	if (hdr->type == TOKTYPE_NON_CCA &&
	    hdr->version == TOKVER_CLEAR_KEY)
		keysize = pkey_keytype_aes_to_size(t->keytype);
	if (!keysize || t->len != keysize)
		return -EINVAL;

	/* try two times in case of failure */
	for (i = 0, rc = -ENODEV; i < 2 && rc; i++) {
		tmplen = MAXEP11AESKEYBLOBSIZE;
		rc = ep11_clr2key(NULL, 0, t->keytype, PKEY_TYPE_EP11,
				  8 * keysize, 0, t->clearkey, t->len,
				  tmpbuf, &tmplen, NULL, pflags);
		pr_debug("ep11_clr2key()=%d\n", rc);
		if (rc)
			continue;
		rc = ep11_key2protkey(NULL, 0, tmpbuf, tmplen,
				      protkey, protkeylen, protkeytype, pflags);
		pr_debug("ep11_key2protkey()=%d\n", rc);
	}

	pr_debug("rc=%d\n", rc);
	return rc;
}

static struct pkey_handler ep11_handler = {
	.module			 = THIS_MODULE,
	.name			 = "PKEY EP11 handler",
	.is_supported_key	 = is_ep11_key,
	.is_supported_keytype	 = is_ep11_keytype,
	.key_to_protkey		 = ep11_key2protkey,
	.slowpath_key_to_protkey = ep11_slowpath_key2protkey,
	.gen_key		 = ep11_gen_key,
	.clr_to_key		 = ep11_clr2key,
	.verify_key		 = ep11_verifykey,
	.apqns_for_key		 = ep11_apqns4key,
	.apqns_for_keytype	 = ep11_apqns4type,
};

/*
 * Module init
 */
static int __init pkey_ep11_init(void)
{
	/* register this module as pkey handler for all the ep11 stuff */
	return pkey_handler_register(&ep11_handler);
}

/*
 * Module exit
 */
static void __exit pkey_ep11_exit(void)
{
	/* unregister this module as pkey handler */
	pkey_handler_unregister(&ep11_handler);
}

module_init(pkey_ep11_init);
module_exit(pkey_ep11_exit);
