File Index
Files and directories
Sign in
FILE

pkey_cca.c

File preview with syntax highlighting.

linux-6.19.14/drivers/s390/crypto/pkey_cca.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 *  pkey cca specific code
  4 *
  5 *  Copyright IBM Corp. 2024
  6 */
  7
  8#define pr_fmt(fmt) "pkey: " fmt
  9
 10#include <linux/init.h>
 11#include <linux/module.h>
 12#include <linux/cpufeature.h>
 13
 14#include "zcrypt_ccamisc.h"
 15#include "pkey_base.h"
 16
 17MODULE_LICENSE("GPL");
 18MODULE_AUTHOR("IBM Corporation");
 19MODULE_DESCRIPTION("s390 protected key CCA handler");
 20
 21#if IS_MODULE(CONFIG_PKEY_CCA)
 22static struct ap_device_id pkey_cca_card_ids[] = {
 23	{ .dev_type = AP_DEVICE_TYPE_CEX4 },
 24	{ .dev_type = AP_DEVICE_TYPE_CEX5 },
 25	{ .dev_type = AP_DEVICE_TYPE_CEX6 },
 26	{ .dev_type = AP_DEVICE_TYPE_CEX7 },
 27	{ .dev_type = AP_DEVICE_TYPE_CEX8 },
 28	{ /* end of list */ },
 29};
 30MODULE_DEVICE_TABLE(ap, pkey_cca_card_ids);
 31#endif
 32
 33/*
 34 * Check key blob for known and supported CCA key.
 35 */
 36static bool is_cca_key(const u8 *key, u32 keylen)
 37{
 38	struct keytoken_header *hdr = (struct keytoken_header *)key;
 39
 40	if (keylen < sizeof(*hdr))
 41		return false;
 42
 43	switch (hdr->type) {
 44	case TOKTYPE_CCA_INTERNAL:
 45		switch (hdr->version) {
 46		case TOKVER_CCA_AES:
 47		case TOKVER_CCA_VLSC:
 48			return true;
 49		default:
 50			return false;
 51		}
 52	case TOKTYPE_CCA_INTERNAL_PKA:
 53		return true;
 54	default:
 55		return false;
 56	}
 57}
 58
 59static bool is_cca_keytype(enum pkey_key_type key_type)
 60{
 61	switch (key_type) {
 62	case PKEY_TYPE_CCA_DATA:
 63	case PKEY_TYPE_CCA_CIPHER:
 64	case PKEY_TYPE_CCA_ECC:
 65		return true;
 66	default:
 67		return false;
 68	}
 69}
 70
 71static int cca_apqns4key(const u8 *key, u32 keylen, u32 flags,
 72			 struct pkey_apqn *apqns, size_t *nr_apqns, u32 pflags)
 73{
 74	struct keytoken_header *hdr = (struct keytoken_header *)key;
 75	u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
 76	u32 xflags;
 77	int rc;
 78
 79	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
 80
 81	if (!flags)
 82		flags = PKEY_FLAGS_MATCH_CUR_MKVP | PKEY_FLAGS_MATCH_ALT_MKVP;
 83
 84	if (keylen < sizeof(struct keytoken_header))
 85		return -EINVAL;
 86
 87	zcrypt_wait_api_operational();
 88
 89	if (hdr->type == TOKTYPE_CCA_INTERNAL) {
 90		u64 cur_mkvp = 0, old_mkvp = 0;
 91		int minhwtype = ZCRYPT_CEX3C;
 92
 93		if (hdr->version == TOKVER_CCA_AES) {
 94			struct secaeskeytoken *t = (struct secaeskeytoken *)key;
 95
 96			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
 97				cur_mkvp = t->mkvp;
 98			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
 99				old_mkvp = t->mkvp;
100		} else if (hdr->version == TOKVER_CCA_VLSC) {
101			struct cipherkeytoken *t = (struct cipherkeytoken *)key;
102
103			minhwtype = ZCRYPT_CEX6;
104			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
105				cur_mkvp = t->mkvp0;
106			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
107				old_mkvp = t->mkvp0;
108		} else {
109			/* unknown CCA internal token type */
110			return -EINVAL;
111		}
112		rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
113				   minhwtype, AES_MK_SET,
114				   cur_mkvp, old_mkvp, xflags);
115		if (rc)
116			goto out;
117
118	} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
119		struct eccprivkeytoken *t = (struct eccprivkeytoken *)key;
120		u64 cur_mkvp = 0, old_mkvp = 0;
121
122		if (t->secid == 0x20) {
123			if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
124				cur_mkvp = t->mkvp;
125			if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
126				old_mkvp = t->mkvp;
127		} else {
128			/* unknown CCA internal 2 token type */
129			return -EINVAL;
130		}
131		rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
132				   ZCRYPT_CEX7, APKA_MK_SET,
133				   cur_mkvp, old_mkvp, xflags);
134		if (rc)
135			goto out;
136
137	} else {
138		PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",
139			     __func__, hdr->type, hdr->version);
140		return -EINVAL;
141	}
142
143	if (apqns) {
144		if (*nr_apqns < _nr_apqns)
145			rc = -ENOSPC;
146		else
147			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
148	}
149	*nr_apqns = _nr_apqns;
150
151out:
152	pr_debug("rc=%d\n", rc);
153	return rc;
154}
155
156static int cca_apqns4type(enum pkey_key_type ktype,
157			  u8 cur_mkvp[32], u8 alt_mkvp[32], u32 flags,
158			  struct pkey_apqn *apqns, size_t *nr_apqns,
159			  u32 pflags)
160{
161	u32 _apqns[MAXAPQNSINLIST], _nr_apqns = ARRAY_SIZE(_apqns);
162	u32 xflags;
163	int rc;
164
165	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
166
167	zcrypt_wait_api_operational();
168
169	if (ktype == PKEY_TYPE_CCA_DATA || ktype == PKEY_TYPE_CCA_CIPHER) {
170		u64 cur_mkvp = 0, old_mkvp = 0;
171		int minhwtype = ZCRYPT_CEX3C;
172
173		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
174			cur_mkvp = *((u64 *)cur_mkvp);
175		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
176			old_mkvp = *((u64 *)alt_mkvp);
177		if (ktype == PKEY_TYPE_CCA_CIPHER)
178			minhwtype = ZCRYPT_CEX6;
179		rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
180				   minhwtype, AES_MK_SET,
181				   cur_mkvp, old_mkvp, xflags);
182		if (rc)
183			goto out;
184
185	} else if (ktype == PKEY_TYPE_CCA_ECC) {
186		u64 cur_mkvp = 0, old_mkvp = 0;
187
188		if (flags & PKEY_FLAGS_MATCH_CUR_MKVP)
189			cur_mkvp = *((u64 *)cur_mkvp);
190		if (flags & PKEY_FLAGS_MATCH_ALT_MKVP)
191			old_mkvp = *((u64 *)alt_mkvp);
192		rc = cca_findcard2(_apqns, &_nr_apqns, 0xFFFF, 0xFFFF,
193				   ZCRYPT_CEX7, APKA_MK_SET,
194				   cur_mkvp, old_mkvp, xflags);
195		if (rc)
196			goto out;
197
198	} else {
199		PKEY_DBF_ERR("%s unknown/unsupported key type %d",
200			     __func__, (int)ktype);
201		return -EINVAL;
202	}
203
204	if (apqns) {
205		if (*nr_apqns < _nr_apqns)
206			rc = -ENOSPC;
207		else
208			memcpy(apqns, _apqns, _nr_apqns * sizeof(u32));
209	}
210	*nr_apqns = _nr_apqns;
211
212out:
213	pr_debug("rc=%d\n", rc);
214	return rc;
215}
216
217static int cca_key2protkey(const struct pkey_apqn *apqns, size_t nr_apqns,
218			   const u8 *key, u32 keylen,
219			   u8 *protkey, u32 *protkeylen, u32 *protkeytype,
220			   u32 pflags)
221{
222	struct keytoken_header *hdr = (struct keytoken_header *)key;
223	struct pkey_apqn _apqns[MAXAPQNSINLIST];
224	u32 xflags;
225	int i, rc;
226
227	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
228
229	if (keylen < sizeof(*hdr))
230		return -EINVAL;
231
232	if (hdr->type == TOKTYPE_CCA_INTERNAL &&
233	    hdr->version == TOKVER_CCA_AES) {
234		/* CCA AES data key */
235		if (keylen < sizeof(struct secaeskeytoken))
236			return -EINVAL;
237		if (cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0))
238			return -EINVAL;
239	} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
240		   hdr->version == TOKVER_CCA_VLSC) {
241		/* CCA AES cipher key */
242		if (keylen < hdr->len)
243			return -EINVAL;
244		if (cca_check_secaescipherkey(pkey_dbf_info,
245					      3, key, 0, 1))
246			return -EINVAL;
247	} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
248		/* CCA ECC (private) key */
249		if (keylen < sizeof(struct eccprivkeytoken))
250			return -EINVAL;
251		if (cca_check_sececckeytoken(pkey_dbf_info, 3, key, keylen, 1))
252			return -EINVAL;
253	} else {
254		PKEY_DBF_ERR("%s unknown/unsupported blob type %d version %d\n",
255			     __func__, hdr->type, hdr->version);
256		return -EINVAL;
257	}
258
259	zcrypt_wait_api_operational();
260
261	if (!apqns || (nr_apqns == 1 &&
262		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
263		nr_apqns = MAXAPQNSINLIST;
264		rc = cca_apqns4key(key, keylen, 0, _apqns, &nr_apqns, pflags);
265		if (rc)
266			goto out;
267		apqns = _apqns;
268	}
269
270	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
271		if (hdr->type == TOKTYPE_CCA_INTERNAL &&
272		    hdr->version == TOKVER_CCA_AES) {
273			rc = cca_sec2protkey(apqns[i].card, apqns[i].domain,
274					     key, protkey,
275					     protkeylen, protkeytype, xflags);
276		} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
277			   hdr->version == TOKVER_CCA_VLSC) {
278			rc = cca_cipher2protkey(apqns[i].card, apqns[i].domain,
279						key, protkey,
280						protkeylen, protkeytype, xflags);
281		} else if (hdr->type == TOKTYPE_CCA_INTERNAL_PKA) {
282			rc = cca_ecc2protkey(apqns[i].card, apqns[i].domain,
283					     key, protkey,
284					     protkeylen, protkeytype, xflags);
285		} else {
286			rc = -EINVAL;
287			break;
288		}
289	}
290
291out:
292	pr_debug("rc=%d\n", rc);
293	return rc;
294}
295
296/*
297 * Generate CCA secure key.
298 * As of now only CCA AES Data or Cipher secure keys are
299 * supported.
300 * keytype is one of the PKEY_KEYTYPE_* constants,
301 * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER,
302 * keybitsize is the bit size of the key (may be 0 for
303 * keytype PKEY_KEYTYPE_AES_*).
304 */
305static int cca_gen_key(const struct pkey_apqn *apqns, size_t nr_apqns,
306		       u32 keytype, u32 subtype,
307		       u32 keybitsize, u32 flags,
308		       u8 *keybuf, u32 *keybuflen, u32 *_keyinfo, u32 pflags)
309{
310	struct pkey_apqn _apqns[MAXAPQNSINLIST];
311	int i, len, rc;
312	u32 xflags;
313
314	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
315
316	/* check keytype, subtype, keybitsize */
317	switch (keytype) {
318	case PKEY_KEYTYPE_AES_128:
319	case PKEY_KEYTYPE_AES_192:
320	case PKEY_KEYTYPE_AES_256:
321		len = pkey_keytype_aes_to_size(keytype);
322		if (keybitsize && keybitsize != 8 * len) {
323			PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
324				     __func__, keybitsize);
325			return -EINVAL;
326		}
327		keybitsize = 8 * len;
328		switch (subtype) {
329		case PKEY_TYPE_CCA_DATA:
330		case PKEY_TYPE_CCA_CIPHER:
331			break;
332		default:
333			PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
334				     __func__, subtype);
335			return -EINVAL;
336		}
337		break;
338	default:
339		PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
340			     __func__, keytype);
341		return -EINVAL;
342	}
343
344	zcrypt_wait_api_operational();
345
346	if (!apqns || (nr_apqns == 1 &&
347		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
348		nr_apqns = MAXAPQNSINLIST;
349		rc = cca_apqns4type(subtype, NULL, NULL, 0,
350				    _apqns, &nr_apqns, pflags);
351		if (rc)
352			goto out;
353		apqns = _apqns;
354	}
355
356	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
357		if (subtype == PKEY_TYPE_CCA_CIPHER) {
358			rc = cca_gencipherkey(apqns[i].card, apqns[i].domain,
359					      keybitsize, flags,
360					      keybuf, keybuflen, xflags);
361		} else {
362			/* PKEY_TYPE_CCA_DATA */
363			rc = cca_genseckey(apqns[i].card, apqns[i].domain,
364					   keybitsize, keybuf, xflags);
365			*keybuflen = (rc ? 0 : SECKEYBLOBSIZE);
366		}
367	}
368
369out:
370	pr_debug("rc=%d\n", rc);
371	return rc;
372}
373
374/*
375 * Generate CCA secure key with given clear key value.
376 * As of now only CCA AES Data or Cipher secure keys are
377 * supported.
378 * keytype is one of the PKEY_KEYTYPE_* constants,
379 * subtype may be 0 or PKEY_TYPE_CCA_DATA or PKEY_TYPE_CCA_CIPHER,
380 * keybitsize is the bit size of the key (may be 0 for
381 * keytype PKEY_KEYTYPE_AES_*).
382 */
383static int cca_clr2key(const struct pkey_apqn *apqns, size_t nr_apqns,
384		       u32 keytype, u32 subtype,
385		       u32 keybitsize, u32 flags,
386		       const u8 *clrkey, u32 clrkeylen,
387		       u8 *keybuf, u32 *keybuflen, u32 *_keyinfo, u32 pflags)
388{
389	struct pkey_apqn _apqns[MAXAPQNSINLIST];
390	int i, len, rc;
391	u32 xflags;
392
393	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
394
395	/* check keytype, subtype, clrkeylen, keybitsize */
396	switch (keytype) {
397	case PKEY_KEYTYPE_AES_128:
398	case PKEY_KEYTYPE_AES_192:
399	case PKEY_KEYTYPE_AES_256:
400		len = pkey_keytype_aes_to_size(keytype);
401		if (keybitsize && keybitsize != 8 * len) {
402			PKEY_DBF_ERR("%s unknown/unsupported keybitsize %d\n",
403				     __func__, keybitsize);
404			return -EINVAL;
405		}
406		keybitsize = 8 * len;
407		if (clrkeylen != len) {
408			PKEY_DBF_ERR("%s invalid clear key len %d != %d\n",
409				     __func__, clrkeylen, len);
410			return -EINVAL;
411		}
412		switch (subtype) {
413		case PKEY_TYPE_CCA_DATA:
414		case PKEY_TYPE_CCA_CIPHER:
415			break;
416		default:
417			PKEY_DBF_ERR("%s unknown/unsupported subtype %d\n",
418				     __func__, subtype);
419			return -EINVAL;
420		}
421		break;
422	default:
423		PKEY_DBF_ERR("%s unknown/unsupported keytype %d\n",
424			     __func__, keytype);
425		return -EINVAL;
426	}
427
428	zcrypt_wait_api_operational();
429
430	if (!apqns || (nr_apqns == 1 &&
431		       apqns[0].card == 0xFFFF && apqns[0].domain == 0xFFFF)) {
432		nr_apqns = MAXAPQNSINLIST;
433		rc = cca_apqns4type(subtype, NULL, NULL, 0,
434				    _apqns, &nr_apqns, pflags);
435		if (rc)
436			goto out;
437		apqns = _apqns;
438	}
439
440	for (rc = -ENODEV, i = 0; rc && i < nr_apqns; i++) {
441		if (subtype == PKEY_TYPE_CCA_CIPHER) {
442			rc = cca_clr2cipherkey(apqns[i].card, apqns[i].domain,
443					       keybitsize, flags, clrkey,
444					       keybuf, keybuflen, xflags);
445		} else {
446			/* PKEY_TYPE_CCA_DATA */
447			rc = cca_clr2seckey(apqns[i].card, apqns[i].domain,
448					    keybitsize, clrkey, keybuf, xflags);
449			*keybuflen = (rc ? 0 : SECKEYBLOBSIZE);
450		}
451	}
452
453out:
454	pr_debug("rc=%d\n", rc);
455	return rc;
456}
457
458static int cca_verifykey(const u8 *key, u32 keylen,
459			 u16 *card, u16 *dom,
460			 u32 *keytype, u32 *keybitsize, u32 *flags, u32 pflags)
461{
462	struct keytoken_header *hdr = (struct keytoken_header *)key;
463	u32 apqns[MAXAPQNSINLIST], nr_apqns = ARRAY_SIZE(apqns);
464	u32 xflags;
465	int rc;
466
467	xflags = pflags & PKEY_XFLAG_NOMEMALLOC ? ZCRYPT_XFLAG_NOMEMALLOC : 0;
468
469	if (keylen < sizeof(*hdr))
470		return -EINVAL;
471
472	zcrypt_wait_api_operational();
473
474	if (hdr->type == TOKTYPE_CCA_INTERNAL &&
475	    hdr->version == TOKVER_CCA_AES) {
476		struct secaeskeytoken *t = (struct secaeskeytoken *)key;
477
478		rc = cca_check_secaeskeytoken(pkey_dbf_info, 3, key, 0);
479		if (rc)
480			goto out;
481		*keytype = PKEY_TYPE_CCA_DATA;
482		*keybitsize = t->bitsize;
483		rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
484				   ZCRYPT_CEX3C, AES_MK_SET,
485				   t->mkvp, 0, xflags);
486		if (!rc)
487			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
488		if (rc == -ENODEV) {
489			nr_apqns = ARRAY_SIZE(apqns);
490			rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
491					   ZCRYPT_CEX3C, AES_MK_SET,
492					   0, t->mkvp, xflags);
493			if (!rc)
494				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
495		}
496		if (rc)
497			goto out;
498
499		*card = ((struct pkey_apqn *)apqns)->card;
500		*dom = ((struct pkey_apqn *)apqns)->domain;
501
502	} else if (hdr->type == TOKTYPE_CCA_INTERNAL &&
503		   hdr->version == TOKVER_CCA_VLSC) {
504		struct cipherkeytoken *t = (struct cipherkeytoken *)key;
505
506		rc = cca_check_secaescipherkey(pkey_dbf_info, 3, key, 0, 1);
507		if (rc)
508			goto out;
509		*keytype = PKEY_TYPE_CCA_CIPHER;
510		*keybitsize = PKEY_SIZE_UNKNOWN;
511		if (!t->plfver && t->wpllen == 512)
512			*keybitsize = PKEY_SIZE_AES_128;
513		else if (!t->plfver && t->wpllen == 576)
514			*keybitsize = PKEY_SIZE_AES_192;
515		else if (!t->plfver && t->wpllen == 640)
516			*keybitsize = PKEY_SIZE_AES_256;
517		rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
518				   ZCRYPT_CEX6, AES_MK_SET,
519				   t->mkvp0, 0, xflags);
520		if (!rc)
521			*flags = PKEY_FLAGS_MATCH_CUR_MKVP;
522		if (rc == -ENODEV) {
523			nr_apqns = ARRAY_SIZE(apqns);
524			rc = cca_findcard2(apqns, &nr_apqns, *card, *dom,
525					   ZCRYPT_CEX6, AES_MK_SET,
526					   0, t->mkvp0, xflags);
527			if (!rc)
528				*flags = PKEY_FLAGS_MATCH_ALT_MKVP;
529		}
530		if (rc)
531			goto out;
532
533		*card = ((struct pkey_apqn *)apqns)->card;
534		*dom = ((struct pkey_apqn *)apqns)->domain;
535
536	} else {
537		/* unknown/unsupported key blob */
538		rc = -EINVAL;
539	}
540
541out:
542	pr_debug("rc=%d\n", rc);
543	return rc;
544}
545
546/*
547 * This function provides an alternate but usually slow way
548 * to convert a 'clear key token' with AES key material into
549 * a protected key. This is done via an intermediate step
550 * which creates a CCA AES DATA secure key first and then
551 * derives the protected key from this secure key.
552 */
553static int cca_slowpath_key2protkey(const struct pkey_apqn *apqns,
554				    size_t nr_apqns,
555				    const u8 *key, u32 keylen,
556				    u8 *protkey, u32 *protkeylen,
557				    u32 *protkeytype, u32 pflags)
558{
559	const struct keytoken_header *hdr = (const struct keytoken_header *)key;
560	const struct clearkeytoken *t = (const struct clearkeytoken *)key;
561	u8 tmpbuf[SECKEYBLOBSIZE]; /* 64 bytes */
562	u32 tmplen, keysize = 0;
563	int i, rc;
564
565	if (keylen < sizeof(*hdr))
566		return -EINVAL;
567
568	if (hdr->type == TOKTYPE_NON_CCA &&
569	    hdr->version == TOKVER_CLEAR_KEY)
570		keysize = pkey_keytype_aes_to_size(t->keytype);
571	if (!keysize || t->len != keysize)
572		return -EINVAL;
573
574	/* try two times in case of failure */
575	for (i = 0, rc = -ENODEV; i < 2 && rc; i++) {
576		tmplen = SECKEYBLOBSIZE;
577		rc = cca_clr2key(NULL, 0, t->keytype, PKEY_TYPE_CCA_DATA,
578				 8 * keysize, 0, t->clearkey, t->len,
579				 tmpbuf, &tmplen, NULL, pflags);
580		pr_debug("cca_clr2key()=%d\n", rc);
581		if (rc)
582			continue;
583		rc = cca_key2protkey(NULL, 0, tmpbuf, tmplen,
584				     protkey, protkeylen, protkeytype, pflags);
585		pr_debug("cca_key2protkey()=%d\n", rc);
586	}
587
588	pr_debug("rc=%d\n", rc);
589	return rc;
590}
591
592static struct pkey_handler cca_handler = {
593	.module			 = THIS_MODULE,
594	.name			 = "PKEY CCA handler",
595	.is_supported_key	 = is_cca_key,
596	.is_supported_keytype	 = is_cca_keytype,
597	.key_to_protkey		 = cca_key2protkey,
598	.slowpath_key_to_protkey = cca_slowpath_key2protkey,
599	.gen_key		 = cca_gen_key,
600	.clr_to_key		 = cca_clr2key,
601	.verify_key		 = cca_verifykey,
602	.apqns_for_key		 = cca_apqns4key,
603	.apqns_for_keytype	 = cca_apqns4type,
604};
605
606/*
607 * Module init
608 */
609static int __init pkey_cca_init(void)
610{
611	/* register this module as pkey handler for all the cca stuff */
612	return pkey_handler_register(&cca_handler);
613}
614
615/*
616 * Module exit
617 */
618static void __exit pkey_cca_exit(void)
619{
620	/* unregister this module as pkey handler */
621	pkey_handler_unregister(&cca_handler);
622}
623
624module_init(pkey_cca_init);
625module_exit(pkey_cca_exit);
~/ Read-only file preview.