Loading...
Note: File does not exist in v6.2.
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * pkey uv specific code
4 *
5 * Copyright IBM Corp. 2024
6 */
7
8#define KMSG_COMPONENT "pkey"
9#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10
11#include <linux/cpufeature.h>
12#include <linux/init.h>
13#include <linux/module.h>
14#include <asm/uv.h>
15
16#include "zcrypt_ccamisc.h"
17#include "pkey_base.h"
18
19MODULE_LICENSE("GPL");
20MODULE_AUTHOR("IBM Corporation");
21MODULE_DESCRIPTION("s390 protected key UV handler");
22
23/*
24 * UV secret token struct and defines.
25 */
26
27#define TOKVER_UV_SECRET 0x09
28
29struct 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;
38
39/*
40 * Check key blob for known and supported UV key.
41 */
42static bool is_uv_key(const u8 *key, u32 keylen)
43{
44 struct uvsecrettoken *t = (struct uvsecrettoken *)key;
45
46 if (keylen < sizeof(*t))
47 return false;
48
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;
69 }
70 default:
71 return false;
72 }
73 default:
74 return false;
75 }
76}
77
78static bool is_uv_keytype(enum pkey_key_type keytype)
79{
80 switch (keytype) {
81 case PKEY_TYPE_UVSECRET:
82 return true;
83 default:
84 return false;
85 }
86}
87
88static int retrieve_secret(const u8 secret_id[UV_SECRET_ID_LEN],
89 u16 *secret_type, u8 *buf, u32 *buflen)
90{
91 struct uv_secret_list_item_hdr secret_meta_data;
92 int rc;
93
94 rc = uv_get_secret_metadata(secret_id, &secret_meta_data);
95 if (rc)
96 return rc;
97
98 if (*buflen < secret_meta_data.length)
99 return -EINVAL;
100
101 rc = uv_retrieve_secret(secret_meta_data.index,
102 buf, secret_meta_data.length);
103 if (rc)
104 return rc;
105
106 *secret_type = secret_meta_data.type;
107 *buflen = secret_meta_data.length;
108
109 return 0;
110}
111
112static int uv_get_size_and_type(u16 secret_type, u32 *pkeysize, u32 *pkeytype)
113{
114 int rc = 0;
115
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;
167 }
168
169 return rc;
170}
171
172static 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)
176{
177 struct uvsecrettoken *t = (struct uvsecrettoken *)key;
178 u32 pkeysize, pkeytype;
179 u16 secret_type;
180 int rc;
181
182 rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
183 if (rc)
184 goto out;
185
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;
191 }
192
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;
198 }
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;
204 }
205
206 if (keyinfo)
207 *keyinfo = pkeytype;
208
209out:
210 pr_debug("rc=%d\n", rc);
211 return rc;
212}
213
214static 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)
218{
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;
223
224 rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
225 if (rc)
226 goto out;
227
228 rc = uv_get_secret_metadata(t->secret_id, &secret_meta_data);
229 if (rc)
230 goto out;
231
232 if (secret_meta_data.type != t->secret_type) {
233 rc = -EINVAL;
234 goto out;
235 }
236
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;
243 }
244 if (flags)
245 *flags = pkeytype;
246
247out:
248 pr_debug("rc=%d\n", rc);
249 return rc;
250}
251
252static 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,
259};
260
261/*
262 * Module init
263 */
264static int __init pkey_uv_init(void)
265{
266 if (!is_prot_virt_guest())
267 return -ENODEV;
268
269 if (!test_bit_inv(BIT_UVC_CMD_RETR_SECRET, uv_info.inst_calls_list))
270 return -ENODEV;
271
272 return pkey_handler_register(&uv_handler);
273}
274
275/*
276 * Module exit
277 */
278static void __exit pkey_uv_exit(void)
279{
280 pkey_handler_unregister(&uv_handler);
281}
282
283module_cpu_feature_match(S390_CPU_FEATURE_UV, pkey_uv_init);
284module_exit(pkey_uv_exit);