xref: /openbmc/linux/net/rxrpc/key.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /* RxRPC key management
3   *
4   * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
5   * Written by David Howells (dhowells@redhat.com)
6   *
7   * RxRPC keys should have a description of describing their purpose:
8   *	"afs@example.com"
9   */
10  
11  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
12  
13  #include <crypto/skcipher.h>
14  #include <linux/module.h>
15  #include <linux/net.h>
16  #include <linux/skbuff.h>
17  #include <linux/key-type.h>
18  #include <linux/ctype.h>
19  #include <linux/slab.h>
20  #include <net/sock.h>
21  #include <net/af_rxrpc.h>
22  #include <keys/rxrpc-type.h>
23  #include <keys/user-type.h>
24  #include "ar-internal.h"
25  
26  static int rxrpc_preparse(struct key_preparsed_payload *);
27  static void rxrpc_free_preparse(struct key_preparsed_payload *);
28  static void rxrpc_destroy(struct key *);
29  static void rxrpc_describe(const struct key *, struct seq_file *);
30  static long rxrpc_read(const struct key *, char *, size_t);
31  
32  /*
33   * rxrpc defined keys take an arbitrary string as the description and an
34   * arbitrary blob of data as the payload
35   */
36  struct key_type key_type_rxrpc = {
37  	.name		= "rxrpc",
38  	.flags		= KEY_TYPE_NET_DOMAIN,
39  	.preparse	= rxrpc_preparse,
40  	.free_preparse	= rxrpc_free_preparse,
41  	.instantiate	= generic_key_instantiate,
42  	.destroy	= rxrpc_destroy,
43  	.describe	= rxrpc_describe,
44  	.read		= rxrpc_read,
45  };
46  EXPORT_SYMBOL(key_type_rxrpc);
47  
48  /*
49   * parse an RxKAD type XDR format token
50   * - the caller guarantees we have at least 4 words
51   */
rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload * prep,size_t datalen,const __be32 * xdr,unsigned int toklen)52  static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,
53  				    size_t datalen,
54  				    const __be32 *xdr, unsigned int toklen)
55  {
56  	struct rxrpc_key_token *token, **pptoken;
57  	time64_t expiry;
58  	size_t plen;
59  	u32 tktlen;
60  
61  	_enter(",{%x,%x,%x,%x},%u",
62  	       ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
63  	       toklen);
64  
65  	if (toklen <= 8 * 4)
66  		return -EKEYREJECTED;
67  	tktlen = ntohl(xdr[7]);
68  	_debug("tktlen: %x", tktlen);
69  	if (tktlen > AFSTOKEN_RK_TIX_MAX)
70  		return -EKEYREJECTED;
71  	if (toklen < 8 * 4 + tktlen)
72  		return -EKEYREJECTED;
73  
74  	plen = sizeof(*token) + sizeof(*token->kad) + tktlen;
75  	prep->quotalen = datalen + plen;
76  
77  	plen -= sizeof(*token);
78  	token = kzalloc(sizeof(*token), GFP_KERNEL);
79  	if (!token)
80  		return -ENOMEM;
81  
82  	token->kad = kzalloc(plen, GFP_KERNEL);
83  	if (!token->kad) {
84  		kfree(token);
85  		return -ENOMEM;
86  	}
87  
88  	token->security_index	= RXRPC_SECURITY_RXKAD;
89  	token->kad->ticket_len	= tktlen;
90  	token->kad->vice_id	= ntohl(xdr[0]);
91  	token->kad->kvno	= ntohl(xdr[1]);
92  	token->kad->start	= ntohl(xdr[4]);
93  	token->kad->expiry	= ntohl(xdr[5]);
94  	token->kad->primary_flag = ntohl(xdr[6]);
95  	memcpy(&token->kad->session_key, &xdr[2], 8);
96  	memcpy(&token->kad->ticket, &xdr[8], tktlen);
97  
98  	_debug("SCIX: %u", token->security_index);
99  	_debug("TLEN: %u", token->kad->ticket_len);
100  	_debug("EXPY: %x", token->kad->expiry);
101  	_debug("KVNO: %u", token->kad->kvno);
102  	_debug("PRIM: %u", token->kad->primary_flag);
103  	_debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
104  	       token->kad->session_key[0], token->kad->session_key[1],
105  	       token->kad->session_key[2], token->kad->session_key[3],
106  	       token->kad->session_key[4], token->kad->session_key[5],
107  	       token->kad->session_key[6], token->kad->session_key[7]);
108  	if (token->kad->ticket_len >= 8)
109  		_debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
110  		       token->kad->ticket[0], token->kad->ticket[1],
111  		       token->kad->ticket[2], token->kad->ticket[3],
112  		       token->kad->ticket[4], token->kad->ticket[5],
113  		       token->kad->ticket[6], token->kad->ticket[7]);
114  
115  	/* count the number of tokens attached */
116  	prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
117  
118  	/* attach the data */
119  	for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
120  	     *pptoken;
121  	     pptoken = &(*pptoken)->next)
122  		continue;
123  	*pptoken = token;
124  	expiry = rxrpc_u32_to_time64(token->kad->expiry);
125  	if (expiry < prep->expiry)
126  		prep->expiry = expiry;
127  
128  	_leave(" = 0");
129  	return 0;
130  }
131  
132  /*
133   * attempt to parse the data as the XDR format
134   * - the caller guarantees we have more than 7 words
135   */
rxrpc_preparse_xdr(struct key_preparsed_payload * prep)136  static int rxrpc_preparse_xdr(struct key_preparsed_payload *prep)
137  {
138  	const __be32 *xdr = prep->data, *token, *p;
139  	const char *cp;
140  	unsigned int len, paddedlen, loop, ntoken, toklen, sec_ix;
141  	size_t datalen = prep->datalen;
142  	int ret, ret2;
143  
144  	_enter(",{%x,%x,%x,%x},%zu",
145  	       ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
146  	       prep->datalen);
147  
148  	if (datalen > AFSTOKEN_LENGTH_MAX)
149  		goto not_xdr;
150  
151  	/* XDR is an array of __be32's */
152  	if (datalen & 3)
153  		goto not_xdr;
154  
155  	/* the flags should be 0 (the setpag bit must be handled by
156  	 * userspace) */
157  	if (ntohl(*xdr++) != 0)
158  		goto not_xdr;
159  	datalen -= 4;
160  
161  	/* check the cell name */
162  	len = ntohl(*xdr++);
163  	if (len < 1 || len > AFSTOKEN_CELL_MAX)
164  		goto not_xdr;
165  	datalen -= 4;
166  	paddedlen = (len + 3) & ~3;
167  	if (paddedlen > datalen)
168  		goto not_xdr;
169  
170  	cp = (const char *) xdr;
171  	for (loop = 0; loop < len; loop++)
172  		if (!isprint(cp[loop]))
173  			goto not_xdr;
174  	for (; loop < paddedlen; loop++)
175  		if (cp[loop])
176  			goto not_xdr;
177  	_debug("cellname: [%u/%u] '%*.*s'",
178  	       len, paddedlen, len, len, (const char *) xdr);
179  	datalen -= paddedlen;
180  	xdr += paddedlen >> 2;
181  
182  	/* get the token count */
183  	if (datalen < 12)
184  		goto not_xdr;
185  	ntoken = ntohl(*xdr++);
186  	datalen -= 4;
187  	_debug("ntoken: %x", ntoken);
188  	if (ntoken < 1 || ntoken > AFSTOKEN_MAX)
189  		goto not_xdr;
190  
191  	/* check each token wrapper */
192  	p = xdr;
193  	loop = ntoken;
194  	do {
195  		if (datalen < 8)
196  			goto not_xdr;
197  		toklen = ntohl(*p++);
198  		sec_ix = ntohl(*p);
199  		datalen -= 4;
200  		_debug("token: [%x/%zx] %x", toklen, datalen, sec_ix);
201  		paddedlen = (toklen + 3) & ~3;
202  		if (toklen < 20 || toklen > datalen || paddedlen > datalen)
203  			goto not_xdr;
204  		datalen -= paddedlen;
205  		p += paddedlen >> 2;
206  
207  	} while (--loop > 0);
208  
209  	_debug("remainder: %zu", datalen);
210  	if (datalen != 0)
211  		goto not_xdr;
212  
213  	/* okay: we're going to assume it's valid XDR format
214  	 * - we ignore the cellname, relying on the key to be correctly named
215  	 */
216  	ret = -EPROTONOSUPPORT;
217  	do {
218  		toklen = ntohl(*xdr++);
219  		token = xdr;
220  		xdr += (toklen + 3) / 4;
221  
222  		sec_ix = ntohl(*token++);
223  		toklen -= 4;
224  
225  		_debug("TOKEN type=%x len=%x", sec_ix, toklen);
226  
227  		switch (sec_ix) {
228  		case RXRPC_SECURITY_RXKAD:
229  			ret2 = rxrpc_preparse_xdr_rxkad(prep, datalen, token, toklen);
230  			break;
231  		default:
232  			ret2 = -EPROTONOSUPPORT;
233  			break;
234  		}
235  
236  		switch (ret2) {
237  		case 0:
238  			ret = 0;
239  			break;
240  		case -EPROTONOSUPPORT:
241  			break;
242  		case -ENOPKG:
243  			if (ret != 0)
244  				ret = -ENOPKG;
245  			break;
246  		default:
247  			ret = ret2;
248  			goto error;
249  		}
250  
251  	} while (--ntoken > 0);
252  
253  error:
254  	_leave(" = %d", ret);
255  	return ret;
256  
257  not_xdr:
258  	_leave(" = -EPROTO");
259  	return -EPROTO;
260  }
261  
262  /*
263   * Preparse an rxrpc defined key.
264   *
265   * Data should be of the form:
266   *	OFFSET	LEN	CONTENT
267   *	0	4	key interface version number
268   *	4	2	security index (type)
269   *	6	2	ticket length
270   *	8	4	key expiry time (time_t)
271   *	12	4	kvno
272   *	16	8	session key
273   *	24	[len]	ticket
274   *
275   * if no data is provided, then a no-security key is made
276   */
rxrpc_preparse(struct key_preparsed_payload * prep)277  static int rxrpc_preparse(struct key_preparsed_payload *prep)
278  {
279  	const struct rxrpc_key_data_v1 *v1;
280  	struct rxrpc_key_token *token, **pp;
281  	time64_t expiry;
282  	size_t plen;
283  	u32 kver;
284  	int ret;
285  
286  	_enter("%zu", prep->datalen);
287  
288  	/* handle a no-security key */
289  	if (!prep->data && prep->datalen == 0)
290  		return 0;
291  
292  	/* determine if the XDR payload format is being used */
293  	if (prep->datalen > 7 * 4) {
294  		ret = rxrpc_preparse_xdr(prep);
295  		if (ret != -EPROTO)
296  			return ret;
297  	}
298  
299  	/* get the key interface version number */
300  	ret = -EINVAL;
301  	if (prep->datalen <= 4 || !prep->data)
302  		goto error;
303  	memcpy(&kver, prep->data, sizeof(kver));
304  	prep->data += sizeof(kver);
305  	prep->datalen -= sizeof(kver);
306  
307  	_debug("KEY I/F VERSION: %u", kver);
308  
309  	ret = -EKEYREJECTED;
310  	if (kver != 1)
311  		goto error;
312  
313  	/* deal with a version 1 key */
314  	ret = -EINVAL;
315  	if (prep->datalen < sizeof(*v1))
316  		goto error;
317  
318  	v1 = prep->data;
319  	if (prep->datalen != sizeof(*v1) + v1->ticket_length)
320  		goto error;
321  
322  	_debug("SCIX: %u", v1->security_index);
323  	_debug("TLEN: %u", v1->ticket_length);
324  	_debug("EXPY: %x", v1->expiry);
325  	_debug("KVNO: %u", v1->kvno);
326  	_debug("SKEY: %02x%02x%02x%02x%02x%02x%02x%02x",
327  	       v1->session_key[0], v1->session_key[1],
328  	       v1->session_key[2], v1->session_key[3],
329  	       v1->session_key[4], v1->session_key[5],
330  	       v1->session_key[6], v1->session_key[7]);
331  	if (v1->ticket_length >= 8)
332  		_debug("TCKT: %02x%02x%02x%02x%02x%02x%02x%02x",
333  		       v1->ticket[0], v1->ticket[1],
334  		       v1->ticket[2], v1->ticket[3],
335  		       v1->ticket[4], v1->ticket[5],
336  		       v1->ticket[6], v1->ticket[7]);
337  
338  	ret = -EPROTONOSUPPORT;
339  	if (v1->security_index != RXRPC_SECURITY_RXKAD)
340  		goto error;
341  
342  	plen = sizeof(*token->kad) + v1->ticket_length;
343  	prep->quotalen = plen + sizeof(*token);
344  
345  	ret = -ENOMEM;
346  	token = kzalloc(sizeof(*token), GFP_KERNEL);
347  	if (!token)
348  		goto error;
349  	token->kad = kzalloc(plen, GFP_KERNEL);
350  	if (!token->kad)
351  		goto error_free;
352  
353  	token->security_index		= RXRPC_SECURITY_RXKAD;
354  	token->kad->ticket_len		= v1->ticket_length;
355  	token->kad->expiry		= v1->expiry;
356  	token->kad->kvno		= v1->kvno;
357  	memcpy(&token->kad->session_key, &v1->session_key, 8);
358  	memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
359  
360  	/* count the number of tokens attached */
361  	prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
362  
363  	/* attach the data */
364  	pp = (struct rxrpc_key_token **)&prep->payload.data[0];
365  	while (*pp)
366  		pp = &(*pp)->next;
367  	*pp = token;
368  	expiry = rxrpc_u32_to_time64(token->kad->expiry);
369  	if (expiry < prep->expiry)
370  		prep->expiry = expiry;
371  	token = NULL;
372  	ret = 0;
373  
374  error_free:
375  	kfree(token);
376  error:
377  	return ret;
378  }
379  
380  /*
381   * Free token list.
382   */
rxrpc_free_token_list(struct rxrpc_key_token * token)383  static void rxrpc_free_token_list(struct rxrpc_key_token *token)
384  {
385  	struct rxrpc_key_token *next;
386  
387  	for (; token; token = next) {
388  		next = token->next;
389  		switch (token->security_index) {
390  		case RXRPC_SECURITY_RXKAD:
391  			kfree(token->kad);
392  			break;
393  		default:
394  			pr_err("Unknown token type %x on rxrpc key\n",
395  			       token->security_index);
396  			BUG();
397  		}
398  
399  		kfree(token);
400  	}
401  }
402  
403  /*
404   * Clean up preparse data.
405   */
rxrpc_free_preparse(struct key_preparsed_payload * prep)406  static void rxrpc_free_preparse(struct key_preparsed_payload *prep)
407  {
408  	rxrpc_free_token_list(prep->payload.data[0]);
409  }
410  
411  /*
412   * dispose of the data dangling from the corpse of a rxrpc key
413   */
rxrpc_destroy(struct key * key)414  static void rxrpc_destroy(struct key *key)
415  {
416  	rxrpc_free_token_list(key->payload.data[0]);
417  }
418  
419  /*
420   * describe the rxrpc key
421   */
rxrpc_describe(const struct key * key,struct seq_file * m)422  static void rxrpc_describe(const struct key *key, struct seq_file *m)
423  {
424  	const struct rxrpc_key_token *token;
425  	const char *sep = ": ";
426  
427  	seq_puts(m, key->description);
428  
429  	for (token = key->payload.data[0]; token; token = token->next) {
430  		seq_puts(m, sep);
431  
432  		switch (token->security_index) {
433  		case RXRPC_SECURITY_RXKAD:
434  			seq_puts(m, "ka");
435  			break;
436  		default: /* we have a ticket we can't encode */
437  			seq_printf(m, "%u", token->security_index);
438  			break;
439  		}
440  
441  		sep = " ";
442  	}
443  }
444  
445  /*
446   * grab the security key for a socket
447   */
rxrpc_request_key(struct rxrpc_sock * rx,sockptr_t optval,int optlen)448  int rxrpc_request_key(struct rxrpc_sock *rx, sockptr_t optval, int optlen)
449  {
450  	struct key *key;
451  	char *description;
452  
453  	_enter("");
454  
455  	if (optlen <= 0 || optlen > PAGE_SIZE - 1 || rx->securities)
456  		return -EINVAL;
457  
458  	description = memdup_sockptr_nul(optval, optlen);
459  	if (IS_ERR(description))
460  		return PTR_ERR(description);
461  
462  	key = request_key_net(&key_type_rxrpc, description, sock_net(&rx->sk), NULL);
463  	if (IS_ERR(key)) {
464  		kfree(description);
465  		_leave(" = %ld", PTR_ERR(key));
466  		return PTR_ERR(key);
467  	}
468  
469  	rx->key = key;
470  	kfree(description);
471  	_leave(" = 0 [key %x]", key->serial);
472  	return 0;
473  }
474  
475  /*
476   * generate a server data key
477   */
rxrpc_get_server_data_key(struct rxrpc_connection * conn,const void * session_key,time64_t expiry,u32 kvno)478  int rxrpc_get_server_data_key(struct rxrpc_connection *conn,
479  			      const void *session_key,
480  			      time64_t expiry,
481  			      u32 kvno)
482  {
483  	const struct cred *cred = current_cred();
484  	struct key *key;
485  	int ret;
486  
487  	struct {
488  		u32 kver;
489  		struct rxrpc_key_data_v1 v1;
490  	} data;
491  
492  	_enter("");
493  
494  	key = key_alloc(&key_type_rxrpc, "x",
495  			GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, 0,
496  			KEY_ALLOC_NOT_IN_QUOTA, NULL);
497  	if (IS_ERR(key)) {
498  		_leave(" = -ENOMEM [alloc %ld]", PTR_ERR(key));
499  		return -ENOMEM;
500  	}
501  
502  	_debug("key %d", key_serial(key));
503  
504  	data.kver = 1;
505  	data.v1.security_index = RXRPC_SECURITY_RXKAD;
506  	data.v1.ticket_length = 0;
507  	data.v1.expiry = rxrpc_time64_to_u32(expiry);
508  	data.v1.kvno = 0;
509  
510  	memcpy(&data.v1.session_key, session_key, sizeof(data.v1.session_key));
511  
512  	ret = key_instantiate_and_link(key, &data, sizeof(data), NULL, NULL);
513  	if (ret < 0)
514  		goto error;
515  
516  	conn->key = key;
517  	_leave(" = 0 [%d]", key_serial(key));
518  	return 0;
519  
520  error:
521  	key_revoke(key);
522  	key_put(key);
523  	_leave(" = -ENOMEM [ins %d]", ret);
524  	return -ENOMEM;
525  }
526  EXPORT_SYMBOL(rxrpc_get_server_data_key);
527  
528  /**
529   * rxrpc_get_null_key - Generate a null RxRPC key
530   * @keyname: The name to give the key.
531   *
532   * Generate a null RxRPC key that can be used to indicate anonymous security is
533   * required for a particular domain.
534   */
rxrpc_get_null_key(const char * keyname)535  struct key *rxrpc_get_null_key(const char *keyname)
536  {
537  	const struct cred *cred = current_cred();
538  	struct key *key;
539  	int ret;
540  
541  	key = key_alloc(&key_type_rxrpc, keyname,
542  			GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
543  			KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA, NULL);
544  	if (IS_ERR(key))
545  		return key;
546  
547  	ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL);
548  	if (ret < 0) {
549  		key_revoke(key);
550  		key_put(key);
551  		return ERR_PTR(ret);
552  	}
553  
554  	return key;
555  }
556  EXPORT_SYMBOL(rxrpc_get_null_key);
557  
558  /*
559   * read the contents of an rxrpc key
560   * - this returns the result in XDR form
561   */
rxrpc_read(const struct key * key,char * buffer,size_t buflen)562  static long rxrpc_read(const struct key *key,
563  		       char *buffer, size_t buflen)
564  {
565  	const struct rxrpc_key_token *token;
566  	size_t size;
567  	__be32 *xdr, *oldxdr;
568  	u32 cnlen, toksize, ntoks, tok, zero;
569  	u16 toksizes[AFSTOKEN_MAX];
570  
571  	_enter("");
572  
573  	/* we don't know what form we should return non-AFS keys in */
574  	if (memcmp(key->description, "afs@", 4) != 0)
575  		return -EOPNOTSUPP;
576  	cnlen = strlen(key->description + 4);
577  
578  #define RND(X) (((X) + 3) & ~3)
579  
580  	/* AFS keys we return in XDR form, so we need to work out the size of
581  	 * the XDR */
582  	size = 2 * 4;	/* flags, cellname len */
583  	size += RND(cnlen);	/* cellname */
584  	size += 1 * 4;	/* token count */
585  
586  	ntoks = 0;
587  	for (token = key->payload.data[0]; token; token = token->next) {
588  		toksize = 4;	/* sec index */
589  
590  		switch (token->security_index) {
591  		case RXRPC_SECURITY_RXKAD:
592  			toksize += 8 * 4;	/* viceid, kvno, key*2, begin,
593  						 * end, primary, tktlen */
594  			if (!token->no_leak_key)
595  				toksize += RND(token->kad->ticket_len);
596  			break;
597  
598  		default: /* we have a ticket we can't encode */
599  			pr_err("Unsupported key token type (%u)\n",
600  			       token->security_index);
601  			return -ENOPKG;
602  		}
603  
604  		_debug("token[%u]: toksize=%u", ntoks, toksize);
605  		if (WARN_ON(toksize > AFSTOKEN_LENGTH_MAX))
606  			return -EIO;
607  
608  		toksizes[ntoks++] = toksize;
609  		size += toksize + 4; /* each token has a length word */
610  	}
611  
612  #undef RND
613  
614  	if (!buffer || buflen < size)
615  		return size;
616  
617  	xdr = (__be32 *)buffer;
618  	zero = 0;
619  #define ENCODE(x)				\
620  	do {					\
621  		*xdr++ = htonl(x);		\
622  	} while(0)
623  #define ENCODE_DATA(l, s)						\
624  	do {								\
625  		u32 _l = (l);						\
626  		ENCODE(l);						\
627  		memcpy(xdr, (s), _l);					\
628  		if (_l & 3)						\
629  			memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3));	\
630  		xdr += (_l + 3) >> 2;					\
631  	} while(0)
632  #define ENCODE_BYTES(l, s)						\
633  	do {								\
634  		u32 _l = (l);						\
635  		memcpy(xdr, (s), _l);					\
636  		if (_l & 3)						\
637  			memcpy((u8 *)xdr + _l, &zero, 4 - (_l & 3));	\
638  		xdr += (_l + 3) >> 2;					\
639  	} while(0)
640  #define ENCODE64(x)					\
641  	do {						\
642  		__be64 y = cpu_to_be64(x);		\
643  		memcpy(xdr, &y, 8);			\
644  		xdr += 8 >> 2;				\
645  	} while(0)
646  #define ENCODE_STR(s)				\
647  	do {					\
648  		const char *_s = (s);		\
649  		ENCODE_DATA(strlen(_s), _s);	\
650  	} while(0)
651  
652  	ENCODE(0);					/* flags */
653  	ENCODE_DATA(cnlen, key->description + 4);	/* cellname */
654  	ENCODE(ntoks);
655  
656  	tok = 0;
657  	for (token = key->payload.data[0]; token; token = token->next) {
658  		toksize = toksizes[tok++];
659  		ENCODE(toksize);
660  		oldxdr = xdr;
661  		ENCODE(token->security_index);
662  
663  		switch (token->security_index) {
664  		case RXRPC_SECURITY_RXKAD:
665  			ENCODE(token->kad->vice_id);
666  			ENCODE(token->kad->kvno);
667  			ENCODE_BYTES(8, token->kad->session_key);
668  			ENCODE(token->kad->start);
669  			ENCODE(token->kad->expiry);
670  			ENCODE(token->kad->primary_flag);
671  			if (token->no_leak_key)
672  				ENCODE(0);
673  			else
674  				ENCODE_DATA(token->kad->ticket_len, token->kad->ticket);
675  			break;
676  
677  		default:
678  			pr_err("Unsupported key token type (%u)\n",
679  			       token->security_index);
680  			return -ENOPKG;
681  		}
682  
683  		if (WARN_ON((unsigned long)xdr - (unsigned long)oldxdr !=
684  			    toksize))
685  			return -EIO;
686  	}
687  
688  #undef ENCODE_STR
689  #undef ENCODE_DATA
690  #undef ENCODE64
691  #undef ENCODE
692  
693  	if (WARN_ON(tok != ntoks))
694  		return -EIO;
695  	if (WARN_ON((unsigned long)xdr - (unsigned long)buffer != size))
696  		return -EIO;
697  	_leave(" = %zu", size);
698  	return size;
699  }
700