File Index
Files and directories
Sign in
FILE

pkey_uv.c

File preview with syntax highlighting.

linux-6.19.14/drivers/s390/crypto/pkey_uv.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 *  pkey uv specific code
  4 *
  5 *  Copyright IBM Corp. 2024
  6 */
  7
  8#define pr_fmt(fmt) "pkey: " fmt
  9
 10#include <linux/cpufeature.h>
 11#include <linux/init.h>
 12#include <linux/module.h>
 13#include <asm/uv.h>
 14
 15#include "zcrypt_ccamisc.h"
 16#include "pkey_base.h"
 17
 18MODULE_LICENSE("GPL");
 19MODULE_AUTHOR("IBM Corporation");
 20MODULE_DESCRIPTION("s390 protected key UV handler");
 21
 22/*
 23 * One pre-allocated uv_secret_list for use with uv_find_secret()
 24 */
 25static struct uv_secret_list *uv_list;
 26static DEFINE_MUTEX(uv_list_mutex);
 27
 28/*
 29 * UV secret token struct and defines.
 30 */
 31
 32#define TOKVER_UV_SECRET 0x09
 33
 34struct uvsecrettoken {
 35	u8  type;		/* 0x00 = TOKTYPE_NON_CCA */
 36	u8  res0[3];
 37	u8  version;		/* 0x09 = TOKVER_UV_SECRET */
 38	u8  res1[3];
 39	u16 secret_type;	/* one of enum uv_secret_types from uv.h */
 40	u16 secret_len;		/* length in bytes of the secret */
 41	u8  secret_id[UV_SECRET_ID_LEN]; /* the secret id for this secret */
 42} __packed;
 43
 44/*
 45 * Check key blob for known and supported UV key.
 46 */
 47static bool is_uv_key(const u8 *key, u32 keylen)
 48{
 49	struct uvsecrettoken *t = (struct uvsecrettoken *)key;
 50
 51	if (keylen < sizeof(*t))
 52		return false;
 53
 54	switch (t->type) {
 55	case TOKTYPE_NON_CCA:
 56		switch (t->version) {
 57		case TOKVER_UV_SECRET:
 58			switch (t->secret_type) {
 59			case UV_SECRET_AES_128:
 60			case UV_SECRET_AES_192:
 61			case UV_SECRET_AES_256:
 62			case UV_SECRET_AES_XTS_128:
 63			case UV_SECRET_AES_XTS_256:
 64			case UV_SECRET_HMAC_SHA_256:
 65			case UV_SECRET_HMAC_SHA_512:
 66			case UV_SECRET_ECDSA_P256:
 67			case UV_SECRET_ECDSA_P384:
 68			case UV_SECRET_ECDSA_P521:
 69			case UV_SECRET_ECDSA_ED25519:
 70			case UV_SECRET_ECDSA_ED448:
 71				return true;
 72			default:
 73				return false;
 74			}
 75		default:
 76			return false;
 77		}
 78	default:
 79		return false;
 80	}
 81}
 82
 83static bool is_uv_keytype(enum pkey_key_type keytype)
 84{
 85	switch (keytype) {
 86	case PKEY_TYPE_UVSECRET:
 87		return true;
 88	default:
 89		return false;
 90	}
 91}
 92
 93static int get_secret_metadata(const u8 secret_id[UV_SECRET_ID_LEN],
 94			       struct uv_secret_list_item_hdr *secret)
 95{
 96	int rc;
 97
 98	mutex_lock(&uv_list_mutex);
 99	memset(uv_list, 0, sizeof(*uv_list));
100	rc = uv_find_secret(secret_id, uv_list, secret);
101	mutex_unlock(&uv_list_mutex);
102
103	return rc;
104}
105
106static int retrieve_secret(const u8 secret_id[UV_SECRET_ID_LEN],
107			   u16 *secret_type, u8 *buf, u32 *buflen)
108{
109	struct uv_secret_list_item_hdr secret_meta_data;
110	int rc;
111
112	rc = get_secret_metadata(secret_id, &secret_meta_data);
113	if (rc)
114		return rc;
115
116	if (*buflen < secret_meta_data.length)
117		return -EINVAL;
118
119	rc = uv_retrieve_secret(secret_meta_data.index,
120				buf, secret_meta_data.length);
121	if (rc)
122		return rc;
123
124	*secret_type = secret_meta_data.type;
125	*buflen = secret_meta_data.length;
126
127	return 0;
128}
129
130static int uv_get_size_and_type(u16 secret_type, u32 *pkeysize, u32 *pkeytype)
131{
132	int rc = 0;
133
134	switch (secret_type) {
135	case UV_SECRET_AES_128:
136		*pkeysize = 16 + AES_WK_VP_SIZE;
137		*pkeytype = PKEY_KEYTYPE_AES_128;
138		break;
139	case UV_SECRET_AES_192:
140		*pkeysize = 24 + AES_WK_VP_SIZE;
141		*pkeytype = PKEY_KEYTYPE_AES_192;
142		break;
143	case UV_SECRET_AES_256:
144		*pkeysize = 32 + AES_WK_VP_SIZE;
145		*pkeytype = PKEY_KEYTYPE_AES_256;
146		break;
147	case UV_SECRET_AES_XTS_128:
148		*pkeysize = 16 + 16 + AES_WK_VP_SIZE;
149		*pkeytype = PKEY_KEYTYPE_AES_XTS_128;
150		break;
151	case UV_SECRET_AES_XTS_256:
152		*pkeysize = 32 + 32 + AES_WK_VP_SIZE;
153		*pkeytype = PKEY_KEYTYPE_AES_XTS_256;
154		break;
155	case UV_SECRET_HMAC_SHA_256:
156		*pkeysize = 64 + AES_WK_VP_SIZE;
157		*pkeytype = PKEY_KEYTYPE_HMAC_512;
158		break;
159	case UV_SECRET_HMAC_SHA_512:
160		*pkeysize = 128 + AES_WK_VP_SIZE;
161		*pkeytype = PKEY_KEYTYPE_HMAC_1024;
162		break;
163	case UV_SECRET_ECDSA_P256:
164		*pkeysize = 32 + AES_WK_VP_SIZE;
165		*pkeytype = PKEY_KEYTYPE_ECC_P256;
166		break;
167	case UV_SECRET_ECDSA_P384:
168		*pkeysize = 48 + AES_WK_VP_SIZE;
169		*pkeytype = PKEY_KEYTYPE_ECC_P384;
170		break;
171	case UV_SECRET_ECDSA_P521:
172		*pkeysize = 80 + AES_WK_VP_SIZE;
173		*pkeytype = PKEY_KEYTYPE_ECC_P521;
174		break;
175	case UV_SECRET_ECDSA_ED25519:
176		*pkeysize = 32 + AES_WK_VP_SIZE;
177		*pkeytype = PKEY_KEYTYPE_ECC_ED25519;
178		break;
179	case UV_SECRET_ECDSA_ED448:
180		*pkeysize = 64 + AES_WK_VP_SIZE;
181		*pkeytype = PKEY_KEYTYPE_ECC_ED448;
182		break;
183	default:
184		rc = -EINVAL;
185	}
186
187	return rc;
188}
189
190static int uv_key2protkey(const struct pkey_apqn *_apqns __always_unused,
191			  size_t _nr_apqns __always_unused,
192			  const u8 *key, u32 keylen,
193			  u8 *protkey, u32 *protkeylen, u32 *keyinfo,
194			  u32 _xflags __always_unused)
195{
196	struct uvsecrettoken *t = (struct uvsecrettoken *)key;
197	u32 pkeysize, pkeytype;
198	u16 secret_type;
199	int rc;
200
201	rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
202	if (rc)
203		goto out;
204
205	if (*protkeylen < pkeysize) {
206		PKEY_DBF_ERR("%s prot key buffer size too small: %u < %u\n",
207			     __func__, *protkeylen, pkeysize);
208		rc = -EINVAL;
209		goto out;
210	}
211
212	rc = retrieve_secret(t->secret_id, &secret_type, protkey, protkeylen);
213	if (rc) {
214		PKEY_DBF_ERR("%s retrieve_secret() failed with %d\n",
215			     __func__, rc);
216		goto out;
217	}
218	if (secret_type != t->secret_type) {
219		PKEY_DBF_ERR("%s retrieved secret type %u != expected type %u\n",
220			     __func__, secret_type, t->secret_type);
221		rc = -EINVAL;
222		goto out;
223	}
224
225	if (keyinfo)
226		*keyinfo = pkeytype;
227
228out:
229	pr_debug("rc=%d\n", rc);
230	return rc;
231}
232
233static int uv_verifykey(const u8 *key, u32 keylen,
234			u16 *_card __always_unused,
235			u16 *_dom __always_unused,
236			u32 *keytype, u32 *keybitsize, u32 *flags,
237			u32 xflags __always_unused)
238{
239	struct uvsecrettoken *t = (struct uvsecrettoken *)key;
240	struct uv_secret_list_item_hdr secret_meta_data;
241	u32 pkeysize, pkeytype, bitsize;
242	int rc;
243
244	rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
245	if (rc)
246		goto out;
247
248	rc = get_secret_metadata(t->secret_id, &secret_meta_data);
249	if (rc)
250		goto out;
251
252	if (secret_meta_data.type != t->secret_type) {
253		rc = -EINVAL;
254		goto out;
255	}
256
257	/* set keytype; keybitsize and flags are not supported */
258	if (keytype)
259		*keytype = PKEY_TYPE_UVSECRET;
260	if (keybitsize) {
261		bitsize = 8 * pkey_keytype_to_size(pkeytype);
262		*keybitsize = bitsize ?: PKEY_SIZE_UNKNOWN;
263	}
264	if (flags)
265		*flags = pkeytype;
266
267out:
268	pr_debug("rc=%d\n", rc);
269	return rc;
270}
271
272static struct pkey_handler uv_handler = {
273	.module			 = THIS_MODULE,
274	.name			 = "PKEY UV handler",
275	.is_supported_key	 = is_uv_key,
276	.is_supported_keytype	 = is_uv_keytype,
277	.key_to_protkey		 = uv_key2protkey,
278	.verify_key		 = uv_verifykey,
279};
280
281/*
282 * Module init
283 */
284static int __init pkey_uv_init(void)
285{
286	int rc;
287
288	if (!is_prot_virt_guest())
289		return -ENODEV;
290
291	if (!test_bit_inv(BIT_UVC_CMD_RETR_SECRET, uv_info.inst_calls_list))
292		return -ENODEV;
293
294	uv_list = kmalloc(sizeof(*uv_list), GFP_KERNEL);
295	if (!uv_list)
296		return -ENOMEM;
297
298	rc = pkey_handler_register(&uv_handler);
299	if (rc)
300		kfree(uv_list);
301
302	return rc;
303}
304
305/*
306 * Module exit
307 */
308static void __exit pkey_uv_exit(void)
309{
310	pkey_handler_unregister(&uv_handler);
311	mutex_lock(&uv_list_mutex);
312	kvfree(uv_list);
313	mutex_unlock(&uv_list_mutex);
314}
315
316module_cpu_feature_match(S390_CPU_FEATURE_UV, pkey_uv_init);
317module_exit(pkey_uv_exit);
~/ Read-only file preview.