brintos

brintos / linux-shallow public Read only

0
0
Text · 14.8 KiB · f42d397 Raw
579 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 *  pkey ep11 specific code4 *5 *  Copyright IBM Corp. 20246 */7 8#define KMSG_COMPONENT "pkey"9#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt10 11#include <linux/init.h>12#include <linux/module.h>13#include <linux/cpufeature.h>14 15#include "zcrypt_api.h"16#include "zcrypt_ccamisc.h"17#include "zcrypt_ep11misc.h"18#include "pkey_base.h"19 20MODULE_LICENSE("GPL");21MODULE_AUTHOR("IBM Corporation");22MODULE_DESCRIPTION("s390 protected key EP11 handler");23 24#if IS_MODULE(CONFIG_PKEY_EP11)25static struct ap_device_id pkey_ep11_card_ids[] = {26	{ .dev_type = AP_DEVICE_TYPE_CEX4 },27	{ .dev_type = AP_DEVICE_TYPE_CEX5 },28	{ .dev_type = AP_DEVICE_TYPE_CEX6 },29	{ .dev_type = AP_DEVICE_TYPE_CEX7 },30	{ .dev_type = AP_DEVICE_TYPE_CEX8 },31	{ /* end of list */ },32};33MODULE_DEVICE_TABLE(ap, pkey_ep11_card_ids);34#endif35 36/*37 * Check key blob for known and supported EP11 key.38 */39static bool is_ep11_key(const u8 *key, u32 keylen)40{41	struct keytoken_header *hdr = (struct keytoken_header *)key;42 43	if (keylen < sizeof(*hdr))44		return false;45 46	switch (hdr->type) {47	case TOKTYPE_NON_CCA:48		switch (hdr->version) {49		case TOKVER_EP11_AES:50		case TOKVER_EP11_AES_WITH_HEADER:51		case TOKVER_EP11_ECC_WITH_HEADER:52			return true;53		default:54			return false;55		}56	default:57		return false;58	}59}60 61static bool is_ep11_keytype(enum pkey_key_type key_type)62{63	switch (key_type) {64	case PKEY_TYPE_EP11:65	case PKEY_TYPE_EP11_AES:66	case PKEY_TYPE_EP11_ECC:67		return true;68	default:69		return false;70	}71}72 73static int ep11_apqns4key(const u8 *key, u32 keylen, u32 flags,74			  struct pkey_apqn *apqns, size_t *nr_apqns)75{76	struct keytoken_header *hdr = (struct keytoken_header *)key;77	u32 _nr_apqns, *_apqns = NULL;78	int rc;79 80	if (!flags)81		flags = PKEY_FLAGS_MATCH_CUR_MKVP;82 83	if (keylen < sizeof(struct keytoken_header) || flags == 0)84		return -EINVAL;85 86	zcrypt_wait_api_operational();87 88	if (hdr->type == TOKTYPE_NON_CCA &&89	    (hdr->version == TOKVER_EP11_AES_WITH_HEADER ||90	     hdr->version == TOKVER_EP11_ECC_WITH_HEADER) &&91	    is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {92		struct ep11keyblob *kb = (struct ep11keyblob *)93			(key + sizeof(struct ep11kblob_header));94		int minhwtype = 0, api = 0;95 96		if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)97			return -EINVAL;98		if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {99			minhwtype = ZCRYPT_CEX7;100			api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;101		}102		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,103				    minhwtype, api, kb->wkvp);104		if (rc)105			goto out;106 107	} else if (hdr->type == TOKTYPE_NON_CCA &&108		   hdr->version == TOKVER_EP11_AES &&109		   is_ep11_keyblob(key)) {110		struct ep11keyblob *kb = (struct ep11keyblob *)key;111		int minhwtype = 0, api = 0;112 113		if (flags != PKEY_FLAGS_MATCH_CUR_MKVP)114			return -EINVAL;115		if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) {116			minhwtype = ZCRYPT_CEX7;117			api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;118		}119		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,120				    minhwtype, api, kb->wkvp);121		if (rc)122			goto out;123 124	} else {125		PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",126			     __func__, hdr->type, hdr->version);127		return -EINVAL;128	}129 130	if (apqns) {131		if (*nr_apqns < _nr_apqns)132			rc = -ENOSPC;133		else134			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));135	}136	*nr_apqns = _nr_apqns;137 138out:139	kfree(_apqns);140	pr_debug("rc=%d\n", rc);141	return rc;142}143 144static int ep11_apqns4type(enum pkey_key_type ktype,145			   u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,146			   struct pkey_apqn *apqns, size_t *nr_apqns)147{148	u32 _nr_apqns, *_apqns = NULL;149	int rc;150 151	zcrypt_wait_api_operational();152 153	if (ktype == PKEY_TYPE_EP11 ||154	    ktype == PKEY_TYPE_EP11_AES ||155	    ktype == PKEY_TYPE_EP11_ECC) {156		u8 *wkvp = NULL;157		int api;158 159		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)160			wkvp = cur_mkvp;161		api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;162		rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,163				    ZCRYPT_CEX7, api, wkvp);164		if (rc)165			goto out;166 167	} else {168		PKEY_DBF_ERR("%s unknown/unsupported key type %d\n",169			     __func__, (int)ktype);170		return -EINVAL;171	}172 173	if (apqns) {174		if (*nr_apqns < _nr_apqns)175			rc = -ENOSPC;176		else177			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));178	}179	*nr_apqns = _nr_apqns;180 181out:182	kfree(_apqns);183	pr_debug("rc=%d\n", rc);184	return rc;185}186 187static int ep11_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,188			    const u8 *key, u32 keylen,189			    u8 *protkey, u32 *protkeylen, u32 *protkeytype)190{191	struct keytoken_header *hdr = (struct keytoken_header *)key;192	struct pkey_apqn *local_apqns = NULL;193	int i, rc;194 195	if (keylen < sizeof(*hdr))196		return -EINVAL;197 198	if (hdr->type == TOKTYPE_NON_CCA &&199	    hdr->version == TOKVER_EP11_AES_WITH_HEADER &&200	    is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {201		/* EP11 AES key blob with header */202		if (ep11_check_aes_key_with_hdr(pkey_dbf_info,203						3, key, keylen, 1))204			return -EINVAL;205	} else if (hdr->type == TOKTYPE_NON_CCA &&206		   hdr->version == TOKVER_EP11_ECC_WITH_HEADER &&207		   is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {208		/* EP11 ECC key blob with header */209		if (ep11_check_ecc_key_with_hdr(pkey_dbf_info,210						3, key, keylen, 1))211			return -EINVAL;212	} else if (hdr->type == TOKTYPE_NON_CCA &&213		   hdr->version == TOKVER_EP11_AES &&214		   is_ep11_keyblob(key)) {215		/* EP11 AES key blob with header in session field */216		if (ep11_check_aes_key(pkey_dbf_info, 3, key, keylen, 1))217			return -EINVAL;218	} else {219		PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",220			     __func__, hdr->type, hdr->version);221		return -EINVAL;222	}223 224	zcrypt_wait_api_operational();225 226	if (!apqns || (nr_apqns == 1 &&227		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {228		nr_apqns = MAXAPQNSINLIST;229		local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),230					    GFP_KERNEL);231		if (!local_apqns)232			return -ENOMEM;233		rc = ep11_apqns4key(key, keylen, 0, local_apqns, &nr_apqns);234		if (rc)235			goto out;236		apqns = local_apqns;237	}238 239	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {240		if (hdr->type == TOKTYPE_NON_CCA &&241		    hdr->version == TOKVER_EP11_AES_WITH_HEADER &&242		    is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {243			rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain,244						key, hdr->len, protkey,245						protkeylen, protkeytype);246		} else if (hdr->type == TOKTYPE_NON_CCA &&247			   hdr->version == TOKVER_EP11_ECC_WITH_HEADER &&248			   is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) {249			rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain,250						key, hdr->len, protkey,251						protkeylen, protkeytype);252		} else if (hdr->type == TOKTYPE_NON_CCA &&253			   hdr->version == TOKVER_EP11_AES &&254			   is_ep11_keyblob(key)) {255			rc = ep11_kblob2protkey(apqns[i].card, apqns[i].domain,256						key, hdr->len, protkey,257						protkeylen, protkeytype);258		} else {259			rc = -EINVAL;260			break;261		}262	}263 264out:265	kfree(local_apqns);266	pr_debug("rc=%d\n", rc);267	return rc;268}269 270/*271 * Generate EP11 secure key.272 * As of now only EP11 AES secure keys are supported.273 * keytype is one of the PKEY_KEYTYPE_* constants,274 * subtype may be PKEY_TYPE_EP11 or PKEY_TYPE_EP11_AES275 * or 0 (results in subtype PKEY_TYPE_EP11_AES),276 * keybitsize is the bit size of the key (may be 0 for277 * keytype PKEY_KEYTYPE_AES_*).278 */279static int ep11_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,280			u32 keytype, u32 subtype,281			u32 keybitsize, u32 flags,282			u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)283{284	struct pkey_apqn *local_apqns = NULL;285	int i, len, rc;286 287	/* check keytype, subtype, keybitsize */288	switch (keytype) {289	case PKEY_KEYTYPE_AES_128:290	case PKEY_KEYTYPE_AES_192:291	case PKEY_KEYTYPE_AES_256:292		len = pkey_keytype_aes_to_size(keytype);293		if (keybitsize && keybitsize != 8 * len) {294			PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",295				     __func__, keybitsize);296			return -EINVAL;297		}298		keybitsize = 8 * len;299		switch (subtype) {300		case PKEY_TYPE_EP11:301		case PKEY_TYPE_EP11_AES:302			break;303		default:304			PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",305				     __func__, subtype);306			return -EINVAL;307		}308		break;309	default:310		PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",311			     __func__, keytype);312		return -EINVAL;313	}314 315	zcrypt_wait_api_operational();316 317	if (!apqns || (nr_apqns == 1 &&318		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {319		nr_apqns = MAXAPQNSINLIST;320		local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),321					    GFP_KERNEL);322		if (!local_apqns)323			return -ENOMEM;324		rc = ep11_apqns4type(subtype, NULL, NULL, 0,325				     local_apqns, &nr_apqns);326		if (rc)327			goto out;328		apqns = local_apqns;329	}330 331	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {332		rc = ep11_genaeskey(apqns[i].card, apqns[i].domain,333				    keybitsize, flags,334				    keybuf, keybuflen, subtype);335	}336 337out:338	kfree(local_apqns);339	pr_debug("rc=%d\n", rc);340	return rc;341}342 343/*344 * Generate EP11 secure key with given clear key value.345 * As of now only EP11 AES secure keys are supported.346 * keytype is one of the PKEY_KEYTYPE_* constants,347 * subtype may be PKEY_TYPE_EP11 or PKEY_TYPE_EP11_AES348 * or 0 (assumes PKEY_TYPE_EP11_AES then).349 * keybitsize is the bit size of the key (may be 0 for350 * keytype PKEY_KEYTYPE_AES_*).351 */352static int ep11_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,353			u32 keytype, u32 subtype,354			u32 keybitsize, u32 flags,355			const u8 *clrkey, u32 clrkeylen,356			u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)357{358	struct pkey_apqn *local_apqns = NULL;359	int i, len, rc;360 361	/* check keytype, subtype, clrkeylen, keybitsize */362	switch (keytype) {363	case PKEY_KEYTYPE_AES_128:364	case PKEY_KEYTYPE_AES_192:365	case PKEY_KEYTYPE_AES_256:366		len = pkey_keytype_aes_to_size(keytype);367		if (keybitsize && keybitsize != 8 * len) {368			PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",369				     __func__, keybitsize);370			return -EINVAL;371		}372		keybitsize = 8 * len;373		if (clrkeylen != len) {374			PKEY_DBF_ERR("%s invalid clear key len %d != %d\n",375				     __func__, clrkeylen, len);376			return -EINVAL;377		}378		switch (subtype) {379		case PKEY_TYPE_EP11:380		case PKEY_TYPE_EP11_AES:381			break;382		default:383			PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",384				     __func__, subtype);385			return -EINVAL;386		}387		break;388	default:389		PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",390			     __func__, keytype);391		return -EINVAL;392	}393 394	zcrypt_wait_api_operational();395 396	if (!apqns || (nr_apqns == 1 &&397		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {398		nr_apqns = MAXAPQNSINLIST;399		local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),400					    GFP_KERNEL);401		if (!local_apqns)402			return -ENOMEM;403		rc = ep11_apqns4type(subtype, NULL, NULL, 0,404				     local_apqns, &nr_apqns);405		if (rc)406			goto out;407		apqns = local_apqns;408	}409 410	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {411		rc = ep11_clr2keyblob(apqns[i].card, apqns[i].domain,412				      keybitsize, flags, clrkey,413				      keybuf, keybuflen, subtype);414	}415 416out:417	kfree(local_apqns);418	pr_debug("rc=%d\n", rc);419	return rc;420}421 422static int ep11_verifykey(const u8 *key, u32 keylen,423			  u16 *card, u16 *dom,424			  u32 *keytype, u32 *keybitsize, u32 *flags)425{426	struct keytoken_header *hdr = (struct keytoken_header *)key;427	u32 nr_apqns, *apqns = NULL;428	int rc;429 430	if (keylen < sizeof(*hdr))431		return -EINVAL;432 433	zcrypt_wait_api_operational();434 435	if (hdr->type == TOKTYPE_NON_CCA &&436	    hdr->version == TOKVER_EP11_AES) {437		struct ep11keyblob *kb = (struct ep11keyblob *)key;438		int api;439 440		rc = ep11_check_aes_key(pkey_dbf_info, 3, key, keylen, 1);441		if (rc)442			goto out;443		*keytype = PKEY_TYPE_EP11;444		*keybitsize = kb->head.bitlen;445 446		api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;447		rc = ep11_findcard2(&apqns, &nr_apqns, *card, *dom,448				    ZCRYPT_CEX7, api,449				    ep11_kb_wkvp(key, keylen));450		if (rc)451			goto out;452 453		*flags = PKEY_FLAGS_MATCH_CUR_MKVP;454 455		*card = ((struct pkey_apqn *)apqns)->card;456		*dom = ((struct pkey_apqn *)apqns)->domain;457 458	} else if (hdr->type == TOKTYPE_NON_CCA &&459		   hdr->version == TOKVER_EP11_AES_WITH_HEADER) {460		struct ep11kblob_header *kh = (struct ep11kblob_header *)key;461		int api;462 463		rc = ep11_check_aes_key_with_hdr(pkey_dbf_info,464						 3, key, keylen, 1);465		if (rc)466			goto out;467		*keytype = PKEY_TYPE_EP11_AES;468		*keybitsize = kh->bitlen;469 470		api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4;471		rc = ep11_findcard2(&apqns, &nr_apqns, *card, *dom,472				    ZCRYPT_CEX7, api,473				    ep11_kb_wkvp(key, keylen));474		if (rc)475			goto out;476 477		*flags = PKEY_FLAGS_MATCH_CUR_MKVP;478 479		*card = ((struct pkey_apqn *)apqns)->card;480		*dom = ((struct pkey_apqn *)apqns)->domain;481 482	} else {483		/* unknown/unsupported key blob */484		rc = -EINVAL;485	}486 487out:488	kfree(apqns);489	pr_debug("rc=%d\n", rc);490	return rc;491}492 493/*494 * This function provides an alternate but usually slow way495 * to convert a 'clear key token' with AES key material into496 * a protected key. That is done via an intermediate step497 * which creates an EP11 AES secure key first and then derives498 * the protected key from this secure key.499 */500static int ep11_slowpath_key2protkey(const struct pkey_apqn *apqns,501				     size_t nr_apqns,502				     const u8 *key, u32 keylen,503				     u8 *protkey, u32 *protkeylen,504				     u32 *protkeytype)505{506	const struct keytoken_header *hdr = (const struct keytoken_header *)key;507	const struct clearkeytoken *t = (const struct clearkeytoken *)key;508	u32 tmplen, keysize = 0;509	u8 *tmpbuf;510	int i, rc;511 512	if (keylen < sizeof(*hdr))513		return -EINVAL;514 515	if (hdr->type == TOKTYPE_NON_CCA &&516	    hdr->version == TOKVER_CLEAR_KEY)517		keysize = pkey_keytype_aes_to_size(t->keytype);518	if (!keysize || t->len != keysize)519		return -EINVAL;520 521	/* alloc tmp key buffer */522	tmpbuf = kmalloc(MAXEP11AESKEYBLOBSIZE, GFP_ATOMIC);523	if (!tmpbuf)524		return -ENOMEM;525 526	/* try two times in case of failure */527	for (i = 0, rc = -ENODEV; i < 2 && rc; i++) {528		tmplen = MAXEP11AESKEYBLOBSIZE;529		rc = ep11_clr2key(NULL, 0, t->keytype, PKEY_TYPE_EP11,530				  8 * keysize, 0, t->clearkey, t->len,531				  tmpbuf, &tmplen, NULL);532		pr_debug("ep11_clr2key()=%d\n", rc);533		if (rc)534			continue;535		rc = ep11_key2protkey(NULL, 0, tmpbuf, tmplen,536				      protkey, protkeylen, protkeytype);537		pr_debug("ep11_key2protkey()=%d\n", rc);538	}539 540	kfree(tmpbuf);541	pr_debug("rc=%d\n", rc);542	return rc;543}544 545static struct pkey_handler ep11_handler = {546	.module			 = THIS_MODULE,547	.name			 = "PKEY EP11 handler",548	.is_supported_key	 = is_ep11_key,549	.is_supported_keytype	 = is_ep11_keytype,550	.key_to_protkey		 = ep11_key2protkey,551	.slowpath_key_to_protkey = ep11_slowpath_key2protkey,552	.gen_key		 = ep11_gen_key,553	.clr_to_key		 = ep11_clr2key,554	.verify_key		 = ep11_verifykey,555	.apqns_for_key		 = ep11_apqns4key,556	.apqns_for_keytype	 = ep11_apqns4type,557};558 559/*560 * Module init561 */562static int __init pkey_ep11_init(void)563{564	/* register this module as pkey handler for all the ep11 stuff */565	return pkey_handler_register(&ep11_handler);566}567 568/*569 * Module exit570 */571static void __exit pkey_ep11_exit(void)572{573	/* unregister this module as pkey handler */574	pkey_handler_unregister(&ep11_handler);575}576 577module_init(pkey_ep11_init);578module_exit(pkey_ep11_exit);579