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