1091d81d1SSam Leffler /* $OpenBSD: cryptosoft.c,v 1.35 2002/04/26 08:43:50 deraadt Exp $ */ 2091d81d1SSam Leffler 360727d8bSWarner Losh /*- 4091d81d1SSam Leffler * The author of this code is Angelos D. Keromytis (angelos@cis.upenn.edu) 56810ad6fSSam Leffler * Copyright (c) 2002-2006 Sam Leffler, Errno Consulting 6091d81d1SSam Leffler * 7091d81d1SSam Leffler * This code was written by Angelos D. Keromytis in Athens, Greece, in 8091d81d1SSam Leffler * February 2000. Network Security Technologies Inc. (NSTI) kindly 9091d81d1SSam Leffler * supported the development of this code. 10091d81d1SSam Leffler * 11091d81d1SSam Leffler * Copyright (c) 2000, 2001 Angelos D. Keromytis 12091d81d1SSam Leffler * 13091d81d1SSam Leffler * Permission to use, copy, and modify this software with or without fee 14091d81d1SSam Leffler * is hereby granted, provided that this entire notice is included in 15091d81d1SSam Leffler * all source code copies of any software which is or includes a copy or 16091d81d1SSam Leffler * modification of this software. 17091d81d1SSam Leffler * 18091d81d1SSam Leffler * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 19091d81d1SSam Leffler * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 20091d81d1SSam Leffler * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 21091d81d1SSam Leffler * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 22091d81d1SSam Leffler * PURPOSE. 23091d81d1SSam Leffler */ 24091d81d1SSam Leffler 252c446514SDavid E. O'Brien #include <sys/cdefs.h> 262c446514SDavid E. O'Brien __FBSDID("$FreeBSD$"); 272c446514SDavid E. O'Brien 28091d81d1SSam Leffler #include <sys/param.h> 29091d81d1SSam Leffler #include <sys/systm.h> 30091d81d1SSam Leffler #include <sys/malloc.h> 31091d81d1SSam Leffler #include <sys/mbuf.h> 326810ad6fSSam Leffler #include <sys/module.h> 33091d81d1SSam Leffler #include <sys/sysctl.h> 34091d81d1SSam Leffler #include <sys/errno.h> 35091d81d1SSam Leffler #include <sys/random.h> 36091d81d1SSam Leffler #include <sys/kernel.h> 37091d81d1SSam Leffler #include <sys/uio.h> 38091d81d1SSam Leffler 39091d81d1SSam Leffler #include <crypto/blowfish/blowfish.h> 40091d81d1SSam Leffler #include <crypto/sha1.h> 41091d81d1SSam Leffler #include <opencrypto/rmd160.h> 429f65b10bSHajimu UMEMOTO #include <opencrypto/cast.h> 43091d81d1SSam Leffler #include <opencrypto/skipjack.h> 44091d81d1SSam Leffler #include <sys/md5.h> 45091d81d1SSam Leffler 46091d81d1SSam Leffler #include <opencrypto/cryptodev.h> 47091d81d1SSam Leffler #include <opencrypto/cryptosoft.h> 48091d81d1SSam Leffler #include <opencrypto/xform.h> 49091d81d1SSam Leffler 506810ad6fSSam Leffler #include <sys/kobj.h> 516810ad6fSSam Leffler #include <sys/bus.h> 526810ad6fSSam Leffler #include "cryptodev_if.h" 53091d81d1SSam Leffler 546810ad6fSSam Leffler static int32_t swcr_id; 556810ad6fSSam Leffler static struct swcr_data **swcr_sessions = NULL; 566810ad6fSSam Leffler static u_int32_t swcr_sesnum; 576810ad6fSSam Leffler 586810ad6fSSam Leffler u_int8_t hmac_ipad_buffer[HMAC_MAX_BLOCK_LEN]; 596810ad6fSSam Leffler u_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN]; 60091d81d1SSam Leffler 61091d81d1SSam Leffler static int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); 62f34a967bSPawel Jakub Dawidek static int swcr_authcompute(struct cryptodesc *, struct swcr_data *, caddr_t, int); 63091d81d1SSam Leffler static int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); 646810ad6fSSam Leffler static int swcr_freesession(device_t dev, u_int64_t tid); 65091d81d1SSam Leffler 66091d81d1SSam Leffler /* 67091d81d1SSam Leffler * Apply a symmetric encryption/decryption algorithm. 68091d81d1SSam Leffler */ 69091d81d1SSam Leffler static int 70091d81d1SSam Leffler swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, 71f34a967bSPawel Jakub Dawidek int flags) 72091d81d1SSam Leffler { 73091d81d1SSam Leffler unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN], *idat; 74091d81d1SSam Leffler unsigned char *ivp, piv[EALG_MAX_BLOCK_LEN]; 75091d81d1SSam Leffler struct enc_xform *exf; 76091d81d1SSam Leffler int i, k, j, blks; 77091d81d1SSam Leffler 78091d81d1SSam Leffler exf = sw->sw_exf; 79091d81d1SSam Leffler blks = exf->blocksize; 80091d81d1SSam Leffler 81091d81d1SSam Leffler /* Check for non-padded data */ 82091d81d1SSam Leffler if (crd->crd_len % blks) 83091d81d1SSam Leffler return EINVAL; 84091d81d1SSam Leffler 85091d81d1SSam Leffler /* Initialize the IV */ 86091d81d1SSam Leffler if (crd->crd_flags & CRD_F_ENCRYPT) { 87091d81d1SSam Leffler /* IV explicitly provided ? */ 88091d81d1SSam Leffler if (crd->crd_flags & CRD_F_IV_EXPLICIT) 89091d81d1SSam Leffler bcopy(crd->crd_iv, iv, blks); 9048b0f2e1SPawel Jakub Dawidek else 9148b0f2e1SPawel Jakub Dawidek arc4rand(iv, blks, 0); 92091d81d1SSam Leffler 93091d81d1SSam Leffler /* Do we need to write the IV */ 94f34a967bSPawel Jakub Dawidek if (!(crd->crd_flags & CRD_F_IV_PRESENT)) 95f34a967bSPawel Jakub Dawidek crypto_copyback(flags, buf, crd->crd_inject, blks, iv); 96091d81d1SSam Leffler 97091d81d1SSam Leffler } else { /* Decryption */ 98091d81d1SSam Leffler /* IV explicitly provided ? */ 99091d81d1SSam Leffler if (crd->crd_flags & CRD_F_IV_EXPLICIT) 100091d81d1SSam Leffler bcopy(crd->crd_iv, iv, blks); 101091d81d1SSam Leffler else { 102091d81d1SSam Leffler /* Get IV off buf */ 103f34a967bSPawel Jakub Dawidek crypto_copydata(flags, buf, crd->crd_inject, blks, iv); 104091d81d1SSam Leffler } 105091d81d1SSam Leffler } 106091d81d1SSam Leffler 107c740ae4bSPoul-Henning Kamp if (crd->crd_flags & CRD_F_KEY_EXPLICIT) { 108c740ae4bSPoul-Henning Kamp int error; 109c740ae4bSPoul-Henning Kamp 110c740ae4bSPoul-Henning Kamp if (sw->sw_kschedule) 111c740ae4bSPoul-Henning Kamp exf->zerokey(&(sw->sw_kschedule)); 112c740ae4bSPoul-Henning Kamp error = exf->setkey(&sw->sw_kschedule, 113c740ae4bSPoul-Henning Kamp crd->crd_key, crd->crd_klen / 8); 114c740ae4bSPoul-Henning Kamp if (error) 115c740ae4bSPoul-Henning Kamp return (error); 116c740ae4bSPoul-Henning Kamp } 117d295bdeeSPawel Jakub Dawidek 118091d81d1SSam Leffler ivp = iv; 119091d81d1SSam Leffler 120d295bdeeSPawel Jakub Dawidek /* 121d295bdeeSPawel Jakub Dawidek * xforms that provide a reinit method perform all IV 122d295bdeeSPawel Jakub Dawidek * handling themselves. 123d295bdeeSPawel Jakub Dawidek */ 124d295bdeeSPawel Jakub Dawidek if (exf->reinit) 125d295bdeeSPawel Jakub Dawidek exf->reinit(sw->sw_kschedule, iv); 126d295bdeeSPawel Jakub Dawidek 127f34a967bSPawel Jakub Dawidek if (flags & CRYPTO_F_IMBUF) { 128091d81d1SSam Leffler struct mbuf *m = (struct mbuf *) buf; 129091d81d1SSam Leffler 130091d81d1SSam Leffler /* Find beginning of data */ 131091d81d1SSam Leffler m = m_getptr(m, crd->crd_skip, &k); 132091d81d1SSam Leffler if (m == NULL) 133091d81d1SSam Leffler return EINVAL; 134091d81d1SSam Leffler 135091d81d1SSam Leffler i = crd->crd_len; 136091d81d1SSam Leffler 137091d81d1SSam Leffler while (i > 0) { 138091d81d1SSam Leffler /* 139091d81d1SSam Leffler * If there's insufficient data at the end of 140091d81d1SSam Leffler * an mbuf, we have to do some copying. 141091d81d1SSam Leffler */ 142091d81d1SSam Leffler if (m->m_len < k + blks && m->m_len != k) { 143091d81d1SSam Leffler m_copydata(m, k, blks, blk); 144091d81d1SSam Leffler 145091d81d1SSam Leffler /* Actual encryption/decryption */ 146d295bdeeSPawel Jakub Dawidek if (exf->reinit) { 147091d81d1SSam Leffler if (crd->crd_flags & CRD_F_ENCRYPT) { 148d295bdeeSPawel Jakub Dawidek exf->encrypt(sw->sw_kschedule, 149d295bdeeSPawel Jakub Dawidek blk); 150d295bdeeSPawel Jakub Dawidek } else { 151d295bdeeSPawel Jakub Dawidek exf->decrypt(sw->sw_kschedule, 152d295bdeeSPawel Jakub Dawidek blk); 153d295bdeeSPawel Jakub Dawidek } 154d295bdeeSPawel Jakub Dawidek } else if (crd->crd_flags & CRD_F_ENCRYPT) { 155091d81d1SSam Leffler /* XOR with previous block */ 156091d81d1SSam Leffler for (j = 0; j < blks; j++) 157091d81d1SSam Leffler blk[j] ^= ivp[j]; 158091d81d1SSam Leffler 159091d81d1SSam Leffler exf->encrypt(sw->sw_kschedule, blk); 160091d81d1SSam Leffler 161091d81d1SSam Leffler /* 162091d81d1SSam Leffler * Keep encrypted block for XOR'ing 163091d81d1SSam Leffler * with next block 164091d81d1SSam Leffler */ 165091d81d1SSam Leffler bcopy(blk, iv, blks); 166091d81d1SSam Leffler ivp = iv; 167091d81d1SSam Leffler } else { /* decrypt */ 168091d81d1SSam Leffler /* 169091d81d1SSam Leffler * Keep encrypted block for XOR'ing 170091d81d1SSam Leffler * with next block 171091d81d1SSam Leffler */ 172091d81d1SSam Leffler if (ivp == iv) 173091d81d1SSam Leffler bcopy(blk, piv, blks); 174091d81d1SSam Leffler else 175091d81d1SSam Leffler bcopy(blk, iv, blks); 176091d81d1SSam Leffler 177091d81d1SSam Leffler exf->decrypt(sw->sw_kschedule, blk); 178091d81d1SSam Leffler 179091d81d1SSam Leffler /* XOR with previous block */ 180091d81d1SSam Leffler for (j = 0; j < blks; j++) 181091d81d1SSam Leffler blk[j] ^= ivp[j]; 182091d81d1SSam Leffler 183091d81d1SSam Leffler if (ivp == iv) 184091d81d1SSam Leffler bcopy(piv, iv, blks); 185091d81d1SSam Leffler else 186091d81d1SSam Leffler ivp = iv; 187091d81d1SSam Leffler } 188091d81d1SSam Leffler 189091d81d1SSam Leffler /* Copy back decrypted block */ 190091d81d1SSam Leffler m_copyback(m, k, blks, blk); 191091d81d1SSam Leffler 192091d81d1SSam Leffler /* Advance pointer */ 193091d81d1SSam Leffler m = m_getptr(m, k + blks, &k); 194091d81d1SSam Leffler if (m == NULL) 195091d81d1SSam Leffler return EINVAL; 196091d81d1SSam Leffler 197091d81d1SSam Leffler i -= blks; 198091d81d1SSam Leffler 199091d81d1SSam Leffler /* Could be done... */ 200091d81d1SSam Leffler if (i == 0) 201091d81d1SSam Leffler break; 202091d81d1SSam Leffler } 203091d81d1SSam Leffler 204091d81d1SSam Leffler /* Skip possibly empty mbufs */ 205091d81d1SSam Leffler if (k == m->m_len) { 206091d81d1SSam Leffler for (m = m->m_next; m && m->m_len == 0; 207091d81d1SSam Leffler m = m->m_next) 208091d81d1SSam Leffler ; 209091d81d1SSam Leffler k = 0; 210091d81d1SSam Leffler } 211091d81d1SSam Leffler 212091d81d1SSam Leffler /* Sanity check */ 213091d81d1SSam Leffler if (m == NULL) 214091d81d1SSam Leffler return EINVAL; 215091d81d1SSam Leffler 216091d81d1SSam Leffler /* 217091d81d1SSam Leffler * Warning: idat may point to garbage here, but 218091d81d1SSam Leffler * we only use it in the while() loop, only if 219091d81d1SSam Leffler * there are indeed enough data. 220091d81d1SSam Leffler */ 221091d81d1SSam Leffler idat = mtod(m, unsigned char *) + k; 222091d81d1SSam Leffler 223091d81d1SSam Leffler while (m->m_len >= k + blks && i > 0) { 224d295bdeeSPawel Jakub Dawidek if (exf->reinit) { 225091d81d1SSam Leffler if (crd->crd_flags & CRD_F_ENCRYPT) { 226d295bdeeSPawel Jakub Dawidek exf->encrypt(sw->sw_kschedule, 227d295bdeeSPawel Jakub Dawidek idat); 228d295bdeeSPawel Jakub Dawidek } else { 229d295bdeeSPawel Jakub Dawidek exf->decrypt(sw->sw_kschedule, 230d295bdeeSPawel Jakub Dawidek idat); 231d295bdeeSPawel Jakub Dawidek } 232d295bdeeSPawel Jakub Dawidek } else if (crd->crd_flags & CRD_F_ENCRYPT) { 233091d81d1SSam Leffler /* XOR with previous block/IV */ 234091d81d1SSam Leffler for (j = 0; j < blks; j++) 235091d81d1SSam Leffler idat[j] ^= ivp[j]; 236091d81d1SSam Leffler 237091d81d1SSam Leffler exf->encrypt(sw->sw_kschedule, idat); 238091d81d1SSam Leffler ivp = idat; 239091d81d1SSam Leffler } else { /* decrypt */ 240091d81d1SSam Leffler /* 241091d81d1SSam Leffler * Keep encrypted block to be used 242091d81d1SSam Leffler * in next block's processing. 243091d81d1SSam Leffler */ 244091d81d1SSam Leffler if (ivp == iv) 245091d81d1SSam Leffler bcopy(idat, piv, blks); 246091d81d1SSam Leffler else 247091d81d1SSam Leffler bcopy(idat, iv, blks); 248091d81d1SSam Leffler 249091d81d1SSam Leffler exf->decrypt(sw->sw_kschedule, idat); 250091d81d1SSam Leffler 251091d81d1SSam Leffler /* XOR with previous block/IV */ 252091d81d1SSam Leffler for (j = 0; j < blks; j++) 253091d81d1SSam Leffler idat[j] ^= ivp[j]; 254091d81d1SSam Leffler 255091d81d1SSam Leffler if (ivp == iv) 256091d81d1SSam Leffler bcopy(piv, iv, blks); 257091d81d1SSam Leffler else 258091d81d1SSam Leffler ivp = iv; 259091d81d1SSam Leffler } 260091d81d1SSam Leffler 261091d81d1SSam Leffler idat += blks; 262091d81d1SSam Leffler k += blks; 263091d81d1SSam Leffler i -= blks; 264091d81d1SSam Leffler } 265091d81d1SSam Leffler } 266091d81d1SSam Leffler 267091d81d1SSam Leffler return 0; /* Done with mbuf encryption/decryption */ 268f34a967bSPawel Jakub Dawidek } else if (flags & CRYPTO_F_IOV) { 269091d81d1SSam Leffler struct uio *uio = (struct uio *) buf; 270091d81d1SSam Leffler struct iovec *iov; 271091d81d1SSam Leffler 272091d81d1SSam Leffler /* Find beginning of data */ 273091d81d1SSam Leffler iov = cuio_getptr(uio, crd->crd_skip, &k); 274091d81d1SSam Leffler if (iov == NULL) 275091d81d1SSam Leffler return EINVAL; 276091d81d1SSam Leffler 277091d81d1SSam Leffler i = crd->crd_len; 278091d81d1SSam Leffler 279091d81d1SSam Leffler while (i > 0) { 280091d81d1SSam Leffler /* 281091d81d1SSam Leffler * If there's insufficient data at the end of 282091d81d1SSam Leffler * an iovec, we have to do some copying. 283091d81d1SSam Leffler */ 284091d81d1SSam Leffler if (iov->iov_len < k + blks && iov->iov_len != k) { 285091d81d1SSam Leffler cuio_copydata(uio, k, blks, blk); 286091d81d1SSam Leffler 287091d81d1SSam Leffler /* Actual encryption/decryption */ 288d295bdeeSPawel Jakub Dawidek if (exf->reinit) { 289091d81d1SSam Leffler if (crd->crd_flags & CRD_F_ENCRYPT) { 290d295bdeeSPawel Jakub Dawidek exf->encrypt(sw->sw_kschedule, 291d295bdeeSPawel Jakub Dawidek blk); 292d295bdeeSPawel Jakub Dawidek } else { 293d295bdeeSPawel Jakub Dawidek exf->decrypt(sw->sw_kschedule, 294d295bdeeSPawel Jakub Dawidek blk); 295d295bdeeSPawel Jakub Dawidek } 296d295bdeeSPawel Jakub Dawidek } else if (crd->crd_flags & CRD_F_ENCRYPT) { 297091d81d1SSam Leffler /* XOR with previous block */ 298091d81d1SSam Leffler for (j = 0; j < blks; j++) 299091d81d1SSam Leffler blk[j] ^= ivp[j]; 300091d81d1SSam Leffler 301091d81d1SSam Leffler exf->encrypt(sw->sw_kschedule, blk); 302091d81d1SSam Leffler 303091d81d1SSam Leffler /* 304091d81d1SSam Leffler * Keep encrypted block for XOR'ing 305091d81d1SSam Leffler * with next block 306091d81d1SSam Leffler */ 307091d81d1SSam Leffler bcopy(blk, iv, blks); 308091d81d1SSam Leffler ivp = iv; 309091d81d1SSam Leffler } else { /* decrypt */ 310091d81d1SSam Leffler /* 311091d81d1SSam Leffler * Keep encrypted block for XOR'ing 312091d81d1SSam Leffler * with next block 313091d81d1SSam Leffler */ 314091d81d1SSam Leffler if (ivp == iv) 315091d81d1SSam Leffler bcopy(blk, piv, blks); 316091d81d1SSam Leffler else 317091d81d1SSam Leffler bcopy(blk, iv, blks); 318091d81d1SSam Leffler 319091d81d1SSam Leffler exf->decrypt(sw->sw_kschedule, blk); 320091d81d1SSam Leffler 321091d81d1SSam Leffler /* XOR with previous block */ 322091d81d1SSam Leffler for (j = 0; j < blks; j++) 323091d81d1SSam Leffler blk[j] ^= ivp[j]; 324091d81d1SSam Leffler 325091d81d1SSam Leffler if (ivp == iv) 326091d81d1SSam Leffler bcopy(piv, iv, blks); 327091d81d1SSam Leffler else 328091d81d1SSam Leffler ivp = iv; 329091d81d1SSam Leffler } 330091d81d1SSam Leffler 331091d81d1SSam Leffler /* Copy back decrypted block */ 332091d81d1SSam Leffler cuio_copyback(uio, k, blks, blk); 333091d81d1SSam Leffler 334091d81d1SSam Leffler /* Advance pointer */ 335091d81d1SSam Leffler iov = cuio_getptr(uio, k + blks, &k); 336091d81d1SSam Leffler if (iov == NULL) 337091d81d1SSam Leffler return EINVAL; 338091d81d1SSam Leffler 339091d81d1SSam Leffler i -= blks; 340091d81d1SSam Leffler 341091d81d1SSam Leffler /* Could be done... */ 342091d81d1SSam Leffler if (i == 0) 343091d81d1SSam Leffler break; 344091d81d1SSam Leffler } 345091d81d1SSam Leffler 346091d81d1SSam Leffler /* 347091d81d1SSam Leffler * Warning: idat may point to garbage here, but 348091d81d1SSam Leffler * we only use it in the while() loop, only if 349091d81d1SSam Leffler * there are indeed enough data. 350091d81d1SSam Leffler */ 3512b7f24d2SMike Barcroft idat = (char *)iov->iov_base + k; 352091d81d1SSam Leffler 353091d81d1SSam Leffler while (iov->iov_len >= k + blks && i > 0) { 354d295bdeeSPawel Jakub Dawidek if (exf->reinit) { 355091d81d1SSam Leffler if (crd->crd_flags & CRD_F_ENCRYPT) { 356d295bdeeSPawel Jakub Dawidek exf->encrypt(sw->sw_kschedule, 357d295bdeeSPawel Jakub Dawidek idat); 358d295bdeeSPawel Jakub Dawidek } else { 359d295bdeeSPawel Jakub Dawidek exf->decrypt(sw->sw_kschedule, 360d295bdeeSPawel Jakub Dawidek idat); 361d295bdeeSPawel Jakub Dawidek } 362d295bdeeSPawel Jakub Dawidek } else if (crd->crd_flags & CRD_F_ENCRYPT) { 363091d81d1SSam Leffler /* XOR with previous block/IV */ 364091d81d1SSam Leffler for (j = 0; j < blks; j++) 365091d81d1SSam Leffler idat[j] ^= ivp[j]; 366091d81d1SSam Leffler 367091d81d1SSam Leffler exf->encrypt(sw->sw_kschedule, idat); 368091d81d1SSam Leffler ivp = idat; 369091d81d1SSam Leffler } else { /* decrypt */ 370091d81d1SSam Leffler /* 371091d81d1SSam Leffler * Keep encrypted block to be used 372091d81d1SSam Leffler * in next block's processing. 373091d81d1SSam Leffler */ 374091d81d1SSam Leffler if (ivp == iv) 375091d81d1SSam Leffler bcopy(idat, piv, blks); 376091d81d1SSam Leffler else 377091d81d1SSam Leffler bcopy(idat, iv, blks); 378091d81d1SSam Leffler 379091d81d1SSam Leffler exf->decrypt(sw->sw_kschedule, idat); 380091d81d1SSam Leffler 381091d81d1SSam Leffler /* XOR with previous block/IV */ 382091d81d1SSam Leffler for (j = 0; j < blks; j++) 383091d81d1SSam Leffler idat[j] ^= ivp[j]; 384091d81d1SSam Leffler 385091d81d1SSam Leffler if (ivp == iv) 386091d81d1SSam Leffler bcopy(piv, iv, blks); 387091d81d1SSam Leffler else 388091d81d1SSam Leffler ivp = iv; 389091d81d1SSam Leffler } 390091d81d1SSam Leffler 391091d81d1SSam Leffler idat += blks; 392091d81d1SSam Leffler k += blks; 393091d81d1SSam Leffler i -= blks; 394091d81d1SSam Leffler } 395bfd50e27SDoug Rabson if (k == iov->iov_len) { 396bfd50e27SDoug Rabson iov++; 397bfd50e27SDoug Rabson k = 0; 398bfd50e27SDoug Rabson } 399091d81d1SSam Leffler } 400091d81d1SSam Leffler 401f6c4bc3bSPawel Jakub Dawidek return 0; /* Done with iovec encryption/decryption */ 402f34a967bSPawel Jakub Dawidek } else { /* contiguous buffer */ 403d295bdeeSPawel Jakub Dawidek if (exf->reinit) { 404d295bdeeSPawel Jakub Dawidek for (i = crd->crd_skip; 405d295bdeeSPawel Jakub Dawidek i < crd->crd_skip + crd->crd_len; i += blks) { 406d295bdeeSPawel Jakub Dawidek if (crd->crd_flags & CRD_F_ENCRYPT) 407d295bdeeSPawel Jakub Dawidek exf->encrypt(sw->sw_kschedule, buf + i); 408d295bdeeSPawel Jakub Dawidek else 409d295bdeeSPawel Jakub Dawidek exf->decrypt(sw->sw_kschedule, buf + i); 410d295bdeeSPawel Jakub Dawidek } 411d295bdeeSPawel Jakub Dawidek } else if (crd->crd_flags & CRD_F_ENCRYPT) { 412f34a967bSPawel Jakub Dawidek for (i = crd->crd_skip; 413f34a967bSPawel Jakub Dawidek i < crd->crd_skip + crd->crd_len; i += blks) { 414f34a967bSPawel Jakub Dawidek /* XOR with the IV/previous block, as appropriate. */ 415f34a967bSPawel Jakub Dawidek if (i == crd->crd_skip) 416f34a967bSPawel Jakub Dawidek for (k = 0; k < blks; k++) 417f34a967bSPawel Jakub Dawidek buf[i + k] ^= ivp[k]; 418f34a967bSPawel Jakub Dawidek else 419f34a967bSPawel Jakub Dawidek for (k = 0; k < blks; k++) 420f34a967bSPawel Jakub Dawidek buf[i + k] ^= buf[i + k - blks]; 421f34a967bSPawel Jakub Dawidek exf->encrypt(sw->sw_kschedule, buf + i); 422f34a967bSPawel Jakub Dawidek } 423f34a967bSPawel Jakub Dawidek } else { /* Decrypt */ 424f34a967bSPawel Jakub Dawidek /* 425f34a967bSPawel Jakub Dawidek * Start at the end, so we don't need to keep the encrypted 426f34a967bSPawel Jakub Dawidek * block as the IV for the next block. 427f34a967bSPawel Jakub Dawidek */ 428f34a967bSPawel Jakub Dawidek for (i = crd->crd_skip + crd->crd_len - blks; 429f34a967bSPawel Jakub Dawidek i >= crd->crd_skip; i -= blks) { 430f34a967bSPawel Jakub Dawidek exf->decrypt(sw->sw_kschedule, buf + i); 431f34a967bSPawel Jakub Dawidek 432f34a967bSPawel Jakub Dawidek /* XOR with the IV/previous block, as appropriate */ 433f34a967bSPawel Jakub Dawidek if (i == crd->crd_skip) 434f34a967bSPawel Jakub Dawidek for (k = 0; k < blks; k++) 435f34a967bSPawel Jakub Dawidek buf[i + k] ^= ivp[k]; 436f34a967bSPawel Jakub Dawidek else 437f34a967bSPawel Jakub Dawidek for (k = 0; k < blks; k++) 438f34a967bSPawel Jakub Dawidek buf[i + k] ^= buf[i + k - blks]; 439f34a967bSPawel Jakub Dawidek } 440f34a967bSPawel Jakub Dawidek } 441f34a967bSPawel Jakub Dawidek 442f34a967bSPawel Jakub Dawidek return 0; /* Done with contiguous buffer encryption/decryption */ 443091d81d1SSam Leffler } 444091d81d1SSam Leffler 445091d81d1SSam Leffler /* Unreachable */ 446091d81d1SSam Leffler return EINVAL; 447091d81d1SSam Leffler } 448091d81d1SSam Leffler 449f6c4bc3bSPawel Jakub Dawidek static void 450f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key, 451f6c4bc3bSPawel Jakub Dawidek int klen) 452f6c4bc3bSPawel Jakub Dawidek { 453f6c4bc3bSPawel Jakub Dawidek int k; 454f6c4bc3bSPawel Jakub Dawidek 455f6c4bc3bSPawel Jakub Dawidek klen /= 8; 456f6c4bc3bSPawel Jakub Dawidek 457f6c4bc3bSPawel Jakub Dawidek switch (axf->type) { 458f6c4bc3bSPawel Jakub Dawidek case CRYPTO_MD5_HMAC: 459f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA1_HMAC: 460f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 461f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 462f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 463f6c4bc3bSPawel Jakub Dawidek case CRYPTO_NULL_HMAC: 464f6c4bc3bSPawel Jakub Dawidek case CRYPTO_RIPEMD160_HMAC: 465f6c4bc3bSPawel Jakub Dawidek for (k = 0; k < klen; k++) 466f6c4bc3bSPawel Jakub Dawidek key[k] ^= HMAC_IPAD_VAL; 467f6c4bc3bSPawel Jakub Dawidek 468f6c4bc3bSPawel Jakub Dawidek axf->Init(sw->sw_ictx); 469f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_ictx, key, klen); 470f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_ictx, hmac_ipad_buffer, axf->blocksize - klen); 471f6c4bc3bSPawel Jakub Dawidek 472f6c4bc3bSPawel Jakub Dawidek for (k = 0; k < klen; k++) 473f6c4bc3bSPawel Jakub Dawidek key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 474f6c4bc3bSPawel Jakub Dawidek 475f6c4bc3bSPawel Jakub Dawidek axf->Init(sw->sw_octx); 476f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_octx, key, klen); 477f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_octx, hmac_opad_buffer, axf->blocksize - klen); 478f6c4bc3bSPawel Jakub Dawidek 479f6c4bc3bSPawel Jakub Dawidek for (k = 0; k < klen; k++) 480f6c4bc3bSPawel Jakub Dawidek key[k] ^= HMAC_OPAD_VAL; 481f6c4bc3bSPawel Jakub Dawidek break; 482f6c4bc3bSPawel Jakub Dawidek case CRYPTO_MD5_KPDK: 483f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA1_KPDK: 4841f4990a6SBjoern A. Zeeb { 48577680d96SBjoern A. Zeeb /* 48677680d96SBjoern A. Zeeb * We need a buffer that can hold an md5 and a sha1 result 48777680d96SBjoern A. Zeeb * just to throw it away. 48877680d96SBjoern A. Zeeb * What we do here is the initial part of: 48977680d96SBjoern A. Zeeb * ALGO( key, keyfill, .. ) 49077680d96SBjoern A. Zeeb * adding the key to sw_ictx and abusing Final() to get the 49177680d96SBjoern A. Zeeb * "keyfill" padding. 49277680d96SBjoern A. Zeeb * In addition we abuse the sw_octx to save the key to have 49377680d96SBjoern A. Zeeb * it to be able to append it at the end in swcr_authcompute(). 49477680d96SBjoern A. Zeeb */ 4951f4990a6SBjoern A. Zeeb u_char buf[SHA1_RESULTLEN]; 4961f4990a6SBjoern A. Zeeb 497f6c4bc3bSPawel Jakub Dawidek sw->sw_klen = klen; 498f6c4bc3bSPawel Jakub Dawidek bcopy(key, sw->sw_octx, klen); 499f6c4bc3bSPawel Jakub Dawidek axf->Init(sw->sw_ictx); 500f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_ictx, key, klen); 5011f4990a6SBjoern A. Zeeb axf->Final(buf, sw->sw_ictx); 502f6c4bc3bSPawel Jakub Dawidek break; 5031f4990a6SBjoern A. Zeeb } 504f6c4bc3bSPawel Jakub Dawidek default: 505f6c4bc3bSPawel Jakub Dawidek printf("%s: CRD_F_KEY_EXPLICIT flag given, but algorithm %d " 506f6c4bc3bSPawel Jakub Dawidek "doesn't use keys.\n", __func__, axf->type); 507f6c4bc3bSPawel Jakub Dawidek } 508f6c4bc3bSPawel Jakub Dawidek } 509f6c4bc3bSPawel Jakub Dawidek 510091d81d1SSam Leffler /* 511091d81d1SSam Leffler * Compute keyed-hash authenticator. 512091d81d1SSam Leffler */ 513091d81d1SSam Leffler static int 51438d2f8d6SPawel Jakub Dawidek swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, 515f34a967bSPawel Jakub Dawidek int flags) 516091d81d1SSam Leffler { 5170bbc4bf9SPawel Jakub Dawidek unsigned char aalg[HASH_MAX_LEN]; 518091d81d1SSam Leffler struct auth_hash *axf; 519091d81d1SSam Leffler union authctx ctx; 520091d81d1SSam Leffler int err; 521091d81d1SSam Leffler 522091d81d1SSam Leffler if (sw->sw_ictx == 0) 523091d81d1SSam Leffler return EINVAL; 524091d81d1SSam Leffler 525091d81d1SSam Leffler axf = sw->sw_axf; 526091d81d1SSam Leffler 527f6c4bc3bSPawel Jakub Dawidek if (crd->crd_flags & CRD_F_KEY_EXPLICIT) 528f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen); 529f6c4bc3bSPawel Jakub Dawidek 530091d81d1SSam Leffler bcopy(sw->sw_ictx, &ctx, axf->ctxsize); 531091d81d1SSam Leffler 532f34a967bSPawel Jakub Dawidek err = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, 533f34a967bSPawel Jakub Dawidek (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); 534091d81d1SSam Leffler if (err) 535091d81d1SSam Leffler return err; 536091d81d1SSam Leffler 537091d81d1SSam Leffler switch (sw->sw_alg) { 538091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 539091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 540f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 541f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 542f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 543091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 544091d81d1SSam Leffler if (sw->sw_octx == NULL) 545091d81d1SSam Leffler return EINVAL; 546091d81d1SSam Leffler 547091d81d1SSam Leffler axf->Final(aalg, &ctx); 548091d81d1SSam Leffler bcopy(sw->sw_octx, &ctx, axf->ctxsize); 549091d81d1SSam Leffler axf->Update(&ctx, aalg, axf->hashsize); 550091d81d1SSam Leffler axf->Final(aalg, &ctx); 551091d81d1SSam Leffler break; 552091d81d1SSam Leffler 553091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 554091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 55577680d96SBjoern A. Zeeb /* If we have no key saved, return error. */ 556091d81d1SSam Leffler if (sw->sw_octx == NULL) 557091d81d1SSam Leffler return EINVAL; 558091d81d1SSam Leffler 55977680d96SBjoern A. Zeeb /* 56077680d96SBjoern A. Zeeb * Add the trailing copy of the key (see comment in 56177680d96SBjoern A. Zeeb * swcr_authprepare()) after the data: 56277680d96SBjoern A. Zeeb * ALGO( .., key, algofill ) 56377680d96SBjoern A. Zeeb * and let Final() do the proper, natural "algofill" 56477680d96SBjoern A. Zeeb * padding. 56577680d96SBjoern A. Zeeb */ 566091d81d1SSam Leffler axf->Update(&ctx, sw->sw_octx, sw->sw_klen); 567091d81d1SSam Leffler axf->Final(aalg, &ctx); 568091d81d1SSam Leffler break; 569091d81d1SSam Leffler 570091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 571091d81d1SSam Leffler axf->Final(aalg, &ctx); 572091d81d1SSam Leffler break; 573091d81d1SSam Leffler } 574091d81d1SSam Leffler 575091d81d1SSam Leffler /* Inject the authentication data */ 576f34a967bSPawel Jakub Dawidek crypto_copyback(flags, buf, crd->crd_inject, 577f6c4bc3bSPawel Jakub Dawidek sw->sw_mlen == 0 ? axf->hashsize : sw->sw_mlen, aalg); 578091d81d1SSam Leffler return 0; 579091d81d1SSam Leffler } 580091d81d1SSam Leffler 581091d81d1SSam Leffler /* 582091d81d1SSam Leffler * Apply a compression/decompression algorithm 583091d81d1SSam Leffler */ 584091d81d1SSam Leffler static int 585091d81d1SSam Leffler swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw, 586f34a967bSPawel Jakub Dawidek caddr_t buf, int flags) 587091d81d1SSam Leffler { 588091d81d1SSam Leffler u_int8_t *data, *out; 589091d81d1SSam Leffler struct comp_algo *cxf; 590091d81d1SSam Leffler int adj; 591091d81d1SSam Leffler u_int32_t result; 592091d81d1SSam Leffler 593091d81d1SSam Leffler cxf = sw->sw_cxf; 594091d81d1SSam Leffler 595091d81d1SSam Leffler /* We must handle the whole buffer of data in one time 596091d81d1SSam Leffler * then if there is not all the data in the mbuf, we must 597091d81d1SSam Leffler * copy in a buffer. 598091d81d1SSam Leffler */ 599091d81d1SSam Leffler 6001ede983cSDag-Erling Smørgrav data = malloc(crd->crd_len, M_CRYPTO_DATA, M_NOWAIT); 601091d81d1SSam Leffler if (data == NULL) 602091d81d1SSam Leffler return (EINVAL); 603f34a967bSPawel Jakub Dawidek crypto_copydata(flags, buf, crd->crd_skip, crd->crd_len, data); 604091d81d1SSam Leffler 605091d81d1SSam Leffler if (crd->crd_flags & CRD_F_COMP) 606091d81d1SSam Leffler result = cxf->compress(data, crd->crd_len, &out); 607091d81d1SSam Leffler else 608091d81d1SSam Leffler result = cxf->decompress(data, crd->crd_len, &out); 609091d81d1SSam Leffler 6101ede983cSDag-Erling Smørgrav free(data, M_CRYPTO_DATA); 611091d81d1SSam Leffler if (result == 0) 612091d81d1SSam Leffler return EINVAL; 613091d81d1SSam Leffler 614091d81d1SSam Leffler /* Copy back the (de)compressed data. m_copyback is 615091d81d1SSam Leffler * extending the mbuf as necessary. 616091d81d1SSam Leffler */ 617091d81d1SSam Leffler sw->sw_size = result; 618091d81d1SSam Leffler /* Check the compressed size when doing compression */ 619091d81d1SSam Leffler if (crd->crd_flags & CRD_F_COMP) { 620df4dece1SBjoern A. Zeeb if (result >= crd->crd_len) { 621091d81d1SSam Leffler /* Compression was useless, we lost time */ 6221ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 623091d81d1SSam Leffler return 0; 624091d81d1SSam Leffler } 625091d81d1SSam Leffler } 626091d81d1SSam Leffler 627f34a967bSPawel Jakub Dawidek crypto_copyback(flags, buf, crd->crd_skip, result, out); 628091d81d1SSam Leffler if (result < crd->crd_len) { 629091d81d1SSam Leffler adj = result - crd->crd_len; 630f34a967bSPawel Jakub Dawidek if (flags & CRYPTO_F_IMBUF) { 631091d81d1SSam Leffler adj = result - crd->crd_len; 632091d81d1SSam Leffler m_adj((struct mbuf *)buf, adj); 633f34a967bSPawel Jakub Dawidek } else if (flags & CRYPTO_F_IOV) { 634091d81d1SSam Leffler struct uio *uio = (struct uio *)buf; 635091d81d1SSam Leffler int ind; 636091d81d1SSam Leffler 637091d81d1SSam Leffler adj = crd->crd_len - result; 638091d81d1SSam Leffler ind = uio->uio_iovcnt - 1; 639091d81d1SSam Leffler 640091d81d1SSam Leffler while (adj > 0 && ind >= 0) { 641091d81d1SSam Leffler if (adj < uio->uio_iov[ind].iov_len) { 642091d81d1SSam Leffler uio->uio_iov[ind].iov_len -= adj; 643091d81d1SSam Leffler break; 644091d81d1SSam Leffler } 645091d81d1SSam Leffler 646091d81d1SSam Leffler adj -= uio->uio_iov[ind].iov_len; 647091d81d1SSam Leffler uio->uio_iov[ind].iov_len = 0; 648091d81d1SSam Leffler ind--; 649091d81d1SSam Leffler uio->uio_iovcnt--; 650091d81d1SSam Leffler } 651091d81d1SSam Leffler } 652091d81d1SSam Leffler } 6531ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 654091d81d1SSam Leffler return 0; 655091d81d1SSam Leffler } 656091d81d1SSam Leffler 657091d81d1SSam Leffler /* 658091d81d1SSam Leffler * Generate a new software session. 659091d81d1SSam Leffler */ 660091d81d1SSam Leffler static int 6616810ad6fSSam Leffler swcr_newsession(device_t dev, u_int32_t *sid, struct cryptoini *cri) 662091d81d1SSam Leffler { 663091d81d1SSam Leffler struct swcr_data **swd; 664091d81d1SSam Leffler struct auth_hash *axf; 665091d81d1SSam Leffler struct enc_xform *txf; 666091d81d1SSam Leffler struct comp_algo *cxf; 667091d81d1SSam Leffler u_int32_t i; 668f6c4bc3bSPawel Jakub Dawidek int error; 669091d81d1SSam Leffler 670091d81d1SSam Leffler if (sid == NULL || cri == NULL) 671091d81d1SSam Leffler return EINVAL; 672091d81d1SSam Leffler 673091d81d1SSam Leffler if (swcr_sessions) { 674091d81d1SSam Leffler for (i = 1; i < swcr_sesnum; i++) 675091d81d1SSam Leffler if (swcr_sessions[i] == NULL) 676091d81d1SSam Leffler break; 677091d81d1SSam Leffler } else 678091d81d1SSam Leffler i = 1; /* NB: to silence compiler warning */ 679091d81d1SSam Leffler 680091d81d1SSam Leffler if (swcr_sessions == NULL || i == swcr_sesnum) { 681091d81d1SSam Leffler if (swcr_sessions == NULL) { 682091d81d1SSam Leffler i = 1; /* We leave swcr_sessions[0] empty */ 683091d81d1SSam Leffler swcr_sesnum = CRYPTO_SW_SESSIONS; 684091d81d1SSam Leffler } else 685091d81d1SSam Leffler swcr_sesnum *= 2; 686091d81d1SSam Leffler 687091d81d1SSam Leffler swd = malloc(swcr_sesnum * sizeof(struct swcr_data *), 688091d81d1SSam Leffler M_CRYPTO_DATA, M_NOWAIT|M_ZERO); 689091d81d1SSam Leffler if (swd == NULL) { 690091d81d1SSam Leffler /* Reset session number */ 691091d81d1SSam Leffler if (swcr_sesnum == CRYPTO_SW_SESSIONS) 692091d81d1SSam Leffler swcr_sesnum = 0; 693091d81d1SSam Leffler else 694091d81d1SSam Leffler swcr_sesnum /= 2; 695091d81d1SSam Leffler return ENOBUFS; 696091d81d1SSam Leffler } 697091d81d1SSam Leffler 698091d81d1SSam Leffler /* Copy existing sessions */ 6996810ad6fSSam Leffler if (swcr_sessions != NULL) { 700091d81d1SSam Leffler bcopy(swcr_sessions, swd, 701091d81d1SSam Leffler (swcr_sesnum / 2) * sizeof(struct swcr_data *)); 702091d81d1SSam Leffler free(swcr_sessions, M_CRYPTO_DATA); 703091d81d1SSam Leffler } 704091d81d1SSam Leffler 705091d81d1SSam Leffler swcr_sessions = swd; 706091d81d1SSam Leffler } 707091d81d1SSam Leffler 708091d81d1SSam Leffler swd = &swcr_sessions[i]; 709091d81d1SSam Leffler *sid = i; 710091d81d1SSam Leffler 711091d81d1SSam Leffler while (cri) { 7121ede983cSDag-Erling Smørgrav *swd = malloc(sizeof(struct swcr_data), 713091d81d1SSam Leffler M_CRYPTO_DATA, M_NOWAIT|M_ZERO); 714091d81d1SSam Leffler if (*swd == NULL) { 7156810ad6fSSam Leffler swcr_freesession(dev, i); 716091d81d1SSam Leffler return ENOBUFS; 717091d81d1SSam Leffler } 718091d81d1SSam Leffler 719091d81d1SSam Leffler switch (cri->cri_alg) { 720091d81d1SSam Leffler case CRYPTO_DES_CBC: 721091d81d1SSam Leffler txf = &enc_xform_des; 722091d81d1SSam Leffler goto enccommon; 723091d81d1SSam Leffler case CRYPTO_3DES_CBC: 724091d81d1SSam Leffler txf = &enc_xform_3des; 725091d81d1SSam Leffler goto enccommon; 726091d81d1SSam Leffler case CRYPTO_BLF_CBC: 727091d81d1SSam Leffler txf = &enc_xform_blf; 728091d81d1SSam Leffler goto enccommon; 729091d81d1SSam Leffler case CRYPTO_CAST_CBC: 730091d81d1SSam Leffler txf = &enc_xform_cast5; 731091d81d1SSam Leffler goto enccommon; 732091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 733091d81d1SSam Leffler txf = &enc_xform_skipjack; 734091d81d1SSam Leffler goto enccommon; 735091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 736091d81d1SSam Leffler txf = &enc_xform_rijndael128; 737091d81d1SSam Leffler goto enccommon; 738d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 739d295bdeeSPawel Jakub Dawidek txf = &enc_xform_aes_xts; 740d295bdeeSPawel Jakub Dawidek goto enccommon; 741559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 742559d3390SGeorge V. Neville-Neil txf = &enc_xform_camellia; 743559d3390SGeorge V. Neville-Neil goto enccommon; 744091d81d1SSam Leffler case CRYPTO_NULL_CBC: 745091d81d1SSam Leffler txf = &enc_xform_null; 746091d81d1SSam Leffler goto enccommon; 747091d81d1SSam Leffler enccommon: 748f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 749091d81d1SSam Leffler error = txf->setkey(&((*swd)->sw_kschedule), 750091d81d1SSam Leffler cri->cri_key, cri->cri_klen / 8); 751091d81d1SSam Leffler if (error) { 7526810ad6fSSam Leffler swcr_freesession(dev, i); 753091d81d1SSam Leffler return error; 754091d81d1SSam Leffler } 755f6c4bc3bSPawel Jakub Dawidek } 756091d81d1SSam Leffler (*swd)->sw_exf = txf; 757091d81d1SSam Leffler break; 758091d81d1SSam Leffler 759091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 760f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_md5; 761091d81d1SSam Leffler goto authcommon; 762091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 763f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_sha1; 764091d81d1SSam Leffler goto authcommon; 765f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 766091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_256; 767f6c4bc3bSPawel Jakub Dawidek goto authcommon; 768f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 769091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_384; 770f6c4bc3bSPawel Jakub Dawidek goto authcommon; 771f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 772091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_512; 773091d81d1SSam Leffler goto authcommon; 774091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 775091d81d1SSam Leffler axf = &auth_hash_null; 776091d81d1SSam Leffler goto authcommon; 777091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 778f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_ripemd_160; 779091d81d1SSam Leffler authcommon: 780091d81d1SSam Leffler (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 781091d81d1SSam Leffler M_NOWAIT); 782091d81d1SSam Leffler if ((*swd)->sw_ictx == NULL) { 7836810ad6fSSam Leffler swcr_freesession(dev, i); 784091d81d1SSam Leffler return ENOBUFS; 785091d81d1SSam Leffler } 786091d81d1SSam Leffler 787091d81d1SSam Leffler (*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, 788091d81d1SSam Leffler M_NOWAIT); 789091d81d1SSam Leffler if ((*swd)->sw_octx == NULL) { 7906810ad6fSSam Leffler swcr_freesession(dev, i); 791091d81d1SSam Leffler return ENOBUFS; 792091d81d1SSam Leffler } 793091d81d1SSam Leffler 794f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 795f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(axf, *swd, cri->cri_key, 796f6c4bc3bSPawel Jakub Dawidek cri->cri_klen); 797f6c4bc3bSPawel Jakub Dawidek } 798091d81d1SSam Leffler 799f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_mlen = cri->cri_mlen; 800091d81d1SSam Leffler (*swd)->sw_axf = axf; 801091d81d1SSam Leffler break; 802091d81d1SSam Leffler 803091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 804091d81d1SSam Leffler axf = &auth_hash_key_md5; 805091d81d1SSam Leffler goto auth2common; 806091d81d1SSam Leffler 807091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 808091d81d1SSam Leffler axf = &auth_hash_key_sha1; 809091d81d1SSam Leffler auth2common: 810091d81d1SSam Leffler (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 811091d81d1SSam Leffler M_NOWAIT); 812091d81d1SSam Leffler if ((*swd)->sw_ictx == NULL) { 8136810ad6fSSam Leffler swcr_freesession(dev, i); 814091d81d1SSam Leffler return ENOBUFS; 815091d81d1SSam Leffler } 816091d81d1SSam Leffler 817f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_octx = malloc(cri->cri_klen / 8, 818f6c4bc3bSPawel Jakub Dawidek M_CRYPTO_DATA, M_NOWAIT); 819091d81d1SSam Leffler if ((*swd)->sw_octx == NULL) { 8206810ad6fSSam Leffler swcr_freesession(dev, i); 821091d81d1SSam Leffler return ENOBUFS; 822091d81d1SSam Leffler } 823091d81d1SSam Leffler 824f6c4bc3bSPawel Jakub Dawidek /* Store the key so we can "append" it to the payload */ 825f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 826f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(axf, *swd, cri->cri_key, 827f6c4bc3bSPawel Jakub Dawidek cri->cri_klen); 828f6c4bc3bSPawel Jakub Dawidek } 829f6c4bc3bSPawel Jakub Dawidek 830f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_mlen = cri->cri_mlen; 831091d81d1SSam Leffler (*swd)->sw_axf = axf; 832091d81d1SSam Leffler break; 833091d81d1SSam Leffler #ifdef notdef 834091d81d1SSam Leffler case CRYPTO_MD5: 835091d81d1SSam Leffler axf = &auth_hash_md5; 836091d81d1SSam Leffler goto auth3common; 837091d81d1SSam Leffler 838091d81d1SSam Leffler case CRYPTO_SHA1: 839091d81d1SSam Leffler axf = &auth_hash_sha1; 840091d81d1SSam Leffler auth3common: 841091d81d1SSam Leffler (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 842091d81d1SSam Leffler M_NOWAIT); 843091d81d1SSam Leffler if ((*swd)->sw_ictx == NULL) { 8446810ad6fSSam Leffler swcr_freesession(dev, i); 845091d81d1SSam Leffler return ENOBUFS; 846091d81d1SSam Leffler } 847091d81d1SSam Leffler 848091d81d1SSam Leffler axf->Init((*swd)->sw_ictx); 849f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_mlen = cri->cri_mlen; 850091d81d1SSam Leffler (*swd)->sw_axf = axf; 851091d81d1SSam Leffler break; 852091d81d1SSam Leffler #endif 853091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 854091d81d1SSam Leffler cxf = &comp_algo_deflate; 855091d81d1SSam Leffler (*swd)->sw_cxf = cxf; 856091d81d1SSam Leffler break; 857091d81d1SSam Leffler default: 8586810ad6fSSam Leffler swcr_freesession(dev, i); 859091d81d1SSam Leffler return EINVAL; 860091d81d1SSam Leffler } 861091d81d1SSam Leffler 862091d81d1SSam Leffler (*swd)->sw_alg = cri->cri_alg; 863091d81d1SSam Leffler cri = cri->cri_next; 864091d81d1SSam Leffler swd = &((*swd)->sw_next); 865091d81d1SSam Leffler } 866091d81d1SSam Leffler return 0; 867091d81d1SSam Leffler } 868091d81d1SSam Leffler 869091d81d1SSam Leffler /* 870091d81d1SSam Leffler * Free a session. 871091d81d1SSam Leffler */ 872091d81d1SSam Leffler static int 8736810ad6fSSam Leffler swcr_freesession(device_t dev, u_int64_t tid) 874091d81d1SSam Leffler { 875091d81d1SSam Leffler struct swcr_data *swd; 876091d81d1SSam Leffler struct enc_xform *txf; 877091d81d1SSam Leffler struct auth_hash *axf; 878091d81d1SSam Leffler struct comp_algo *cxf; 87907d0c94aSSam Leffler u_int32_t sid = CRYPTO_SESID2LID(tid); 880091d81d1SSam Leffler 881091d81d1SSam Leffler if (sid > swcr_sesnum || swcr_sessions == NULL || 882091d81d1SSam Leffler swcr_sessions[sid] == NULL) 883091d81d1SSam Leffler return EINVAL; 884091d81d1SSam Leffler 885091d81d1SSam Leffler /* Silently accept and return */ 886091d81d1SSam Leffler if (sid == 0) 887091d81d1SSam Leffler return 0; 888091d81d1SSam Leffler 889091d81d1SSam Leffler while ((swd = swcr_sessions[sid]) != NULL) { 890091d81d1SSam Leffler swcr_sessions[sid] = swd->sw_next; 891091d81d1SSam Leffler 892091d81d1SSam Leffler switch (swd->sw_alg) { 893091d81d1SSam Leffler case CRYPTO_DES_CBC: 894091d81d1SSam Leffler case CRYPTO_3DES_CBC: 895091d81d1SSam Leffler case CRYPTO_BLF_CBC: 896091d81d1SSam Leffler case CRYPTO_CAST_CBC: 897091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 898091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 899d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 900559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 901091d81d1SSam Leffler case CRYPTO_NULL_CBC: 902091d81d1SSam Leffler txf = swd->sw_exf; 903091d81d1SSam Leffler 904091d81d1SSam Leffler if (swd->sw_kschedule) 905091d81d1SSam Leffler txf->zerokey(&(swd->sw_kschedule)); 906091d81d1SSam Leffler break; 907091d81d1SSam Leffler 908091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 909091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 910f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 911f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 912f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 913091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 914091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 915091d81d1SSam Leffler axf = swd->sw_axf; 916091d81d1SSam Leffler 917091d81d1SSam Leffler if (swd->sw_ictx) { 918091d81d1SSam Leffler bzero(swd->sw_ictx, axf->ctxsize); 919091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 920091d81d1SSam Leffler } 921091d81d1SSam Leffler if (swd->sw_octx) { 922091d81d1SSam Leffler bzero(swd->sw_octx, axf->ctxsize); 923091d81d1SSam Leffler free(swd->sw_octx, M_CRYPTO_DATA); 924091d81d1SSam Leffler } 925091d81d1SSam Leffler break; 926091d81d1SSam Leffler 927091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 928091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 929091d81d1SSam Leffler axf = swd->sw_axf; 930091d81d1SSam Leffler 931091d81d1SSam Leffler if (swd->sw_ictx) { 932091d81d1SSam Leffler bzero(swd->sw_ictx, axf->ctxsize); 933091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 934091d81d1SSam Leffler } 935091d81d1SSam Leffler if (swd->sw_octx) { 936091d81d1SSam Leffler bzero(swd->sw_octx, swd->sw_klen); 937091d81d1SSam Leffler free(swd->sw_octx, M_CRYPTO_DATA); 938091d81d1SSam Leffler } 939091d81d1SSam Leffler break; 940091d81d1SSam Leffler 941091d81d1SSam Leffler case CRYPTO_MD5: 942091d81d1SSam Leffler case CRYPTO_SHA1: 943091d81d1SSam Leffler axf = swd->sw_axf; 944091d81d1SSam Leffler 945091d81d1SSam Leffler if (swd->sw_ictx) 946091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 947091d81d1SSam Leffler break; 948091d81d1SSam Leffler 949091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 950091d81d1SSam Leffler cxf = swd->sw_cxf; 951091d81d1SSam Leffler break; 952091d81d1SSam Leffler } 953091d81d1SSam Leffler 9541ede983cSDag-Erling Smørgrav free(swd, M_CRYPTO_DATA); 955091d81d1SSam Leffler } 956091d81d1SSam Leffler return 0; 957091d81d1SSam Leffler } 958091d81d1SSam Leffler 959091d81d1SSam Leffler /* 960091d81d1SSam Leffler * Process a software request. 961091d81d1SSam Leffler */ 962091d81d1SSam Leffler static int 9636810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint) 964091d81d1SSam Leffler { 965091d81d1SSam Leffler struct cryptodesc *crd; 966091d81d1SSam Leffler struct swcr_data *sw; 967091d81d1SSam Leffler u_int32_t lid; 968091d81d1SSam Leffler 969091d81d1SSam Leffler /* Sanity check */ 970091d81d1SSam Leffler if (crp == NULL) 971091d81d1SSam Leffler return EINVAL; 972091d81d1SSam Leffler 973091d81d1SSam Leffler if (crp->crp_desc == NULL || crp->crp_buf == NULL) { 974091d81d1SSam Leffler crp->crp_etype = EINVAL; 975091d81d1SSam Leffler goto done; 976091d81d1SSam Leffler } 977091d81d1SSam Leffler 978091d81d1SSam Leffler lid = crp->crp_sid & 0xffffffff; 979091d81d1SSam Leffler if (lid >= swcr_sesnum || lid == 0 || swcr_sessions[lid] == NULL) { 980091d81d1SSam Leffler crp->crp_etype = ENOENT; 981091d81d1SSam Leffler goto done; 982091d81d1SSam Leffler } 983091d81d1SSam Leffler 984091d81d1SSam Leffler /* Go through crypto descriptors, processing as we go */ 985091d81d1SSam Leffler for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 986091d81d1SSam Leffler /* 987091d81d1SSam Leffler * Find the crypto context. 988091d81d1SSam Leffler * 989091d81d1SSam Leffler * XXX Note that the logic here prevents us from having 990091d81d1SSam Leffler * XXX the same algorithm multiple times in a session 991091d81d1SSam Leffler * XXX (or rather, we can but it won't give us the right 992091d81d1SSam Leffler * XXX results). To do that, we'd need some way of differentiating 993091d81d1SSam Leffler * XXX between the various instances of an algorithm (so we can 994091d81d1SSam Leffler * XXX locate the correct crypto context). 995091d81d1SSam Leffler */ 996091d81d1SSam Leffler for (sw = swcr_sessions[lid]; 997091d81d1SSam Leffler sw && sw->sw_alg != crd->crd_alg; 998091d81d1SSam Leffler sw = sw->sw_next) 999091d81d1SSam Leffler ; 1000091d81d1SSam Leffler 1001091d81d1SSam Leffler /* No such context ? */ 1002091d81d1SSam Leffler if (sw == NULL) { 1003091d81d1SSam Leffler crp->crp_etype = EINVAL; 1004091d81d1SSam Leffler goto done; 1005091d81d1SSam Leffler } 1006091d81d1SSam Leffler switch (sw->sw_alg) { 1007091d81d1SSam Leffler case CRYPTO_DES_CBC: 1008091d81d1SSam Leffler case CRYPTO_3DES_CBC: 1009091d81d1SSam Leffler case CRYPTO_BLF_CBC: 1010091d81d1SSam Leffler case CRYPTO_CAST_CBC: 1011091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 1012091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 1013d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 1014559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 1015091d81d1SSam Leffler if ((crp->crp_etype = swcr_encdec(crd, sw, 1016f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1017091d81d1SSam Leffler goto done; 1018091d81d1SSam Leffler break; 1019091d81d1SSam Leffler case CRYPTO_NULL_CBC: 1020091d81d1SSam Leffler crp->crp_etype = 0; 1021091d81d1SSam Leffler break; 1022091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 1023091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1024f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1025f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1026f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1027091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 1028091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1029091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 1030091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 1031091d81d1SSam Leffler case CRYPTO_MD5: 1032091d81d1SSam Leffler case CRYPTO_SHA1: 103338d2f8d6SPawel Jakub Dawidek if ((crp->crp_etype = swcr_authcompute(crd, sw, 1034f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1035091d81d1SSam Leffler goto done; 1036091d81d1SSam Leffler break; 1037091d81d1SSam Leffler 1038091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 1039091d81d1SSam Leffler if ((crp->crp_etype = swcr_compdec(crd, sw, 1040f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1041091d81d1SSam Leffler goto done; 1042091d81d1SSam Leffler else 1043091d81d1SSam Leffler crp->crp_olen = (int)sw->sw_size; 1044091d81d1SSam Leffler break; 1045091d81d1SSam Leffler 1046091d81d1SSam Leffler default: 1047091d81d1SSam Leffler /* Unknown/unsupported algorithm */ 1048091d81d1SSam Leffler crp->crp_etype = EINVAL; 1049091d81d1SSam Leffler goto done; 1050091d81d1SSam Leffler } 1051091d81d1SSam Leffler } 1052091d81d1SSam Leffler 1053091d81d1SSam Leffler done: 1054091d81d1SSam Leffler crypto_done(crp); 1055091d81d1SSam Leffler return 0; 1056091d81d1SSam Leffler } 1057091d81d1SSam Leffler 1058091d81d1SSam Leffler static void 10593f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent) 1060091d81d1SSam Leffler { 10616810ad6fSSam Leffler /* NB: order 10 is so we get attached after h/w devices */ 10626810ad6fSSam Leffler if (device_find_child(parent, "cryptosoft", -1) == NULL && 10636810ad6fSSam Leffler BUS_ADD_CHILD(parent, 10, "cryptosoft", -1) == 0) 10646810ad6fSSam Leffler panic("cryptosoft: could not attach"); 10656810ad6fSSam Leffler } 1066f6c4bc3bSPawel Jakub Dawidek 10676810ad6fSSam Leffler static int 10686810ad6fSSam Leffler swcr_probe(device_t dev) 10696810ad6fSSam Leffler { 10706810ad6fSSam Leffler device_set_desc(dev, "software crypto"); 10716810ad6fSSam Leffler return (0); 10726810ad6fSSam Leffler } 1073f6c4bc3bSPawel Jakub Dawidek 10746810ad6fSSam Leffler static int 10756810ad6fSSam Leffler swcr_attach(device_t dev) 10766810ad6fSSam Leffler { 10776810ad6fSSam Leffler memset(hmac_ipad_buffer, HMAC_IPAD_VAL, HMAC_MAX_BLOCK_LEN); 10786810ad6fSSam Leffler memset(hmac_opad_buffer, HMAC_OPAD_VAL, HMAC_MAX_BLOCK_LEN); 10796810ad6fSSam Leffler 10806810ad6fSSam Leffler swcr_id = crypto_get_driverid(dev, 10816810ad6fSSam Leffler CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); 10826810ad6fSSam Leffler if (swcr_id < 0) { 10836810ad6fSSam Leffler device_printf(dev, "cannot initialize!"); 10846810ad6fSSam Leffler return ENOMEM; 10856810ad6fSSam Leffler } 1086091d81d1SSam Leffler #define REGISTER(alg) \ 10876810ad6fSSam Leffler crypto_register(swcr_id, alg, 0,0) 10886810ad6fSSam Leffler REGISTER(CRYPTO_DES_CBC); 1089091d81d1SSam Leffler REGISTER(CRYPTO_3DES_CBC); 1090091d81d1SSam Leffler REGISTER(CRYPTO_BLF_CBC); 1091091d81d1SSam Leffler REGISTER(CRYPTO_CAST_CBC); 1092091d81d1SSam Leffler REGISTER(CRYPTO_SKIPJACK_CBC); 1093091d81d1SSam Leffler REGISTER(CRYPTO_NULL_CBC); 1094091d81d1SSam Leffler REGISTER(CRYPTO_MD5_HMAC); 1095091d81d1SSam Leffler REGISTER(CRYPTO_SHA1_HMAC); 1096f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_256_HMAC); 1097f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_384_HMAC); 1098f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_512_HMAC); 1099091d81d1SSam Leffler REGISTER(CRYPTO_RIPEMD160_HMAC); 1100091d81d1SSam Leffler REGISTER(CRYPTO_NULL_HMAC); 1101091d81d1SSam Leffler REGISTER(CRYPTO_MD5_KPDK); 1102091d81d1SSam Leffler REGISTER(CRYPTO_SHA1_KPDK); 1103091d81d1SSam Leffler REGISTER(CRYPTO_MD5); 1104091d81d1SSam Leffler REGISTER(CRYPTO_SHA1); 1105091d81d1SSam Leffler REGISTER(CRYPTO_RIJNDAEL128_CBC); 1106d295bdeeSPawel Jakub Dawidek REGISTER(CRYPTO_AES_XTS); 1107559d3390SGeorge V. Neville-Neil REGISTER(CRYPTO_CAMELLIA_CBC); 1108091d81d1SSam Leffler REGISTER(CRYPTO_DEFLATE_COMP); 1109091d81d1SSam Leffler #undef REGISTER 11106810ad6fSSam Leffler 11116810ad6fSSam Leffler return 0; 1112091d81d1SSam Leffler } 11134b465da2SPawel Jakub Dawidek 11143f147ab2SWarner Losh static int 11156810ad6fSSam Leffler swcr_detach(device_t dev) 11164b465da2SPawel Jakub Dawidek { 11176810ad6fSSam Leffler crypto_unregister_all(swcr_id); 11184b465da2SPawel Jakub Dawidek if (swcr_sessions != NULL) 11191ede983cSDag-Erling Smørgrav free(swcr_sessions, M_CRYPTO_DATA); 11203f147ab2SWarner Losh return 0; 11214b465da2SPawel Jakub Dawidek } 11226810ad6fSSam Leffler 11236810ad6fSSam Leffler static device_method_t swcr_methods[] = { 11246810ad6fSSam Leffler DEVMETHOD(device_identify, swcr_identify), 11256810ad6fSSam Leffler DEVMETHOD(device_probe, swcr_probe), 11266810ad6fSSam Leffler DEVMETHOD(device_attach, swcr_attach), 11276810ad6fSSam Leffler DEVMETHOD(device_detach, swcr_detach), 11286810ad6fSSam Leffler 11296810ad6fSSam Leffler DEVMETHOD(cryptodev_newsession, swcr_newsession), 11306810ad6fSSam Leffler DEVMETHOD(cryptodev_freesession,swcr_freesession), 11316810ad6fSSam Leffler DEVMETHOD(cryptodev_process, swcr_process), 11326810ad6fSSam Leffler 11336810ad6fSSam Leffler {0, 0}, 11346810ad6fSSam Leffler }; 11356810ad6fSSam Leffler 11366810ad6fSSam Leffler static driver_t swcr_driver = { 11376810ad6fSSam Leffler "cryptosoft", 11386810ad6fSSam Leffler swcr_methods, 11396810ad6fSSam Leffler 0, /* NB: no softc */ 11406810ad6fSSam Leffler }; 11416810ad6fSSam Leffler static devclass_t swcr_devclass; 11426810ad6fSSam Leffler 11436810ad6fSSam Leffler /* 11446810ad6fSSam Leffler * NB: We explicitly reference the crypto module so we 11456810ad6fSSam Leffler * get the necessary ordering when built as a loadable 11466810ad6fSSam Leffler * module. This is required because we bundle the crypto 11476810ad6fSSam Leffler * module code together with the cryptosoft driver (otherwise 11486810ad6fSSam Leffler * normal module dependencies would handle things). 11496810ad6fSSam Leffler */ 11506810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *); 11516810ad6fSSam Leffler /* XXX where to attach */ 11526810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0); 11536810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1); 11546810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1); 1155