Commit | Line | Data |
---|---|---|
812141a9 | 1 | // SPDX-License-Identifier: GPL-2.0 |
e80d4af0 HF |
2 | /* |
3 | * pkey device driver | |
4 | * | |
9e436c19 HF |
5 | * Copyright IBM Corp. 2017, 2023 |
6 | * | |
e80d4af0 | 7 | * Author(s): Harald Freudenberger |
e80d4af0 HF |
8 | */ |
9 | ||
10 | #define KMSG_COMPONENT "pkey" | |
11 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | |
12 | ||
13 | #include <linux/fs.h> | |
14 | #include <linux/init.h> | |
15 | #include <linux/miscdevice.h> | |
16 | #include <linux/module.h> | |
17 | #include <linux/slab.h> | |
18 | #include <linux/kallsyms.h> | |
19 | #include <linux/debugfs.h> | |
a45a5c7d | 20 | #include <linux/random.h> |
63c19be0 | 21 | #include <linux/cpufeature.h> |
e80d4af0 HF |
22 | #include <asm/zcrypt.h> |
23 | #include <asm/cpacf.h> | |
24 | #include <asm/pkey.h> | |
cb26b9ff | 25 | #include <crypto/aes.h> |
e80d4af0 HF |
26 | |
27 | #include "zcrypt_api.h" | |
efc598e6 | 28 | #include "zcrypt_ccamisc.h" |
55d0a513 | 29 | #include "zcrypt_ep11misc.h" |
e80d4af0 HF |
30 | |
31 | MODULE_LICENSE("GPL"); | |
32 | MODULE_AUTHOR("IBM Corporation"); | |
33 | MODULE_DESCRIPTION("s390 protected key interface"); | |
34 | ||
fa6999e3 | 35 | #define KEYBLOBBUFSIZE 8192 /* key buffer size used for internal processing */ |
9e436c19 | 36 | #define MINKEYBLOBBUFSIZE (sizeof(struct keytoken_header)) |
fa6999e3 HF |
37 | #define PROTKEYBLOBBUFSIZE 256 /* protected key buffer size used internal */ |
38 | #define MAXAPQNSINLIST 64 /* max 64 apqns within a apqn list */ | |
f370f45c | 39 | #define AES_WK_VP_SIZE 32 /* Size of WK VP block appended to a prot key */ |
f2bbc96e | 40 | |
e80d4af0 HF |
41 | /* |
42 | * debug feature data and functions | |
43 | */ | |
44 | ||
0ccac452 | 45 | static debug_info_t *pkey_dbf_info; |
e80d4af0 | 46 | |
0ccac452 HF |
47 | #define PKEY_DBF_INFO(...) debug_sprintf_event(pkey_dbf_info, 5, ##__VA_ARGS__) |
48 | #define PKEY_DBF_WARN(...) debug_sprintf_event(pkey_dbf_info, 4, ##__VA_ARGS__) | |
49 | #define PKEY_DBF_ERR(...) debug_sprintf_event(pkey_dbf_info, 3, ##__VA_ARGS__) | |
e80d4af0 HF |
50 | |
51 | static void __init pkey_debug_init(void) | |
52 | { | |
6b1f16ba | 53 | /* 5 arguments per dbf entry (including the format string ptr) */ |
0ccac452 HF |
54 | pkey_dbf_info = debug_register("pkey", 1, 1, 5 * sizeof(long)); |
55 | debug_register_view(pkey_dbf_info, &debug_sprintf_view); | |
56 | debug_set_level(pkey_dbf_info, 3); | |
e80d4af0 HF |
57 | } |
58 | ||
59 | static void __exit pkey_debug_exit(void) | |
60 | { | |
0ccac452 | 61 | debug_unregister(pkey_dbf_info); |
e80d4af0 HF |
62 | } |
63 | ||
0534bde7 IF |
64 | /* inside view of a protected key token (only type 0x00 version 0x01) */ |
65 | struct protaeskeytoken { | |
66 | u8 type; /* 0x00 for PAES specific key tokens */ | |
67 | u8 res0[3]; | |
68 | u8 version; /* should be 0x01 for protected AES key token */ | |
69 | u8 res1[3]; | |
70 | u32 keytype; /* key type, one of the PKEY_KEYTYPE values */ | |
71 | u32 len; /* bytes actually stored in protkey[] */ | |
72 | u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ | |
73 | } __packed; | |
74 | ||
888edbc4 | 75 | /* inside view of a clear key token (type 0x00 version 0x02) */ |
9e436c19 HF |
76 | struct clearkeytoken { |
77 | u8 type; /* 0x00 for PAES specific key tokens */ | |
888edbc4 | 78 | u8 res0[3]; |
9e436c19 | 79 | u8 version; /* 0x02 for clear key token */ |
888edbc4 | 80 | u8 res1[3]; |
9e436c19 HF |
81 | u32 keytype; /* key type, one of the PKEY_KEYTYPE_* values */ |
82 | u32 len; /* bytes actually stored in clearkey[] */ | |
fa226f1d | 83 | u8 clearkey[]; /* clear key value */ |
888edbc4 HF |
84 | } __packed; |
85 | ||
9e436c19 HF |
86 | /* helper function which translates the PKEY_KEYTYPE_AES_* to their keysize */ |
87 | static inline u32 pkey_keytype_aes_to_size(u32 keytype) | |
88 | { | |
89 | switch (keytype) { | |
90 | case PKEY_KEYTYPE_AES_128: | |
91 | return 16; | |
92 | case PKEY_KEYTYPE_AES_192: | |
93 | return 24; | |
94 | case PKEY_KEYTYPE_AES_256: | |
95 | return 32; | |
96 | default: | |
97 | return 0; | |
98 | } | |
99 | } | |
100 | ||
e80d4af0 | 101 | /* |
f370f45c | 102 | * Create a protected key from a clear key value via PCKMO instruction. |
e80d4af0 | 103 | */ |
f370f45c HF |
104 | static int pkey_clr2protkey(u32 keytype, const u8 *clrkey, |
105 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) | |
e80d4af0 | 106 | { |
5b35047e HF |
107 | /* mask of available pckmo subfunctions */ |
108 | static cpacf_mask_t pckmo_functions; | |
109 | ||
9e436c19 HF |
110 | u8 paramblock[112]; |
111 | u32 pkeytype; | |
46a29b03 HF |
112 | int keysize; |
113 | long fc; | |
e80d4af0 HF |
114 | |
115 | switch (keytype) { | |
116 | case PKEY_KEYTYPE_AES_128: | |
9e436c19 | 117 | /* 16 byte key, 32 byte aes wkvp, total 48 bytes */ |
e80d4af0 | 118 | keysize = 16; |
9e436c19 | 119 | pkeytype = keytype; |
e80d4af0 HF |
120 | fc = CPACF_PCKMO_ENC_AES_128_KEY; |
121 | break; | |
122 | case PKEY_KEYTYPE_AES_192: | |
9e436c19 | 123 | /* 24 byte key, 32 byte aes wkvp, total 56 bytes */ |
e80d4af0 | 124 | keysize = 24; |
9e436c19 | 125 | pkeytype = keytype; |
e80d4af0 HF |
126 | fc = CPACF_PCKMO_ENC_AES_192_KEY; |
127 | break; | |
128 | case PKEY_KEYTYPE_AES_256: | |
9e436c19 | 129 | /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ |
e80d4af0 | 130 | keysize = 32; |
9e436c19 | 131 | pkeytype = keytype; |
e80d4af0 HF |
132 | fc = CPACF_PCKMO_ENC_AES_256_KEY; |
133 | break; | |
9e436c19 HF |
134 | case PKEY_KEYTYPE_ECC_P256: |
135 | /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ | |
136 | keysize = 32; | |
137 | pkeytype = PKEY_KEYTYPE_ECC; | |
138 | fc = CPACF_PCKMO_ENC_ECC_P256_KEY; | |
139 | break; | |
140 | case PKEY_KEYTYPE_ECC_P384: | |
141 | /* 48 byte key, 32 byte aes wkvp, total 80 bytes */ | |
142 | keysize = 48; | |
143 | pkeytype = PKEY_KEYTYPE_ECC; | |
144 | fc = CPACF_PCKMO_ENC_ECC_P384_KEY; | |
145 | break; | |
146 | case PKEY_KEYTYPE_ECC_P521: | |
147 | /* 80 byte key, 32 byte aes wkvp, total 112 bytes */ | |
148 | keysize = 80; | |
149 | pkeytype = PKEY_KEYTYPE_ECC; | |
150 | fc = CPACF_PCKMO_ENC_ECC_P521_KEY; | |
151 | break; | |
152 | case PKEY_KEYTYPE_ECC_ED25519: | |
153 | /* 32 byte key, 32 byte aes wkvp, total 64 bytes */ | |
154 | keysize = 32; | |
155 | pkeytype = PKEY_KEYTYPE_ECC; | |
156 | fc = CPACF_PCKMO_ENC_ECC_ED25519_KEY; | |
157 | break; | |
158 | case PKEY_KEYTYPE_ECC_ED448: | |
159 | /* 64 byte key, 32 byte aes wkvp, total 96 bytes */ | |
160 | keysize = 64; | |
161 | pkeytype = PKEY_KEYTYPE_ECC; | |
162 | fc = CPACF_PCKMO_ENC_ECC_ED448_KEY; | |
163 | break; | |
e80d4af0 | 164 | default: |
0ccac452 HF |
165 | PKEY_DBF_ERR("%s unknown/unsupported keytype %u\n", |
166 | __func__, keytype); | |
e80d4af0 HF |
167 | return -EINVAL; |
168 | } | |
169 | ||
f370f45c | 170 | if (*protkeylen < keysize + AES_WK_VP_SIZE) { |
0ccac452 HF |
171 | PKEY_DBF_ERR("%s prot key buffer size too small: %u < %d\n", |
172 | __func__, *protkeylen, keysize + AES_WK_VP_SIZE); | |
f370f45c HF |
173 | return -EINVAL; |
174 | } | |
175 | ||
5b35047e HF |
176 | /* Did we already check for PCKMO ? */ |
177 | if (!pckmo_functions.bytes[0]) { | |
178 | /* no, so check now */ | |
179 | if (!cpacf_query(CPACF_PCKMO, &pckmo_functions)) | |
180 | return -ENODEV; | |
181 | } | |
182 | /* check for the pckmo subfunction we need now */ | |
f822ad2c | 183 | if (!cpacf_test_func(&pckmo_functions, fc)) { |
0ccac452 | 184 | PKEY_DBF_ERR("%s pckmo functions not available\n", __func__); |
58443b67 | 185 | return -ENODEV; |
f822ad2c HF |
186 | } |
187 | ||
e80d4af0 HF |
188 | /* prepare param block */ |
189 | memset(paramblock, 0, sizeof(paramblock)); | |
f370f45c | 190 | memcpy(paramblock, clrkey, keysize); |
e80d4af0 HF |
191 | |
192 | /* call the pckmo instruction */ | |
193 | cpacf_pckmo(fc, paramblock); | |
194 | ||
f370f45c HF |
195 | /* copy created protected key to key buffer including the wkvp block */ |
196 | *protkeylen = keysize + AES_WK_VP_SIZE; | |
197 | memcpy(protkey, paramblock, *protkeylen); | |
9e436c19 | 198 | *protkeytype = pkeytype; |
e80d4af0 HF |
199 | |
200 | return 0; | |
201 | } | |
e80d4af0 | 202 | |
e80d4af0 HF |
203 | /* |
204 | * Find card and transform secure key into protected key. | |
205 | */ | |
f370f45c HF |
206 | static int pkey_skey2pkey(const u8 *key, u8 *protkey, |
207 | u32 *protkeylen, u32 *protkeytype) | |
e80d4af0 | 208 | { |
f2bbc96e | 209 | struct keytoken_header *hdr = (struct keytoken_header *)key; |
46a29b03 HF |
210 | u16 cardnr, domain; |
211 | int rc, verify; | |
e80d4af0 | 212 | |
43cb5a7c HF |
213 | zcrypt_wait_api_operational(); |
214 | ||
e80d4af0 | 215 | /* |
f2bbc96e | 216 | * The cca_xxx2protkey call may fail when a card has been |
e80d4af0 | 217 | * addressed where the master key was changed after last fetch |
f4272c03 | 218 | * of the mkvp into the cache. Try 3 times: First without verify |
efc598e6 HF |
219 | * then with verify and last round with verify and old master |
220 | * key verification pattern match not ignored. | |
e80d4af0 | 221 | */ |
efc598e6 | 222 | for (verify = 0; verify < 3; verify++) { |
f2bbc96e | 223 | rc = cca_findcard(key, &cardnr, &domain, verify); |
efc598e6 HF |
224 | if (rc < 0) |
225 | continue; | |
226 | if (rc > 0 && verify < 2) | |
e80d4af0 | 227 | continue; |
f2bbc96e HF |
228 | switch (hdr->version) { |
229 | case TOKVER_CCA_AES: | |
f370f45c HF |
230 | rc = cca_sec2protkey(cardnr, domain, key, |
231 | protkey, protkeylen, protkeytype); | |
f2bbc96e HF |
232 | break; |
233 | case TOKVER_CCA_VLSC: | |
f370f45c HF |
234 | rc = cca_cipher2protkey(cardnr, domain, key, |
235 | protkey, protkeylen, | |
236 | protkeytype); | |
f2bbc96e HF |
237 | break; |
238 | default: | |
239 | return -EINVAL; | |
240 | } | |
e80d4af0 HF |
241 | if (rc == 0) |
242 | break; | |
243 | } | |
244 | ||
245 | if (rc) | |
6d749b4e | 246 | pr_debug("%s failed rc=%d\n", __func__, rc); |
e80d4af0 HF |
247 | |
248 | return rc; | |
249 | } | |
e80d4af0 | 250 | |
55d0a513 HF |
251 | /* |
252 | * Construct EP11 key with given clear key value. | |
253 | */ | |
254 | static int pkey_clr2ep11key(const u8 *clrkey, size_t clrkeylen, | |
255 | u8 *keybuf, size_t *keybuflen) | |
256 | { | |
55d0a513 | 257 | u32 nr_apqns, *apqns = NULL; |
46a29b03 HF |
258 | u16 card, dom; |
259 | int i, rc; | |
55d0a513 | 260 | |
43cb5a7c HF |
261 | zcrypt_wait_api_operational(); |
262 | ||
55d0a513 HF |
263 | /* build a list of apqns suitable for ep11 keys with cpacf support */ |
264 | rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, | |
386cb81e HD |
265 | ZCRYPT_CEX7, |
266 | ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, | |
267 | NULL); | |
55d0a513 HF |
268 | if (rc) |
269 | goto out; | |
270 | ||
271 | /* go through the list of apqns and try to bild an ep11 key */ | |
272 | for (rc = -ENODEV, i = 0; i < nr_apqns; i++) { | |
273 | card = apqns[i] >> 16; | |
274 | dom = apqns[i] & 0xFFFF; | |
275 | rc = ep11_clr2keyblob(card, dom, clrkeylen * 8, | |
da2863f1 HD |
276 | 0, clrkey, keybuf, keybuflen, |
277 | PKEY_TYPE_EP11); | |
55d0a513 HF |
278 | if (rc == 0) |
279 | break; | |
280 | } | |
281 | ||
282 | out: | |
283 | kfree(apqns); | |
284 | if (rc) | |
6d749b4e | 285 | pr_debug("%s failed rc=%d\n", __func__, rc); |
55d0a513 HF |
286 | return rc; |
287 | } | |
288 | ||
289 | /* | |
290 | * Find card and transform EP11 secure key into protected key. | |
291 | */ | |
d1fdfb0b HD |
292 | static int pkey_ep11key2pkey(const u8 *key, size_t keylen, |
293 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) | |
55d0a513 | 294 | { |
46a29b03 | 295 | u32 nr_apqns, *apqns = NULL; |
5dabfeca | 296 | int i, j, rc = -ENODEV; |
46a29b03 | 297 | u16 card, dom; |
55d0a513 | 298 | |
43cb5a7c HF |
299 | zcrypt_wait_api_operational(); |
300 | ||
5dabfeca HF |
301 | /* try two times in case of failure */ |
302 | for (i = 0; i < 2 && rc; i++) { | |
303 | ||
304 | /* build a list of apqns suitable for this key */ | |
305 | rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, | |
306 | ZCRYPT_CEX7, | |
307 | ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, | |
308 | ep11_kb_wkvp(key, keylen)); | |
309 | if (rc) | |
310 | continue; /* retry findcard on failure */ | |
311 | ||
312 | /* go through the list of apqns and try to derive an pkey */ | |
313 | for (rc = -ENODEV, j = 0; j < nr_apqns && rc; j++) { | |
314 | card = apqns[j] >> 16; | |
315 | dom = apqns[j] & 0xFFFF; | |
316 | rc = ep11_kblob2protkey(card, dom, key, keylen, | |
317 | protkey, protkeylen, protkeytype); | |
318 | } | |
55d0a513 | 319 | |
5dabfeca | 320 | kfree(apqns); |
55d0a513 HF |
321 | } |
322 | ||
55d0a513 | 323 | if (rc) |
6d749b4e | 324 | pr_debug("%s failed rc=%d\n", __func__, rc); |
5dabfeca | 325 | |
55d0a513 HF |
326 | return rc; |
327 | } | |
328 | ||
e61a6134 HF |
329 | /* |
330 | * Verify key and give back some info about the key. | |
331 | */ | |
183cb469 HF |
332 | static int pkey_verifykey(const struct pkey_seckey *seckey, |
333 | u16 *pcardnr, u16 *pdomain, | |
334 | u16 *pkeysize, u32 *pattributes) | |
e61a6134 | 335 | { |
2004b57c | 336 | struct secaeskeytoken *t = (struct secaeskeytoken *)seckey; |
e61a6134 | 337 | u16 cardnr, domain; |
e61a6134 HF |
338 | int rc; |
339 | ||
340 | /* check the secure key for valid AES secure key */ | |
0ccac452 | 341 | rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, (u8 *)seckey, 0); |
e61a6134 HF |
342 | if (rc) |
343 | goto out; | |
344 | if (pattributes) | |
345 | *pattributes = PKEY_VERIFY_ATTR_AES; | |
346 | if (pkeysize) | |
347 | *pkeysize = t->bitsize; | |
348 | ||
349 | /* try to find a card which can handle this key */ | |
efc598e6 HF |
350 | rc = cca_findcard(seckey->seckey, &cardnr, &domain, 1); |
351 | if (rc < 0) | |
e61a6134 HF |
352 | goto out; |
353 | ||
efc598e6 HF |
354 | if (rc > 0) { |
355 | /* key mkvp matches to old master key mkvp */ | |
6d749b4e | 356 | pr_debug("%s secure key has old mkvp\n", __func__); |
e61a6134 HF |
357 | if (pattributes) |
358 | *pattributes |= PKEY_VERIFY_ATTR_OLD_MKVP; | |
efc598e6 | 359 | rc = 0; |
e61a6134 HF |
360 | } |
361 | ||
362 | if (pcardnr) | |
363 | *pcardnr = cardnr; | |
364 | if (pdomain) | |
365 | *pdomain = domain; | |
366 | ||
367 | out: | |
6d749b4e | 368 | pr_debug("%s rc=%d\n", __func__, rc); |
e61a6134 HF |
369 | return rc; |
370 | } | |
e61a6134 | 371 | |
a45a5c7d IF |
372 | /* |
373 | * Generate a random protected key | |
374 | */ | |
f370f45c HF |
375 | static int pkey_genprotkey(u32 keytype, u8 *protkey, |
376 | u32 *protkeylen, u32 *protkeytype) | |
a45a5c7d | 377 | { |
f370f45c | 378 | u8 clrkey[32]; |
a45a5c7d IF |
379 | int keysize; |
380 | int rc; | |
381 | ||
9e436c19 HF |
382 | keysize = pkey_keytype_aes_to_size(keytype); |
383 | if (!keysize) { | |
0ccac452 HF |
384 | PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n", __func__, |
385 | keytype); | |
a45a5c7d IF |
386 | return -EINVAL; |
387 | } | |
388 | ||
389 | /* generate a dummy random clear key */ | |
f370f45c | 390 | get_random_bytes(clrkey, keysize); |
a45a5c7d IF |
391 | |
392 | /* convert it to a dummy protected key */ | |
f370f45c HF |
393 | rc = pkey_clr2protkey(keytype, clrkey, |
394 | protkey, protkeylen, protkeytype); | |
a45a5c7d IF |
395 | if (rc) |
396 | return rc; | |
397 | ||
398 | /* replace the key part of the protected key with random bytes */ | |
f370f45c | 399 | get_random_bytes(protkey, keysize); |
a45a5c7d IF |
400 | |
401 | return 0; | |
402 | } | |
a45a5c7d | 403 | |
cb26b9ff IF |
404 | /* |
405 | * Verify if a protected key is still valid | |
406 | */ | |
f370f45c HF |
407 | static int pkey_verifyprotkey(const u8 *protkey, u32 protkeylen, |
408 | u32 protkeytype) | |
cb26b9ff | 409 | { |
cb26b9ff IF |
410 | struct { |
411 | u8 iv[AES_BLOCK_SIZE]; | |
412 | u8 key[MAXPROTKEYSIZE]; | |
413 | } param; | |
414 | u8 null_msg[AES_BLOCK_SIZE]; | |
415 | u8 dest_buf[AES_BLOCK_SIZE]; | |
f370f45c | 416 | unsigned int k, pkeylen; |
46a29b03 | 417 | unsigned long fc; |
cb26b9ff | 418 | |
f370f45c | 419 | switch (protkeytype) { |
cb26b9ff | 420 | case PKEY_KEYTYPE_AES_128: |
f370f45c | 421 | pkeylen = 16 + AES_WK_VP_SIZE; |
cb26b9ff IF |
422 | fc = CPACF_KMC_PAES_128; |
423 | break; | |
424 | case PKEY_KEYTYPE_AES_192: | |
f370f45c | 425 | pkeylen = 24 + AES_WK_VP_SIZE; |
cb26b9ff IF |
426 | fc = CPACF_KMC_PAES_192; |
427 | break; | |
428 | case PKEY_KEYTYPE_AES_256: | |
f370f45c | 429 | pkeylen = 32 + AES_WK_VP_SIZE; |
cb26b9ff IF |
430 | fc = CPACF_KMC_PAES_256; |
431 | break; | |
432 | default: | |
0ccac452 HF |
433 | PKEY_DBF_ERR("%s unknown/unsupported keytype %u\n", __func__, |
434 | protkeytype); | |
f370f45c HF |
435 | return -EINVAL; |
436 | } | |
437 | if (protkeylen != pkeylen) { | |
0ccac452 HF |
438 | PKEY_DBF_ERR("%s invalid protected key size %u for keytype %u\n", |
439 | __func__, protkeylen, protkeytype); | |
cb26b9ff IF |
440 | return -EINVAL; |
441 | } | |
442 | ||
443 | memset(null_msg, 0, sizeof(null_msg)); | |
444 | ||
445 | memset(param.iv, 0, sizeof(param.iv)); | |
f370f45c | 446 | memcpy(param.key, protkey, protkeylen); |
cb26b9ff IF |
447 | |
448 | k = cpacf_kmc(fc | CPACF_ENCRYPT, ¶m, null_msg, dest_buf, | |
449 | sizeof(null_msg)); | |
450 | if (k != sizeof(null_msg)) { | |
0ccac452 | 451 | PKEY_DBF_ERR("%s protected key is not valid\n", __func__); |
cb26b9ff IF |
452 | return -EKEYREJECTED; |
453 | } | |
454 | ||
455 | return 0; | |
456 | } | |
cb26b9ff | 457 | |
9e436c19 HF |
458 | /* Helper for pkey_nonccatok2pkey, handles aes clear key token */ |
459 | static int nonccatokaes2pkey(const struct clearkeytoken *t, | |
460 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) | |
461 | { | |
462 | size_t tmpbuflen = max_t(size_t, SECKEYBLOBSIZE, MAXEP11AESKEYBLOBSIZE); | |
463 | u8 *tmpbuf = NULL; | |
464 | u32 keysize; | |
465 | int rc; | |
466 | ||
467 | keysize = pkey_keytype_aes_to_size(t->keytype); | |
468 | if (!keysize) { | |
0ccac452 HF |
469 | PKEY_DBF_ERR("%s unknown/unsupported keytype %u\n", |
470 | __func__, t->keytype); | |
9e436c19 HF |
471 | return -EINVAL; |
472 | } | |
473 | if (t->len != keysize) { | |
0ccac452 HF |
474 | PKEY_DBF_ERR("%s non clear key aes token: invalid key len %u\n", |
475 | __func__, t->len); | |
9e436c19 HF |
476 | return -EINVAL; |
477 | } | |
478 | ||
479 | /* try direct way with the PCKMO instruction */ | |
480 | rc = pkey_clr2protkey(t->keytype, t->clearkey, | |
481 | protkey, protkeylen, protkeytype); | |
482 | if (!rc) | |
483 | goto out; | |
484 | ||
485 | /* PCKMO failed, so try the CCA secure key way */ | |
486 | tmpbuf = kmalloc(tmpbuflen, GFP_ATOMIC); | |
487 | if (!tmpbuf) | |
488 | return -ENOMEM; | |
489 | zcrypt_wait_api_operational(); | |
490 | rc = cca_clr2seckey(0xFFFF, 0xFFFF, t->keytype, t->clearkey, tmpbuf); | |
491 | if (rc) | |
492 | goto try_via_ep11; | |
493 | rc = pkey_skey2pkey(tmpbuf, | |
494 | protkey, protkeylen, protkeytype); | |
495 | if (!rc) | |
496 | goto out; | |
497 | ||
498 | try_via_ep11: | |
499 | /* if the CCA way also failed, let's try via EP11 */ | |
500 | rc = pkey_clr2ep11key(t->clearkey, t->len, | |
501 | tmpbuf, &tmpbuflen); | |
502 | if (rc) | |
503 | goto failure; | |
d1fdfb0b | 504 | rc = pkey_ep11key2pkey(tmpbuf, tmpbuflen, |
9e436c19 HF |
505 | protkey, protkeylen, protkeytype); |
506 | if (!rc) | |
507 | goto out; | |
508 | ||
509 | failure: | |
0ccac452 | 510 | PKEY_DBF_ERR("%s unable to build protected key from clear", __func__); |
9e436c19 HF |
511 | |
512 | out: | |
513 | kfree(tmpbuf); | |
514 | return rc; | |
515 | } | |
516 | ||
517 | /* Helper for pkey_nonccatok2pkey, handles ecc clear key token */ | |
518 | static int nonccatokecc2pkey(const struct clearkeytoken *t, | |
519 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) | |
520 | { | |
521 | u32 keylen; | |
522 | int rc; | |
523 | ||
524 | switch (t->keytype) { | |
525 | case PKEY_KEYTYPE_ECC_P256: | |
526 | keylen = 32; | |
527 | break; | |
528 | case PKEY_KEYTYPE_ECC_P384: | |
529 | keylen = 48; | |
530 | break; | |
531 | case PKEY_KEYTYPE_ECC_P521: | |
532 | keylen = 80; | |
533 | break; | |
534 | case PKEY_KEYTYPE_ECC_ED25519: | |
535 | keylen = 32; | |
536 | break; | |
537 | case PKEY_KEYTYPE_ECC_ED448: | |
538 | keylen = 64; | |
539 | break; | |
540 | default: | |
0ccac452 HF |
541 | PKEY_DBF_ERR("%s unknown/unsupported keytype %u\n", |
542 | __func__, t->keytype); | |
9e436c19 HF |
543 | return -EINVAL; |
544 | } | |
545 | ||
546 | if (t->len != keylen) { | |
0ccac452 HF |
547 | PKEY_DBF_ERR("%s non clear key ecc token: invalid key len %u\n", |
548 | __func__, t->len); | |
9e436c19 HF |
549 | return -EINVAL; |
550 | } | |
551 | ||
552 | /* only one path possible: via PCKMO instruction */ | |
553 | rc = pkey_clr2protkey(t->keytype, t->clearkey, | |
554 | protkey, protkeylen, protkeytype); | |
555 | if (rc) { | |
0ccac452 HF |
556 | PKEY_DBF_ERR("%s unable to build protected key from clear", |
557 | __func__); | |
9e436c19 HF |
558 | } |
559 | ||
560 | return rc; | |
561 | } | |
562 | ||
fb1136d6 IF |
563 | /* |
564 | * Transform a non-CCA key token into a protected key | |
565 | */ | |
183cb469 | 566 | static int pkey_nonccatok2pkey(const u8 *key, u32 keylen, |
f370f45c | 567 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
fb1136d6 IF |
568 | { |
569 | struct keytoken_header *hdr = (struct keytoken_header *)key; | |
46a29b03 | 570 | int rc = -EINVAL; |
fb1136d6 IF |
571 | |
572 | switch (hdr->version) { | |
888edbc4 HF |
573 | case TOKVER_PROTECTED_KEY: { |
574 | struct protaeskeytoken *t; | |
fb1136d6 | 575 | |
888edbc4 HF |
576 | if (keylen != sizeof(struct protaeskeytoken)) |
577 | goto out; | |
fb1136d6 | 578 | t = (struct protaeskeytoken *)key; |
f370f45c HF |
579 | rc = pkey_verifyprotkey(t->protkey, t->len, t->keytype); |
580 | if (rc) | |
581 | goto out; | |
582 | memcpy(protkey, t->protkey, t->len); | |
583 | *protkeylen = t->len; | |
584 | *protkeytype = t->keytype; | |
888edbc4 HF |
585 | break; |
586 | } | |
587 | case TOKVER_CLEAR_KEY: { | |
9e436c19 HF |
588 | struct clearkeytoken *t = (struct clearkeytoken *)key; |
589 | ||
590 | if (keylen < sizeof(struct clearkeytoken) || | |
591 | keylen != sizeof(*t) + t->len) | |
55d0a513 | 592 | goto out; |
9e436c19 HF |
593 | switch (t->keytype) { |
594 | case PKEY_KEYTYPE_AES_128: | |
595 | case PKEY_KEYTYPE_AES_192: | |
596 | case PKEY_KEYTYPE_AES_256: | |
597 | rc = nonccatokaes2pkey(t, protkey, | |
598 | protkeylen, protkeytype); | |
888edbc4 | 599 | break; |
9e436c19 HF |
600 | case PKEY_KEYTYPE_ECC_P256: |
601 | case PKEY_KEYTYPE_ECC_P384: | |
602 | case PKEY_KEYTYPE_ECC_P521: | |
603 | case PKEY_KEYTYPE_ECC_ED25519: | |
604 | case PKEY_KEYTYPE_ECC_ED448: | |
605 | rc = nonccatokecc2pkey(t, protkey, | |
606 | protkeylen, protkeytype); | |
888edbc4 | 607 | break; |
9e436c19 | 608 | default: |
0ccac452 HF |
609 | PKEY_DBF_ERR("%s unknown/unsupported non cca clear key type %u\n", |
610 | __func__, t->keytype); | |
9e436c19 HF |
611 | return -EINVAL; |
612 | } | |
888edbc4 HF |
613 | break; |
614 | } | |
55d0a513 | 615 | case TOKVER_EP11_AES: { |
55d0a513 | 616 | /* check ep11 key for exportable as protected key */ |
0ccac452 | 617 | rc = ep11_check_aes_key(pkey_dbf_info, 3, key, keylen, 1); |
55d0a513 HF |
618 | if (rc) |
619 | goto out; | |
d1fdfb0b | 620 | rc = pkey_ep11key2pkey(key, keylen, |
f370f45c | 621 | protkey, protkeylen, protkeytype); |
55d0a513 HF |
622 | break; |
623 | } | |
fa6999e3 HF |
624 | case TOKVER_EP11_AES_WITH_HEADER: |
625 | /* check ep11 key with header for exportable as protected key */ | |
0ccac452 HF |
626 | rc = ep11_check_aes_key_with_hdr(pkey_dbf_info, |
627 | 3, key, keylen, 1); | |
fa6999e3 HF |
628 | if (rc) |
629 | goto out; | |
d1fdfb0b | 630 | rc = pkey_ep11key2pkey(key, keylen, |
f370f45c | 631 | protkey, protkeylen, protkeytype); |
fa6999e3 | 632 | break; |
fb1136d6 | 633 | default: |
0ccac452 HF |
634 | PKEY_DBF_ERR("%s unknown/unsupported non-CCA token version %d\n", |
635 | __func__, hdr->version); | |
fb1136d6 | 636 | } |
888edbc4 HF |
637 | |
638 | out: | |
639 | return rc; | |
fb1136d6 IF |
640 | } |
641 | ||
642 | /* | |
643 | * Transform a CCA internal key token into a protected key | |
644 | */ | |
183cb469 | 645 | static int pkey_ccainttok2pkey(const u8 *key, u32 keylen, |
f370f45c | 646 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
fb1136d6 IF |
647 | { |
648 | struct keytoken_header *hdr = (struct keytoken_header *)key; | |
649 | ||
650 | switch (hdr->version) { | |
651 | case TOKVER_CCA_AES: | |
652 | if (keylen != sizeof(struct secaeskeytoken)) | |
653 | return -EINVAL; | |
f2bbc96e HF |
654 | break; |
655 | case TOKVER_CCA_VLSC: | |
656 | if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) | |
657 | return -EINVAL; | |
658 | break; | |
fb1136d6 | 659 | default: |
0ccac452 HF |
660 | PKEY_DBF_ERR("%s unknown/unsupported CCA internal token version %d\n", |
661 | __func__, hdr->version); | |
fb1136d6 IF |
662 | return -EINVAL; |
663 | } | |
f2bbc96e | 664 | |
f370f45c | 665 | return pkey_skey2pkey(key, protkey, protkeylen, protkeytype); |
fb1136d6 IF |
666 | } |
667 | ||
668 | /* | |
669 | * Transform a key blob (of any type) into a protected key | |
670 | */ | |
183cb469 | 671 | int pkey_keyblob2pkey(const u8 *key, u32 keylen, |
f370f45c | 672 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
fb1136d6 IF |
673 | { |
674 | struct keytoken_header *hdr = (struct keytoken_header *)key; | |
46a29b03 | 675 | int rc; |
fb1136d6 | 676 | |
f2bbc96e | 677 | if (keylen < sizeof(struct keytoken_header)) { |
0ccac452 | 678 | PKEY_DBF_ERR("%s invalid keylen %d\n", __func__, keylen); |
fb1136d6 | 679 | return -EINVAL; |
f2bbc96e | 680 | } |
fb1136d6 IF |
681 | |
682 | switch (hdr->type) { | |
683 | case TOKTYPE_NON_CCA: | |
f370f45c HF |
684 | rc = pkey_nonccatok2pkey(key, keylen, |
685 | protkey, protkeylen, protkeytype); | |
f2bbc96e | 686 | break; |
fb1136d6 | 687 | case TOKTYPE_CCA_INTERNAL: |
f370f45c HF |
688 | rc = pkey_ccainttok2pkey(key, keylen, |
689 | protkey, protkeylen, protkeytype); | |
f2bbc96e | 690 | break; |
fb1136d6 | 691 | default: |
0ccac452 HF |
692 | PKEY_DBF_ERR("%s unknown/unsupported blob type %d\n", |
693 | __func__, hdr->type); | |
fb1136d6 IF |
694 | return -EINVAL; |
695 | } | |
f2bbc96e | 696 | |
6d749b4e | 697 | pr_debug("%s rc=%d\n", __func__, rc); |
f2bbc96e | 698 | return rc; |
fb1136d6 IF |
699 | } |
700 | EXPORT_SYMBOL(pkey_keyblob2pkey); | |
701 | ||
f2bbc96e HF |
702 | static int pkey_genseckey2(const struct pkey_apqn *apqns, size_t nr_apqns, |
703 | enum pkey_key_type ktype, enum pkey_key_size ksize, | |
704 | u32 kflags, u8 *keybuf, size_t *keybufsize) | |
705 | { | |
706 | int i, card, dom, rc; | |
707 | ||
708 | /* check for at least one apqn given */ | |
709 | if (!apqns || !nr_apqns) | |
710 | return -EINVAL; | |
711 | ||
712 | /* check key type and size */ | |
713 | switch (ktype) { | |
714 | case PKEY_TYPE_CCA_DATA: | |
715 | case PKEY_TYPE_CCA_CIPHER: | |
716 | if (*keybufsize < SECKEYBLOBSIZE) | |
717 | return -EINVAL; | |
718 | break; | |
55d0a513 HF |
719 | case PKEY_TYPE_EP11: |
720 | if (*keybufsize < MINEP11AESKEYBLOBSIZE) | |
721 | return -EINVAL; | |
722 | break; | |
fb249ce7 HD |
723 | case PKEY_TYPE_EP11_AES: |
724 | if (*keybufsize < (sizeof(struct ep11kblob_header) + | |
725 | MINEP11AESKEYBLOBSIZE)) | |
726 | return -EINVAL; | |
727 | break; | |
f2bbc96e HF |
728 | default: |
729 | return -EINVAL; | |
730 | } | |
731 | switch (ksize) { | |
732 | case PKEY_SIZE_AES_128: | |
733 | case PKEY_SIZE_AES_192: | |
734 | case PKEY_SIZE_AES_256: | |
735 | break; | |
736 | default: | |
737 | return -EINVAL; | |
738 | } | |
739 | ||
740 | /* simple try all apqns from the list */ | |
741 | for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { | |
742 | card = apqns[i].card; | |
743 | dom = apqns[i].domain; | |
fb249ce7 HD |
744 | if (ktype == PKEY_TYPE_EP11 || |
745 | ktype == PKEY_TYPE_EP11_AES) { | |
55d0a513 | 746 | rc = ep11_genaeskey(card, dom, ksize, kflags, |
fb249ce7 | 747 | keybuf, keybufsize, ktype); |
55d0a513 | 748 | } else if (ktype == PKEY_TYPE_CCA_DATA) { |
f2bbc96e HF |
749 | rc = cca_genseckey(card, dom, ksize, keybuf); |
750 | *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); | |
2004b57c HF |
751 | } else { |
752 | /* TOKVER_CCA_VLSC */ | |
f2bbc96e HF |
753 | rc = cca_gencipherkey(card, dom, ksize, kflags, |
754 | keybuf, keybufsize); | |
2004b57c | 755 | } |
f2bbc96e HF |
756 | if (rc == 0) |
757 | break; | |
758 | } | |
759 | ||
760 | return rc; | |
761 | } | |
762 | ||
763 | static int pkey_clr2seckey2(const struct pkey_apqn *apqns, size_t nr_apqns, | |
764 | enum pkey_key_type ktype, enum pkey_key_size ksize, | |
765 | u32 kflags, const u8 *clrkey, | |
766 | u8 *keybuf, size_t *keybufsize) | |
767 | { | |
768 | int i, card, dom, rc; | |
769 | ||
770 | /* check for at least one apqn given */ | |
771 | if (!apqns || !nr_apqns) | |
772 | return -EINVAL; | |
773 | ||
774 | /* check key type and size */ | |
775 | switch (ktype) { | |
776 | case PKEY_TYPE_CCA_DATA: | |
777 | case PKEY_TYPE_CCA_CIPHER: | |
778 | if (*keybufsize < SECKEYBLOBSIZE) | |
779 | return -EINVAL; | |
780 | break; | |
55d0a513 HF |
781 | case PKEY_TYPE_EP11: |
782 | if (*keybufsize < MINEP11AESKEYBLOBSIZE) | |
783 | return -EINVAL; | |
784 | break; | |
da2863f1 HD |
785 | case PKEY_TYPE_EP11_AES: |
786 | if (*keybufsize < (sizeof(struct ep11kblob_header) + | |
787 | MINEP11AESKEYBLOBSIZE)) | |
788 | return -EINVAL; | |
789 | break; | |
f2bbc96e HF |
790 | default: |
791 | return -EINVAL; | |
792 | } | |
793 | switch (ksize) { | |
794 | case PKEY_SIZE_AES_128: | |
795 | case PKEY_SIZE_AES_192: | |
796 | case PKEY_SIZE_AES_256: | |
797 | break; | |
798 | default: | |
799 | return -EINVAL; | |
800 | } | |
801 | ||
43cb5a7c HF |
802 | zcrypt_wait_api_operational(); |
803 | ||
f2bbc96e HF |
804 | /* simple try all apqns from the list */ |
805 | for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { | |
806 | card = apqns[i].card; | |
807 | dom = apqns[i].domain; | |
da2863f1 HD |
808 | if (ktype == PKEY_TYPE_EP11 || |
809 | ktype == PKEY_TYPE_EP11_AES) { | |
55d0a513 | 810 | rc = ep11_clr2keyblob(card, dom, ksize, kflags, |
da2863f1 HD |
811 | clrkey, keybuf, keybufsize, |
812 | ktype); | |
55d0a513 | 813 | } else if (ktype == PKEY_TYPE_CCA_DATA) { |
f2bbc96e HF |
814 | rc = cca_clr2seckey(card, dom, ksize, |
815 | clrkey, keybuf); | |
816 | *keybufsize = (rc ? 0 : SECKEYBLOBSIZE); | |
2004b57c HF |
817 | } else { |
818 | /* TOKVER_CCA_VLSC */ | |
f2bbc96e HF |
819 | rc = cca_clr2cipherkey(card, dom, ksize, kflags, |
820 | clrkey, keybuf, keybufsize); | |
2004b57c | 821 | } |
f2bbc96e HF |
822 | if (rc == 0) |
823 | break; | |
824 | } | |
825 | ||
826 | return rc; | |
827 | } | |
828 | ||
829 | static int pkey_verifykey2(const u8 *key, size_t keylen, | |
830 | u16 *cardnr, u16 *domain, | |
831 | enum pkey_key_type *ktype, | |
832 | enum pkey_key_size *ksize, u32 *flags) | |
833 | { | |
f2bbc96e | 834 | struct keytoken_header *hdr = (struct keytoken_header *)key; |
46a29b03 HF |
835 | u32 _nr_apqns, *_apqns = NULL; |
836 | int rc; | |
f2bbc96e | 837 | |
55d0a513 | 838 | if (keylen < sizeof(struct keytoken_header)) |
f2bbc96e HF |
839 | return -EINVAL; |
840 | ||
2004b57c HF |
841 | if (hdr->type == TOKTYPE_CCA_INTERNAL && |
842 | hdr->version == TOKVER_CCA_AES) { | |
f2bbc96e HF |
843 | struct secaeskeytoken *t = (struct secaeskeytoken *)key; |
844 | ||
0ccac452 | 845 | rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0); |
f2bbc96e HF |
846 | if (rc) |
847 | goto out; | |
848 | if (ktype) | |
849 | *ktype = PKEY_TYPE_CCA_DATA; | |
850 | if (ksize) | |
2004b57c | 851 | *ksize = (enum pkey_key_size)t->bitsize; |
f2bbc96e HF |
852 | |
853 | rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, | |
32ca04bb | 854 | ZCRYPT_CEX3C, AES_MK_SET, t->mkvp, 0, 1); |
f2bbc96e HF |
855 | if (rc == 0 && flags) |
856 | *flags = PKEY_FLAGS_MATCH_CUR_MKVP; | |
857 | if (rc == -ENODEV) { | |
858 | rc = cca_findcard2(&_apqns, &_nr_apqns, | |
859 | *cardnr, *domain, | |
32ca04bb HF |
860 | ZCRYPT_CEX3C, AES_MK_SET, |
861 | 0, t->mkvp, 1); | |
f2bbc96e HF |
862 | if (rc == 0 && flags) |
863 | *flags = PKEY_FLAGS_MATCH_ALT_MKVP; | |
864 | } | |
865 | if (rc) | |
866 | goto out; | |
867 | ||
868 | *cardnr = ((struct pkey_apqn *)_apqns)->card; | |
869 | *domain = ((struct pkey_apqn *)_apqns)->domain; | |
870 | ||
2004b57c HF |
871 | } else if (hdr->type == TOKTYPE_CCA_INTERNAL && |
872 | hdr->version == TOKVER_CCA_VLSC) { | |
f2bbc96e HF |
873 | struct cipherkeytoken *t = (struct cipherkeytoken *)key; |
874 | ||
0ccac452 | 875 | rc = cca_check_secaescipherkey(pkey_dbf_info, 3, key, 0, 1); |
f2bbc96e HF |
876 | if (rc) |
877 | goto out; | |
878 | if (ktype) | |
879 | *ktype = PKEY_TYPE_CCA_CIPHER; | |
880 | if (ksize) { | |
881 | *ksize = PKEY_SIZE_UNKNOWN; | |
882 | if (!t->plfver && t->wpllen == 512) | |
883 | *ksize = PKEY_SIZE_AES_128; | |
884 | else if (!t->plfver && t->wpllen == 576) | |
885 | *ksize = PKEY_SIZE_AES_192; | |
886 | else if (!t->plfver && t->wpllen == 640) | |
887 | *ksize = PKEY_SIZE_AES_256; | |
888 | } | |
889 | ||
890 | rc = cca_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, | |
32ca04bb | 891 | ZCRYPT_CEX6, AES_MK_SET, t->mkvp0, 0, 1); |
f2bbc96e HF |
892 | if (rc == 0 && flags) |
893 | *flags = PKEY_FLAGS_MATCH_CUR_MKVP; | |
894 | if (rc == -ENODEV) { | |
895 | rc = cca_findcard2(&_apqns, &_nr_apqns, | |
896 | *cardnr, *domain, | |
32ca04bb HF |
897 | ZCRYPT_CEX6, AES_MK_SET, |
898 | 0, t->mkvp0, 1); | |
f2bbc96e HF |
899 | if (rc == 0 && flags) |
900 | *flags = PKEY_FLAGS_MATCH_ALT_MKVP; | |
901 | } | |
902 | if (rc) | |
903 | goto out; | |
904 | ||
905 | *cardnr = ((struct pkey_apqn *)_apqns)->card; | |
906 | *domain = ((struct pkey_apqn *)_apqns)->domain; | |
907 | ||
2004b57c HF |
908 | } else if (hdr->type == TOKTYPE_NON_CCA && |
909 | hdr->version == TOKVER_EP11_AES) { | |
55d0a513 | 910 | struct ep11keyblob *kb = (struct ep11keyblob *)key; |
386cb81e | 911 | int api; |
55d0a513 | 912 | |
0ccac452 | 913 | rc = ep11_check_aes_key(pkey_dbf_info, 3, key, keylen, 1); |
55d0a513 HF |
914 | if (rc) |
915 | goto out; | |
916 | if (ktype) | |
917 | *ktype = PKEY_TYPE_EP11; | |
918 | if (ksize) | |
37a08f01 | 919 | *ksize = kb->head.bitlen; |
55d0a513 | 920 | |
386cb81e | 921 | api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; |
55d0a513 | 922 | rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, |
386cb81e | 923 | ZCRYPT_CEX7, api, |
745742db | 924 | ep11_kb_wkvp(key, keylen)); |
55d0a513 HF |
925 | if (rc) |
926 | goto out; | |
927 | ||
928 | if (flags) | |
929 | *flags = PKEY_FLAGS_MATCH_CUR_MKVP; | |
930 | ||
931 | *cardnr = ((struct pkey_apqn *)_apqns)->card; | |
932 | *domain = ((struct pkey_apqn *)_apqns)->domain; | |
933 | ||
745742db HD |
934 | } else if (hdr->type == TOKTYPE_NON_CCA && |
935 | hdr->version == TOKVER_EP11_AES_WITH_HEADER) { | |
936 | struct ep11kblob_header *kh = (struct ep11kblob_header *)key; | |
386cb81e | 937 | int api; |
745742db | 938 | |
0ccac452 HF |
939 | rc = ep11_check_aes_key_with_hdr(pkey_dbf_info, |
940 | 3, key, keylen, 1); | |
745742db HD |
941 | if (rc) |
942 | goto out; | |
943 | if (ktype) | |
944 | *ktype = PKEY_TYPE_EP11_AES; | |
945 | if (ksize) | |
946 | *ksize = kh->bitlen; | |
947 | ||
386cb81e | 948 | api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; |
745742db | 949 | rc = ep11_findcard2(&_apqns, &_nr_apqns, *cardnr, *domain, |
386cb81e | 950 | ZCRYPT_CEX7, api, |
745742db HD |
951 | ep11_kb_wkvp(key, keylen)); |
952 | if (rc) | |
953 | goto out; | |
954 | ||
955 | if (flags) | |
956 | *flags = PKEY_FLAGS_MATCH_CUR_MKVP; | |
957 | ||
958 | *cardnr = ((struct pkey_apqn *)_apqns)->card; | |
959 | *domain = ((struct pkey_apqn *)_apqns)->domain; | |
2004b57c | 960 | } else { |
f2bbc96e | 961 | rc = -EINVAL; |
2004b57c | 962 | } |
f2bbc96e HF |
963 | |
964 | out: | |
965 | kfree(_apqns); | |
966 | return rc; | |
967 | } | |
968 | ||
969 | static int pkey_keyblob2pkey2(const struct pkey_apqn *apqns, size_t nr_apqns, | |
970 | const u8 *key, size_t keylen, | |
f370f45c | 971 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) |
f2bbc96e | 972 | { |
f2bbc96e | 973 | struct keytoken_header *hdr = (struct keytoken_header *)key; |
46a29b03 | 974 | int i, card, dom, rc; |
f2bbc96e HF |
975 | |
976 | /* check for at least one apqn given */ | |
977 | if (!apqns || !nr_apqns) | |
978 | return -EINVAL; | |
979 | ||
980 | if (keylen < sizeof(struct keytoken_header)) | |
981 | return -EINVAL; | |
982 | ||
55d0a513 HF |
983 | if (hdr->type == TOKTYPE_CCA_INTERNAL) { |
984 | if (hdr->version == TOKVER_CCA_AES) { | |
f2bbc96e HF |
985 | if (keylen != sizeof(struct secaeskeytoken)) |
986 | return -EINVAL; | |
0ccac452 | 987 | if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0)) |
f2bbc96e | 988 | return -EINVAL; |
55d0a513 | 989 | } else if (hdr->version == TOKVER_CCA_VLSC) { |
f2bbc96e HF |
990 | if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) |
991 | return -EINVAL; | |
0ccac452 HF |
992 | if (cca_check_secaescipherkey(pkey_dbf_info, |
993 | 3, key, 0, 1)) | |
f2bbc96e | 994 | return -EINVAL; |
55d0a513 | 995 | } else { |
0ccac452 HF |
996 | PKEY_DBF_ERR("%s unknown CCA internal token version %d\n", |
997 | __func__, hdr->version); | |
f2bbc96e HF |
998 | return -EINVAL; |
999 | } | |
55d0a513 HF |
1000 | } else if (hdr->type == TOKTYPE_NON_CCA) { |
1001 | if (hdr->version == TOKVER_EP11_AES) { | |
0ccac452 HF |
1002 | if (ep11_check_aes_key(pkey_dbf_info, |
1003 | 3, key, keylen, 1)) | |
55d0a513 | 1004 | return -EINVAL; |
d1fdfb0b | 1005 | } else if (hdr->version == TOKVER_EP11_AES_WITH_HEADER) { |
0ccac452 HF |
1006 | if (ep11_check_aes_key_with_hdr(pkey_dbf_info, |
1007 | 3, key, keylen, 1)) | |
d1fdfb0b | 1008 | return -EINVAL; |
55d0a513 | 1009 | } else { |
f370f45c HF |
1010 | return pkey_nonccatok2pkey(key, keylen, |
1011 | protkey, protkeylen, | |
1012 | protkeytype); | |
55d0a513 HF |
1013 | } |
1014 | } else { | |
0ccac452 HF |
1015 | PKEY_DBF_ERR("%s unknown/unsupported blob type %d\n", |
1016 | __func__, hdr->type); | |
f2bbc96e HF |
1017 | return -EINVAL; |
1018 | } | |
1019 | ||
43cb5a7c HF |
1020 | zcrypt_wait_api_operational(); |
1021 | ||
f2bbc96e HF |
1022 | /* simple try all apqns from the list */ |
1023 | for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { | |
1024 | card = apqns[i].card; | |
1025 | dom = apqns[i].domain; | |
2004b57c HF |
1026 | if (hdr->type == TOKTYPE_CCA_INTERNAL && |
1027 | hdr->version == TOKVER_CCA_AES) { | |
f370f45c HF |
1028 | rc = cca_sec2protkey(card, dom, key, |
1029 | protkey, protkeylen, protkeytype); | |
2004b57c HF |
1030 | } else if (hdr->type == TOKTYPE_CCA_INTERNAL && |
1031 | hdr->version == TOKVER_CCA_VLSC) { | |
f370f45c HF |
1032 | rc = cca_cipher2protkey(card, dom, key, |
1033 | protkey, protkeylen, | |
1034 | protkeytype); | |
2004b57c | 1035 | } else { |
d1fdfb0b | 1036 | rc = ep11_kblob2protkey(card, dom, key, keylen, |
f370f45c HF |
1037 | protkey, protkeylen, |
1038 | protkeytype); | |
55d0a513 | 1039 | } |
f2bbc96e HF |
1040 | if (rc == 0) |
1041 | break; | |
1042 | } | |
1043 | ||
1044 | return rc; | |
1045 | } | |
1046 | ||
1047 | static int pkey_apqns4key(const u8 *key, size_t keylen, u32 flags, | |
1048 | struct pkey_apqn *apqns, size_t *nr_apqns) | |
1049 | { | |
f2bbc96e | 1050 | struct keytoken_header *hdr = (struct keytoken_header *)key; |
46a29b03 HF |
1051 | u32 _nr_apqns, *_apqns = NULL; |
1052 | int rc; | |
f2bbc96e | 1053 | |
55d0a513 | 1054 | if (keylen < sizeof(struct keytoken_header) || flags == 0) |
f2bbc96e HF |
1055 | return -EINVAL; |
1056 | ||
43cb5a7c HF |
1057 | zcrypt_wait_api_operational(); |
1058 | ||
2004b57c HF |
1059 | if (hdr->type == TOKTYPE_NON_CCA && |
1060 | (hdr->version == TOKVER_EP11_AES_WITH_HEADER || | |
1061 | hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && | |
1062 | is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { | |
fa6999e3 HF |
1063 | struct ep11keyblob *kb = (struct ep11keyblob *) |
1064 | (key + sizeof(struct ep11kblob_header)); | |
46a29b03 | 1065 | int minhwtype = 0, api = 0; |
fa6999e3 HF |
1066 | |
1067 | if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) | |
1068 | return -EINVAL; | |
1069 | if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { | |
1070 | minhwtype = ZCRYPT_CEX7; | |
386cb81e | 1071 | api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; |
fa6999e3 HF |
1072 | } |
1073 | rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, | |
1074 | minhwtype, api, kb->wkvp); | |
1075 | if (rc) | |
1076 | goto out; | |
2004b57c HF |
1077 | } else if (hdr->type == TOKTYPE_NON_CCA && |
1078 | hdr->version == TOKVER_EP11_AES && | |
1079 | is_ep11_keyblob(key)) { | |
2004b57c | 1080 | struct ep11keyblob *kb = (struct ep11keyblob *)key; |
46a29b03 | 1081 | int minhwtype = 0, api = 0; |
55d0a513 HF |
1082 | |
1083 | if (flags != PKEY_FLAGS_MATCH_CUR_MKVP) | |
1084 | return -EINVAL; | |
1085 | if (kb->attr & EP11_BLOB_PKEY_EXTRACTABLE) { | |
1086 | minhwtype = ZCRYPT_CEX7; | |
386cb81e | 1087 | api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; |
55d0a513 HF |
1088 | } |
1089 | rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, | |
1090 | minhwtype, api, kb->wkvp); | |
1091 | if (rc) | |
1092 | goto out; | |
1093 | } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { | |
f2bbc96e | 1094 | u64 cur_mkvp = 0, old_mkvp = 0; |
46a29b03 | 1095 | int minhwtype = ZCRYPT_CEX3C; |
f2bbc96e HF |
1096 | |
1097 | if (hdr->version == TOKVER_CCA_AES) { | |
1098 | struct secaeskeytoken *t = (struct secaeskeytoken *)key; | |
1099 | ||
1100 | if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) | |
1101 | cur_mkvp = t->mkvp; | |
1102 | if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) | |
1103 | old_mkvp = t->mkvp; | |
55d0a513 | 1104 | } else if (hdr->version == TOKVER_CCA_VLSC) { |
f2bbc96e HF |
1105 | struct cipherkeytoken *t = (struct cipherkeytoken *)key; |
1106 | ||
1107 | minhwtype = ZCRYPT_CEX6; | |
1108 | if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) | |
1109 | cur_mkvp = t->mkvp0; | |
1110 | if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) | |
1111 | old_mkvp = t->mkvp0; | |
55d0a513 HF |
1112 | } else { |
1113 | /* unknown cca internal token type */ | |
1114 | return -EINVAL; | |
f2bbc96e HF |
1115 | } |
1116 | rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, | |
32ca04bb HF |
1117 | minhwtype, AES_MK_SET, |
1118 | cur_mkvp, old_mkvp, 1); | |
f2bbc96e HF |
1119 | if (rc) |
1120 | goto out; | |
fa6999e3 | 1121 | } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { |
fa6999e3 | 1122 | struct eccprivkeytoken *t = (struct eccprivkeytoken *)key; |
46a29b03 | 1123 | u64 cur_mkvp = 0, old_mkvp = 0; |
fa6999e3 HF |
1124 | |
1125 | if (t->secid == 0x20) { | |
1126 | if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) | |
1127 | cur_mkvp = t->mkvp; | |
1128 | if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) | |
1129 | old_mkvp = t->mkvp; | |
1130 | } else { | |
1131 | /* unknown cca internal 2 token type */ | |
1132 | return -EINVAL; | |
1133 | } | |
1134 | rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, | |
1135 | ZCRYPT_CEX7, APKA_MK_SET, | |
1136 | cur_mkvp, old_mkvp, 1); | |
1137 | if (rc) | |
1138 | goto out; | |
2004b57c | 1139 | } else { |
55d0a513 | 1140 | return -EINVAL; |
2004b57c | 1141 | } |
55d0a513 HF |
1142 | |
1143 | if (apqns) { | |
1144 | if (*nr_apqns < _nr_apqns) | |
1145 | rc = -ENOSPC; | |
1146 | else | |
1147 | memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); | |
f2bbc96e | 1148 | } |
55d0a513 | 1149 | *nr_apqns = _nr_apqns; |
f2bbc96e HF |
1150 | |
1151 | out: | |
1152 | kfree(_apqns); | |
1153 | return rc; | |
1154 | } | |
1155 | ||
1156 | static int pkey_apqns4keytype(enum pkey_key_type ktype, | |
1157 | u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags, | |
1158 | struct pkey_apqn *apqns, size_t *nr_apqns) | |
1159 | { | |
f2bbc96e | 1160 | u32 _nr_apqns, *_apqns = NULL; |
46a29b03 | 1161 | int rc; |
f2bbc96e | 1162 | |
43cb5a7c HF |
1163 | zcrypt_wait_api_operational(); |
1164 | ||
f2bbc96e HF |
1165 | if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) { |
1166 | u64 cur_mkvp = 0, old_mkvp = 0; | |
1167 | int minhwtype = ZCRYPT_CEX3C; | |
1168 | ||
1169 | if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) | |
2004b57c | 1170 | cur_mkvp = *((u64 *)cur_mkvp); |
f2bbc96e | 1171 | if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) |
2004b57c | 1172 | old_mkvp = *((u64 *)alt_mkvp); |
f2bbc96e HF |
1173 | if (ktype == PKEY_TYPE_CCA_CIPHER) |
1174 | minhwtype = ZCRYPT_CEX6; | |
1175 | rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, | |
32ca04bb HF |
1176 | minhwtype, AES_MK_SET, |
1177 | cur_mkvp, old_mkvp, 1); | |
f2bbc96e HF |
1178 | if (rc) |
1179 | goto out; | |
fa6999e3 HF |
1180 | } else if (ktype == PKEY_TYPE_CCA_ECC) { |
1181 | u64 cur_mkvp = 0, old_mkvp = 0; | |
1182 | ||
1183 | if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) | |
2004b57c | 1184 | cur_mkvp = *((u64 *)cur_mkvp); |
fa6999e3 | 1185 | if (flags & PKEY_FLAGS_MATCH_ALT_MKVP) |
2004b57c | 1186 | old_mkvp = *((u64 *)alt_mkvp); |
fa6999e3 HF |
1187 | rc = cca_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, |
1188 | ZCRYPT_CEX7, APKA_MK_SET, | |
1189 | cur_mkvp, old_mkvp, 1); | |
1190 | if (rc) | |
1191 | goto out; | |
1192 | ||
1193 | } else if (ktype == PKEY_TYPE_EP11 || | |
1194 | ktype == PKEY_TYPE_EP11_AES || | |
1195 | ktype == PKEY_TYPE_EP11_ECC) { | |
55d0a513 | 1196 | u8 *wkvp = NULL; |
386cb81e | 1197 | int api; |
55d0a513 HF |
1198 | |
1199 | if (flags & PKEY_FLAGS_MATCH_CUR_MKVP) | |
1200 | wkvp = cur_mkvp; | |
386cb81e | 1201 | api = ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4; |
55d0a513 | 1202 | rc = ep11_findcard2(&_apqns, &_nr_apqns, 0xFFFF, 0xFFFF, |
386cb81e | 1203 | ZCRYPT_CEX7, api, wkvp); |
55d0a513 HF |
1204 | if (rc) |
1205 | goto out; | |
1206 | ||
2004b57c | 1207 | } else { |
55d0a513 | 1208 | return -EINVAL; |
2004b57c | 1209 | } |
55d0a513 HF |
1210 | |
1211 | if (apqns) { | |
1212 | if (*nr_apqns < _nr_apqns) | |
1213 | rc = -ENOSPC; | |
1214 | else | |
1215 | memcpy(apqns, _apqns, _nr_apqns * sizeof(u32)); | |
f2bbc96e | 1216 | } |
55d0a513 | 1217 | *nr_apqns = _nr_apqns; |
f2bbc96e HF |
1218 | |
1219 | out: | |
1220 | kfree(_apqns); | |
1221 | return rc; | |
1222 | } | |
1223 | ||
fa6999e3 | 1224 | static int pkey_keyblob2pkey3(const struct pkey_apqn *apqns, size_t nr_apqns, |
f370f45c HF |
1225 | const u8 *key, size_t keylen, |
1226 | u8 *protkey, u32 *protkeylen, u32 *protkeytype) | |
fa6999e3 | 1227 | { |
fa6999e3 | 1228 | struct keytoken_header *hdr = (struct keytoken_header *)key; |
46a29b03 | 1229 | int i, card, dom, rc; |
fa6999e3 HF |
1230 | |
1231 | /* check for at least one apqn given */ | |
1232 | if (!apqns || !nr_apqns) | |
1233 | return -EINVAL; | |
1234 | ||
1235 | if (keylen < sizeof(struct keytoken_header)) | |
1236 | return -EINVAL; | |
1237 | ||
2004b57c HF |
1238 | if (hdr->type == TOKTYPE_NON_CCA && |
1239 | hdr->version == TOKVER_EP11_AES_WITH_HEADER && | |
1240 | is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { | |
fa6999e3 | 1241 | /* EP11 AES key blob with header */ |
0ccac452 HF |
1242 | if (ep11_check_aes_key_with_hdr(pkey_dbf_info, |
1243 | 3, key, keylen, 1)) | |
fa6999e3 | 1244 | return -EINVAL; |
2004b57c HF |
1245 | } else if (hdr->type == TOKTYPE_NON_CCA && |
1246 | hdr->version == TOKVER_EP11_ECC_WITH_HEADER && | |
1247 | is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) { | |
fa6999e3 | 1248 | /* EP11 ECC key blob with header */ |
0ccac452 HF |
1249 | if (ep11_check_ecc_key_with_hdr(pkey_dbf_info, |
1250 | 3, key, keylen, 1)) | |
fa6999e3 | 1251 | return -EINVAL; |
2004b57c HF |
1252 | } else if (hdr->type == TOKTYPE_NON_CCA && |
1253 | hdr->version == TOKVER_EP11_AES && | |
1254 | is_ep11_keyblob(key)) { | |
fa6999e3 | 1255 | /* EP11 AES key blob with header in session field */ |
0ccac452 | 1256 | if (ep11_check_aes_key(pkey_dbf_info, 3, key, keylen, 1)) |
fa6999e3 HF |
1257 | return -EINVAL; |
1258 | } else if (hdr->type == TOKTYPE_CCA_INTERNAL) { | |
1259 | if (hdr->version == TOKVER_CCA_AES) { | |
1260 | /* CCA AES data key */ | |
1261 | if (keylen != sizeof(struct secaeskeytoken)) | |
1262 | return -EINVAL; | |
0ccac452 | 1263 | if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0)) |
fa6999e3 HF |
1264 | return -EINVAL; |
1265 | } else if (hdr->version == TOKVER_CCA_VLSC) { | |
1266 | /* CCA AES cipher key */ | |
1267 | if (keylen < hdr->len || keylen > MAXCCAVLSCTOKENSIZE) | |
1268 | return -EINVAL; | |
0ccac452 HF |
1269 | if (cca_check_secaescipherkey(pkey_dbf_info, |
1270 | 3, key, 0, 1)) | |
fa6999e3 HF |
1271 | return -EINVAL; |
1272 | } else { | |
0ccac452 HF |
1273 | PKEY_DBF_ERR("%s unknown CCA internal token version %d\n", |
1274 | __func__, hdr->version); | |
fa6999e3 HF |
1275 | return -EINVAL; |
1276 | } | |
1277 | } else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) { | |
1278 | /* CCA ECC (private) key */ | |
1279 | if (keylen < sizeof(struct eccprivkeytoken)) | |
1280 | return -EINVAL; | |
0ccac452 | 1281 | if (cca_check_sececckeytoken(pkey_dbf_info, 3, key, keylen, 1)) |
fa6999e3 HF |
1282 | return -EINVAL; |
1283 | } else if (hdr->type == TOKTYPE_NON_CCA) { | |
f370f45c HF |
1284 | return pkey_nonccatok2pkey(key, keylen, |
1285 | protkey, protkeylen, protkeytype); | |
fa6999e3 | 1286 | } else { |
0ccac452 HF |
1287 | PKEY_DBF_ERR("%s unknown/unsupported blob type %d\n", |
1288 | __func__, hdr->type); | |
fa6999e3 HF |
1289 | return -EINVAL; |
1290 | } | |
1291 | ||
1292 | /* simple try all apqns from the list */ | |
1293 | for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) { | |
1294 | card = apqns[i].card; | |
1295 | dom = apqns[i].domain; | |
2004b57c HF |
1296 | if (hdr->type == TOKTYPE_NON_CCA && |
1297 | (hdr->version == TOKVER_EP11_AES_WITH_HEADER || | |
1298 | hdr->version == TOKVER_EP11_ECC_WITH_HEADER) && | |
1299 | is_ep11_keyblob(key + sizeof(struct ep11kblob_header))) | |
fa6999e3 | 1300 | rc = ep11_kblob2protkey(card, dom, key, hdr->len, |
d1fdfb0b HD |
1301 | protkey, protkeylen, |
1302 | protkeytype); | |
2004b57c HF |
1303 | else if (hdr->type == TOKTYPE_NON_CCA && |
1304 | hdr->version == TOKVER_EP11_AES && | |
1305 | is_ep11_keyblob(key)) | |
fa6999e3 | 1306 | rc = ep11_kblob2protkey(card, dom, key, hdr->len, |
d1fdfb0b HD |
1307 | protkey, protkeylen, |
1308 | protkeytype); | |
fa6999e3 HF |
1309 | else if (hdr->type == TOKTYPE_CCA_INTERNAL && |
1310 | hdr->version == TOKVER_CCA_AES) | |
1311 | rc = cca_sec2protkey(card, dom, key, protkey, | |
1312 | protkeylen, protkeytype); | |
1313 | else if (hdr->type == TOKTYPE_CCA_INTERNAL && | |
1314 | hdr->version == TOKVER_CCA_VLSC) | |
1315 | rc = cca_cipher2protkey(card, dom, key, protkey, | |
1316 | protkeylen, protkeytype); | |
1317 | else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) | |
1318 | rc = cca_ecc2protkey(card, dom, key, protkey, | |
1319 | protkeylen, protkeytype); | |
1320 | else | |
1321 | return -EINVAL; | |
1322 | } | |
1323 | ||
1324 | return rc; | |
1325 | } | |
1326 | ||
e80d4af0 HF |
1327 | /* |
1328 | * File io functions | |
1329 | */ | |
1330 | ||
f2bbc96e HF |
1331 | static void *_copy_key_from_user(void __user *ukey, size_t keylen) |
1332 | { | |
9e436c19 | 1333 | if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE) |
f2bbc96e | 1334 | return ERR_PTR(-EINVAL); |
f2bbc96e | 1335 | |
8b57e7c8 | 1336 | return memdup_user(ukey, keylen); |
f2bbc96e HF |
1337 | } |
1338 | ||
1339 | static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns) | |
1340 | { | |
8b57e7c8 ME |
1341 | if (!uapqns || nr_apqns == 0) |
1342 | return NULL; | |
f2bbc96e | 1343 | |
8b57e7c8 | 1344 | return memdup_user(uapqns, nr_apqns * sizeof(struct pkey_apqn)); |
f2bbc96e HF |
1345 | } |
1346 | ||
e80d4af0 HF |
1347 | static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, |
1348 | unsigned long arg) | |
1349 | { | |
1350 | int rc; | |
1351 | ||
1352 | switch (cmd) { | |
1353 | case PKEY_GENSECK: { | |
2004b57c | 1354 | struct pkey_genseck __user *ugs = (void __user *)arg; |
e80d4af0 HF |
1355 | struct pkey_genseck kgs; |
1356 | ||
1357 | if (copy_from_user(&kgs, ugs, sizeof(kgs))) | |
1358 | return -EFAULT; | |
efc598e6 HF |
1359 | rc = cca_genseckey(kgs.cardnr, kgs.domain, |
1360 | kgs.keytype, kgs.seckey.seckey); | |
6d749b4e | 1361 | pr_debug("%s cca_genseckey()=%d\n", __func__, rc); |
e80d4af0 HF |
1362 | if (rc) |
1363 | break; | |
1364 | if (copy_to_user(ugs, &kgs, sizeof(kgs))) | |
1365 | return -EFAULT; | |
1366 | break; | |
1367 | } | |
1368 | case PKEY_CLR2SECK: { | |
2004b57c | 1369 | struct pkey_clr2seck __user *ucs = (void __user *)arg; |
e80d4af0 HF |
1370 | struct pkey_clr2seck kcs; |
1371 | ||
1372 | if (copy_from_user(&kcs, ucs, sizeof(kcs))) | |
1373 | return -EFAULT; | |
efc598e6 HF |
1374 | rc = cca_clr2seckey(kcs.cardnr, kcs.domain, kcs.keytype, |
1375 | kcs.clrkey.clrkey, kcs.seckey.seckey); | |
6d749b4e | 1376 | pr_debug("%s cca_clr2seckey()=%d\n", __func__, rc); |
e80d4af0 HF |
1377 | if (rc) |
1378 | break; | |
1379 | if (copy_to_user(ucs, &kcs, sizeof(kcs))) | |
1d8c270d | 1380 | rc = -EFAULT; |
e80d4af0 HF |
1381 | memzero_explicit(&kcs, sizeof(kcs)); |
1382 | break; | |
1383 | } | |
1384 | case PKEY_SEC2PROTK: { | |
2004b57c | 1385 | struct pkey_sec2protk __user *usp = (void __user *)arg; |
e80d4af0 HF |
1386 | struct pkey_sec2protk ksp; |
1387 | ||
1388 | if (copy_from_user(&ksp, usp, sizeof(ksp))) | |
1389 | return -EFAULT; | |
f370f45c | 1390 | ksp.protkey.len = sizeof(ksp.protkey.protkey); |
efc598e6 HF |
1391 | rc = cca_sec2protkey(ksp.cardnr, ksp.domain, |
1392 | ksp.seckey.seckey, ksp.protkey.protkey, | |
aab73d27 | 1393 | &ksp.protkey.len, &ksp.protkey.type); |
6d749b4e | 1394 | pr_debug("%s cca_sec2protkey()=%d\n", __func__, rc); |
e80d4af0 HF |
1395 | if (rc) |
1396 | break; | |
1397 | if (copy_to_user(usp, &ksp, sizeof(ksp))) | |
1398 | return -EFAULT; | |
1399 | break; | |
1400 | } | |
1401 | case PKEY_CLR2PROTK: { | |
2004b57c | 1402 | struct pkey_clr2protk __user *ucp = (void __user *)arg; |
e80d4af0 HF |
1403 | struct pkey_clr2protk kcp; |
1404 | ||
1405 | if (copy_from_user(&kcp, ucp, sizeof(kcp))) | |
1406 | return -EFAULT; | |
f370f45c HF |
1407 | kcp.protkey.len = sizeof(kcp.protkey.protkey); |
1408 | rc = pkey_clr2protkey(kcp.keytype, kcp.clrkey.clrkey, | |
1409 | kcp.protkey.protkey, | |
1410 | &kcp.protkey.len, &kcp.protkey.type); | |
6d749b4e | 1411 | pr_debug("%s pkey_clr2protkey()=%d\n", __func__, rc); |
e80d4af0 HF |
1412 | if (rc) |
1413 | break; | |
1414 | if (copy_to_user(ucp, &kcp, sizeof(kcp))) | |
1d8c270d | 1415 | rc = -EFAULT; |
e80d4af0 HF |
1416 | memzero_explicit(&kcp, sizeof(kcp)); |
1417 | break; | |
1418 | } | |
1419 | case PKEY_FINDCARD: { | |
2004b57c | 1420 | struct pkey_findcard __user *ufc = (void __user *)arg; |
e80d4af0 HF |
1421 | struct pkey_findcard kfc; |
1422 | ||
1423 | if (copy_from_user(&kfc, ufc, sizeof(kfc))) | |
1424 | return -EFAULT; | |
efc598e6 HF |
1425 | rc = cca_findcard(kfc.seckey.seckey, |
1426 | &kfc.cardnr, &kfc.domain, 1); | |
6d749b4e | 1427 | pr_debug("%s cca_findcard()=%d\n", __func__, rc); |
efc598e6 | 1428 | if (rc < 0) |
e80d4af0 HF |
1429 | break; |
1430 | if (copy_to_user(ufc, &kfc, sizeof(kfc))) | |
1431 | return -EFAULT; | |
1432 | break; | |
1433 | } | |
1434 | case PKEY_SKEY2PKEY: { | |
2004b57c | 1435 | struct pkey_skey2pkey __user *usp = (void __user *)arg; |
e80d4af0 HF |
1436 | struct pkey_skey2pkey ksp; |
1437 | ||
1438 | if (copy_from_user(&ksp, usp, sizeof(ksp))) | |
1439 | return -EFAULT; | |
f370f45c HF |
1440 | ksp.protkey.len = sizeof(ksp.protkey.protkey); |
1441 | rc = pkey_skey2pkey(ksp.seckey.seckey, ksp.protkey.protkey, | |
1442 | &ksp.protkey.len, &ksp.protkey.type); | |
6d749b4e | 1443 | pr_debug("%s pkey_skey2pkey()=%d\n", __func__, rc); |
e80d4af0 HF |
1444 | if (rc) |
1445 | break; | |
1446 | if (copy_to_user(usp, &ksp, sizeof(ksp))) | |
1447 | return -EFAULT; | |
1448 | break; | |
1449 | } | |
e61a6134 | 1450 | case PKEY_VERIFYKEY: { |
2004b57c | 1451 | struct pkey_verifykey __user *uvk = (void __user *)arg; |
e61a6134 HF |
1452 | struct pkey_verifykey kvk; |
1453 | ||
1454 | if (copy_from_user(&kvk, uvk, sizeof(kvk))) | |
1455 | return -EFAULT; | |
1456 | rc = pkey_verifykey(&kvk.seckey, &kvk.cardnr, &kvk.domain, | |
1457 | &kvk.keysize, &kvk.attributes); | |
6d749b4e | 1458 | pr_debug("%s pkey_verifykey()=%d\n", __func__, rc); |
e61a6134 HF |
1459 | if (rc) |
1460 | break; | |
1461 | if (copy_to_user(uvk, &kvk, sizeof(kvk))) | |
1462 | return -EFAULT; | |
1463 | break; | |
1464 | } | |
a45a5c7d | 1465 | case PKEY_GENPROTK: { |
2004b57c | 1466 | struct pkey_genprotk __user *ugp = (void __user *)arg; |
a45a5c7d IF |
1467 | struct pkey_genprotk kgp; |
1468 | ||
1469 | if (copy_from_user(&kgp, ugp, sizeof(kgp))) | |
1470 | return -EFAULT; | |
f370f45c HF |
1471 | kgp.protkey.len = sizeof(kgp.protkey.protkey); |
1472 | rc = pkey_genprotkey(kgp.keytype, kgp.protkey.protkey, | |
1473 | &kgp.protkey.len, &kgp.protkey.type); | |
6d749b4e | 1474 | pr_debug("%s pkey_genprotkey()=%d\n", __func__, rc); |
a45a5c7d IF |
1475 | if (rc) |
1476 | break; | |
1477 | if (copy_to_user(ugp, &kgp, sizeof(kgp))) | |
1478 | return -EFAULT; | |
1479 | break; | |
1480 | } | |
cb26b9ff | 1481 | case PKEY_VERIFYPROTK: { |
2004b57c | 1482 | struct pkey_verifyprotk __user *uvp = (void __user *)arg; |
cb26b9ff IF |
1483 | struct pkey_verifyprotk kvp; |
1484 | ||
1485 | if (copy_from_user(&kvp, uvp, sizeof(kvp))) | |
1486 | return -EFAULT; | |
f370f45c HF |
1487 | rc = pkey_verifyprotkey(kvp.protkey.protkey, |
1488 | kvp.protkey.len, kvp.protkey.type); | |
6d749b4e | 1489 | pr_debug("%s pkey_verifyprotkey()=%d\n", __func__, rc); |
cb26b9ff IF |
1490 | break; |
1491 | } | |
fb1136d6 | 1492 | case PKEY_KBLOB2PROTK: { |
2004b57c | 1493 | struct pkey_kblob2pkey __user *utp = (void __user *)arg; |
fb1136d6 | 1494 | struct pkey_kblob2pkey ktp; |
183cb469 | 1495 | u8 *kkey; |
fb1136d6 IF |
1496 | |
1497 | if (copy_from_user(&ktp, utp, sizeof(ktp))) | |
1498 | return -EFAULT; | |
f2bbc96e HF |
1499 | kkey = _copy_key_from_user(ktp.key, ktp.keylen); |
1500 | if (IS_ERR(kkey)) | |
1501 | return PTR_ERR(kkey); | |
f370f45c HF |
1502 | ktp.protkey.len = sizeof(ktp.protkey.protkey); |
1503 | rc = pkey_keyblob2pkey(kkey, ktp.keylen, ktp.protkey.protkey, | |
1504 | &ktp.protkey.len, &ktp.protkey.type); | |
6d749b4e | 1505 | pr_debug("%s pkey_keyblob2pkey()=%d\n", __func__, rc); |
22e68246 | 1506 | kfree_sensitive(kkey); |
f2bbc96e HF |
1507 | if (rc) |
1508 | break; | |
1509 | if (copy_to_user(utp, &ktp, sizeof(ktp))) | |
1510 | return -EFAULT; | |
1511 | break; | |
1512 | } | |
1513 | case PKEY_GENSECK2: { | |
2004b57c | 1514 | struct pkey_genseck2 __user *ugs = (void __user *)arg; |
46a29b03 | 1515 | size_t klen = KEYBLOBBUFSIZE; |
f2bbc96e HF |
1516 | struct pkey_genseck2 kgs; |
1517 | struct pkey_apqn *apqns; | |
f2bbc96e HF |
1518 | u8 *kkey; |
1519 | ||
1520 | if (copy_from_user(&kgs, ugs, sizeof(kgs))) | |
1521 | return -EFAULT; | |
1522 | apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries); | |
1523 | if (IS_ERR(apqns)) | |
1524 | return PTR_ERR(apqns); | |
fb249ce7 | 1525 | kkey = kzalloc(klen, GFP_KERNEL); |
f2bbc96e HF |
1526 | if (!kkey) { |
1527 | kfree(apqns); | |
fb1136d6 | 1528 | return -ENOMEM; |
f2bbc96e HF |
1529 | } |
1530 | rc = pkey_genseckey2(apqns, kgs.apqn_entries, | |
1531 | kgs.type, kgs.size, kgs.keygenflags, | |
1532 | kkey, &klen); | |
6d749b4e | 1533 | pr_debug("%s pkey_genseckey2()=%d\n", __func__, rc); |
f2bbc96e HF |
1534 | kfree(apqns); |
1535 | if (rc) { | |
fb1136d6 | 1536 | kfree(kkey); |
f2bbc96e HF |
1537 | break; |
1538 | } | |
1539 | if (kgs.key) { | |
1540 | if (kgs.keylen < klen) { | |
1541 | kfree(kkey); | |
1542 | return -EINVAL; | |
1543 | } | |
1544 | if (copy_to_user(kgs.key, kkey, klen)) { | |
1545 | kfree(kkey); | |
1546 | return -EFAULT; | |
1547 | } | |
1548 | } | |
1549 | kgs.keylen = klen; | |
1550 | if (copy_to_user(ugs, &kgs, sizeof(kgs))) | |
1551 | rc = -EFAULT; | |
1552 | kfree(kkey); | |
1553 | break; | |
1554 | } | |
1555 | case PKEY_CLR2SECK2: { | |
2004b57c | 1556 | struct pkey_clr2seck2 __user *ucs = (void __user *)arg; |
46a29b03 | 1557 | size_t klen = KEYBLOBBUFSIZE; |
f2bbc96e HF |
1558 | struct pkey_clr2seck2 kcs; |
1559 | struct pkey_apqn *apqns; | |
f2bbc96e HF |
1560 | u8 *kkey; |
1561 | ||
1562 | if (copy_from_user(&kcs, ucs, sizeof(kcs))) | |
fb1136d6 | 1563 | return -EFAULT; |
f2bbc96e HF |
1564 | apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries); |
1565 | if (IS_ERR(apqns)) | |
1566 | return PTR_ERR(apqns); | |
da2863f1 | 1567 | kkey = kzalloc(klen, GFP_KERNEL); |
f2bbc96e HF |
1568 | if (!kkey) { |
1569 | kfree(apqns); | |
1570 | return -ENOMEM; | |
fb1136d6 | 1571 | } |
f2bbc96e HF |
1572 | rc = pkey_clr2seckey2(apqns, kcs.apqn_entries, |
1573 | kcs.type, kcs.size, kcs.keygenflags, | |
1574 | kcs.clrkey.clrkey, kkey, &klen); | |
6d749b4e | 1575 | pr_debug("%s pkey_clr2seckey2()=%d\n", __func__, rc); |
f2bbc96e HF |
1576 | kfree(apqns); |
1577 | if (rc) { | |
1578 | kfree(kkey); | |
1579 | break; | |
1580 | } | |
1581 | if (kcs.key) { | |
1582 | if (kcs.keylen < klen) { | |
1583 | kfree(kkey); | |
1584 | return -EINVAL; | |
1585 | } | |
1586 | if (copy_to_user(kcs.key, kkey, klen)) { | |
1587 | kfree(kkey); | |
1588 | return -EFAULT; | |
1589 | } | |
1590 | } | |
1591 | kcs.keylen = klen; | |
1592 | if (copy_to_user(ucs, &kcs, sizeof(kcs))) | |
1593 | rc = -EFAULT; | |
1594 | memzero_explicit(&kcs, sizeof(kcs)); | |
1595 | kfree(kkey); | |
1596 | break; | |
1597 | } | |
1598 | case PKEY_VERIFYKEY2: { | |
2004b57c | 1599 | struct pkey_verifykey2 __user *uvk = (void __user *)arg; |
f2bbc96e HF |
1600 | struct pkey_verifykey2 kvk; |
1601 | u8 *kkey; | |
1602 | ||
1603 | if (copy_from_user(&kvk, uvk, sizeof(kvk))) | |
1604 | return -EFAULT; | |
1605 | kkey = _copy_key_from_user(kvk.key, kvk.keylen); | |
1606 | if (IS_ERR(kkey)) | |
1607 | return PTR_ERR(kkey); | |
1608 | rc = pkey_verifykey2(kkey, kvk.keylen, | |
1609 | &kvk.cardnr, &kvk.domain, | |
1610 | &kvk.type, &kvk.size, &kvk.flags); | |
6d749b4e | 1611 | pr_debug("%s pkey_verifykey2()=%d\n", __func__, rc); |
f2bbc96e HF |
1612 | kfree(kkey); |
1613 | if (rc) | |
1614 | break; | |
1615 | if (copy_to_user(uvk, &kvk, sizeof(kvk))) | |
1616 | return -EFAULT; | |
1617 | break; | |
1618 | } | |
1619 | case PKEY_KBLOB2PROTK2: { | |
2004b57c | 1620 | struct pkey_kblob2pkey2 __user *utp = (void __user *)arg; |
f2bbc96e | 1621 | struct pkey_apqn *apqns = NULL; |
46a29b03 | 1622 | struct pkey_kblob2pkey2 ktp; |
f2bbc96e HF |
1623 | u8 *kkey; |
1624 | ||
1625 | if (copy_from_user(&ktp, utp, sizeof(ktp))) | |
1626 | return -EFAULT; | |
1627 | apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); | |
1628 | if (IS_ERR(apqns)) | |
1629 | return PTR_ERR(apqns); | |
1630 | kkey = _copy_key_from_user(ktp.key, ktp.keylen); | |
1631 | if (IS_ERR(kkey)) { | |
1632 | kfree(apqns); | |
1633 | return PTR_ERR(kkey); | |
1634 | } | |
f370f45c | 1635 | ktp.protkey.len = sizeof(ktp.protkey.protkey); |
f2bbc96e | 1636 | rc = pkey_keyblob2pkey2(apqns, ktp.apqn_entries, |
f370f45c HF |
1637 | kkey, ktp.keylen, |
1638 | ktp.protkey.protkey, &ktp.protkey.len, | |
1639 | &ktp.protkey.type); | |
6d749b4e | 1640 | pr_debug("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); |
f2bbc96e | 1641 | kfree(apqns); |
22e68246 | 1642 | kfree_sensitive(kkey); |
fb1136d6 IF |
1643 | if (rc) |
1644 | break; | |
1645 | if (copy_to_user(utp, &ktp, sizeof(ktp))) | |
1646 | return -EFAULT; | |
1647 | break; | |
1648 | } | |
f2bbc96e | 1649 | case PKEY_APQNS4K: { |
2004b57c | 1650 | struct pkey_apqns4key __user *uak = (void __user *)arg; |
f2bbc96e | 1651 | struct pkey_apqn *apqns = NULL; |
46a29b03 | 1652 | struct pkey_apqns4key kak; |
f2bbc96e HF |
1653 | size_t nr_apqns, len; |
1654 | u8 *kkey; | |
1655 | ||
1656 | if (copy_from_user(&kak, uak, sizeof(kak))) | |
1657 | return -EFAULT; | |
1658 | nr_apqns = kak.apqn_entries; | |
1659 | if (nr_apqns) { | |
1660 | apqns = kmalloc_array(nr_apqns, | |
1661 | sizeof(struct pkey_apqn), | |
1662 | GFP_KERNEL); | |
1663 | if (!apqns) | |
1664 | return -ENOMEM; | |
1665 | } | |
1666 | kkey = _copy_key_from_user(kak.key, kak.keylen); | |
1667 | if (IS_ERR(kkey)) { | |
1668 | kfree(apqns); | |
1669 | return PTR_ERR(kkey); | |
1670 | } | |
1671 | rc = pkey_apqns4key(kkey, kak.keylen, kak.flags, | |
1672 | apqns, &nr_apqns); | |
6d749b4e | 1673 | pr_debug("%s pkey_apqns4key()=%d\n", __func__, rc); |
f2bbc96e HF |
1674 | kfree(kkey); |
1675 | if (rc && rc != -ENOSPC) { | |
1676 | kfree(apqns); | |
1677 | break; | |
1678 | } | |
1679 | if (!rc && kak.apqns) { | |
1680 | if (nr_apqns > kak.apqn_entries) { | |
1681 | kfree(apqns); | |
1682 | return -EINVAL; | |
1683 | } | |
1684 | len = nr_apqns * sizeof(struct pkey_apqn); | |
1685 | if (len) { | |
1686 | if (copy_to_user(kak.apqns, apqns, len)) { | |
1687 | kfree(apqns); | |
1688 | return -EFAULT; | |
1689 | } | |
1690 | } | |
1691 | } | |
1692 | kak.apqn_entries = nr_apqns; | |
1693 | if (copy_to_user(uak, &kak, sizeof(kak))) | |
1694 | rc = -EFAULT; | |
1695 | kfree(apqns); | |
1696 | break; | |
1697 | } | |
1698 | case PKEY_APQNS4KT: { | |
2004b57c | 1699 | struct pkey_apqns4keytype __user *uat = (void __user *)arg; |
f2bbc96e | 1700 | struct pkey_apqn *apqns = NULL; |
46a29b03 | 1701 | struct pkey_apqns4keytype kat; |
f2bbc96e HF |
1702 | size_t nr_apqns, len; |
1703 | ||
1704 | if (copy_from_user(&kat, uat, sizeof(kat))) | |
1705 | return -EFAULT; | |
1706 | nr_apqns = kat.apqn_entries; | |
1707 | if (nr_apqns) { | |
1708 | apqns = kmalloc_array(nr_apqns, | |
1709 | sizeof(struct pkey_apqn), | |
1710 | GFP_KERNEL); | |
1711 | if (!apqns) | |
1712 | return -ENOMEM; | |
1713 | } | |
1714 | rc = pkey_apqns4keytype(kat.type, kat.cur_mkvp, kat.alt_mkvp, | |
1715 | kat.flags, apqns, &nr_apqns); | |
6d749b4e | 1716 | pr_debug("%s pkey_apqns4keytype()=%d\n", __func__, rc); |
f2bbc96e HF |
1717 | if (rc && rc != -ENOSPC) { |
1718 | kfree(apqns); | |
1719 | break; | |
1720 | } | |
1721 | if (!rc && kat.apqns) { | |
1722 | if (nr_apqns > kat.apqn_entries) { | |
1723 | kfree(apqns); | |
1724 | return -EINVAL; | |
1725 | } | |
1726 | len = nr_apqns * sizeof(struct pkey_apqn); | |
1727 | if (len) { | |
1728 | if (copy_to_user(kat.apqns, apqns, len)) { | |
1729 | kfree(apqns); | |
1730 | return -EFAULT; | |
1731 | } | |
1732 | } | |
1733 | } | |
1734 | kat.apqn_entries = nr_apqns; | |
1735 | if (copy_to_user(uat, &kat, sizeof(kat))) | |
1736 | rc = -EFAULT; | |
1737 | kfree(apqns); | |
1738 | break; | |
1739 | } | |
fa6999e3 | 1740 | case PKEY_KBLOB2PROTK3: { |
2004b57c | 1741 | struct pkey_kblob2pkey3 __user *utp = (void __user *)arg; |
fa6999e3 | 1742 | u32 protkeylen = PROTKEYBLOBBUFSIZE; |
46a29b03 HF |
1743 | struct pkey_apqn *apqns = NULL; |
1744 | struct pkey_kblob2pkey3 ktp; | |
fa6999e3 HF |
1745 | u8 *kkey, *protkey; |
1746 | ||
1747 | if (copy_from_user(&ktp, utp, sizeof(ktp))) | |
1748 | return -EFAULT; | |
1749 | apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries); | |
1750 | if (IS_ERR(apqns)) | |
1751 | return PTR_ERR(apqns); | |
1752 | kkey = _copy_key_from_user(ktp.key, ktp.keylen); | |
1753 | if (IS_ERR(kkey)) { | |
1754 | kfree(apqns); | |
1755 | return PTR_ERR(kkey); | |
1756 | } | |
1757 | protkey = kmalloc(protkeylen, GFP_KERNEL); | |
1758 | if (!protkey) { | |
1759 | kfree(apqns); | |
1760 | kfree(kkey); | |
1761 | return -ENOMEM; | |
1762 | } | |
f370f45c HF |
1763 | rc = pkey_keyblob2pkey3(apqns, ktp.apqn_entries, |
1764 | kkey, ktp.keylen, | |
1765 | protkey, &protkeylen, &ktp.pkeytype); | |
6d749b4e | 1766 | pr_debug("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); |
fa6999e3 | 1767 | kfree(apqns); |
22e68246 | 1768 | kfree_sensitive(kkey); |
fa6999e3 HF |
1769 | if (rc) { |
1770 | kfree(protkey); | |
1771 | break; | |
1772 | } | |
1773 | if (ktp.pkey && ktp.pkeylen) { | |
1774 | if (protkeylen > ktp.pkeylen) { | |
1775 | kfree(protkey); | |
1776 | return -EINVAL; | |
1777 | } | |
1778 | if (copy_to_user(ktp.pkey, protkey, protkeylen)) { | |
1779 | kfree(protkey); | |
1780 | return -EFAULT; | |
1781 | } | |
1782 | } | |
1783 | kfree(protkey); | |
1784 | ktp.pkeylen = protkeylen; | |
1785 | if (copy_to_user(utp, &ktp, sizeof(ktp))) | |
1786 | return -EFAULT; | |
1787 | break; | |
1788 | } | |
e80d4af0 HF |
1789 | default: |
1790 | /* unknown/unsupported ioctl cmd */ | |
1791 | return -ENOTTY; | |
1792 | } | |
1793 | ||
1794 | return rc; | |
1795 | } | |
1796 | ||
1797 | /* | |
1798 | * Sysfs and file io operations | |
1799 | */ | |
d632c047 IF |
1800 | |
1801 | /* | |
1802 | * Sysfs attribute read function for all protected key binary attributes. | |
1803 | * The implementation can not deal with partial reads, because a new random | |
1804 | * protected key blob is generated with each read. In case of partial reads | |
1805 | * (i.e. off != 0 or count < key blob size) -EINVAL is returned. | |
1806 | */ | |
1807 | static ssize_t pkey_protkey_aes_attr_read(u32 keytype, bool is_xts, char *buf, | |
1808 | loff_t off, size_t count) | |
1809 | { | |
1810 | struct protaeskeytoken protkeytoken; | |
1811 | struct pkey_protkey protkey; | |
1812 | int rc; | |
1813 | ||
1814 | if (off != 0 || count < sizeof(protkeytoken)) | |
1815 | return -EINVAL; | |
1816 | if (is_xts) | |
1817 | if (count < 2 * sizeof(protkeytoken)) | |
1818 | return -EINVAL; | |
1819 | ||
1820 | memset(&protkeytoken, 0, sizeof(protkeytoken)); | |
1821 | protkeytoken.type = TOKTYPE_NON_CCA; | |
1822 | protkeytoken.version = TOKVER_PROTECTED_KEY; | |
1823 | protkeytoken.keytype = keytype; | |
1824 | ||
f370f45c HF |
1825 | protkey.len = sizeof(protkey.protkey); |
1826 | rc = pkey_genprotkey(protkeytoken.keytype, | |
1827 | protkey.protkey, &protkey.len, &protkey.type); | |
d632c047 IF |
1828 | if (rc) |
1829 | return rc; | |
1830 | ||
1831 | protkeytoken.len = protkey.len; | |
1832 | memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); | |
1833 | ||
1834 | memcpy(buf, &protkeytoken, sizeof(protkeytoken)); | |
1835 | ||
1836 | if (is_xts) { | |
f370f45c HF |
1837 | /* xts needs a second protected key, reuse protkey struct */ |
1838 | protkey.len = sizeof(protkey.protkey); | |
1839 | rc = pkey_genprotkey(protkeytoken.keytype, | |
1840 | protkey.protkey, &protkey.len, &protkey.type); | |
d632c047 IF |
1841 | if (rc) |
1842 | return rc; | |
1843 | ||
1844 | protkeytoken.len = protkey.len; | |
1845 | memcpy(&protkeytoken.protkey, &protkey.protkey, protkey.len); | |
1846 | ||
1847 | memcpy(buf + sizeof(protkeytoken), &protkeytoken, | |
1848 | sizeof(protkeytoken)); | |
1849 | ||
1850 | return 2 * sizeof(protkeytoken); | |
1851 | } | |
1852 | ||
1853 | return sizeof(protkeytoken); | |
1854 | } | |
1855 | ||
1856 | static ssize_t protkey_aes_128_read(struct file *filp, | |
1857 | struct kobject *kobj, | |
1858 | struct bin_attribute *attr, | |
1859 | char *buf, loff_t off, | |
1860 | size_t count) | |
1861 | { | |
1862 | return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, | |
1863 | off, count); | |
1864 | } | |
1865 | ||
1866 | static ssize_t protkey_aes_192_read(struct file *filp, | |
1867 | struct kobject *kobj, | |
1868 | struct bin_attribute *attr, | |
1869 | char *buf, loff_t off, | |
1870 | size_t count) | |
1871 | { | |
1872 | return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, | |
1873 | off, count); | |
1874 | } | |
1875 | ||
1876 | static ssize_t protkey_aes_256_read(struct file *filp, | |
1877 | struct kobject *kobj, | |
1878 | struct bin_attribute *attr, | |
1879 | char *buf, loff_t off, | |
1880 | size_t count) | |
1881 | { | |
1882 | return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, | |
1883 | off, count); | |
1884 | } | |
1885 | ||
1886 | static ssize_t protkey_aes_128_xts_read(struct file *filp, | |
1887 | struct kobject *kobj, | |
1888 | struct bin_attribute *attr, | |
1889 | char *buf, loff_t off, | |
1890 | size_t count) | |
1891 | { | |
1892 | return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, | |
1893 | off, count); | |
1894 | } | |
1895 | ||
1896 | static ssize_t protkey_aes_256_xts_read(struct file *filp, | |
1897 | struct kobject *kobj, | |
1898 | struct bin_attribute *attr, | |
1899 | char *buf, loff_t off, | |
1900 | size_t count) | |
1901 | { | |
1902 | return pkey_protkey_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, | |
1903 | off, count); | |
1904 | } | |
1905 | ||
1906 | static BIN_ATTR_RO(protkey_aes_128, sizeof(struct protaeskeytoken)); | |
1907 | static BIN_ATTR_RO(protkey_aes_192, sizeof(struct protaeskeytoken)); | |
1908 | static BIN_ATTR_RO(protkey_aes_256, sizeof(struct protaeskeytoken)); | |
1909 | static BIN_ATTR_RO(protkey_aes_128_xts, 2 * sizeof(struct protaeskeytoken)); | |
1910 | static BIN_ATTR_RO(protkey_aes_256_xts, 2 * sizeof(struct protaeskeytoken)); | |
1911 | ||
1912 | static struct bin_attribute *protkey_attrs[] = { | |
1913 | &bin_attr_protkey_aes_128, | |
1914 | &bin_attr_protkey_aes_192, | |
1915 | &bin_attr_protkey_aes_256, | |
1916 | &bin_attr_protkey_aes_128_xts, | |
1917 | &bin_attr_protkey_aes_256_xts, | |
1918 | NULL | |
1919 | }; | |
1920 | ||
1921 | static struct attribute_group protkey_attr_group = { | |
1922 | .name = "protkey", | |
1923 | .bin_attrs = protkey_attrs, | |
1924 | }; | |
1925 | ||
af504452 IF |
1926 | /* |
1927 | * Sysfs attribute read function for all secure key ccadata binary attributes. | |
1928 | * The implementation can not deal with partial reads, because a new random | |
1929 | * protected key blob is generated with each read. In case of partial reads | |
1930 | * (i.e. off != 0 or count < key blob size) -EINVAL is returned. | |
1931 | */ | |
1932 | static ssize_t pkey_ccadata_aes_attr_read(u32 keytype, bool is_xts, char *buf, | |
1933 | loff_t off, size_t count) | |
1934 | { | |
2004b57c | 1935 | struct pkey_seckey *seckey = (struct pkey_seckey *)buf; |
46a29b03 | 1936 | int rc; |
af504452 IF |
1937 | |
1938 | if (off != 0 || count < sizeof(struct secaeskeytoken)) | |
1939 | return -EINVAL; | |
1940 | if (is_xts) | |
1941 | if (count < 2 * sizeof(struct secaeskeytoken)) | |
1942 | return -EINVAL; | |
1943 | ||
efc598e6 | 1944 | rc = cca_genseckey(-1, -1, keytype, seckey->seckey); |
af504452 IF |
1945 | if (rc) |
1946 | return rc; | |
1947 | ||
1948 | if (is_xts) { | |
efc598e6 HF |
1949 | seckey++; |
1950 | rc = cca_genseckey(-1, -1, keytype, seckey->seckey); | |
af504452 IF |
1951 | if (rc) |
1952 | return rc; | |
1953 | ||
1954 | return 2 * sizeof(struct secaeskeytoken); | |
1955 | } | |
1956 | ||
1957 | return sizeof(struct secaeskeytoken); | |
1958 | } | |
1959 | ||
1960 | static ssize_t ccadata_aes_128_read(struct file *filp, | |
1961 | struct kobject *kobj, | |
1962 | struct bin_attribute *attr, | |
1963 | char *buf, loff_t off, | |
1964 | size_t count) | |
1965 | { | |
1966 | return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, false, buf, | |
1967 | off, count); | |
1968 | } | |
1969 | ||
1970 | static ssize_t ccadata_aes_192_read(struct file *filp, | |
1971 | struct kobject *kobj, | |
1972 | struct bin_attribute *attr, | |
1973 | char *buf, loff_t off, | |
1974 | size_t count) | |
1975 | { | |
1976 | return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_192, false, buf, | |
1977 | off, count); | |
1978 | } | |
1979 | ||
1980 | static ssize_t ccadata_aes_256_read(struct file *filp, | |
1981 | struct kobject *kobj, | |
1982 | struct bin_attribute *attr, | |
1983 | char *buf, loff_t off, | |
1984 | size_t count) | |
1985 | { | |
1986 | return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, false, buf, | |
1987 | off, count); | |
1988 | } | |
1989 | ||
1990 | static ssize_t ccadata_aes_128_xts_read(struct file *filp, | |
1991 | struct kobject *kobj, | |
1992 | struct bin_attribute *attr, | |
1993 | char *buf, loff_t off, | |
1994 | size_t count) | |
1995 | { | |
1996 | return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_128, true, buf, | |
1997 | off, count); | |
1998 | } | |
1999 | ||
2000 | static ssize_t ccadata_aes_256_xts_read(struct file *filp, | |
2001 | struct kobject *kobj, | |
2002 | struct bin_attribute *attr, | |
2003 | char *buf, loff_t off, | |
2004 | size_t count) | |
2005 | { | |
2006 | return pkey_ccadata_aes_attr_read(PKEY_KEYTYPE_AES_256, true, buf, | |
2007 | off, count); | |
2008 | } | |
2009 | ||
2010 | static BIN_ATTR_RO(ccadata_aes_128, sizeof(struct secaeskeytoken)); | |
2011 | static BIN_ATTR_RO(ccadata_aes_192, sizeof(struct secaeskeytoken)); | |
2012 | static BIN_ATTR_RO(ccadata_aes_256, sizeof(struct secaeskeytoken)); | |
2013 | static BIN_ATTR_RO(ccadata_aes_128_xts, 2 * sizeof(struct secaeskeytoken)); | |
2014 | static BIN_ATTR_RO(ccadata_aes_256_xts, 2 * sizeof(struct secaeskeytoken)); | |
2015 | ||
2016 | static struct bin_attribute *ccadata_attrs[] = { | |
2017 | &bin_attr_ccadata_aes_128, | |
2018 | &bin_attr_ccadata_aes_192, | |
2019 | &bin_attr_ccadata_aes_256, | |
2020 | &bin_attr_ccadata_aes_128_xts, | |
2021 | &bin_attr_ccadata_aes_256_xts, | |
2022 | NULL | |
2023 | }; | |
2024 | ||
2025 | static struct attribute_group ccadata_attr_group = { | |
2026 | .name = "ccadata", | |
2027 | .bin_attrs = ccadata_attrs, | |
2028 | }; | |
2029 | ||
f71fee27 IF |
2030 | #define CCACIPHERTOKENSIZE (sizeof(struct cipherkeytoken) + 80) |
2031 | ||
2032 | /* | |
2033 | * Sysfs attribute read function for all secure key ccacipher binary attributes. | |
2034 | * The implementation can not deal with partial reads, because a new random | |
2035 | * secure key blob is generated with each read. In case of partial reads | |
2036 | * (i.e. off != 0 or count < key blob size) -EINVAL is returned. | |
2037 | */ | |
2038 | static ssize_t pkey_ccacipher_aes_attr_read(enum pkey_key_size keybits, | |
2039 | bool is_xts, char *buf, loff_t off, | |
2040 | size_t count) | |
2041 | { | |
55d0a513 | 2042 | size_t keysize = CCACIPHERTOKENSIZE; |
46a29b03 HF |
2043 | u32 nr_apqns, *apqns = NULL; |
2044 | int i, rc, card, dom; | |
f71fee27 IF |
2045 | |
2046 | if (off != 0 || count < CCACIPHERTOKENSIZE) | |
2047 | return -EINVAL; | |
2048 | if (is_xts) | |
2049 | if (count < 2 * CCACIPHERTOKENSIZE) | |
2050 | return -EINVAL; | |
2051 | ||
55d0a513 HF |
2052 | /* build a list of apqns able to generate an cipher key */ |
2053 | rc = cca_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, | |
32ca04bb | 2054 | ZCRYPT_CEX6, 0, 0, 0, 0); |
f71fee27 IF |
2055 | if (rc) |
2056 | return rc; | |
f71fee27 | 2057 | |
55d0a513 HF |
2058 | memset(buf, 0, is_xts ? 2 * keysize : keysize); |
2059 | ||
2060 | /* simple try all apqns from the list */ | |
2061 | for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { | |
2062 | card = apqns[i] >> 16; | |
2063 | dom = apqns[i] & 0xFFFF; | |
2064 | rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); | |
2065 | if (rc == 0) | |
2066 | break; | |
2067 | } | |
c6337c6e HF |
2068 | if (rc) |
2069 | return rc; | |
f71fee27 | 2070 | |
55d0a513 HF |
2071 | if (is_xts) { |
2072 | keysize = CCACIPHERTOKENSIZE; | |
2073 | buf += CCACIPHERTOKENSIZE; | |
2074 | rc = cca_gencipherkey(card, dom, keybits, 0, buf, &keysize); | |
2075 | if (rc == 0) | |
2076 | return 2 * CCACIPHERTOKENSIZE; | |
f71fee27 IF |
2077 | } |
2078 | ||
2079 | return CCACIPHERTOKENSIZE; | |
2080 | } | |
2081 | ||
2082 | static ssize_t ccacipher_aes_128_read(struct file *filp, | |
2083 | struct kobject *kobj, | |
2084 | struct bin_attribute *attr, | |
2085 | char *buf, loff_t off, | |
2086 | size_t count) | |
2087 | { | |
2088 | return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, false, buf, | |
2089 | off, count); | |
2090 | } | |
2091 | ||
2092 | static ssize_t ccacipher_aes_192_read(struct file *filp, | |
2093 | struct kobject *kobj, | |
2094 | struct bin_attribute *attr, | |
2095 | char *buf, loff_t off, | |
2096 | size_t count) | |
2097 | { | |
2098 | return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_192, false, buf, | |
2099 | off, count); | |
2100 | } | |
2101 | ||
2102 | static ssize_t ccacipher_aes_256_read(struct file *filp, | |
2103 | struct kobject *kobj, | |
2104 | struct bin_attribute *attr, | |
2105 | char *buf, loff_t off, | |
2106 | size_t count) | |
2107 | { | |
2108 | return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, false, buf, | |
2109 | off, count); | |
2110 | } | |
2111 | ||
2112 | static ssize_t ccacipher_aes_128_xts_read(struct file *filp, | |
2113 | struct kobject *kobj, | |
2114 | struct bin_attribute *attr, | |
2115 | char *buf, loff_t off, | |
2116 | size_t count) | |
2117 | { | |
2118 | return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_128, true, buf, | |
2119 | off, count); | |
2120 | } | |
2121 | ||
2122 | static ssize_t ccacipher_aes_256_xts_read(struct file *filp, | |
2123 | struct kobject *kobj, | |
2124 | struct bin_attribute *attr, | |
2125 | char *buf, loff_t off, | |
2126 | size_t count) | |
2127 | { | |
2128 | return pkey_ccacipher_aes_attr_read(PKEY_SIZE_AES_256, true, buf, | |
2129 | off, count); | |
2130 | } | |
2131 | ||
2132 | static BIN_ATTR_RO(ccacipher_aes_128, CCACIPHERTOKENSIZE); | |
2133 | static BIN_ATTR_RO(ccacipher_aes_192, CCACIPHERTOKENSIZE); | |
2134 | static BIN_ATTR_RO(ccacipher_aes_256, CCACIPHERTOKENSIZE); | |
2135 | static BIN_ATTR_RO(ccacipher_aes_128_xts, 2 * CCACIPHERTOKENSIZE); | |
2136 | static BIN_ATTR_RO(ccacipher_aes_256_xts, 2 * CCACIPHERTOKENSIZE); | |
2137 | ||
2138 | static struct bin_attribute *ccacipher_attrs[] = { | |
2139 | &bin_attr_ccacipher_aes_128, | |
2140 | &bin_attr_ccacipher_aes_192, | |
2141 | &bin_attr_ccacipher_aes_256, | |
2142 | &bin_attr_ccacipher_aes_128_xts, | |
2143 | &bin_attr_ccacipher_aes_256_xts, | |
2144 | NULL | |
2145 | }; | |
2146 | ||
2147 | static struct attribute_group ccacipher_attr_group = { | |
2148 | .name = "ccacipher", | |
2149 | .bin_attrs = ccacipher_attrs, | |
2150 | }; | |
2151 | ||
55d0a513 HF |
2152 | /* |
2153 | * Sysfs attribute read function for all ep11 aes key binary attributes. | |
2154 | * The implementation can not deal with partial reads, because a new random | |
2155 | * secure key blob is generated with each read. In case of partial reads | |
2156 | * (i.e. off != 0 or count < key blob size) -EINVAL is returned. | |
2157 | * This function and the sysfs attributes using it provide EP11 key blobs | |
2158 | * padded to the upper limit of MAXEP11AESKEYBLOBSIZE which is currently | |
b9352e4b | 2159 | * 336 bytes. |
55d0a513 HF |
2160 | */ |
2161 | static ssize_t pkey_ep11_aes_attr_read(enum pkey_key_size keybits, | |
2162 | bool is_xts, char *buf, loff_t off, | |
2163 | size_t count) | |
2164 | { | |
55d0a513 | 2165 | size_t keysize = MAXEP11AESKEYBLOBSIZE; |
46a29b03 HF |
2166 | u32 nr_apqns, *apqns = NULL; |
2167 | int i, rc, card, dom; | |
55d0a513 HF |
2168 | |
2169 | if (off != 0 || count < MAXEP11AESKEYBLOBSIZE) | |
2170 | return -EINVAL; | |
2171 | if (is_xts) | |
2172 | if (count < 2 * MAXEP11AESKEYBLOBSIZE) | |
2173 | return -EINVAL; | |
2174 | ||
2175 | /* build a list of apqns able to generate an cipher key */ | |
2176 | rc = ep11_findcard2(&apqns, &nr_apqns, 0xFFFF, 0xFFFF, | |
386cb81e HD |
2177 | ZCRYPT_CEX7, |
2178 | ap_is_se_guest() ? EP11_API_V6 : EP11_API_V4, | |
2179 | NULL); | |
55d0a513 HF |
2180 | if (rc) |
2181 | return rc; | |
2182 | ||
2183 | memset(buf, 0, is_xts ? 2 * keysize : keysize); | |
2184 | ||
2185 | /* simple try all apqns from the list */ | |
2186 | for (i = 0, rc = -ENODEV; i < nr_apqns; i++) { | |
2187 | card = apqns[i] >> 16; | |
2188 | dom = apqns[i] & 0xFFFF; | |
fb249ce7 | 2189 | rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize, |
b9352e4b | 2190 | PKEY_TYPE_EP11_AES); |
55d0a513 HF |
2191 | if (rc == 0) |
2192 | break; | |
2193 | } | |
2194 | if (rc) | |
2195 | return rc; | |
2196 | ||
2197 | if (is_xts) { | |
2198 | keysize = MAXEP11AESKEYBLOBSIZE; | |
2199 | buf += MAXEP11AESKEYBLOBSIZE; | |
fb249ce7 | 2200 | rc = ep11_genaeskey(card, dom, keybits, 0, buf, &keysize, |
b9352e4b | 2201 | PKEY_TYPE_EP11_AES); |
55d0a513 HF |
2202 | if (rc == 0) |
2203 | return 2 * MAXEP11AESKEYBLOBSIZE; | |
2204 | } | |
2205 | ||
2206 | return MAXEP11AESKEYBLOBSIZE; | |
2207 | } | |
2208 | ||
2209 | static ssize_t ep11_aes_128_read(struct file *filp, | |
2210 | struct kobject *kobj, | |
2211 | struct bin_attribute *attr, | |
2212 | char *buf, loff_t off, | |
2213 | size_t count) | |
2214 | { | |
2215 | return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, false, buf, | |
2216 | off, count); | |
2217 | } | |
2218 | ||
2219 | static ssize_t ep11_aes_192_read(struct file *filp, | |
2220 | struct kobject *kobj, | |
2221 | struct bin_attribute *attr, | |
2222 | char *buf, loff_t off, | |
2223 | size_t count) | |
2224 | { | |
2225 | return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_192, false, buf, | |
2226 | off, count); | |
2227 | } | |
2228 | ||
2229 | static ssize_t ep11_aes_256_read(struct file *filp, | |
2230 | struct kobject *kobj, | |
2231 | struct bin_attribute *attr, | |
2232 | char *buf, loff_t off, | |
2233 | size_t count) | |
2234 | { | |
2235 | return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, false, buf, | |
2236 | off, count); | |
2237 | } | |
2238 | ||
2239 | static ssize_t ep11_aes_128_xts_read(struct file *filp, | |
2240 | struct kobject *kobj, | |
2241 | struct bin_attribute *attr, | |
2242 | char *buf, loff_t off, | |
2243 | size_t count) | |
2244 | { | |
2245 | return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_128, true, buf, | |
2246 | off, count); | |
2247 | } | |
2248 | ||
2249 | static ssize_t ep11_aes_256_xts_read(struct file *filp, | |
2250 | struct kobject *kobj, | |
2251 | struct bin_attribute *attr, | |
2252 | char *buf, loff_t off, | |
2253 | size_t count) | |
2254 | { | |
2255 | return pkey_ep11_aes_attr_read(PKEY_SIZE_AES_256, true, buf, | |
2256 | off, count); | |
2257 | } | |
2258 | ||
2259 | static BIN_ATTR_RO(ep11_aes_128, MAXEP11AESKEYBLOBSIZE); | |
2260 | static BIN_ATTR_RO(ep11_aes_192, MAXEP11AESKEYBLOBSIZE); | |
2261 | static BIN_ATTR_RO(ep11_aes_256, MAXEP11AESKEYBLOBSIZE); | |
2262 | static BIN_ATTR_RO(ep11_aes_128_xts, 2 * MAXEP11AESKEYBLOBSIZE); | |
2263 | static BIN_ATTR_RO(ep11_aes_256_xts, 2 * MAXEP11AESKEYBLOBSIZE); | |
2264 | ||
2265 | static struct bin_attribute *ep11_attrs[] = { | |
2266 | &bin_attr_ep11_aes_128, | |
2267 | &bin_attr_ep11_aes_192, | |
2268 | &bin_attr_ep11_aes_256, | |
2269 | &bin_attr_ep11_aes_128_xts, | |
2270 | &bin_attr_ep11_aes_256_xts, | |
2271 | NULL | |
2272 | }; | |
2273 | ||
2274 | static struct attribute_group ep11_attr_group = { | |
2275 | .name = "ep11", | |
2276 | .bin_attrs = ep11_attrs, | |
2277 | }; | |
2278 | ||
d632c047 IF |
2279 | static const struct attribute_group *pkey_attr_groups[] = { |
2280 | &protkey_attr_group, | |
af504452 | 2281 | &ccadata_attr_group, |
f71fee27 | 2282 | &ccacipher_attr_group, |
55d0a513 | 2283 | &ep11_attr_group, |
d632c047 IF |
2284 | NULL, |
2285 | }; | |
2286 | ||
e80d4af0 HF |
2287 | static const struct file_operations pkey_fops = { |
2288 | .owner = THIS_MODULE, | |
2289 | .open = nonseekable_open, | |
2290 | .llseek = no_llseek, | |
2291 | .unlocked_ioctl = pkey_unlocked_ioctl, | |
2292 | }; | |
2293 | ||
2294 | static struct miscdevice pkey_dev = { | |
2295 | .name = "pkey", | |
2296 | .minor = MISC_DYNAMIC_MINOR, | |
2297 | .mode = 0666, | |
2298 | .fops = &pkey_fops, | |
d632c047 | 2299 | .groups = pkey_attr_groups, |
e80d4af0 HF |
2300 | }; |
2301 | ||
2302 | /* | |
2303 | * Module init | |
2304 | */ | |
cb4ef3c2 | 2305 | static int __init pkey_init(void) |
e80d4af0 | 2306 | { |
5b35047e | 2307 | cpacf_mask_t func_mask; |
e80d4af0 | 2308 | |
f822ad2c HF |
2309 | /* |
2310 | * The pckmo instruction should be available - even if we don't | |
2311 | * actually invoke it. This instruction comes with MSA 3 which | |
2312 | * is also the minimum level for the kmc instructions which | |
2313 | * are able to work with protected keys. | |
2314 | */ | |
5b35047e | 2315 | if (!cpacf_query(CPACF_PCKMO, &func_mask)) |
58443b67 | 2316 | return -ENODEV; |
e80d4af0 | 2317 | |
cb26b9ff | 2318 | /* check for kmc instructions available */ |
5b35047e | 2319 | if (!cpacf_query(CPACF_KMC, &func_mask)) |
58443b67 | 2320 | return -ENODEV; |
5b35047e HF |
2321 | if (!cpacf_test_func(&func_mask, CPACF_KMC_PAES_128) || |
2322 | !cpacf_test_func(&func_mask, CPACF_KMC_PAES_192) || | |
2323 | !cpacf_test_func(&func_mask, CPACF_KMC_PAES_256)) | |
58443b67 | 2324 | return -ENODEV; |
cb26b9ff | 2325 | |
e80d4af0 HF |
2326 | pkey_debug_init(); |
2327 | ||
2328 | return misc_register(&pkey_dev); | |
2329 | } | |
2330 | ||
2331 | /* | |
2332 | * Module exit | |
2333 | */ | |
2334 | static void __exit pkey_exit(void) | |
2335 | { | |
2336 | misc_deregister(&pkey_dev); | |
e80d4af0 HF |
2337 | pkey_debug_exit(); |
2338 | } | |
2339 | ||
0a5f9b38 | 2340 | module_cpu_feature_match(S390_CPU_FEATURE_MSA, pkey_init); |
e80d4af0 | 2341 | module_exit(pkey_exit); |