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

#define KMSG_COMPONENT "pkey"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

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

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

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

/*
 * UV secret token struct and defines.
 */

#define TOKVER_UV_SECRET 0x09

struct uvsecrettoken {
	u8  type;		/* 0x00 = TOKTYPE_NON_CCA */
	u8  res0[3];
	u8  version;		/* 0x09 = TOKVER_UV_SECRET */
	u8  res1[3];
	u16 secret_type;	/* one of enum uv_secret_types from uv.h */
	u16 secret_len;		/* length in bytes of the secret */
	u8  secret_id[UV_SECRET_ID_LEN]; /* the secret id for this secret */
} __packed;

/*
 * Check key blob for known and supported UV key.
 */
static bool is_uv_key(const u8 *key, u32 keylen)
{
	struct uvsecrettoken *t = (struct uvsecrettoken *)key;

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

	switch (t->type) {
	case TOKTYPE_NON_CCA:
		switch (t->version) {
		case TOKVER_UV_SECRET:
			switch (t->secret_type) {
			case UV_SECRET_AES_128:
			case UV_SECRET_AES_192:
			case UV_SECRET_AES_256:
			case UV_SECRET_AES_XTS_128:
			case UV_SECRET_AES_XTS_256:
			case UV_SECRET_HMAC_SHA_256:
			case UV_SECRET_HMAC_SHA_512:
			case UV_SECRET_ECDSA_P256:
			case UV_SECRET_ECDSA_P384:
			case UV_SECRET_ECDSA_P521:
			case UV_SECRET_ECDSA_ED25519:
			case UV_SECRET_ECDSA_ED448:
				return true;
			default:
				return false;
			}
		default:
			return false;
		}
	default:
		return false;
	}
}

static bool is_uv_keytype(enum pkey_key_type keytype)
{
	switch (keytype) {
	case PKEY_TYPE_UVSECRET:
		return true;
	default:
		return false;
	}
}

static int retrieve_secret(const u8 secret_id[UV_SECRET_ID_LEN],
			   u16 *secret_type, u8 *buf, u32 *buflen)
{
	struct uv_secret_list_item_hdr secret_meta_data;
	int rc;

	rc = uv_get_secret_metadata(secret_id, &secret_meta_data);
	if (rc)
		return rc;

	if (*buflen < secret_meta_data.length)
		return -EINVAL;

	rc = uv_retrieve_secret(secret_meta_data.index,
				buf, secret_meta_data.length);
	if (rc)
		return rc;

	*secret_type = secret_meta_data.type;
	*buflen = secret_meta_data.length;

	return 0;
}

static int uv_get_size_and_type(u16 secret_type, u32 *pkeysize, u32 *pkeytype)
{
	int rc = 0;

	switch (secret_type) {
	case UV_SECRET_AES_128:
		*pkeysize = 16 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_AES_128;
		break;
	case UV_SECRET_AES_192:
		*pkeysize = 24 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_AES_192;
		break;
	case UV_SECRET_AES_256:
		*pkeysize = 32 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_AES_256;
		break;
	case UV_SECRET_AES_XTS_128:
		*pkeysize = 16 + 16 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_AES_XTS_128;
		break;
	case UV_SECRET_AES_XTS_256:
		*pkeysize = 32 + 32 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_AES_XTS_256;
		break;
	case UV_SECRET_HMAC_SHA_256:
		*pkeysize = 64 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_HMAC_512;
		break;
	case UV_SECRET_HMAC_SHA_512:
		*pkeysize = 128 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_HMAC_1024;
		break;
	case UV_SECRET_ECDSA_P256:
		*pkeysize = 32 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_ECC_P256;
		break;
	case UV_SECRET_ECDSA_P384:
		*pkeysize = 48 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_ECC_P384;
		break;
	case UV_SECRET_ECDSA_P521:
		*pkeysize = 80 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_ECC_P521;
		break;
	case UV_SECRET_ECDSA_ED25519:
		*pkeysize = 32 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_ECC_ED25519;
		break;
	case UV_SECRET_ECDSA_ED448:
		*pkeysize = 64 + AES_WK_VP_SIZE;
		*pkeytype = PKEY_KEYTYPE_ECC_ED448;
		break;
	default:
		rc = -EINVAL;
	}

	return rc;
}

static int uv_key2protkey(const struct pkey_apqn *_apqns __always_unused,
			  size_t _nr_apqns __always_unused,
			  const u8 *key, u32 keylen,
			  u8 *protkey, u32 *protkeylen, u32 *keyinfo)
{
	struct uvsecrettoken *t = (struct uvsecrettoken *)key;
	u32 pkeysize, pkeytype;
	u16 secret_type;
	int rc;

	rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
	if (rc)
		goto out;

	if (*protkeylen < pkeysize) {
		PKEY_DBF_ERR("%s prot key buffer size too small: %u < %u\n",
			     __func__, *protkeylen, pkeysize);
		rc = -EINVAL;
		goto out;
	}

	rc = retrieve_secret(t->secret_id, &secret_type, protkey, protkeylen);
	if (rc) {
		PKEY_DBF_ERR("%s retrieve_secret() failed with %d\n",
			     __func__, rc);
		goto out;
	}
	if (secret_type != t->secret_type) {
		PKEY_DBF_ERR("%s retrieved secret type %u != expected type %u\n",
			     __func__, secret_type, t->secret_type);
		rc = -EINVAL;
		goto out;
	}

	if (keyinfo)
		*keyinfo = pkeytype;

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

static int uv_verifykey(const u8 *key, u32 keylen,
			u16 *_card __always_unused,
			u16 *_dom __always_unused,
			u32 *keytype, u32 *keybitsize, u32 *flags)
{
	struct uvsecrettoken *t = (struct uvsecrettoken *)key;
	struct uv_secret_list_item_hdr secret_meta_data;
	u32 pkeysize, pkeytype, bitsize;
	int rc;

	rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
	if (rc)
		goto out;

	rc = uv_get_secret_metadata(t->secret_id, &secret_meta_data);
	if (rc)
		goto out;

	if (secret_meta_data.type != t->secret_type) {
		rc = -EINVAL;
		goto out;
	}

	/* set keytype; keybitsize and flags are not supported */
	if (keytype)
		*keytype = PKEY_TYPE_UVSECRET;
	if (keybitsize) {
		bitsize = 8 * pkey_keytype_to_size(pkeytype);
		*keybitsize = bitsize ?: PKEY_SIZE_UNKNOWN;
	}
	if (flags)
		*flags = pkeytype;

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

static struct pkey_handler uv_handler = {
	.module			 = THIS_MODULE,
	.name			 = "PKEY UV handler",
	.is_supported_key	 = is_uv_key,
	.is_supported_keytype	 = is_uv_keytype,
	.key_to_protkey		 = uv_key2protkey,
	.verify_key		 = uv_verifykey,
};

/*
 * Module init
 */
static int __init pkey_uv_init(void)
{
	if (!is_prot_virt_guest())
		return -ENODEV;

	if (!test_bit_inv(BIT_UVC_CMD_RETR_SECRET, uv_info.inst_calls_list))
		return -ENODEV;

	return pkey_handler_register(&uv_handler);
}

/*
 * Module exit
 */
static void __exit pkey_uv_exit(void)
{
	pkey_handler_unregister(&uv_handler);
}

module_cpu_feature_match(S390_CPU_FEATURE_UV, pkey_uv_init);
module_exit(pkey_uv_exit);
