rmisec.c revision 212763
1/*-
2 * Copyright (c) 2003-2009 RMI Corporation
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of RMI Corporation, nor the names of its contributors,
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * RMI_BSD
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD: head/sys/mips/rmi/dev/sec/rmisec.c 212763 2010-09-16 20:23:22Z jchandra $");
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/proc.h>
38#include <sys/errno.h>
39#include <sys/malloc.h>
40#include <sys/kernel.h>
41#include <sys/module.h>
42#include <sys/mbuf.h>
43#include <sys/lock.h>
44#include <sys/mutex.h>
45#include <sys/sysctl.h>
46#include <sys/bus.h>
47#include <sys/random.h>
48#include <sys/rman.h>
49#include <sys/uio.h>
50#include <sys/kobj.h>
51#include <opencrypto/cryptodev.h>
52
53#include "cryptodev_if.h"
54
55#include <vm/vm.h>
56#include <vm/pmap.h>
57
58#include <mips/rmi/dev/sec/rmilib.h>
59
60/* #define RMI_SEC_DEBUG  */
61
62void xlr_sec_print_data(struct cryptop *crp);
63
64static int xlr_sec_newsession(device_t dev, uint32_t * sidp, struct cryptoini *cri);
65static int xlr_sec_freesession(device_t dev, uint64_t tid);
66static int xlr_sec_process(device_t dev, struct cryptop *crp, int hint);
67
68static int xlr_sec_probe(device_t);
69static int xlr_sec_attach(device_t);
70static int xlr_sec_detach(device_t);
71
72
73static device_method_t xlr_sec_methods[] = {
74	/* device interface */
75	DEVMETHOD(device_probe, xlr_sec_probe),
76	DEVMETHOD(device_attach, xlr_sec_attach),
77	DEVMETHOD(device_detach, xlr_sec_detach),
78
79	/* bus interface */
80	DEVMETHOD(bus_print_child, bus_generic_print_child),
81	DEVMETHOD(bus_driver_added, bus_generic_driver_added),
82
83	/* crypto device methods */
84	DEVMETHOD(cryptodev_newsession, xlr_sec_newsession),
85	DEVMETHOD(cryptodev_freesession,xlr_sec_freesession),
86	DEVMETHOD(cryptodev_process,    xlr_sec_process),
87
88	{0, 0}
89};
90
91static driver_t xlr_sec_driver = {
92	"rmisec",
93	xlr_sec_methods,
94	sizeof(struct xlr_sec_softc)
95};
96static devclass_t xlr_sec_devclass;
97
98DRIVER_MODULE(rmisec, iodi, xlr_sec_driver, xlr_sec_devclass, 0, 0);
99MODULE_DEPEND(rmisec, crypto, 1, 1, 1);
100
101static int
102xlr_sec_probe(device_t dev)
103{
104
105	device_set_desc(dev, "XLR Security Accelerator");
106	return (BUS_PROBE_DEFAULT);
107}
108
109/*
110 * Attach an interface that successfully probed.
111 */
112static int
113xlr_sec_attach(device_t dev)
114{
115	struct xlr_sec_softc *sc = device_get_softc(dev);
116
117	sc->sc_dev = dev;
118	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "rmi crypto driver",
119	    MTX_DEF);
120	sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE);
121	if (sc->sc_cid < 0) {
122		printf("xlr_sec - error : could not get the driver id\n");
123		goto error_exit;
124	}
125	if (crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0) != 0)
126		printf("register failed for CRYPTO_DES_CBC\n");
127
128	if (crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0) != 0)
129		printf("register failed for CRYPTO_3DES_CBC\n");
130
131	if (crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0) != 0)
132		printf("register failed for CRYPTO_AES_CBC\n");
133
134	if (crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0) != 0)
135		printf("register failed for CRYPTO_ARC4\n");
136
137	if (crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0) != 0)
138		printf("register failed for CRYPTO_MD5\n");
139
140	if (crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0) != 0)
141		printf("register failed for CRYPTO_SHA1\n");
142
143	if (crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0) != 0)
144		printf("register failed for CRYPTO_MD5_HMAC\n");
145
146	if (crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0) != 0)
147		printf("register failed for CRYPTO_SHA1_HMAC\n");
148
149	xlr_sec_init(sc);
150	device_printf(dev, "Initialization complete!\n");
151	return (0);
152
153error_exit:
154	return (ENXIO);
155
156}
157
158/*
159 * Detach an interface that successfully probed.
160 */
161static int
162xlr_sec_detach(device_t dev)
163{
164	int sesn;
165	struct xlr_sec_softc *sc = device_get_softc(dev);
166	struct xlr_sec_session *ses = NULL;
167	symkey_desc_pt desc;
168
169	for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
170		ses = &sc->sc_sessions[sesn];
171		desc = (symkey_desc_pt) ses->desc_ptr;
172		free(desc->user.kern_src, M_DEVBUF);
173		free(desc->user.kern_dest, M_DEVBUF);
174		free(desc->next_src_buf, M_DEVBUF);
175		free(desc->next_dest_buf, M_DEVBUF);
176		free(ses->desc_ptr, M_DEVBUF);
177	}
178
179	return (0);
180}
181
182/*
183 * Allocate a new 'session' and return an encoded session id.  'sidp'
184 * contains our registration id, and should contain an encoded session
185 * id on successful allocation.
186 */
187static int
188xlr_sec_newsession(device_t dev, u_int32_t *sidp, struct cryptoini *cri)
189{
190	struct cryptoini *c;
191	struct xlr_sec_softc *sc = device_get_softc(dev);
192	int mac = 0, cry = 0, sesn;
193	struct xlr_sec_session *ses = NULL;
194
195	if (sidp == NULL || cri == NULL || sc == NULL)
196		return (EINVAL);
197
198	if (sc->sc_sessions == NULL) {
199		ses = sc->sc_sessions = (struct xlr_sec_session *)malloc(
200		    sizeof(struct xlr_sec_session), M_DEVBUF, M_NOWAIT);
201		if (ses == NULL)
202			return (ENOMEM);
203		sesn = 0;
204		sc->sc_nsessions = 1;
205	} else {
206		for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
207			if (!sc->sc_sessions[sesn].hs_used) {
208				ses = &sc->sc_sessions[sesn];
209				break;
210			}
211		}
212
213		if (ses == NULL) {
214			sesn = sc->sc_nsessions;
215			ses = (struct xlr_sec_session *)malloc((sesn + 1) *
216			    sizeof(struct xlr_sec_session), M_DEVBUF, M_NOWAIT);
217			if (ses == NULL)
218				return (ENOMEM);
219			bcopy(sc->sc_sessions, ses, sesn * sizeof(*ses));
220			bzero(sc->sc_sessions, sesn * sizeof(*ses));
221			free(sc->sc_sessions, M_DEVBUF);
222			sc->sc_sessions = ses;
223			ses = &sc->sc_sessions[sesn];
224			sc->sc_nsessions++;
225		}
226	}
227	bzero(ses, sizeof(*ses));
228	ses->sessionid = sesn;
229	ses->desc_ptr = xlr_sec_allocate_desc(ses);
230	if (ses->desc_ptr == NULL)
231		return (ENOMEM);
232	ses->hs_used = 1;
233
234	for (c = cri; c != NULL; c = c->cri_next) {
235		switch (c->cri_alg) {
236		case CRYPTO_MD5:
237		case CRYPTO_SHA1:
238		case CRYPTO_MD5_HMAC:
239		case CRYPTO_SHA1_HMAC:
240			if (mac)
241				return (EINVAL);
242			mac = 1;
243			ses->hs_mlen = c->cri_mlen;
244			if (ses->hs_mlen == 0) {
245				switch (c->cri_alg) {
246				case CRYPTO_MD5:
247				case CRYPTO_MD5_HMAC:
248					ses->hs_mlen = 16;
249					break;
250				case CRYPTO_SHA1:
251				case CRYPTO_SHA1_HMAC:
252					ses->hs_mlen = 20;
253					break;
254				}
255			}
256			break;
257		case CRYPTO_DES_CBC:
258		case CRYPTO_3DES_CBC:
259		case CRYPTO_AES_CBC:
260			/* XXX this may read fewer, does it matter? */
261			/*
262			 * read_random(ses->hs_iv, c->cri_alg ==
263			 * CRYPTO_AES_CBC ? XLR_SEC_AES_IV_LENGTH :
264			 * XLR_SEC_IV_LENGTH);
265			 */
266			/* FALLTHROUGH */
267		case CRYPTO_ARC4:
268			if (cry)
269				return (EINVAL);
270			cry = 1;
271			break;
272		default:
273			return (EINVAL);
274		}
275	}
276	if (mac == 0 && cry == 0)
277		return (EINVAL);
278
279	*sidp = XLR_SEC_SID(device_get_unit(sc->sc_dev), sesn);
280	return (0);
281}
282
283/*
284 * Deallocate a session.
285 * XXX this routine should run a zero'd mac/encrypt key into context ram.
286 * XXX to blow away any keys already stored there.
287 */
288static int
289xlr_sec_freesession(device_t dev, u_int64_t tid)
290{
291	struct xlr_sec_softc *sc = device_get_softc(dev);
292	int session;
293	u_int32_t sid = CRYPTO_SESID2LID(tid);
294
295	if (sc == NULL)
296		return (EINVAL);
297
298	session = XLR_SEC_SESSION(sid);
299	if (session >= sc->sc_nsessions)
300		return (EINVAL);
301
302	sc->sc_sessions[session].hs_used = 0;
303	return (0);
304}
305
306#ifdef RMI_SEC_DEBUG
307
308void
309xlr_sec_print_data(struct cryptop *crp)
310{
311	int i, key_len;
312	struct cryptodesc *crp_desc;
313
314	printf("session id = 0x%llx, crp_ilen = %d, crp_olen=%d \n",
315	    crp->crp_sid, crp->crp_ilen, crp->crp_olen);
316
317	printf("crp_flags = 0x%x\n", crp->crp_flags);
318
319
320	printf("crp buf:\n");
321	for (i = 0; i < crp->crp_ilen; i++) {
322		printf("%c  ", crp->crp_buf[i]);
323		if (i % 10 == 0)
324			printf("\n");
325	}
326
327	printf("\n");
328	printf("****************** desc ****************\n");
329	crp_desc = crp->crp_desc;
330	printf("crd_skip=%d, crd_len=%d, crd_flags=0x%x, crd_alg=%d\n",
331	    crp_desc->crd_skip, crp_desc->crd_len, crp_desc->crd_flags, crp_desc->crd_alg);
332
333	key_len = crp_desc->crd_klen / 8;
334	printf("key(%d) :\n", key_len);
335	for (i = 0; i < key_len; i++)
336		printf("%d", crp_desc->crd_key[i]);
337	printf("\n");
338
339	printf(" IV : \n");
340	for (i = 0; i < EALG_MAX_BLOCK_LEN; i++)
341		printf("%d", crp_desc->crd_iv[i]);
342	printf("\n");
343
344	printf("crd_next=%p\n", crp_desc->crd_next);
345	return;
346}
347
348#endif
349
350static int
351xlr_sec_process(device_t dev, struct cryptop *crp, int hint)
352{
353	struct xlr_sec_softc *sc = device_get_softc(dev);
354	struct xlr_sec_command *cmd = NULL;
355	int session, err;
356	struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
357	struct xlr_sec_session *ses;
358
359	if (crp == NULL || crp->crp_callback == NULL) {
360		return (EINVAL);
361	}
362	session = XLR_SEC_SESSION(crp->crp_sid);
363	if (sc == NULL || session >= sc->sc_nsessions) {
364		err = EINVAL;
365		goto errout;
366	}
367	ses = &sc->sc_sessions[session];
368
369	cmd = &ses->cmd;
370	if (cmd == NULL) {
371		err = ENOMEM;
372		goto errout;
373	}
374	crd1 = crp->crp_desc;
375	if (crd1 == NULL) {
376		err = EINVAL;
377		goto errout;
378	}
379	crd2 = crd1->crd_next;
380
381	if (crd2 == NULL) {
382		if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
383		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
384		    crd1->crd_alg == CRYPTO_SHA1 ||
385		    crd1->crd_alg == CRYPTO_MD5) {
386			maccrd = crd1;
387			enccrd = NULL;
388		} else if (crd1->crd_alg == CRYPTO_DES_CBC ||
389			    crd1->crd_alg == CRYPTO_3DES_CBC ||
390			    crd1->crd_alg == CRYPTO_AES_CBC ||
391		    crd1->crd_alg == CRYPTO_ARC4) {
392			maccrd = NULL;
393			enccrd = crd1;
394		} else {
395			err = EINVAL;
396			goto errout;
397		}
398	} else {
399		if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
400		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
401		    crd1->crd_alg == CRYPTO_MD5 ||
402		    crd1->crd_alg == CRYPTO_SHA1) &&
403		    (crd2->crd_alg == CRYPTO_DES_CBC ||
404		    crd2->crd_alg == CRYPTO_3DES_CBC ||
405		    crd2->crd_alg == CRYPTO_AES_CBC ||
406		    crd2->crd_alg == CRYPTO_ARC4)) {
407			maccrd = crd1;
408			enccrd = crd2;
409		} else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
410			    crd1->crd_alg == CRYPTO_ARC4 ||
411			    crd1->crd_alg == CRYPTO_3DES_CBC ||
412			    crd1->crd_alg == CRYPTO_AES_CBC) &&
413			    (crd2->crd_alg == CRYPTO_MD5_HMAC ||
414			    crd2->crd_alg == CRYPTO_SHA1_HMAC ||
415			    crd2->crd_alg == CRYPTO_MD5 ||
416			    crd2->crd_alg == CRYPTO_SHA1) &&
417		    (crd1->crd_flags & CRD_F_ENCRYPT)) {
418			enccrd = crd1;
419			maccrd = crd2;
420		} else {
421			err = EINVAL;
422			goto errout;
423		}
424	}
425
426	bzero(&cmd->op, sizeof(xlr_sec_io_t));
427
428	cmd->op.source_buf = (uint64_t) (unsigned long)crp->crp_buf;
429	cmd->op.source_buf_size = crp->crp_ilen;
430	if (crp->crp_flags & CRYPTO_F_REL) {
431		cmd->op.dest_buf = (uint64_t) (unsigned long)crp->crp_buf;
432		cmd->op.dest_buf_size = crp->crp_ilen;
433	} else {
434		cmd->op.dest_buf = (uint64_t) (unsigned long)crp->crp_buf;
435		cmd->op.dest_buf_size = crp->crp_ilen;
436	}
437	cmd->op.num_packets = 1;
438	cmd->op.num_fragments = 1;
439
440	if (cmd->op.source_buf_size > SEC_MAX_FRAG_LEN) {
441		ses->multi_frag_flag = 1;
442	} else {
443		ses->multi_frag_flag = 0;
444	}
445
446	if (maccrd) {
447		cmd->maccrd = maccrd;
448		cmd->op.cipher_op = XLR_SEC_CIPHER_MODE_PASS;
449		cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_NONE;
450		cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_NONE;
451		cmd->op.cipher_init = 0;
452		cmd->op.cipher_offset = 0;
453
454		switch (maccrd->crd_alg) {
455		case CRYPTO_MD5:
456			cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_MD5;
457			cmd->op.digest_init = XLR_SEC_DIGEST_INIT_NEWKEY;
458			cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
459			cmd->op.digest_offset = 0;
460
461			cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
462			cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
463			cmd->op.cksum_offset = 0;
464
465			cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
466			cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
467			cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
468			cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
469			cmd->op.pkt_iv = XLR_SEC_PKT_IV_OLD;
470			cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
471
472		default:
473			printf("currently not handled\n");
474		}
475	}
476	if (enccrd) {
477		cmd->enccrd = enccrd;
478
479#ifdef RMI_SEC_DEBUG
480		xlr_sec_print_data(crp);
481#endif
482
483		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
484			cmd->op.cipher_op = XLR_SEC_CIPHER_OP_ENCRYPT;
485		} else
486			cmd->op.cipher_op = XLR_SEC_CIPHER_OP_DECRYPT;
487
488		switch (enccrd->crd_alg) {
489		case CRYPTO_DES_CBC:
490		case CRYPTO_3DES_CBC:
491			if (enccrd->crd_alg == CRYPTO_DES_CBC) {
492				cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_DES;
493				memcpy(&cmd->op.crypt_key[0], enccrd->crd_key, XLR_SEC_DES_KEY_LENGTH);
494			} else {
495				cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_3DES;
496				//if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
497				{
498					memcpy(&cmd->op.crypt_key[0], enccrd->crd_key,
499					    XLR_SEC_3DES_KEY_LENGTH);
500				}
501			}
502
503			cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_CBC;
504			cmd->op.cipher_init = XLR_SEC_CIPHER_INIT_NK;
505			cmd->op.cipher_offset = XLR_SEC_DES_IV_LENGTH;
506
507			cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_NONE;
508			cmd->op.digest_init = XLR_SEC_DIGEST_INIT_OLDKEY;
509			cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
510			cmd->op.digest_offset = 0;
511
512			cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
513			cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
514			cmd->op.cksum_offset = 0;
515
516			cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
517			cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
518			cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
519			cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
520			cmd->op.pkt_iv = XLR_SEC_PKT_IV_NEW;
521			cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
522
523			//if ((!(enccrd->crd_flags & CRD_F_IV_PRESENT)) &&
524			if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT)) {
525				memcpy(&cmd->op.initial_vector[0], enccrd->crd_iv,
526				    XLR_SEC_DES_IV_LENGTH);
527			}
528			break;
529
530		case CRYPTO_AES_CBC:
531			if (enccrd->crd_alg == CRYPTO_AES_CBC) {
532				cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_AES128;
533				//if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT)
534				{
535					memcpy(&cmd->op.crypt_key[0], enccrd->crd_key,
536					    XLR_SEC_AES128_KEY_LENGTH);
537				}
538			}
539			cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_CBC;
540			cmd->op.cipher_init = XLR_SEC_CIPHER_INIT_NK;
541			cmd->op.cipher_offset = XLR_SEC_AES_BLOCK_SIZE;
542
543			cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_NONE;
544			cmd->op.digest_init = XLR_SEC_DIGEST_INIT_OLDKEY;
545			cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
546			cmd->op.digest_offset = 0;
547
548			cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
549			cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
550			cmd->op.cksum_offset = 0;
551
552			cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
553			cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
554			cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
555			cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
556			cmd->op.pkt_iv = XLR_SEC_PKT_IV_NEW;
557			cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
558
559			//if (!(enccrd->crd_flags & CRD_F_IV_PRESENT)) {
560			if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT)) {
561				memcpy(&cmd->op.initial_vector[0], enccrd->crd_iv,
562				    XLR_SEC_AES_BLOCK_SIZE);
563			}
564			//}
565			break;
566		}
567	}
568	cmd->crp = crp;
569	cmd->session_num = session;
570	xlr_sec_setup(ses, cmd, (symkey_desc_pt) ses->desc_ptr);
571
572	return (0);
573
574errout:
575	if (cmd != NULL)
576		free(cmd, M_DEVBUF);
577	crp->crp_etype = err;
578	crypto_done(crp);
579	return (err);
580}
581