rmisec.c revision 198627
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/param.h>
33#include <sys/systm.h>
34#include <sys/proc.h>
35#include <sys/errno.h>
36#include <sys/malloc.h>
37#include <sys/kernel.h>
38#include <sys/module.h>
39#include <sys/mbuf.h>
40#include <sys/lock.h>
41#include <sys/mutex.h>
42#include <sys/sysctl.h>
43
44#include <vm/vm.h>
45#include <vm/pmap.h>
46
47#include <machine/bus.h>
48#include <machine/resource.h>
49#include <sys/bus.h>
50#include <sys/rman.h>
51
52#include <opencrypto/cryptodev.h>
53#include <sys/random.h>
54
55#include <dev/rmi/sec/rmilib.h>
56
57/*#define RMI_SEC_DEBUG */
58
59
60void xlr_sec_print_data(struct cryptop *crp);
61
62static int xlr_sec_newsession(void *arg, uint32_t * sidp, struct cryptoini *cri);
63static int xlr_sec_freesession(void *arg, uint64_t tid);
64static int xlr_sec_process(void *arg, struct cryptop *crp, int hint);
65
66
67static int xlr_sec_probe(device_t);
68static int xlr_sec_attach(device_t);
69static int xlr_sec_detach(device_t);
70
71
72static device_method_t xlr_sec_methods[] = {
73	/* device interface */
74	DEVMETHOD(device_probe, xlr_sec_probe),
75	DEVMETHOD(device_attach, xlr_sec_attach),
76	DEVMETHOD(device_detach, xlr_sec_detach),
77
78	/* bus interface */
79	DEVMETHOD(bus_print_child, bus_generic_print_child),
80	DEVMETHOD(bus_driver_added, bus_generic_driver_added),
81
82	{0, 0}
83};
84
85static driver_t xlr_sec_driver = {
86	"rmisec",
87	xlr_sec_methods,
88	sizeof(struct xlr_sec_softc)
89};
90static devclass_t xlr_sec_devclass;
91
92DRIVER_MODULE(rmisec, iodi, xlr_sec_driver, xlr_sec_devclass, 0, 0);
93MODULE_DEPEND(rmisec, crypto, 1, 1, 1);
94
95
96
97static int
98xlr_sec_probe(device_t dev)
99{
100	return (BUS_PROBE_DEFAULT);
101
102}
103
104
105/*
106 * Attach an interface that successfully probed.
107 */
108static int
109xlr_sec_attach(device_t dev)
110{
111
112	struct xlr_sec_softc *sc = device_get_softc(dev);
113
114	bzero(sc, sizeof(*sc));
115	sc->sc_dev = dev;
116
117
118	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "rmi crypto driver", MTX_DEF);
119
120	sc->sc_cid = crypto_get_driverid(0);
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,
126	    xlr_sec_newsession, xlr_sec_freesession, xlr_sec_process, sc) != 0)
127		printf("register failed for CRYPTO_DES_CBC\n");
128
129	if (crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0,
130	    xlr_sec_newsession, xlr_sec_freesession, xlr_sec_process, sc) != 0)
131		printf("register failed for CRYPTO_3DES_CBC\n");
132
133	if (crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0,
134	    xlr_sec_newsession, xlr_sec_freesession,
135	    xlr_sec_process, sc) != 0)
136		printf("register failed for CRYPTO_AES_CBC\n");
137
138	if (crypto_register(sc->sc_cid, CRYPTO_ARC4, 0, 0,
139	    xlr_sec_newsession, xlr_sec_freesession, xlr_sec_process, sc) != 0)
140		printf("register failed for CRYPTO_ARC4\n");
141
142
143	if (crypto_register(sc->sc_cid, CRYPTO_MD5, 0, 0,
144	    xlr_sec_newsession, xlr_sec_freesession, xlr_sec_process, sc) != 0)
145		printf("register failed for CRYPTO_MD5\n");
146
147	if (crypto_register(sc->sc_cid, CRYPTO_SHA1, 0, 0,
148	    xlr_sec_newsession, xlr_sec_freesession, xlr_sec_process, sc) != 0)
149		printf("register failed for CRYPTO_SHA1\n");
150
151	if (crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0,
152	    xlr_sec_newsession, xlr_sec_freesession, xlr_sec_process, sc) != 0)
153		printf("register failed for CRYPTO_MD5_HMAC\n");
154
155	if (crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0,
156	    xlr_sec_newsession, xlr_sec_freesession, xlr_sec_process, sc) != 0)
157		printf("register failed for CRYPTO_SHA1_HMAC\n");
158
159
160	xlr_sec_init(sc);
161	return (0);
162
163
164error_exit:
165	return (ENXIO);
166
167}
168
169
170/*
171 * Detach an interface that successfully probed.
172 */
173static int
174xlr_sec_detach(device_t dev)
175{
176	int sesn;
177	struct xlr_sec_softc *sc = device_get_softc(dev);
178	struct xlr_sec_session *ses = NULL;
179	symkey_desc_pt desc;
180
181	for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
182		ses = &sc->sc_sessions[sesn];
183		desc = (symkey_desc_pt) ses->desc_ptr;
184		free(desc->user.kern_src, M_DEVBUF);
185		free(desc->user.kern_dest, M_DEVBUF);
186		free(desc->next_src_buf, M_DEVBUF);
187		free(desc->next_dest_buf, M_DEVBUF);
188		free(ses->desc_ptr, M_DEVBUF);
189	}
190
191	return (0);
192}
193
194
195
196
197/*
198 * Allocate a new 'session' and return an encoded session id.  'sidp'
199 * contains our registration id, and should contain an encoded session
200 * id on successful allocation.
201 */
202static int
203xlr_sec_newsession(void *arg, u_int32_t * sidp, struct cryptoini *cri)
204{
205	struct cryptoini *c;
206	struct xlr_sec_softc *sc = arg;
207	int mac = 0, cry = 0, sesn;
208	struct xlr_sec_session *ses = NULL;
209
210
211	if (sidp == NULL || cri == NULL || sc == NULL)
212		return (EINVAL);
213
214
215	if (sc->sc_sessions == NULL) {
216		ses = sc->sc_sessions = (struct xlr_sec_session *)malloc(
217		    sizeof(struct xlr_sec_session), M_DEVBUF, M_NOWAIT);
218		if (ses == NULL)
219			return (ENOMEM);
220
221		ses->desc_ptr = (void *)xlr_sec_allocate_desc((void *)ses);
222		if (ses->desc_ptr == NULL)
223			return (ENOMEM);
224
225		sesn = 0;
226		ses->sessionid = sesn;
227		sc->sc_nsessions = 1;
228	} else {
229		for (sesn = 0; sesn < sc->sc_nsessions; sesn++) {
230			if (!sc->sc_sessions[sesn].hs_used) {
231				ses = &sc->sc_sessions[sesn];
232				break;
233			}
234		}
235
236		if (ses == NULL) {
237			sesn = sc->sc_nsessions;
238			ses = (struct xlr_sec_session *)malloc((sesn + 1) *
239			    sizeof(struct xlr_sec_session), M_DEVBUF, M_NOWAIT);
240			if (ses == NULL)
241				return (ENOMEM);
242			bcopy(sc->sc_sessions, ses, sesn * sizeof(struct xlr_sec_session));
243			bzero(sc->sc_sessions, sesn * sizeof(struct xlr_sec_session));
244			free(sc->sc_sessions, M_DEVBUF);
245			sc->sc_sessions = ses;
246			ses = &sc->sc_sessions[sesn];
247			ses->sessionid = sesn;
248			ses->desc_ptr = (void *)xlr_sec_allocate_desc((void *)ses);
249			if (ses->desc_ptr == NULL)
250				return (ENOMEM);
251			sc->sc_nsessions++;
252		}
253	}
254	ses->hs_used = 1;
255
256
257	for (c = cri; c != NULL; c = c->cri_next) {
258
259		switch (c->cri_alg) {
260		case CRYPTO_MD5:
261		case CRYPTO_SHA1:
262		case CRYPTO_MD5_HMAC:
263		case CRYPTO_SHA1_HMAC:
264			if (mac)
265				return (EINVAL);
266			mac = 1;
267			ses->hs_mlen = c->cri_mlen;
268			if (ses->hs_mlen == 0) {
269				switch (c->cri_alg) {
270				case CRYPTO_MD5:
271				case CRYPTO_MD5_HMAC:
272					ses->hs_mlen = 16;
273					break;
274				case CRYPTO_SHA1:
275				case CRYPTO_SHA1_HMAC:
276					ses->hs_mlen = 20;
277					break;
278				}
279			}
280			break;
281		case CRYPTO_DES_CBC:
282		case CRYPTO_3DES_CBC:
283		case CRYPTO_AES_CBC:
284			/* XXX this may read fewer, does it matter? */
285			/*
286			 * read_random(ses->hs_iv, c->cri_alg ==
287			 * CRYPTO_AES_CBC ? XLR_SEC_AES_IV_LENGTH :
288			 * XLR_SEC_IV_LENGTH);
289			 */
290			/* FALLTHROUGH */
291		case CRYPTO_ARC4:
292			if (cry)
293				return (EINVAL);
294			cry = 1;
295			break;
296		default:
297			return (EINVAL);
298		}
299	}
300	if (mac == 0 && cry == 0)
301		return (EINVAL);
302
303	*sidp = XLR_SEC_SID(device_get_unit(sc->sc_dev), sesn);
304	return (0);
305}
306
307/*
308 * Deallocate a session.
309 * XXX this routine should run a zero'd mac/encrypt key into context ram.
310 * XXX to blow away any keys already stored there.
311 */
312static int
313xlr_sec_freesession(void *arg, u_int64_t tid)
314{
315	struct xlr_sec_softc *sc = arg;
316	int session;
317	u_int32_t sid = CRYPTO_SESID2LID(tid);
318
319	if (sc == NULL)
320		return (EINVAL);
321
322	session = XLR_SEC_SESSION(sid);
323	if (session >= sc->sc_nsessions)
324		return (EINVAL);
325
326	sc->sc_sessions[session].hs_used = 0;
327
328	return (0);
329}
330
331#ifdef RMI_SEC_DEBUG
332
333void
334xlr_sec_print_data(struct cryptop *crp)
335{
336	int i, key_len;
337	struct cryptodesc *crp_desc;
338
339	printf("session id = 0x%llx, crp_ilen = %d, crp_olen=%d \n",
340	    crp->crp_sid, crp->crp_ilen, crp->crp_olen);
341
342	printf("crp_flags = 0x%x\n", crp->crp_flags);
343
344
345	printf("crp buf:\n");
346	for (i = 0; i < crp->crp_ilen; i++) {
347		printf("%c  ", crp->crp_buf[i]);
348		if (i % 10 == 0)
349			printf("\n");
350	}
351
352	printf("\n");
353	printf("****************** desc ****************\n");
354	crp_desc = crp->crp_desc;
355	printf("crd_skip=%d, crd_len=%d, crd_flags=0x%x, crd_alg=%d\n",
356	    crp_desc->crd_skip, crp_desc->crd_len, crp_desc->crd_flags, crp_desc->crd_alg);
357
358	key_len = crp_desc->crd_klen / 8;
359	printf("key(%d) :\n", key_len);
360	for (i = 0; i < key_len; i++)
361		printf("%d", crp_desc->crd_key[i]);
362	printf("\n");
363
364	printf(" IV : \n");
365	for (i = 0; i < EALG_MAX_BLOCK_LEN; i++)
366		printf("%d", crp_desc->crd_iv[i]);
367	printf("\n");
368
369	printf("crd_next=%p\n", crp_desc->crd_next);
370	return;
371}
372
373#endif
374
375
376static int
377xlr_sec_process(void *arg, struct cryptop *crp, int hint)
378{
379	struct xlr_sec_softc *sc = arg;
380	struct xlr_sec_command *cmd = NULL;
381	int session, err;
382	struct cryptodesc *crd1, *crd2, *maccrd, *enccrd;
383	struct xlr_sec_session *ses;
384
385	if (crp == NULL || crp->crp_callback == NULL) {
386		return (EINVAL);
387	}
388	session = XLR_SEC_SESSION(crp->crp_sid);
389	if (sc == NULL || session >= sc->sc_nsessions) {
390		err = EINVAL;
391		goto errout;
392	}
393	ses = &sc->sc_sessions[session];
394
395	cmd = &ses->cmd;
396	if (cmd == NULL) {
397		err = ENOMEM;
398		goto errout;
399	}
400	crd1 = crp->crp_desc;
401	if (crd1 == NULL) {
402		err = EINVAL;
403		goto errout;
404	}
405	crd2 = crd1->crd_next;
406
407	if (crd2 == NULL) {
408		if (crd1->crd_alg == CRYPTO_MD5_HMAC ||
409		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
410		    crd1->crd_alg == CRYPTO_SHA1 ||
411		    crd1->crd_alg == CRYPTO_MD5) {
412			maccrd = crd1;
413			enccrd = NULL;
414		} else if (crd1->crd_alg == CRYPTO_DES_CBC ||
415			    crd1->crd_alg == CRYPTO_3DES_CBC ||
416			    crd1->crd_alg == CRYPTO_AES_CBC ||
417		    crd1->crd_alg == CRYPTO_ARC4) {
418			maccrd = NULL;
419			enccrd = crd1;
420		} else {
421			err = EINVAL;
422			goto errout;
423		}
424	} else {
425		if ((crd1->crd_alg == CRYPTO_MD5_HMAC ||
426		    crd1->crd_alg == CRYPTO_SHA1_HMAC ||
427		    crd1->crd_alg == CRYPTO_MD5 ||
428		    crd1->crd_alg == CRYPTO_SHA1) &&
429		    (crd2->crd_alg == CRYPTO_DES_CBC ||
430		    crd2->crd_alg == CRYPTO_3DES_CBC ||
431		    crd2->crd_alg == CRYPTO_AES_CBC ||
432		    crd2->crd_alg == CRYPTO_ARC4)) {
433			maccrd = crd1;
434			enccrd = crd2;
435		} else if ((crd1->crd_alg == CRYPTO_DES_CBC ||
436			    crd1->crd_alg == CRYPTO_ARC4 ||
437			    crd1->crd_alg == CRYPTO_3DES_CBC ||
438			    crd1->crd_alg == CRYPTO_AES_CBC) &&
439			    (crd2->crd_alg == CRYPTO_MD5_HMAC ||
440			    crd2->crd_alg == CRYPTO_SHA1_HMAC ||
441			    crd2->crd_alg == CRYPTO_MD5 ||
442			    crd2->crd_alg == CRYPTO_SHA1) &&
443		    (crd1->crd_flags & CRD_F_ENCRYPT)) {
444			enccrd = crd1;
445			maccrd = crd2;
446		} else {
447			err = EINVAL;
448			goto errout;
449		}
450	}
451
452	bzero(&cmd->op, sizeof(xlr_sec_io_t));
453
454	cmd->op.source_buf = (uint64_t) (unsigned long)crp->crp_buf;
455	cmd->op.source_buf_size = crp->crp_ilen;
456	if (crp->crp_flags & CRYPTO_F_REL) {
457		cmd->op.dest_buf = (uint64_t) (unsigned long)crp->crp_buf;
458		cmd->op.dest_buf_size = crp->crp_ilen;
459	} else {
460		cmd->op.dest_buf = (uint64_t) (unsigned long)crp->crp_buf;
461		cmd->op.dest_buf_size = crp->crp_ilen;
462	}
463	cmd->op.num_packets = 1;
464	cmd->op.num_fragments = 1;
465
466
467	if (cmd->op.source_buf_size > SEC_MAX_FRAG_LEN) {
468		ses->multi_frag_flag = 1;
469	} else {
470		ses->multi_frag_flag = 0;
471	}
472
473	if (maccrd) {
474		cmd->maccrd = maccrd;
475		cmd->op.cipher_op = XLR_SEC_CIPHER_MODE_PASS;
476		cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_NONE;
477		cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_NONE;
478		cmd->op.cipher_init = 0;
479		cmd->op.cipher_offset = 0;
480
481		switch (maccrd->crd_alg) {
482		case CRYPTO_MD5:
483			cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_MD5;
484			cmd->op.digest_init = XLR_SEC_DIGEST_INIT_NEWKEY;
485			cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
486			cmd->op.digest_offset = 0;
487
488			cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
489			cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
490			cmd->op.cksum_offset = 0;
491
492			cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
493			cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
494			cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
495			cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
496			cmd->op.pkt_iv = XLR_SEC_PKT_IV_OLD;
497			cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
498
499
500		default:
501			printf("currently not handled\n");
502		}
503	}
504	if (enccrd) {
505		cmd->enccrd = enccrd;
506
507#ifdef RMI_SEC_DEBUG
508		xlr_sec_print_data(crp);
509#endif
510
511		if (enccrd->crd_flags & CRD_F_ENCRYPT) {
512			cmd->op.cipher_op = XLR_SEC_CIPHER_OP_ENCRYPT;
513		} else
514			cmd->op.cipher_op = XLR_SEC_CIPHER_OP_DECRYPT;
515
516		switch (enccrd->crd_alg) {
517		case CRYPTO_DES_CBC:
518		case CRYPTO_3DES_CBC:
519			if (enccrd->crd_alg == CRYPTO_DES_CBC) {
520				cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_DES;
521				memcpy(&cmd->op.crypt_key[0], enccrd->crd_key, XLR_SEC_DES_KEY_LENGTH);
522			} else {
523				cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_3DES;
524				//if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
525					memcpy(&cmd->op.crypt_key[0], enccrd->crd_key, XLR_SEC_3DES_KEY_LENGTH);
526				}
527			}
528
529			cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_CBC;
530			cmd->op.cipher_init = XLR_SEC_CIPHER_INIT_NK;
531			cmd->op.cipher_offset = XLR_SEC_DES_IV_LENGTH;
532
533			cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_NONE;
534			cmd->op.digest_init = XLR_SEC_DIGEST_INIT_OLDKEY;
535			cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
536			cmd->op.digest_offset = 0;
537
538			cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
539			cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
540			cmd->op.cksum_offset = 0;
541
542			cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
543			cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
544			cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
545			cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
546			cmd->op.pkt_iv = XLR_SEC_PKT_IV_NEW;
547			cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
548
549			//if ((!(enccrd->crd_flags & CRD_F_IV_PRESENT)) &&
550				    if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT)) {
551				memcpy(&cmd->op.initial_vector[0], enccrd->crd_iv, XLR_SEC_DES_IV_LENGTH);
552				}
553			break;
554
555		case CRYPTO_AES_CBC:
556			if (enccrd->crd_alg == CRYPTO_AES_CBC) {
557				cmd->op.cipher_type = XLR_SEC_CIPHER_TYPE_AES128;
558				//if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) {
559					memcpy(&cmd->op.crypt_key[0], enccrd->crd_key, XLR_SEC_AES128_KEY_LENGTH);
560				}
561			}
562			cmd->op.cipher_mode = XLR_SEC_CIPHER_MODE_CBC;
563			cmd->op.cipher_init = XLR_SEC_CIPHER_INIT_NK;
564			cmd->op.cipher_offset = XLR_SEC_AES_BLOCK_SIZE;
565
566			cmd->op.digest_type = XLR_SEC_DIGEST_TYPE_NONE;
567			cmd->op.digest_init = XLR_SEC_DIGEST_INIT_OLDKEY;
568			cmd->op.digest_src = XLR_SEC_DIGEST_SRC_DMA;
569			cmd->op.digest_offset = 0;
570
571			cmd->op.cksum_type = XLR_SEC_CKSUM_TYPE_NOP;
572			cmd->op.cksum_src = XLR_SEC_CKSUM_SRC_CIPHER;
573			cmd->op.cksum_offset = 0;
574
575			cmd->op.pkt_hmac = XLR_SEC_LOADHMACKEY_MODE_OLD;
576			cmd->op.pkt_hash = XLR_SEC_PADHASH_PAD;
577			cmd->op.pkt_hashbytes = XLR_SEC_HASHBYTES_ALL8;
578			cmd->op.pkt_next = XLR_SEC_NEXT_FINISH;
579			cmd->op.pkt_iv = XLR_SEC_PKT_IV_NEW;
580			cmd->op.pkt_lastword = XLR_SEC_LASTWORD_128;
581
582			//if (!(enccrd->crd_flags & CRD_F_IV_PRESENT)) {
583				if ((enccrd->crd_flags & CRD_F_IV_EXPLICIT)) {
584					memcpy(&cmd->op.initial_vector[0], enccrd->crd_iv, XLR_SEC_AES_BLOCK_SIZE);
585				}
586				//
587			}
588			break;
589		}
590	}
591	cmd->crp = crp;
592	cmd->session_num = session;
593	xlr_sec_setup(ses, cmd, (symkey_desc_pt) ses->desc_ptr);
594
595	return (0);
596
597errout:
598	if (cmd != NULL)
599		free(cmd, M_DEVBUF);
600	crp->crp_etype = err;
601	crypto_done(crp);
602	return (err);
603}
604