brintos

brintos / linux-shallow public Read only

0
0
Text · 16.0 KiB · 9370513 Raw
630 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 *  pkey cca 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 "pkey_base.h"18 19MODULE_LICENSE("GPL");20MODULE_AUTHOR("IBM Corporation");21MODULE_DESCRIPTION("s390 protected key CCA handler");22 23#if IS_MODULE(CONFIG_PKEY_CCA)24static struct ap_device_id pkey_cca_card_ids[] = {25	{ .dev_type = AP_DEVICE_TYPE_CEX4 },26	{ .dev_type = AP_DEVICE_TYPE_CEX5 },27	{ .dev_type = AP_DEVICE_TYPE_CEX6 },28	{ .dev_type = AP_DEVICE_TYPE_CEX7 },29	{ .dev_type = AP_DEVICE_TYPE_CEX8 },30	{ /* end of list */ },31};32MODULE_DEVICE_TABLE(ap, pkey_cca_card_ids);33#endif34 35/*36 * Check key blob for known and supported CCA key.37 */38static bool is_cca_key(const u8 *key, u32 keylen)39{40	struct keytoken_header *hdr = (struct keytoken_header *)key;41 42	if (keylen < sizeof(*hdr))43		return false;44 45	switch (hdr->type) {46	case TOKTYPE_CCA_INTERNAL:47		switch (hdr->version) {48		case TOKVER_CCA_AES:49		case TOKVER_CCA_VLSC:50			return true;51		default:52			return false;53		}54	case TOKTYPE_CCA_INTERNAL_PKA:55		return true;56	default:57		return false;58	}59}60 61static bool is_cca_keytype(enum pkey_key_type key_type)62{63	switch (key_type) {64	case PKEY_TYPE_CCA_DATA:65	case PKEY_TYPE_CCA_CIPHER:66	case PKEY_TYPE_CCA_ECC:67		return true;68	default:69		return false;70	}71}72 73static int cca_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 | PKEY_FLAGS_MATCH_ALT_MKVP;82 83	if (keylen < sizeof(struct keytoken_header))84		return -EINVAL;85 86	zcrypt_wait_api_operational();87 88	if (hdr->type == TOKTYPE_CCA_INTERNAL) {89		u64 cur_mkvp = 0, old_mkvp = 0;90		int minhwtype = ZCRYPT_CEX3C;91 92		if (hdr->version == TOKVER_CCA_AES) {93			struct secaeskeytoken *t = (struct secaeskeytoken *)key;94 95			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)96				cur_mkvp = t->mkvp;97			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)98				old_mkvp = t->mkvp;99		} else if (hdr->version == TOKVER_CCA_VLSC) {100			struct cipherkeytoken *t = (struct cipherkeytoken *)key;101 102			minhwtype = ZCRYPT_CEX6;103			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)104				cur_mkvp = t->mkvp0;105			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)106				old_mkvp = t->mkvp0;107		} else {108			/* unknown CCA internal token type */109			return -EINVAL;110		}111		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,112				   minhwtype, AES_MK_SET,113				   cur_mkvp, old_mkvp, 1);114		if (rc)115			goto out;116 117	} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {118		struct eccprivkeytoken *t = (struct eccprivkeytoken *)key;119		u64 cur_mkvp = 0, old_mkvp = 0;120 121		if (t->secid == 0x20) {122			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)123				cur_mkvp = t->mkvp;124			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)125				old_mkvp = t->mkvp;126		} else {127			/* unknown CCA internal 2 token type */128			return -EINVAL;129		}130		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,131				   ZCRYPT_CEX7, APKA_MK_SET,132				   cur_mkvp, old_mkvp, 1);133		if (rc)134			goto out;135 136	} else {137		PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",138			     __func__, hdr->type, hdr->version);139		return -EINVAL;140	}141 142	if (apqns) {143		if (*nr_apqns < _nr_apqns)144			rc = -ENOSPC;145		else146			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));147	}148	*nr_apqns = _nr_apqns;149 150out:151	kfree(_apqns);152	pr_debug("rc=%d\n", rc);153	return rc;154}155 156static int cca_apqns4type(enum pkey_key_type ktype,157			  u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,158			  struct pkey_apqn *apqns, size_t *nr_apqns)159{160	u32 _nr_apqns, *_apqns = NULL;161	int rc;162 163	zcrypt_wait_api_operational();164 165	if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) {166		u64 cur_mkvp = 0, old_mkvp = 0;167		int minhwtype = ZCRYPT_CEX3C;168 169		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)170			cur_mkvp = *((u64 *)cur_mkvp);171		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)172			old_mkvp = *((u64 *)alt_mkvp);173		if (ktype == PKEY_TYPE_CCA_CIPHER)174			minhwtype = ZCRYPT_CEX6;175		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,176				   minhwtype, AES_MK_SET,177				   cur_mkvp, old_mkvp, 1);178		if (rc)179			goto out;180 181	} else if (ktype == PKEY_TYPE_CCA_ECC) {182		u64 cur_mkvp = 0, old_mkvp = 0;183 184		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)185			cur_mkvp = *((u64 *)cur_mkvp);186		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)187			old_mkvp = *((u64 *)alt_mkvp);188		rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,189				   ZCRYPT_CEX7, APKA_MK_SET,190				   cur_mkvp, old_mkvp, 1);191		if (rc)192			goto out;193 194	} else {195		PKEY_DBF_ERR("%s unknown/unsupported key type %d",196			     __func__, (int)ktype);197		return -EINVAL;198	}199 200	if (apqns) {201		if (*nr_apqns < _nr_apqns)202			rc = -ENOSPC;203		else204			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));205	}206	*nr_apqns = _nr_apqns;207 208out:209	kfree(_apqns);210	pr_debug("rc=%d\n", rc);211	return rc;212}213 214static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,215			   const u8 *key, u32 keylen,216			   u8 *protkey, u32 *protkeylen, u32 *protkeytype)217{218	struct keytoken_header *hdr = (struct keytoken_header *)key;219	struct pkey_apqn *local_apqns = NULL;220	int i, rc;221 222	if (keylen < sizeof(*hdr))223		return -EINVAL;224 225	if (hdr->type == TOKTYPE_CCA_INTERNAL &&226	    hdr->version == TOKVER_CCA_AES) {227		/* CCA AES data key */228		if (keylen != sizeof(struct secaeskeytoken))229			return -EINVAL;230		if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0))231			return -EINVAL;232	} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&233		   hdr->version == TOKVER_CCA_VLSC) {234		/* CCA AES cipher key */235		if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE)236			return -EINVAL;237		if (cca_check_secaescipherkey(pkey_dbf_info,238					      3, key, 0, 1))239			return -EINVAL;240	} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {241		/* CCA ECC (private) key */242		if (keylen < sizeof(struct eccprivkeytoken))243			return -EINVAL;244		if (cca_check_sececckeytoken(pkey_dbf_info, 3, key, keylen, 1))245			return -EINVAL;246	} else {247		PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",248			     __func__, hdr->type, hdr->version);249		return -EINVAL;250	}251 252	zcrypt_wait_api_operational();253 254	if (!apqns || (nr_apqns == 1 &&255		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {256		nr_apqns = MAXAPQNSINLIST;257		local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),258					    GFP_KERNEL);259		if (!local_apqns)260			return -ENOMEM;261		rc = cca_apqns4key(key, keylen, 0, local_apqns, &nr_apqns);262		if (rc)263			goto out;264		apqns = local_apqns;265	}266 267	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {268		if (hdr->type == TOKTYPE_CCA_INTERNAL &&269		    hdr->version == TOKVER_CCA_AES) {270			rc = cca_sec2protkey(apqns[i].card, apqns[i].domain,271					     key, protkey,272					     protkeylen, protkeytype);273		} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&274			   hdr->version == TOKVER_CCA_VLSC) {275			rc = cca_cipher2protkey(apqns[i].card, apqns[i].domain,276						key, protkey,277						protkeylen, protkeytype);278		} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {279			rc = cca_ecc2protkey(apqns[i].card, apqns[i].domain,280					     key, protkey,281					     protkeylen, protkeytype);282		} else {283			rc = -EINVAL;284			break;285		}286	}287 288out:289	kfree(local_apqns);290	pr_debug("rc=%d\n", rc);291	return rc;292}293 294/*295 * Generate CCA secure key.296 * As of now only CCA AES Data or Cipher secure keys are297 * supported.298 * keytype is one of the PKEY_KEYTYPE_* constants,299 * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER,300 * keybitsize is the bit size of the key (may be 0 for301 * keytype PKEY_KEYTYPE_AES_*).302 */303static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,304		       u32 keytype, u32 subtype,305		       u32 keybitsize, u32 flags,306		       u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)307{308	struct pkey_apqn *local_apqns = NULL;309	int i, len, rc;310 311	/* check keytype, subtype, keybitsize */312	switch (keytype) {313	case PKEY_KEYTYPE_AES_128:314	case PKEY_KEYTYPE_AES_192:315	case PKEY_KEYTYPE_AES_256:316		len = pkey_keytype_aes_to_size(keytype);317		if (keybitsize && keybitsize != 8 * len) {318			PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",319				     __func__, keybitsize);320			return -EINVAL;321		}322		keybitsize = 8 * len;323		switch (subtype) {324		case PKEY_TYPE_CCA_DATA:325		case PKEY_TYPE_CCA_CIPHER:326			break;327		default:328			PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",329				     __func__, subtype);330			return -EINVAL;331		}332		break;333	default:334		PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",335			     __func__, keytype);336		return -EINVAL;337	}338 339	zcrypt_wait_api_operational();340 341	if (!apqns || (nr_apqns == 1 &&342		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {343		nr_apqns = MAXAPQNSINLIST;344		local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),345					    GFP_KERNEL);346		if (!local_apqns)347			return -ENOMEM;348		rc = cca_apqns4type(subtype, NULL, NULL, 0,349				    local_apqns, &nr_apqns);350		if (rc)351			goto out;352		apqns = local_apqns;353	}354 355	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {356		if (subtype == PKEY_TYPE_CCA_CIPHER) {357			rc = cca_gencipherkey(apqns[i].card, apqns[i].domain,358					      keybitsize, flags,359					      keybuf, keybuflen);360		} else {361			/* PKEY_TYPE_CCA_DATA */362			rc = cca_genseckey(apqns[i].card, apqns[i].domain,363					   keybitsize, keybuf);364			*keybuflen = (rc ? 0 : SECKEYBLOBSIZE);365		}366	}367 368out:369	kfree(local_apqns);370	pr_debug("rc=%d\n", rc);371	return rc;372}373 374/*375 * Generate CCA secure key with given clear key value.376 * As of now only CCA AES Data or Cipher secure keys are377 * supported.378 * keytype is one of the PKEY_KEYTYPE_* constants,379 * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER,380 * keybitsize is the bit size of the key (may be 0 for381 * keytype PKEY_KEYTYPE_AES_*).382 */383static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,384		       u32 keytype, u32 subtype,385		       u32 keybitsize, u32 flags,386		       const u8 *clrkey, u32 clrkeylen,387		       u8 *keybuf, u32 *keybuflen, u32 *_keyinfo)388{389	struct pkey_apqn *local_apqns = NULL;390	int i, len, rc;391 392	/* check keytype, subtype, clrkeylen, keybitsize */393	switch (keytype) {394	case PKEY_KEYTYPE_AES_128:395	case PKEY_KEYTYPE_AES_192:396	case PKEY_KEYTYPE_AES_256:397		len = pkey_keytype_aes_to_size(keytype);398		if (keybitsize && keybitsize != 8 * len) {399			PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",400				     __func__, keybitsize);401			return -EINVAL;402		}403		keybitsize = 8 * len;404		if (clrkeylen != len) {405			PKEY_DBF_ERR("%s invalid clear key len %d != %d\n",406				     __func__, clrkeylen, len);407			return -EINVAL;408		}409		switch (subtype) {410		case PKEY_TYPE_CCA_DATA:411		case PKEY_TYPE_CCA_CIPHER:412			break;413		default:414			PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",415				     __func__, subtype);416			return -EINVAL;417		}418		break;419	default:420		PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",421			     __func__, keytype);422		return -EINVAL;423	}424 425	zcrypt_wait_api_operational();426 427	if (!apqns || (nr_apqns == 1 &&428		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {429		nr_apqns = MAXAPQNSINLIST;430		local_apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn),431					    GFP_KERNEL);432		if (!local_apqns)433			return -ENOMEM;434		rc = cca_apqns4type(subtype, NULL, NULL, 0,435				    local_apqns, &nr_apqns);436		if (rc)437			goto out;438		apqns = local_apqns;439	}440 441	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {442		if (subtype == PKEY_TYPE_CCA_CIPHER) {443			rc = cca_clr2cipherkey(apqns[i].card, apqns[i].domain,444					       keybitsize, flags, clrkey,445					       keybuf, keybuflen);446		} else {447			/* PKEY_TYPE_CCA_DATA */448			rc = cca_clr2seckey(apqns[i].card, apqns[i].domain,449					    keybitsize, clrkey, keybuf);450			*keybuflen = (rc ? 0 : SECKEYBLOBSIZE);451		}452	}453 454out:455	kfree(local_apqns);456	pr_debug("rc=%d\n", rc);457	return rc;458}459 460static int cca_verifykey(const u8 *key, u32 keylen,461			 u16 *card, u16 *dom,462			 u32 *keytype, u32 *keybitsize, u32 *flags)463{464	struct keytoken_header *hdr = (struct keytoken_header *)key;465	u32 nr_apqns, *apqns = NULL;466	int rc;467 468	if (keylen < sizeof(*hdr))469		return -EINVAL;470 471	zcrypt_wait_api_operational();472 473	if (hdr->type == TOKTYPE_CCA_INTERNAL &&474	    hdr->version == TOKVER_CCA_AES) {475		struct secaeskeytoken *t = (struct secaeskeytoken *)key;476 477		rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0);478		if (rc)479			goto out;480		*keytype = PKEY_TYPE_CCA_DATA;481		*keybitsize = t->bitsize;482		rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,483				   ZCRYPT_CEX3C, AES_MK_SET,484				   t->mkvp, 0, 1);485		if (!rc)486			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;487		if (rc == -ENODEV) {488			rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,489					   ZCRYPT_CEX3C, AES_MK_SET,490					   0, t->mkvp, 1);491			if (!rc)492				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;493		}494		if (rc)495			goto out;496 497		*card = ((struct pkey_apqn *)apqns)->card;498		*dom = ((struct pkey_apqn *)apqns)->domain;499 500	} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&501		   hdr->version == TOKVER_CCA_VLSC) {502		struct cipherkeytoken *t = (struct cipherkeytoken *)key;503 504		rc = cca_check_secaescipherkey(pkey_dbf_info, 3, key, 0, 1);505		if (rc)506			goto out;507		*keytype = PKEY_TYPE_CCA_CIPHER;508		*keybitsize = PKEY_SIZE_UNKNOWN;509		if (!t->plfver && t->wpllen == 512)510			*keybitsize = PKEY_SIZE_AES_128;511		else if (!t->plfver && t->wpllen == 576)512			*keybitsize = PKEY_SIZE_AES_192;513		else if (!t->plfver && t->wpllen == 640)514			*keybitsize = PKEY_SIZE_AES_256;515		rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,516				   ZCRYPT_CEX6, AES_MK_SET,517				   t->mkvp0, 0, 1);518		if (!rc)519			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;520		if (rc == -ENODEV) {521			rc = cca_findcard2(&apqns, &nr_apqns, *card, *dom,522					   ZCRYPT_CEX6, AES_MK_SET,523					   0, t->mkvp0, 1);524			if (!rc)525				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;526		}527		if (rc)528			goto out;529 530		*card = ((struct pkey_apqn *)apqns)->card;531		*dom = ((struct pkey_apqn *)apqns)->domain;532 533	} else {534		/* unknown/unsupported key blob */535		rc = -EINVAL;536	}537 538out:539	kfree(apqns);540	pr_debug("rc=%d\n", rc);541	return rc;542}543 544/*545 * This function provides an alternate but usually slow way546 * to convert a 'clear key token' with AES key material into547 * a protected key. This is done via an intermediate step548 * which creates a CCA AES DATA secure key first and then549 * derives the protected key from this secure key.550 */551static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns,552				    size_t nr_apqns,553				    const u8 *key, u32 keylen,554				    u8 *protkey, u32 *protkeylen,555				    u32 *protkeytype)556{557	const struct keytoken_header *hdr = (const struct keytoken_header *)key;558	const struct clearkeytoken *t = (const struct clearkeytoken *)key;559	u32 tmplen, keysize = 0;560	u8 *tmpbuf;561	int i, rc;562 563	if (keylen < sizeof(*hdr))564		return -EINVAL;565 566	if (hdr->type == TOKTYPE_NON_CCA &&567	    hdr->version == TOKVER_CLEAR_KEY)568		keysize = pkey_keytype_aes_to_size(t->keytype);569	if (!keysize || t->len != keysize)570		return -EINVAL;571 572	/* alloc tmp key buffer */573	tmpbuf = kmalloc(SECKEYBLOBSIZE, GFP_ATOMIC);574	if (!tmpbuf)575		return -ENOMEM;576 577	/* try two times in case of failure */578	for (i = 0, rc = -ENODEV; i < 2 && rc; i++) {579		tmplen = SECKEYBLOBSIZE;580		rc = cca_clr2key(NULL, 0, t->keytype, PKEY_TYPE_CCA_DATA,581				 8 * keysize, 0, t->clearkey, t->len,582				 tmpbuf, &tmplen, NULL);583		pr_debug("cca_clr2key()=%d\n", rc);584		if (rc)585			continue;586		rc = cca_key2protkey(NULL, 0, tmpbuf, tmplen,587				     protkey, protkeylen, protkeytype);588		pr_debug("cca_key2protkey()=%d\n", rc);589	}590 591	kfree(tmpbuf);592	pr_debug("rc=%d\n", rc);593	return rc;594}595 596static struct pkey_handler cca_handler = {597	.module			 = THIS_MODULE,598	.name			 = "PKEY CCA handler",599	.is_supported_key	 = is_cca_key,600	.is_supported_keytype	 = is_cca_keytype,601	.key_to_protkey		 = cca_key2protkey,602	.slowpath_key_to_protkey = cca_slowpath_key2protkey,603	.gen_key		 = cca_gen_key,604	.clr_to_key		 = cca_clr2key,605	.verify_key		 = cca_verifykey,606	.apqns_for_key		 = cca_apqns4key,607	.apqns_for_keytype	 = cca_apqns4type,608};609 610/*611 * Module init612 */613static int __init pkey_cca_init(void)614{615	/* register this module as pkey handler for all the cca stuff */616	return pkey_handler_register(&cca_handler);617}618 619/*620 * Module exit621 */622static void __exit pkey_cca_exit(void)623{624	/* unregister this module as pkey handler */625	pkey_handler_unregister(&cca_handler);626}627 628module_init(pkey_cca_init);629module_exit(pkey_cca_exit);630