1210312Sjmallett/* 2210312Sjmallett * Octeon Crypto for OCF 3210312Sjmallett * 4210312Sjmallett * Written by David McCullough <david_mccullough@securecomputing.com> 5210312Sjmallett * Copyright (C) 2009 David McCullough 6210312Sjmallett * 7210312Sjmallett * LICENSE TERMS 8210312Sjmallett * 9210312Sjmallett * The free distribution and use of this software in both source and binary 10210312Sjmallett * form is allowed (with or without changes) provided that: 11210312Sjmallett * 12210312Sjmallett * 1. distributions of this source code include the above copyright 13210312Sjmallett * notice, this list of conditions and the following disclaimer; 14210312Sjmallett * 15210312Sjmallett * 2. distributions in binary form include the above copyright 16210312Sjmallett * notice, this list of conditions and the following disclaimer 17210312Sjmallett * in the documentation and/or other associated materials; 18210312Sjmallett * 19210312Sjmallett * 3. the copyright holder's name is not used to endorse products 20210312Sjmallett * built using this software without specific written permission. 21210312Sjmallett * 22210312Sjmallett * DISCLAIMER 23210312Sjmallett * 24210312Sjmallett * This software is provided 'as is' with no explicit or implied warranties 25210312Sjmallett * in respect of its properties, including, but not limited to, correctness 26210312Sjmallett * and/or fitness for purpose. 27210312Sjmallett * --------------------------------------------------------------------------- 28210312Sjmallett */ 29210312Sjmallett 30210312Sjmallett#include <sys/cdefs.h> 31210312Sjmallett__FBSDID("$FreeBSD: releng/10.3/sys/mips/cavium/cryptocteon/cryptocteon.c 210312 2010-07-20 19:32:25Z jmallett $"); 32210312Sjmallett 33210312Sjmallett#include <sys/param.h> 34210312Sjmallett#include <sys/systm.h> 35210312Sjmallett#include <sys/bus.h> 36210312Sjmallett#include <sys/kernel.h> 37210312Sjmallett#include <sys/module.h> 38210312Sjmallett#include <sys/malloc.h> 39210312Sjmallett#include <sys/mbuf.h> 40210312Sjmallett#include <sys/uio.h> 41210312Sjmallett 42210312Sjmallett#include <opencrypto/cryptodev.h> 43210312Sjmallett 44210312Sjmallett#include <contrib/octeon-sdk/cvmx.h> 45210312Sjmallett 46210312Sjmallett#include <mips/cavium/cryptocteon/cryptocteonvar.h> 47210312Sjmallett 48210312Sjmallett#include "cryptodev_if.h" 49210312Sjmallett 50210312Sjmallettstruct cryptocteon_softc { 51210312Sjmallett int32_t sc_cid; /* opencrypto id */ 52210312Sjmallett struct octo_sess **sc_sessions; 53210312Sjmallett uint32_t sc_sesnum; 54210312Sjmallett}; 55210312Sjmallett 56210312Sjmallettint cryptocteon_debug = 0; 57210312SjmallettTUNABLE_INT("hw.cryptocteon.debug", &cryptocteon_debug); 58210312Sjmallett 59210312Sjmallettstatic void cryptocteon_identify(driver_t *, device_t); 60210312Sjmallettstatic int cryptocteon_probe(device_t); 61210312Sjmallettstatic int cryptocteon_attach(device_t); 62210312Sjmallett 63210312Sjmallettstatic int cryptocteon_process(device_t, struct cryptop *, int); 64210312Sjmallettstatic int cryptocteon_newsession(device_t, u_int32_t *, struct cryptoini *); 65210312Sjmallettstatic int cryptocteon_freesession(device_t, u_int64_t); 66210312Sjmallett 67210312Sjmallettstatic void 68210312Sjmallettcryptocteon_identify(driver_t *drv, device_t parent) 69210312Sjmallett{ 70210312Sjmallett if (octeon_has_feature(OCTEON_FEATURE_CRYPTO)) 71210312Sjmallett BUS_ADD_CHILD(parent, 0, "cryptocteon", 0); 72210312Sjmallett} 73210312Sjmallett 74210312Sjmallettstatic int 75210312Sjmallettcryptocteon_probe(device_t dev) 76210312Sjmallett{ 77210312Sjmallett device_set_desc(dev, "Octeon Secure Coprocessor"); 78210312Sjmallett return (0); 79210312Sjmallett} 80210312Sjmallett 81210312Sjmallettstatic int 82210312Sjmallettcryptocteon_attach(device_t dev) 83210312Sjmallett{ 84210312Sjmallett struct cryptocteon_softc *sc; 85210312Sjmallett 86210312Sjmallett sc = device_get_softc(dev); 87210312Sjmallett 88210312Sjmallett sc->sc_cid = crypto_get_driverid(dev, CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SYNC); 89210312Sjmallett if (sc->sc_cid < 0) { 90210312Sjmallett device_printf(dev, "crypto_get_driverid ret %d\n", sc->sc_cid); 91210312Sjmallett return (ENXIO); 92210312Sjmallett } 93210312Sjmallett 94210312Sjmallett crypto_register(sc->sc_cid, CRYPTO_MD5_HMAC, 0, 0); 95210312Sjmallett crypto_register(sc->sc_cid, CRYPTO_SHA1_HMAC, 0, 0); 96210312Sjmallett crypto_register(sc->sc_cid, CRYPTO_DES_CBC, 0, 0); 97210312Sjmallett crypto_register(sc->sc_cid, CRYPTO_3DES_CBC, 0, 0); 98210312Sjmallett crypto_register(sc->sc_cid, CRYPTO_AES_CBC, 0, 0); 99210312Sjmallett 100210312Sjmallett return (0); 101210312Sjmallett} 102210312Sjmallett 103210312Sjmallett/* 104210312Sjmallett * Generate a new octo session. We artifically limit it to a single 105210312Sjmallett * hash/cipher or hash-cipher combo just to make it easier, most callers 106210312Sjmallett * do not expect more than this anyway. 107210312Sjmallett */ 108210312Sjmallettstatic int 109210312Sjmallettcryptocteon_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) 110210312Sjmallett{ 111210312Sjmallett struct cryptoini *c, *encini = NULL, *macini = NULL; 112210312Sjmallett struct cryptocteon_softc *sc; 113210312Sjmallett struct octo_sess **ocd; 114210312Sjmallett int i; 115210312Sjmallett 116210312Sjmallett sc = device_get_softc(dev); 117210312Sjmallett 118210312Sjmallett if (sid == NULL || cri == NULL || sc == NULL) 119210312Sjmallett return (EINVAL); 120210312Sjmallett 121210312Sjmallett /* 122210312Sjmallett * To keep it simple, we only handle hash, cipher or hash/cipher in a 123210312Sjmallett * session, you cannot currently do multiple ciphers/hashes in one 124210312Sjmallett * session even though it would be possibel to code this driver to 125210312Sjmallett * handle it. 126210312Sjmallett */ 127210312Sjmallett for (i = 0, c = cri; c && i < 2; i++) { 128210312Sjmallett if (c->cri_alg == CRYPTO_MD5_HMAC || 129210312Sjmallett c->cri_alg == CRYPTO_SHA1_HMAC || 130210312Sjmallett c->cri_alg == CRYPTO_NULL_HMAC) { 131210312Sjmallett if (macini) { 132210312Sjmallett break; 133210312Sjmallett } 134210312Sjmallett macini = c; 135210312Sjmallett } 136210312Sjmallett if (c->cri_alg == CRYPTO_DES_CBC || 137210312Sjmallett c->cri_alg == CRYPTO_3DES_CBC || 138210312Sjmallett c->cri_alg == CRYPTO_AES_CBC || 139210312Sjmallett c->cri_alg == CRYPTO_NULL_CBC) { 140210312Sjmallett if (encini) { 141210312Sjmallett break; 142210312Sjmallett } 143210312Sjmallett encini = c; 144210312Sjmallett } 145210312Sjmallett c = c->cri_next; 146210312Sjmallett } 147210312Sjmallett if (!macini && !encini) { 148210312Sjmallett dprintf("%s,%d - EINVAL bad cipher/hash or combination\n", 149210312Sjmallett __FILE__, __LINE__); 150210312Sjmallett return EINVAL; 151210312Sjmallett } 152210312Sjmallett if (c) { 153210312Sjmallett dprintf("%s,%d - EINVAL cannot handle chained cipher/hash combos\n", 154210312Sjmallett __FILE__, __LINE__); 155210312Sjmallett return EINVAL; 156210312Sjmallett } 157210312Sjmallett 158210312Sjmallett /* 159210312Sjmallett * So we have something we can do, lets setup the session 160210312Sjmallett */ 161210312Sjmallett 162210312Sjmallett if (sc->sc_sessions) { 163210312Sjmallett for (i = 1; i < sc->sc_sesnum; i++) 164210312Sjmallett if (sc->sc_sessions[i] == NULL) 165210312Sjmallett break; 166210312Sjmallett } else 167210312Sjmallett i = 1; /* NB: to silence compiler warning */ 168210312Sjmallett 169210312Sjmallett if (sc->sc_sessions == NULL || i == sc->sc_sesnum) { 170210312Sjmallett if (sc->sc_sessions == NULL) { 171210312Sjmallett i = 1; /* We leave sc->sc_sessions[0] empty */ 172210312Sjmallett sc->sc_sesnum = CRYPTO_SW_SESSIONS; 173210312Sjmallett } else 174210312Sjmallett sc->sc_sesnum *= 2; 175210312Sjmallett 176210312Sjmallett ocd = malloc(sc->sc_sesnum * sizeof(struct octo_sess *), 177210312Sjmallett M_DEVBUF, M_NOWAIT | M_ZERO); 178210312Sjmallett if (ocd == NULL) { 179210312Sjmallett /* Reset session number */ 180210312Sjmallett if (sc->sc_sesnum == CRYPTO_SW_SESSIONS) 181210312Sjmallett sc->sc_sesnum = 0; 182210312Sjmallett else 183210312Sjmallett sc->sc_sesnum /= 2; 184210312Sjmallett dprintf("%s,%d: ENOBUFS\n", __FILE__, __LINE__); 185210312Sjmallett return ENOBUFS; 186210312Sjmallett } 187210312Sjmallett 188210312Sjmallett /* Copy existing sessions */ 189210312Sjmallett if (sc->sc_sessions) { 190210312Sjmallett memcpy(ocd, sc->sc_sessions, 191210312Sjmallett (sc->sc_sesnum / 2) * sizeof(struct octo_sess *)); 192210312Sjmallett free(sc->sc_sessions, M_DEVBUF); 193210312Sjmallett } 194210312Sjmallett 195210312Sjmallett sc->sc_sessions = ocd; 196210312Sjmallett } 197210312Sjmallett 198210312Sjmallett ocd = &sc->sc_sessions[i]; 199210312Sjmallett *sid = i; 200210312Sjmallett 201210312Sjmallett *ocd = malloc(sizeof(struct octo_sess), M_DEVBUF, M_NOWAIT | M_ZERO); 202210312Sjmallett if (*ocd == NULL) { 203210312Sjmallett cryptocteon_freesession(NULL, i); 204210312Sjmallett dprintf("%s,%d: ENOBUFS\n", __FILE__, __LINE__); 205210312Sjmallett return ENOBUFS; 206210312Sjmallett } 207210312Sjmallett 208210312Sjmallett if (encini && encini->cri_key) { 209210312Sjmallett (*ocd)->octo_encklen = (encini->cri_klen + 7) / 8; 210210312Sjmallett memcpy((*ocd)->octo_enckey, encini->cri_key, (*ocd)->octo_encklen); 211210312Sjmallett } 212210312Sjmallett 213210312Sjmallett if (macini && macini->cri_key) { 214210312Sjmallett (*ocd)->octo_macklen = (macini->cri_klen + 7) / 8; 215210312Sjmallett memcpy((*ocd)->octo_mackey, macini->cri_key, (*ocd)->octo_macklen); 216210312Sjmallett } 217210312Sjmallett 218210312Sjmallett (*ocd)->octo_mlen = 0; 219210312Sjmallett if (encini && encini->cri_mlen) 220210312Sjmallett (*ocd)->octo_mlen = encini->cri_mlen; 221210312Sjmallett else if (macini && macini->cri_mlen) 222210312Sjmallett (*ocd)->octo_mlen = macini->cri_mlen; 223210312Sjmallett else 224210312Sjmallett (*ocd)->octo_mlen = 12; 225210312Sjmallett 226210312Sjmallett /* 227210312Sjmallett * point c at the enc if it exists, otherwise the mac 228210312Sjmallett */ 229210312Sjmallett c = encini ? encini : macini; 230210312Sjmallett 231210312Sjmallett switch (c->cri_alg) { 232210312Sjmallett case CRYPTO_DES_CBC: 233210312Sjmallett case CRYPTO_3DES_CBC: 234210312Sjmallett (*ocd)->octo_ivsize = 8; 235210312Sjmallett switch (macini ? macini->cri_alg : -1) { 236210312Sjmallett case CRYPTO_MD5_HMAC: 237210312Sjmallett (*ocd)->octo_encrypt = octo_des_cbc_md5_encrypt; 238210312Sjmallett (*ocd)->octo_decrypt = octo_des_cbc_md5_decrypt; 239210312Sjmallett octo_calc_hash(0, macini->cri_key, (*ocd)->octo_hminner, 240210312Sjmallett (*ocd)->octo_hmouter); 241210312Sjmallett break; 242210312Sjmallett case CRYPTO_SHA1_HMAC: 243210312Sjmallett (*ocd)->octo_encrypt = octo_des_cbc_sha1_encrypt; 244210312Sjmallett (*ocd)->octo_decrypt = octo_des_cbc_sha1_encrypt; 245210312Sjmallett octo_calc_hash(1, macini->cri_key, (*ocd)->octo_hminner, 246210312Sjmallett (*ocd)->octo_hmouter); 247210312Sjmallett break; 248210312Sjmallett case -1: 249210312Sjmallett (*ocd)->octo_encrypt = octo_des_cbc_encrypt; 250210312Sjmallett (*ocd)->octo_decrypt = octo_des_cbc_decrypt; 251210312Sjmallett break; 252210312Sjmallett default: 253210312Sjmallett cryptocteon_freesession(NULL, i); 254210312Sjmallett dprintf("%s,%d: EINVALn", __FILE__, __LINE__); 255210312Sjmallett return EINVAL; 256210312Sjmallett } 257210312Sjmallett break; 258210312Sjmallett case CRYPTO_AES_CBC: 259210312Sjmallett (*ocd)->octo_ivsize = 16; 260210312Sjmallett switch (macini ? macini->cri_alg : -1) { 261210312Sjmallett case CRYPTO_MD5_HMAC: 262210312Sjmallett (*ocd)->octo_encrypt = octo_aes_cbc_md5_encrypt; 263210312Sjmallett (*ocd)->octo_decrypt = octo_aes_cbc_md5_decrypt; 264210312Sjmallett octo_calc_hash(0, macini->cri_key, (*ocd)->octo_hminner, 265210312Sjmallett (*ocd)->octo_hmouter); 266210312Sjmallett break; 267210312Sjmallett case CRYPTO_SHA1_HMAC: 268210312Sjmallett (*ocd)->octo_encrypt = octo_aes_cbc_sha1_encrypt; 269210312Sjmallett (*ocd)->octo_decrypt = octo_aes_cbc_sha1_decrypt; 270210312Sjmallett octo_calc_hash(1, macini->cri_key, (*ocd)->octo_hminner, 271210312Sjmallett (*ocd)->octo_hmouter); 272210312Sjmallett break; 273210312Sjmallett case -1: 274210312Sjmallett (*ocd)->octo_encrypt = octo_aes_cbc_encrypt; 275210312Sjmallett (*ocd)->octo_decrypt = octo_aes_cbc_decrypt; 276210312Sjmallett break; 277210312Sjmallett default: 278210312Sjmallett cryptocteon_freesession(NULL, i); 279210312Sjmallett dprintf("%s,%d: EINVALn", __FILE__, __LINE__); 280210312Sjmallett return EINVAL; 281210312Sjmallett } 282210312Sjmallett break; 283210312Sjmallett case CRYPTO_MD5_HMAC: 284210312Sjmallett (*ocd)->octo_encrypt = octo_null_md5_encrypt; 285210312Sjmallett (*ocd)->octo_decrypt = octo_null_md5_encrypt; 286210312Sjmallett octo_calc_hash(0, macini->cri_key, (*ocd)->octo_hminner, 287210312Sjmallett (*ocd)->octo_hmouter); 288210312Sjmallett break; 289210312Sjmallett case CRYPTO_SHA1_HMAC: 290210312Sjmallett (*ocd)->octo_encrypt = octo_null_sha1_encrypt; 291210312Sjmallett (*ocd)->octo_decrypt = octo_null_sha1_encrypt; 292210312Sjmallett octo_calc_hash(1, macini->cri_key, (*ocd)->octo_hminner, 293210312Sjmallett (*ocd)->octo_hmouter); 294210312Sjmallett break; 295210312Sjmallett default: 296210312Sjmallett cryptocteon_freesession(NULL, i); 297210312Sjmallett dprintf("%s,%d: EINVALn", __FILE__, __LINE__); 298210312Sjmallett return EINVAL; 299210312Sjmallett } 300210312Sjmallett 301210312Sjmallett (*ocd)->octo_encalg = encini ? encini->cri_alg : -1; 302210312Sjmallett (*ocd)->octo_macalg = macini ? macini->cri_alg : -1; 303210312Sjmallett 304210312Sjmallett return 0; 305210312Sjmallett} 306210312Sjmallett 307210312Sjmallett/* 308210312Sjmallett * Free a session. 309210312Sjmallett */ 310210312Sjmallettstatic int 311210312Sjmallettcryptocteon_freesession(device_t dev, u_int64_t tid) 312210312Sjmallett{ 313210312Sjmallett struct cryptocteon_softc *sc; 314210312Sjmallett u_int32_t sid = CRYPTO_SESID2LID(tid); 315210312Sjmallett 316210312Sjmallett sc = device_get_softc(dev); 317210312Sjmallett 318210312Sjmallett if (sc == NULL) 319210312Sjmallett return (EINVAL); 320210312Sjmallett 321210312Sjmallett if (sid > sc->sc_sesnum || sc->sc_sessions == NULL || 322210312Sjmallett sc->sc_sessions[sid] == NULL) 323210312Sjmallett return (EINVAL); 324210312Sjmallett 325210312Sjmallett /* Silently accept and return */ 326210312Sjmallett if (sid == 0) 327210312Sjmallett return(0); 328210312Sjmallett 329210312Sjmallett if (sc->sc_sessions[sid]) 330210312Sjmallett free(sc->sc_sessions[sid], M_DEVBUF); 331210312Sjmallett sc->sc_sessions[sid] = NULL; 332210312Sjmallett return 0; 333210312Sjmallett} 334210312Sjmallett 335210312Sjmallett/* 336210312Sjmallett * Process a request. 337210312Sjmallett */ 338210312Sjmallettstatic int 339210312Sjmallettcryptocteon_process(device_t dev, struct cryptop *crp, int hint) 340210312Sjmallett{ 341210312Sjmallett struct cryptodesc *crd; 342210312Sjmallett struct octo_sess *od; 343210312Sjmallett u_int32_t lid; 344210312Sjmallett size_t iovcnt, iovlen; 345210312Sjmallett struct mbuf *m = NULL; 346210312Sjmallett struct uio *uiop = NULL; 347210312Sjmallett struct cryptodesc *enccrd = NULL, *maccrd = NULL; 348210312Sjmallett unsigned char *ivp = NULL; 349210312Sjmallett unsigned char iv_data[HASH_MAX_LEN]; 350210312Sjmallett int auth_off = 0, auth_len = 0, crypt_off = 0, crypt_len = 0, icv_off = 0; 351210312Sjmallett struct cryptocteon_softc *sc; 352210312Sjmallett 353210312Sjmallett sc = device_get_softc(dev); 354210312Sjmallett 355210312Sjmallett if (sc == NULL || crp == NULL) 356210312Sjmallett return EINVAL; 357210312Sjmallett 358210312Sjmallett crp->crp_etype = 0; 359210312Sjmallett 360210312Sjmallett if (crp->crp_desc == NULL || crp->crp_buf == NULL) { 361210312Sjmallett dprintf("%s,%d: EINVAL\n", __FILE__, __LINE__); 362210312Sjmallett crp->crp_etype = EINVAL; 363210312Sjmallett goto done; 364210312Sjmallett } 365210312Sjmallett 366210312Sjmallett lid = crp->crp_sid & 0xffffffff; 367210312Sjmallett if (lid >= sc->sc_sesnum || lid == 0 || sc->sc_sessions == NULL || 368210312Sjmallett sc->sc_sessions[lid] == NULL) { 369210312Sjmallett crp->crp_etype = ENOENT; 370210312Sjmallett dprintf("%s,%d: ENOENT\n", __FILE__, __LINE__); 371210312Sjmallett goto done; 372210312Sjmallett } 373210312Sjmallett od = sc->sc_sessions[lid]; 374210312Sjmallett 375210312Sjmallett /* 376210312Sjmallett * do some error checking outside of the loop for m and IOV processing 377210312Sjmallett * this leaves us with valid m or uiop pointers for later 378210312Sjmallett */ 379210312Sjmallett if (crp->crp_flags & CRYPTO_F_IMBUF) { 380210312Sjmallett unsigned frags; 381210312Sjmallett 382210312Sjmallett m = (struct mbuf *) crp->crp_buf; 383210312Sjmallett for (frags = 0; m != NULL; frags++) 384210312Sjmallett m = m->m_next; 385210312Sjmallett 386210312Sjmallett if (frags >= UIO_MAXIOV) { 387210312Sjmallett printf("%s,%d: %d frags > UIO_MAXIOV", __FILE__, __LINE__, frags); 388210312Sjmallett goto done; 389210312Sjmallett } 390210312Sjmallett 391210312Sjmallett m = (struct mbuf *) crp->crp_buf; 392210312Sjmallett } else if (crp->crp_flags & CRYPTO_F_IOV) { 393210312Sjmallett uiop = (struct uio *) crp->crp_buf; 394210312Sjmallett if (uiop->uio_iovcnt > UIO_MAXIOV) { 395210312Sjmallett printf("%s,%d: %d uio_iovcnt > UIO_MAXIOV", __FILE__, __LINE__, 396210312Sjmallett uiop->uio_iovcnt); 397210312Sjmallett goto done; 398210312Sjmallett } 399210312Sjmallett } 400210312Sjmallett 401210312Sjmallett /* point our enccrd and maccrd appropriately */ 402210312Sjmallett crd = crp->crp_desc; 403210312Sjmallett if (crd->crd_alg == od->octo_encalg) enccrd = crd; 404210312Sjmallett if (crd->crd_alg == od->octo_macalg) maccrd = crd; 405210312Sjmallett crd = crd->crd_next; 406210312Sjmallett if (crd) { 407210312Sjmallett if (crd->crd_alg == od->octo_encalg) enccrd = crd; 408210312Sjmallett if (crd->crd_alg == od->octo_macalg) maccrd = crd; 409210312Sjmallett crd = crd->crd_next; 410210312Sjmallett } 411210312Sjmallett if (crd) { 412210312Sjmallett crp->crp_etype = EINVAL; 413210312Sjmallett dprintf("%s,%d: ENOENT - descriptors do not match session\n", 414210312Sjmallett __FILE__, __LINE__); 415210312Sjmallett goto done; 416210312Sjmallett } 417210312Sjmallett 418210312Sjmallett if (enccrd) { 419210312Sjmallett if (enccrd->crd_flags & CRD_F_IV_EXPLICIT) { 420210312Sjmallett ivp = enccrd->crd_iv; 421210312Sjmallett } else { 422210312Sjmallett ivp = iv_data; 423210312Sjmallett crypto_copydata(crp->crp_flags, crp->crp_buf, 424210312Sjmallett enccrd->crd_inject, od->octo_ivsize, (caddr_t) ivp); 425210312Sjmallett } 426210312Sjmallett 427210312Sjmallett if (maccrd) { 428210312Sjmallett auth_off = maccrd->crd_skip; 429210312Sjmallett auth_len = maccrd->crd_len; 430210312Sjmallett icv_off = maccrd->crd_inject; 431210312Sjmallett } 432210312Sjmallett 433210312Sjmallett crypt_off = enccrd->crd_skip; 434210312Sjmallett crypt_len = enccrd->crd_len; 435210312Sjmallett } else { /* if (maccrd) */ 436210312Sjmallett auth_off = maccrd->crd_skip; 437210312Sjmallett auth_len = maccrd->crd_len; 438210312Sjmallett icv_off = maccrd->crd_inject; 439210312Sjmallett } 440210312Sjmallett 441210312Sjmallett /* 442210312Sjmallett * setup the I/O vector to cover the buffer 443210312Sjmallett */ 444210312Sjmallett if (crp->crp_flags & CRYPTO_F_IMBUF) { 445210312Sjmallett iovcnt = 0; 446210312Sjmallett iovlen = 0; 447210312Sjmallett 448210312Sjmallett while (m != NULL) { 449210312Sjmallett od->octo_iov[iovcnt].iov_base = mtod(m, void *); 450210312Sjmallett od->octo_iov[iovcnt].iov_len = m->m_len; 451210312Sjmallett 452210312Sjmallett m = m->m_next; 453210312Sjmallett iovlen += od->octo_iov[iovcnt++].iov_len; 454210312Sjmallett } 455210312Sjmallett } else if (crp->crp_flags & CRYPTO_F_IOV) { 456210312Sjmallett iovlen = 0; 457210312Sjmallett for (iovcnt = 0; iovcnt < uiop->uio_iovcnt; iovcnt++) { 458210312Sjmallett od->octo_iov[iovcnt].iov_base = uiop->uio_iov[iovcnt].iov_base; 459210312Sjmallett od->octo_iov[iovcnt].iov_len = uiop->uio_iov[iovcnt].iov_len; 460210312Sjmallett 461210312Sjmallett iovlen += od->octo_iov[iovcnt].iov_len; 462210312Sjmallett } 463210312Sjmallett } else { 464210312Sjmallett iovlen = crp->crp_ilen; 465210312Sjmallett od->octo_iov[0].iov_base = crp->crp_buf; 466210312Sjmallett od->octo_iov[0].iov_len = crp->crp_ilen; 467210312Sjmallett iovcnt = 1; 468210312Sjmallett } 469210312Sjmallett 470210312Sjmallett 471210312Sjmallett /* 472210312Sjmallett * setup a new explicit key 473210312Sjmallett */ 474210312Sjmallett if (enccrd) { 475210312Sjmallett if (enccrd->crd_flags & CRD_F_KEY_EXPLICIT) { 476210312Sjmallett od->octo_encklen = (enccrd->crd_klen + 7) / 8; 477210312Sjmallett memcpy(od->octo_enckey, enccrd->crd_key, od->octo_encklen); 478210312Sjmallett } 479210312Sjmallett } 480210312Sjmallett if (maccrd) { 481210312Sjmallett if (maccrd->crd_flags & CRD_F_KEY_EXPLICIT) { 482210312Sjmallett od->octo_macklen = (maccrd->crd_klen + 7) / 8; 483210312Sjmallett memcpy(od->octo_mackey, maccrd->crd_key, od->octo_macklen); 484210312Sjmallett od->octo_mackey_set = 0; 485210312Sjmallett } 486210312Sjmallett if (!od->octo_mackey_set) { 487210312Sjmallett octo_calc_hash(maccrd->crd_alg == CRYPTO_MD5_HMAC ? 0 : 1, 488210312Sjmallett maccrd->crd_key, od->octo_hminner, od->octo_hmouter); 489210312Sjmallett od->octo_mackey_set = 1; 490210312Sjmallett } 491210312Sjmallett } 492210312Sjmallett 493210312Sjmallett 494210312Sjmallett if (!enccrd || (enccrd->crd_flags & CRD_F_ENCRYPT)) 495210312Sjmallett (*od->octo_encrypt)(od, od->octo_iov, iovcnt, iovlen, 496210312Sjmallett auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp); 497210312Sjmallett else 498210312Sjmallett (*od->octo_decrypt)(od, od->octo_iov, iovcnt, iovlen, 499210312Sjmallett auth_off, auth_len, crypt_off, crypt_len, icv_off, ivp); 500210312Sjmallett 501210312Sjmallettdone: 502210312Sjmallett crypto_done(crp); 503210312Sjmallett return 0; 504210312Sjmallett} 505210312Sjmallett 506210312Sjmallettstatic device_method_t cryptocteon_methods[] = { 507210312Sjmallett /* device methods */ 508210312Sjmallett DEVMETHOD(device_identify, cryptocteon_identify), 509210312Sjmallett DEVMETHOD(device_probe, cryptocteon_probe), 510210312Sjmallett DEVMETHOD(device_attach, cryptocteon_attach), 511210312Sjmallett 512210312Sjmallett /* crypto device methods */ 513210312Sjmallett DEVMETHOD(cryptodev_newsession, cryptocteon_newsession), 514210312Sjmallett DEVMETHOD(cryptodev_freesession,cryptocteon_freesession), 515210312Sjmallett DEVMETHOD(cryptodev_process, cryptocteon_process), 516210312Sjmallett 517210312Sjmallett { 0, 0 } 518210312Sjmallett}; 519210312Sjmallett 520210312Sjmallettstatic driver_t cryptocteon_driver = { 521210312Sjmallett "cryptocteon", 522210312Sjmallett cryptocteon_methods, 523210312Sjmallett sizeof (struct cryptocteon_softc), 524210312Sjmallett}; 525210312Sjmallettstatic devclass_t cryptocteon_devclass; 526210312SjmallettDRIVER_MODULE(cryptocteon, nexus, cryptocteon_driver, cryptocteon_devclass, 0, 0); 527