File Index
Files and directories
Sign in
FILE

pkey_api.c

File preview with syntax highlighting.

linux-6.19.14/drivers/s390/crypto/pkey_api.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 *  pkey device driver
  4 *
  5 *  Copyright IBM Corp. 2017, 2023
  6 *
  7 *  Author(s): Harald Freudenberger
  8 */
  9
 10#define pr_fmt(fmt) "pkey: " fmt
 11
 12#include <linux/init.h>
 13#include <linux/miscdevice.h>
 14#include <linux/export.h>
 15#include <linux/slab.h>
 16
 17#include "zcrypt_api.h"
 18#include "zcrypt_ccamisc.h"
 19
 20#include "pkey_base.h"
 21
 22/*
 23 * Helper functions
 24 */
 25static int key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
 26		       const u8 *key, size_t keylen,
 27		       u8 *protkey, u32 *protkeylen, u32 *protkeytype,
 28		       u32 xflags)
 29{
 30	int rc;
 31
 32	/* try the direct way */
 33	rc = pkey_handler_key_to_protkey(apqns, nr_apqns,
 34					 key, keylen,
 35					 protkey, protkeylen,
 36					 protkeytype, xflags);
 37
 38	/* if this did not work, try the slowpath way */
 39	if (rc == -ENODEV) {
 40		rc = pkey_handler_slowpath_key_to_protkey(apqns, nr_apqns,
 41							  key, keylen,
 42							  protkey, protkeylen,
 43							  protkeytype, xflags);
 44		if (rc)
 45			rc = -ENODEV;
 46	}
 47
 48	pr_debug("rc=%d\n", rc);
 49	return rc;
 50}
 51
 52/*
 53 * In-Kernel function: Transform a key blob (of any type) into a protected key
 54 */
 55int pkey_key2protkey(const u8 *key, u32 keylen,
 56		     u8 *protkey, u32 *protkeylen, u32 *protkeytype, u32 xflags)
 57{
 58	int rc;
 59
 60	rc = key2protkey(NULL, 0, key, keylen,
 61			 protkey, protkeylen, protkeytype, xflags);
 62	if (rc == -ENODEV) {
 63		pkey_handler_request_modules();
 64		rc = key2protkey(NULL, 0, key, keylen,
 65				 protkey, protkeylen, protkeytype, xflags);
 66	}
 67
 68	return rc;
 69}
 70EXPORT_SYMBOL(pkey_key2protkey);
 71
 72/*
 73 * Ioctl functions
 74 */
 75
 76static void *_copy_key_from_user(void __user *ukey, size_t keylen)
 77{
 78	if (!ukey || keylen < MINKEYBLOBBUFSIZE || keylen > KEYBLOBBUFSIZE)
 79		return ERR_PTR(-EINVAL);
 80
 81	return memdup_user(ukey, keylen);
 82}
 83
 84static void *_copy_apqns_from_user(void __user *uapqns, size_t nr_apqns)
 85{
 86	if (!uapqns || nr_apqns == 0)
 87		return NULL;
 88
 89	return memdup_array_user(uapqns, nr_apqns, sizeof(struct pkey_apqn));
 90}
 91
 92static int pkey_ioctl_genseck(struct pkey_genseck __user *ugs)
 93{
 94	struct pkey_genseck kgs;
 95	struct pkey_apqn apqn;
 96	u32 keybuflen;
 97	int rc;
 98
 99	if (copy_from_user(&kgs, ugs, sizeof(kgs)))
100		return -EFAULT;
101
102	apqn.card = kgs.cardnr;
103	apqn.domain = kgs.domain;
104	keybuflen = sizeof(kgs.seckey.seckey);
105	rc = pkey_handler_gen_key(&apqn, 1,
106				  kgs.keytype, PKEY_TYPE_CCA_DATA, 0, 0,
107				  kgs.seckey.seckey, &keybuflen, NULL, 0);
108	pr_debug("gen_key()=%d\n", rc);
109	if (!rc && copy_to_user(ugs, &kgs, sizeof(kgs)))
110		rc = -EFAULT;
111	memzero_explicit(&kgs, sizeof(kgs));
112
113	return rc;
114}
115
116static int pkey_ioctl_clr2seck(struct pkey_clr2seck __user *ucs)
117{
118	struct pkey_clr2seck kcs;
119	struct pkey_apqn apqn;
120	u32 keybuflen;
121	int rc;
122
123	if (copy_from_user(&kcs, ucs, sizeof(kcs)))
124		return -EFAULT;
125
126	apqn.card = kcs.cardnr;
127	apqn.domain = kcs.domain;
128	keybuflen = sizeof(kcs.seckey.seckey);
129	rc = pkey_handler_clr_to_key(&apqn, 1,
130				     kcs.keytype, PKEY_TYPE_CCA_DATA, 0, 0,
131				     kcs.clrkey.clrkey,
132				     pkey_keytype_aes_to_size(kcs.keytype),
133				     kcs.seckey.seckey, &keybuflen, NULL, 0);
134	pr_debug("clr_to_key()=%d\n", rc);
135	if (!rc && copy_to_user(ucs, &kcs, sizeof(kcs)))
136		rc = -EFAULT;
137	memzero_explicit(&kcs, sizeof(kcs));
138
139	return rc;
140}
141
142static int pkey_ioctl_sec2protk(struct pkey_sec2protk __user *usp)
143{
144	struct pkey_sec2protk ksp;
145	struct pkey_apqn apqn;
146	int rc;
147
148	if (copy_from_user(&ksp, usp, sizeof(ksp)))
149		return -EFAULT;
150
151	apqn.card = ksp.cardnr;
152	apqn.domain = ksp.domain;
153	ksp.protkey.len = sizeof(ksp.protkey.protkey);
154	rc = pkey_handler_key_to_protkey(&apqn, 1,
155					 ksp.seckey.seckey,
156					 sizeof(ksp.seckey.seckey),
157					 ksp.protkey.protkey,
158					 &ksp.protkey.len, &ksp.protkey.type,
159					 0);
160	pr_debug("key_to_protkey()=%d\n", rc);
161	if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
162		rc = -EFAULT;
163	memzero_explicit(&ksp, sizeof(ksp));
164
165	return rc;
166}
167
168static int pkey_ioctl_clr2protk(struct pkey_clr2protk __user *ucp)
169{
170	struct pkey_clr2protk kcp;
171	struct clearkeytoken *t;
172	u32 keylen;
173	u8 *tmpbuf;
174	int rc;
175
176	if (copy_from_user(&kcp, ucp, sizeof(kcp)))
177		return -EFAULT;
178
179	/* build a 'clear key token' from the clear key value */
180	keylen = pkey_keytype_aes_to_size(kcp.keytype);
181	if (!keylen) {
182		PKEY_DBF_ERR("%s unknown/unsupported keytype %u\n",
183			     __func__, kcp.keytype);
184		memzero_explicit(&kcp, sizeof(kcp));
185		return -EINVAL;
186	}
187	tmpbuf = kzalloc(sizeof(*t) + keylen, GFP_KERNEL);
188	if (!tmpbuf) {
189		memzero_explicit(&kcp, sizeof(kcp));
190		return -ENOMEM;
191	}
192	t = (struct clearkeytoken *)tmpbuf;
193	t->type = TOKTYPE_NON_CCA;
194	t->version = TOKVER_CLEAR_KEY;
195	t->keytype = (keylen - 8) >> 3;
196	t->len = keylen;
197	memcpy(t->clearkey, kcp.clrkey.clrkey, keylen);
198	kcp.protkey.len = sizeof(kcp.protkey.protkey);
199
200	rc = key2protkey(NULL, 0,
201			 tmpbuf, sizeof(*t) + keylen,
202			 kcp.protkey.protkey,
203			 &kcp.protkey.len, &kcp.protkey.type, 0);
204	pr_debug("key2protkey()=%d\n", rc);
205
206	kfree_sensitive(tmpbuf);
207
208	if (!rc && copy_to_user(ucp, &kcp, sizeof(kcp)))
209		rc = -EFAULT;
210	memzero_explicit(&kcp, sizeof(kcp));
211
212	return rc;
213}
214
215static int pkey_ioctl_findcard(struct pkey_findcard __user *ufc)
216{
217	struct pkey_findcard kfc;
218	struct pkey_apqn *apqns;
219	size_t nr_apqns;
220	int rc;
221
222	if (copy_from_user(&kfc, ufc, sizeof(kfc)))
223		return -EFAULT;
224
225	nr_apqns = MAXAPQNSINLIST;
226	apqns = kmalloc_array(nr_apqns, sizeof(struct pkey_apqn), GFP_KERNEL);
227	if (!apqns)
228		return -ENOMEM;
229
230	rc = pkey_handler_apqns_for_key(kfc.seckey.seckey,
231					sizeof(kfc.seckey.seckey),
232					PKEY_FLAGS_MATCH_CUR_MKVP,
233					apqns, &nr_apqns, 0);
234	if (rc == -ENODEV)
235		rc = pkey_handler_apqns_for_key(kfc.seckey.seckey,
236						sizeof(kfc.seckey.seckey),
237						PKEY_FLAGS_MATCH_ALT_MKVP,
238						apqns, &nr_apqns, 0);
239	pr_debug("apqns_for_key()=%d\n", rc);
240	if (rc) {
241		kfree(apqns);
242		return rc;
243	}
244	kfc.cardnr = apqns[0].card;
245	kfc.domain = apqns[0].domain;
246	kfree(apqns);
247	if (copy_to_user(ufc, &kfc, sizeof(kfc)))
248		return -EFAULT;
249
250	return 0;
251}
252
253static int pkey_ioctl_skey2pkey(struct pkey_skey2pkey __user *usp)
254{
255	struct pkey_skey2pkey ksp;
256	int rc;
257
258	if (copy_from_user(&ksp, usp, sizeof(ksp)))
259		return -EFAULT;
260
261	ksp.protkey.len = sizeof(ksp.protkey.protkey);
262	rc = pkey_handler_key_to_protkey(NULL, 0,
263					 ksp.seckey.seckey,
264					 sizeof(ksp.seckey.seckey),
265					 ksp.protkey.protkey,
266					 &ksp.protkey.len,
267					 &ksp.protkey.type, 0);
268	pr_debug("key_to_protkey()=%d\n", rc);
269	if (!rc && copy_to_user(usp, &ksp, sizeof(ksp)))
270		rc = -EFAULT;
271	memzero_explicit(&ksp, sizeof(ksp));
272
273	return rc;
274}
275
276static int pkey_ioctl_verifykey(struct pkey_verifykey __user *uvk)
277{
278	u32 keytype, keybitsize, flags;
279	struct pkey_verifykey kvk;
280	int rc;
281
282	if (copy_from_user(&kvk, uvk, sizeof(kvk)))
283		return -EFAULT;
284
285	kvk.cardnr = 0xFFFF;
286	kvk.domain = 0xFFFF;
287	rc = pkey_handler_verify_key(kvk.seckey.seckey,
288				     sizeof(kvk.seckey.seckey),
289				     &kvk.cardnr, &kvk.domain,
290				     &keytype, &keybitsize, &flags, 0);
291	pr_debug("verify_key()=%d\n", rc);
292	if (!rc && keytype != PKEY_TYPE_CCA_DATA)
293		rc = -EINVAL;
294	kvk.attributes = PKEY_VERIFY_ATTR_AES;
295	kvk.keysize = (u16)keybitsize;
296	if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
297		kvk.attributes |= PKEY_VERIFY_ATTR_OLD_MKVP;
298	if (!rc && copy_to_user(uvk, &kvk, sizeof(kvk)))
299		rc = -EFAULT;
300	memzero_explicit(&kvk, sizeof(kvk));
301
302	return rc;
303}
304
305static int pkey_ioctl_genprotk(struct pkey_genprotk __user *ugp)
306{
307	struct pkey_genprotk kgp;
308	int rc;
309
310	if (copy_from_user(&kgp, ugp, sizeof(kgp)))
311		return -EFAULT;
312
313	kgp.protkey.len = sizeof(kgp.protkey.protkey);
314	rc = pkey_handler_gen_key(NULL, 0, kgp.keytype,
315				  PKEY_TYPE_PROTKEY, 0, 0,
316				  kgp.protkey.protkey, &kgp.protkey.len,
317				  &kgp.protkey.type, 0);
318	pr_debug("gen_key()=%d\n", rc);
319	if (!rc && copy_to_user(ugp, &kgp, sizeof(kgp)))
320		rc = -EFAULT;
321	memzero_explicit(&kgp, sizeof(kgp));
322
323	return rc;
324}
325
326static int pkey_ioctl_verifyprotk(struct pkey_verifyprotk __user *uvp)
327{
328	struct pkey_verifyprotk kvp;
329	struct protaeskeytoken *t;
330	u32 keytype;
331	u8 *tmpbuf;
332	int rc;
333
334	if (copy_from_user(&kvp, uvp, sizeof(kvp)))
335		return -EFAULT;
336
337	keytype = pkey_aes_bitsize_to_keytype(8 * kvp.protkey.len);
338	if (!keytype) {
339		PKEY_DBF_ERR("%s unknown/unsupported protkey length %u\n",
340			     __func__, kvp.protkey.len);
341		memzero_explicit(&kvp, sizeof(kvp));
342		return -EINVAL;
343	}
344
345	/* build a 'protected key token' from the raw protected key */
346	tmpbuf = kzalloc(sizeof(*t), GFP_KERNEL);
347	if (!tmpbuf) {
348		memzero_explicit(&kvp, sizeof(kvp));
349		return -ENOMEM;
350	}
351	t = (struct protaeskeytoken *)tmpbuf;
352	t->type = TOKTYPE_NON_CCA;
353	t->version = TOKVER_PROTECTED_KEY;
354	t->keytype = keytype;
355	t->len = kvp.protkey.len;
356	memcpy(t->protkey, kvp.protkey.protkey, kvp.protkey.len);
357
358	rc = pkey_handler_verify_key(tmpbuf, sizeof(*t),
359				     NULL, NULL, NULL, NULL, NULL, 0);
360	pr_debug("verify_key()=%d\n", rc);
361
362	kfree_sensitive(tmpbuf);
363	memzero_explicit(&kvp, sizeof(kvp));
364
365	return rc;
366}
367
368static int pkey_ioctl_kblob2protk(struct pkey_kblob2pkey __user *utp)
369{
370	struct pkey_kblob2pkey ktp;
371	u8 *kkey;
372	int rc;
373
374	if (copy_from_user(&ktp, utp, sizeof(ktp)))
375		return -EFAULT;
376	kkey = _copy_key_from_user(ktp.key, ktp.keylen);
377	if (IS_ERR(kkey))
378		return PTR_ERR(kkey);
379	ktp.protkey.len = sizeof(ktp.protkey.protkey);
380	rc = key2protkey(NULL, 0, kkey, ktp.keylen,
381			 ktp.protkey.protkey, &ktp.protkey.len,
382			 &ktp.protkey.type, 0);
383	pr_debug("key2protkey()=%d\n", rc);
384	kfree_sensitive(kkey);
385	if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
386		rc = -EFAULT;
387	memzero_explicit(&ktp, sizeof(ktp));
388
389	return rc;
390}
391
392static int pkey_ioctl_genseck2(struct pkey_genseck2 __user *ugs)
393{
394	u32 klen = KEYBLOBBUFSIZE;
395	struct pkey_genseck2 kgs;
396	struct pkey_apqn *apqns;
397	u8 *kkey;
398	int rc;
399	u32 u;
400
401	if (copy_from_user(&kgs, ugs, sizeof(kgs)))
402		return -EFAULT;
403	u = pkey_aes_bitsize_to_keytype(kgs.size);
404	if (!u) {
405		PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
406			     __func__, kgs.size);
407		return -EINVAL;
408	}
409	apqns = _copy_apqns_from_user(kgs.apqns, kgs.apqn_entries);
410	if (IS_ERR(apqns))
411		return PTR_ERR(apqns);
412	kkey = kzalloc(klen, GFP_KERNEL);
413	if (!kkey) {
414		kfree(apqns);
415		return -ENOMEM;
416	}
417	rc = pkey_handler_gen_key(apqns, kgs.apqn_entries,
418				  u, kgs.type, kgs.size, kgs.keygenflags,
419				  kkey, &klen, NULL, 0);
420	pr_debug("gen_key()=%d\n", rc);
421	kfree(apqns);
422	if (rc) {
423		kfree_sensitive(kkey);
424		return rc;
425	}
426	if (kgs.key) {
427		if (kgs.keylen < klen) {
428			kfree_sensitive(kkey);
429			return -EINVAL;
430		}
431		if (copy_to_user(kgs.key, kkey, klen)) {
432			kfree_sensitive(kkey);
433			return -EFAULT;
434		}
435	}
436	kgs.keylen = klen;
437	if (copy_to_user(ugs, &kgs, sizeof(kgs)))
438		rc = -EFAULT;
439	kfree_sensitive(kkey);
440
441	return rc;
442}
443
444static int pkey_ioctl_clr2seck2(struct pkey_clr2seck2 __user *ucs)
445{
446	u32 klen = KEYBLOBBUFSIZE;
447	struct pkey_clr2seck2 kcs;
448	struct pkey_apqn *apqns;
449	u8 *kkey;
450	int rc;
451	u32 u;
452
453	if (copy_from_user(&kcs, ucs, sizeof(kcs)))
454		return -EFAULT;
455	u = pkey_aes_bitsize_to_keytype(kcs.size);
456	if (!u) {
457		PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
458			     __func__, kcs.size);
459		memzero_explicit(&kcs, sizeof(kcs));
460		return -EINVAL;
461	}
462	apqns = _copy_apqns_from_user(kcs.apqns, kcs.apqn_entries);
463	if (IS_ERR(apqns)) {
464		memzero_explicit(&kcs, sizeof(kcs));
465		return PTR_ERR(apqns);
466	}
467	kkey = kzalloc(klen, GFP_KERNEL);
468	if (!kkey) {
469		kfree(apqns);
470		memzero_explicit(&kcs, sizeof(kcs));
471		return -ENOMEM;
472	}
473	rc = pkey_handler_clr_to_key(apqns, kcs.apqn_entries,
474				     u, kcs.type, kcs.size, kcs.keygenflags,
475				     kcs.clrkey.clrkey, kcs.size / 8,
476				     kkey, &klen, NULL, 0);
477	pr_debug("clr_to_key()=%d\n", rc);
478	kfree(apqns);
479	if (rc) {
480		kfree_sensitive(kkey);
481		memzero_explicit(&kcs, sizeof(kcs));
482		return rc;
483	}
484	if (kcs.key) {
485		if (kcs.keylen < klen) {
486			kfree_sensitive(kkey);
487			memzero_explicit(&kcs, sizeof(kcs));
488			return -EINVAL;
489		}
490		if (copy_to_user(kcs.key, kkey, klen)) {
491			kfree_sensitive(kkey);
492			memzero_explicit(&kcs, sizeof(kcs));
493			return -EFAULT;
494		}
495	}
496	kcs.keylen = klen;
497	if (copy_to_user(ucs, &kcs, sizeof(kcs)))
498		rc = -EFAULT;
499	memzero_explicit(&kcs, sizeof(kcs));
500	kfree_sensitive(kkey);
501
502	return rc;
503}
504
505static int pkey_ioctl_verifykey2(struct pkey_verifykey2 __user *uvk)
506{
507	struct pkey_verifykey2 kvk;
508	u8 *kkey;
509	int rc;
510
511	if (copy_from_user(&kvk, uvk, sizeof(kvk)))
512		return -EFAULT;
513	kkey = _copy_key_from_user(kvk.key, kvk.keylen);
514	if (IS_ERR(kkey))
515		return PTR_ERR(kkey);
516
517	rc = pkey_handler_verify_key(kkey, kvk.keylen,
518				     &kvk.cardnr, &kvk.domain,
519				     &kvk.type, &kvk.size, &kvk.flags, 0);
520	pr_debug("verify_key()=%d\n", rc);
521
522	kfree_sensitive(kkey);
523	if (!rc && copy_to_user(uvk, &kvk, sizeof(kvk)))
524		return -EFAULT;
525
526	return rc;
527}
528
529static int pkey_ioctl_kblob2protk2(struct pkey_kblob2pkey2 __user *utp)
530{
531	struct pkey_apqn *apqns = NULL;
532	struct pkey_kblob2pkey2 ktp;
533	u8 *kkey;
534	int rc;
535
536	if (copy_from_user(&ktp, utp, sizeof(ktp)))
537		return -EFAULT;
538	apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
539	if (IS_ERR(apqns))
540		return PTR_ERR(apqns);
541	kkey = _copy_key_from_user(ktp.key, ktp.keylen);
542	if (IS_ERR(kkey)) {
543		kfree(apqns);
544		return PTR_ERR(kkey);
545	}
546	ktp.protkey.len = sizeof(ktp.protkey.protkey);
547	rc = key2protkey(apqns, ktp.apqn_entries, kkey, ktp.keylen,
548			 ktp.protkey.protkey, &ktp.protkey.len,
549			 &ktp.protkey.type, 0);
550	pr_debug("key2protkey()=%d\n", rc);
551	kfree(apqns);
552	kfree_sensitive(kkey);
553	if (!rc && copy_to_user(utp, &ktp, sizeof(ktp)))
554		rc = -EFAULT;
555	memzero_explicit(&ktp, sizeof(ktp));
556
557	return rc;
558}
559
560static int pkey_ioctl_apqns4k(struct pkey_apqns4key __user *uak)
561{
562	struct pkey_apqn *apqns = NULL;
563	struct pkey_apqns4key kak;
564	size_t nr_apqns, len;
565	u8 *kkey;
566	int rc;
567
568	if (copy_from_user(&kak, uak, sizeof(kak)))
569		return -EFAULT;
570	nr_apqns = kak.apqn_entries;
571	if (nr_apqns) {
572		apqns = kmalloc_array(nr_apqns,
573				      sizeof(struct pkey_apqn),
574				      GFP_KERNEL);
575		if (!apqns)
576			return -ENOMEM;
577	}
578	kkey = _copy_key_from_user(kak.key, kak.keylen);
579	if (IS_ERR(kkey)) {
580		kfree(apqns);
581		return PTR_ERR(kkey);
582	}
583	rc = pkey_handler_apqns_for_key(kkey, kak.keylen, kak.flags,
584					apqns, &nr_apqns, 0);
585	pr_debug("apqns_for_key()=%d\n", rc);
586	kfree_sensitive(kkey);
587	if (rc && rc != -ENOSPC) {
588		kfree(apqns);
589		return rc;
590	}
591	if (!rc && kak.apqns) {
592		if (nr_apqns > kak.apqn_entries) {
593			kfree(apqns);
594			return -EINVAL;
595		}
596		len = nr_apqns * sizeof(struct pkey_apqn);
597		if (len) {
598			if (copy_to_user(kak.apqns, apqns, len)) {
599				kfree(apqns);
600				return -EFAULT;
601			}
602		}
603	}
604	kak.apqn_entries = nr_apqns;
605	if (copy_to_user(uak, &kak, sizeof(kak)))
606		rc = -EFAULT;
607	kfree(apqns);
608
609	return rc;
610}
611
612static int pkey_ioctl_apqns4kt(struct pkey_apqns4keytype __user *uat)
613{
614	struct pkey_apqn *apqns = NULL;
615	struct pkey_apqns4keytype kat;
616	size_t nr_apqns, len;
617	int rc;
618
619	if (copy_from_user(&kat, uat, sizeof(kat)))
620		return -EFAULT;
621	nr_apqns = kat.apqn_entries;
622	if (nr_apqns) {
623		apqns = kmalloc_array(nr_apqns,
624				      sizeof(struct pkey_apqn),
625				      GFP_KERNEL);
626		if (!apqns)
627			return -ENOMEM;
628	}
629	rc = pkey_handler_apqns_for_keytype(kat.type,
630					    kat.cur_mkvp, kat.alt_mkvp,
631					    kat.flags, apqns, &nr_apqns, 0);
632	pr_debug("apqns_for_keytype()=%d\n", rc);
633	if (rc && rc != -ENOSPC) {
634		kfree(apqns);
635		return rc;
636	}
637	if (!rc && kat.apqns) {
638		if (nr_apqns > kat.apqn_entries) {
639			kfree(apqns);
640			return -EINVAL;
641		}
642		len = nr_apqns * sizeof(struct pkey_apqn);
643		if (len) {
644			if (copy_to_user(kat.apqns, apqns, len)) {
645				kfree(apqns);
646				return -EFAULT;
647			}
648		}
649	}
650	kat.apqn_entries = nr_apqns;
651	if (copy_to_user(uat, &kat, sizeof(kat)))
652		rc = -EFAULT;
653	kfree(apqns);
654
655	return rc;
656}
657
658static int pkey_ioctl_kblob2protk3(struct pkey_kblob2pkey3 __user *utp)
659{
660	u32 protkeylen = PROTKEYBLOBBUFSIZE;
661	struct pkey_apqn *apqns = NULL;
662	struct pkey_kblob2pkey3 ktp;
663	u8 *kkey, *protkey;
664	int rc;
665
666	if (copy_from_user(&ktp, utp, sizeof(ktp)))
667		return -EFAULT;
668	apqns = _copy_apqns_from_user(ktp.apqns, ktp.apqn_entries);
669	if (IS_ERR(apqns))
670		return PTR_ERR(apqns);
671	kkey = _copy_key_from_user(ktp.key, ktp.keylen);
672	if (IS_ERR(kkey)) {
673		kfree(apqns);
674		return PTR_ERR(kkey);
675	}
676	protkey = kmalloc(protkeylen, GFP_KERNEL);
677	if (!protkey) {
678		kfree(apqns);
679		kfree_sensitive(kkey);
680		return -ENOMEM;
681	}
682	rc = key2protkey(apqns, ktp.apqn_entries, kkey, ktp.keylen,
683			 protkey, &protkeylen, &ktp.pkeytype, 0);
684	pr_debug("key2protkey()=%d\n", rc);
685	kfree(apqns);
686	kfree_sensitive(kkey);
687	if (rc) {
688		kfree_sensitive(protkey);
689		return rc;
690	}
691	if (ktp.pkey && ktp.pkeylen) {
692		if (protkeylen > ktp.pkeylen) {
693			kfree_sensitive(protkey);
694			return -EINVAL;
695		}
696		if (copy_to_user(ktp.pkey, protkey, protkeylen)) {
697			kfree_sensitive(protkey);
698			return -EFAULT;
699		}
700	}
701	kfree_sensitive(protkey);
702	ktp.pkeylen = protkeylen;
703	if (copy_to_user(utp, &ktp, sizeof(ktp)))
704		return -EFAULT;
705
706	return 0;
707}
708
709static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd,
710				unsigned long arg)
711{
712	int rc;
713
714	switch (cmd) {
715	case PKEY_GENSECK:
716		rc = pkey_ioctl_genseck((struct pkey_genseck __user *)arg);
717		break;
718	case PKEY_CLR2SECK:
719		rc = pkey_ioctl_clr2seck((struct pkey_clr2seck __user *)arg);
720		break;
721	case PKEY_SEC2PROTK:
722		rc = pkey_ioctl_sec2protk((struct pkey_sec2protk __user *)arg);
723		break;
724	case PKEY_CLR2PROTK:
725		rc = pkey_ioctl_clr2protk((struct pkey_clr2protk __user *)arg);
726		break;
727	case PKEY_FINDCARD:
728		rc = pkey_ioctl_findcard((struct pkey_findcard __user *)arg);
729		break;
730	case PKEY_SKEY2PKEY:
731		rc = pkey_ioctl_skey2pkey((struct pkey_skey2pkey __user *)arg);
732		break;
733	case PKEY_VERIFYKEY:
734		rc = pkey_ioctl_verifykey((struct pkey_verifykey __user *)arg);
735		break;
736	case PKEY_GENPROTK:
737		rc = pkey_ioctl_genprotk((struct pkey_genprotk __user *)arg);
738		break;
739	case PKEY_VERIFYPROTK:
740		rc = pkey_ioctl_verifyprotk((struct pkey_verifyprotk __user *)arg);
741		break;
742	case PKEY_KBLOB2PROTK:
743		rc = pkey_ioctl_kblob2protk((struct pkey_kblob2pkey __user *)arg);
744		break;
745	case PKEY_GENSECK2:
746		rc = pkey_ioctl_genseck2((struct pkey_genseck2 __user *)arg);
747		break;
748	case PKEY_CLR2SECK2:
749		rc = pkey_ioctl_clr2seck2((struct pkey_clr2seck2 __user *)arg);
750		break;
751	case PKEY_VERIFYKEY2:
752		rc = pkey_ioctl_verifykey2((struct pkey_verifykey2 __user *)arg);
753		break;
754	case PKEY_KBLOB2PROTK2:
755		rc = pkey_ioctl_kblob2protk2((struct pkey_kblob2pkey2 __user *)arg);
756		break;
757	case PKEY_APQNS4K:
758		rc = pkey_ioctl_apqns4k((struct pkey_apqns4key __user *)arg);
759		break;
760	case PKEY_APQNS4KT:
761		rc = pkey_ioctl_apqns4kt((struct pkey_apqns4keytype __user *)arg);
762		break;
763	case PKEY_KBLOB2PROTK3:
764		rc = pkey_ioctl_kblob2protk3((struct pkey_kblob2pkey3 __user *)arg);
765		break;
766	default:
767		/* unknown/unsupported ioctl cmd */
768		return -ENOTTY;
769	}
770
771	return rc;
772}
773
774/*
775 * File io operations
776 */
777
778static const struct file_operations pkey_fops = {
779	.owner		= THIS_MODULE,
780	.open		= nonseekable_open,
781	.unlocked_ioctl = pkey_unlocked_ioctl,
782};
783
784static struct miscdevice pkey_dev = {
785	.name	= "pkey",
786	.minor	= MISC_DYNAMIC_MINOR,
787	.mode	= 0666,
788	.fops	= &pkey_fops,
789	.groups = pkey_attr_groups,
790};
791
792int __init pkey_api_init(void)
793{
794	/* register as a misc device */
795	return misc_register(&pkey_dev);
796}
797
798void __exit pkey_api_exit(void)
799{
800	misc_deregister(&pkey_dev);
801}
~/ Read-only file preview.