Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / drivers / s390 / crypto / pkey_uv.c
blob805817b1435401d8c05ea2968a22f7bcdabd59c4
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * pkey uv specific code
5 * Copyright IBM Corp. 2024
6 */
8 #define KMSG_COMPONENT "pkey"
9 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
11 #include <linux/cpufeature.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <asm/uv.h>
16 #include "zcrypt_ccamisc.h"
17 #include "pkey_base.h"
19 MODULE_LICENSE("GPL");
20 MODULE_AUTHOR("IBM Corporation");
21 MODULE_DESCRIPTION("s390 protected key UV handler");
24 * UV secret token struct and defines.
27 #define TOKVER_UV_SECRET 0x09
29 struct uvsecrettoken {
30 u8 type; /* 0x00 = TOKTYPE_NON_CCA */
31 u8 res0[3];
32 u8 version; /* 0x09 = TOKVER_UV_SECRET */
33 u8 res1[3];
34 u16 secret_type; /* one of enum uv_secret_types from uv.h */
35 u16 secret_len; /* length in bytes of the secret */
36 u8 secret_id[UV_SECRET_ID_LEN]; /* the secret id for this secret */
37 } __packed;
40 * Check key blob for known and supported UV key.
42 static bool is_uv_key(const u8 *key, u32 keylen)
44 struct uvsecrettoken *t = (struct uvsecrettoken *)key;
46 if (keylen < sizeof(*t))
47 return false;
49 switch (t->type) {
50 case TOKTYPE_NON_CCA:
51 switch (t->version) {
52 case TOKVER_UV_SECRET:
53 switch (t->secret_type) {
54 case UV_SECRET_AES_128:
55 case UV_SECRET_AES_192:
56 case UV_SECRET_AES_256:
57 case UV_SECRET_AES_XTS_128:
58 case UV_SECRET_AES_XTS_256:
59 case UV_SECRET_HMAC_SHA_256:
60 case UV_SECRET_HMAC_SHA_512:
61 case UV_SECRET_ECDSA_P256:
62 case UV_SECRET_ECDSA_P384:
63 case UV_SECRET_ECDSA_P521:
64 case UV_SECRET_ECDSA_ED25519:
65 case UV_SECRET_ECDSA_ED448:
66 return true;
67 default:
68 return false;
70 default:
71 return false;
73 default:
74 return false;
78 static bool is_uv_keytype(enum pkey_key_type keytype)
80 switch (keytype) {
81 case PKEY_TYPE_UVSECRET:
82 return true;
83 default:
84 return false;
88 static int retrieve_secret(const u8 secret_id[UV_SECRET_ID_LEN],
89 u16 *secret_type, u8 *buf, u32 *buflen)
91 struct uv_secret_list_item_hdr secret_meta_data;
92 int rc;
94 rc = uv_get_secret_metadata(secret_id, &secret_meta_data);
95 if (rc)
96 return rc;
98 if (*buflen < secret_meta_data.length)
99 return -EINVAL;
101 rc = uv_retrieve_secret(secret_meta_data.index,
102 buf, secret_meta_data.length);
103 if (rc)
104 return rc;
106 *secret_type = secret_meta_data.type;
107 *buflen = secret_meta_data.length;
109 return 0;
112 static int uv_get_size_and_type(u16 secret_type, u32 *pkeysize, u32 *pkeytype)
114 int rc = 0;
116 switch (secret_type) {
117 case UV_SECRET_AES_128:
118 *pkeysize = 16 + AES_WK_VP_SIZE;
119 *pkeytype = PKEY_KEYTYPE_AES_128;
120 break;
121 case UV_SECRET_AES_192:
122 *pkeysize = 24 + AES_WK_VP_SIZE;
123 *pkeytype = PKEY_KEYTYPE_AES_192;
124 break;
125 case UV_SECRET_AES_256:
126 *pkeysize = 32 + AES_WK_VP_SIZE;
127 *pkeytype = PKEY_KEYTYPE_AES_256;
128 break;
129 case UV_SECRET_AES_XTS_128:
130 *pkeysize = 16 + 16 + AES_WK_VP_SIZE;
131 *pkeytype = PKEY_KEYTYPE_AES_XTS_128;
132 break;
133 case UV_SECRET_AES_XTS_256:
134 *pkeysize = 32 + 32 + AES_WK_VP_SIZE;
135 *pkeytype = PKEY_KEYTYPE_AES_XTS_256;
136 break;
137 case UV_SECRET_HMAC_SHA_256:
138 *pkeysize = 64 + AES_WK_VP_SIZE;
139 *pkeytype = PKEY_KEYTYPE_HMAC_512;
140 break;
141 case UV_SECRET_HMAC_SHA_512:
142 *pkeysize = 128 + AES_WK_VP_SIZE;
143 *pkeytype = PKEY_KEYTYPE_HMAC_1024;
144 break;
145 case UV_SECRET_ECDSA_P256:
146 *pkeysize = 32 + AES_WK_VP_SIZE;
147 *pkeytype = PKEY_KEYTYPE_ECC_P256;
148 break;
149 case UV_SECRET_ECDSA_P384:
150 *pkeysize = 48 + AES_WK_VP_SIZE;
151 *pkeytype = PKEY_KEYTYPE_ECC_P384;
152 break;
153 case UV_SECRET_ECDSA_P521:
154 *pkeysize = 80 + AES_WK_VP_SIZE;
155 *pkeytype = PKEY_KEYTYPE_ECC_P521;
156 break;
157 case UV_SECRET_ECDSA_ED25519:
158 *pkeysize = 32 + AES_WK_VP_SIZE;
159 *pkeytype = PKEY_KEYTYPE_ECC_ED25519;
160 break;
161 case UV_SECRET_ECDSA_ED448:
162 *pkeysize = 64 + AES_WK_VP_SIZE;
163 *pkeytype = PKEY_KEYTYPE_ECC_ED448;
164 break;
165 default:
166 rc = -EINVAL;
169 return rc;
172 static int uv_key2protkey(const struct pkey_apqn *_apqns __always_unused,
173 size_t _nr_apqns __always_unused,
174 const u8 *key, u32 keylen,
175 u8 *protkey, u32 *protkeylen, u32 *keyinfo)
177 struct uvsecrettoken *t = (struct uvsecrettoken *)key;
178 u32 pkeysize, pkeytype;
179 u16 secret_type;
180 int rc;
182 rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
183 if (rc)
184 goto out;
186 if (*protkeylen < pkeysize) {
187 PKEY_DBF_ERR("%s prot key buffer size too small: %u < %u\n",
188 __func__, *protkeylen, pkeysize);
189 rc = -EINVAL;
190 goto out;
193 rc = retrieve_secret(t->secret_id, &secret_type, protkey, protkeylen);
194 if (rc) {
195 PKEY_DBF_ERR("%s retrieve_secret() failed with %d\n",
196 __func__, rc);
197 goto out;
199 if (secret_type != t->secret_type) {
200 PKEY_DBF_ERR("%s retrieved secret type %u != expected type %u\n",
201 __func__, secret_type, t->secret_type);
202 rc = -EINVAL;
203 goto out;
206 if (keyinfo)
207 *keyinfo = pkeytype;
209 out:
210 pr_debug("rc=%d\n", rc);
211 return rc;
214 static int uv_verifykey(const u8 *key, u32 keylen,
215 u16 *_card __always_unused,
216 u16 *_dom __always_unused,
217 u32 *keytype, u32 *keybitsize, u32 *flags)
219 struct uvsecrettoken *t = (struct uvsecrettoken *)key;
220 struct uv_secret_list_item_hdr secret_meta_data;
221 u32 pkeysize, pkeytype, bitsize;
222 int rc;
224 rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
225 if (rc)
226 goto out;
228 rc = uv_get_secret_metadata(t->secret_id, &secret_meta_data);
229 if (rc)
230 goto out;
232 if (secret_meta_data.type != t->secret_type) {
233 rc = -EINVAL;
234 goto out;
237 /* set keytype; keybitsize and flags are not supported */
238 if (keytype)
239 *keytype = PKEY_TYPE_UVSECRET;
240 if (keybitsize) {
241 bitsize = 8 * pkey_keytype_to_size(pkeytype);
242 *keybitsize = bitsize ?: PKEY_SIZE_UNKNOWN;
244 if (flags)
245 *flags = pkeytype;
247 out:
248 pr_debug("rc=%d\n", rc);
249 return rc;
252 static struct pkey_handler uv_handler = {
253 .module = THIS_MODULE,
254 .name = "PKEY UV handler",
255 .is_supported_key = is_uv_key,
256 .is_supported_keytype = is_uv_keytype,
257 .key_to_protkey = uv_key2protkey,
258 .verify_key = uv_verifykey,
262 * Module init
264 static int __init pkey_uv_init(void)
266 if (!is_prot_virt_guest())
267 return -ENODEV;
269 if (!test_bit_inv(BIT_UVC_CMD_RETR_SECRET, uv_info.inst_calls_list))
270 return -ENODEV;
272 return pkey_handler_register(&uv_handler);
276 * Module exit
278 static void __exit pkey_uv_exit(void)
280 pkey_handler_unregister(&uv_handler);
283 module_cpu_feature_match(S390_CPU_FEATURE_UV, pkey_uv_init);
284 module_exit(pkey_uv_exit);