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 1208fca7a5SJohn-Mark Gurney * Copyright (c) 2014 The FreeBSD Foundation 1308fca7a5SJohn-Mark Gurney * All rights reserved. 1408fca7a5SJohn-Mark Gurney * 1508fca7a5SJohn-Mark Gurney * Portions of this software were developed by John-Mark Gurney 1608fca7a5SJohn-Mark Gurney * under sponsorship of the FreeBSD Foundation and 1708fca7a5SJohn-Mark Gurney * Rubicon Communications, LLC (Netgate). 18091d81d1SSam Leffler * 19091d81d1SSam Leffler * Permission to use, copy, and modify this software with or without fee 20091d81d1SSam Leffler * is hereby granted, provided that this entire notice is included in 21091d81d1SSam Leffler * all source code copies of any software which is or includes a copy or 22091d81d1SSam Leffler * modification of this software. 23091d81d1SSam Leffler * 24091d81d1SSam Leffler * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR 25091d81d1SSam Leffler * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY 26091d81d1SSam Leffler * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE 27091d81d1SSam Leffler * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR 28091d81d1SSam Leffler * PURPOSE. 29091d81d1SSam Leffler */ 30091d81d1SSam Leffler 312c446514SDavid E. O'Brien #include <sys/cdefs.h> 322c446514SDavid E. O'Brien __FBSDID("$FreeBSD$"); 332c446514SDavid E. O'Brien 34091d81d1SSam Leffler #include <sys/param.h> 35091d81d1SSam Leffler #include <sys/systm.h> 36091d81d1SSam Leffler #include <sys/malloc.h> 37091d81d1SSam Leffler #include <sys/mbuf.h> 386810ad6fSSam Leffler #include <sys/module.h> 39091d81d1SSam Leffler #include <sys/sysctl.h> 40091d81d1SSam Leffler #include <sys/errno.h> 41091d81d1SSam Leffler #include <sys/random.h> 42091d81d1SSam Leffler #include <sys/kernel.h> 43091d81d1SSam Leffler #include <sys/uio.h> 44109919c6SBenno Rice #include <sys/lock.h> 45109919c6SBenno Rice #include <sys/rwlock.h> 4608fca7a5SJohn-Mark Gurney #include <sys/endian.h> 4708fca7a5SJohn-Mark Gurney #include <sys/limits.h> 48a7fcb1afSSean Eric Fagan #include <sys/mutex.h> 49091d81d1SSam Leffler 50091d81d1SSam Leffler #include <crypto/blowfish/blowfish.h> 51091d81d1SSam Leffler #include <crypto/sha1.h> 52091d81d1SSam Leffler #include <opencrypto/rmd160.h> 539f65b10bSHajimu UMEMOTO #include <opencrypto/cast.h> 54091d81d1SSam Leffler #include <opencrypto/skipjack.h> 55091d81d1SSam Leffler #include <sys/md5.h> 56091d81d1SSam Leffler 57091d81d1SSam Leffler #include <opencrypto/cryptodev.h> 58091d81d1SSam Leffler #include <opencrypto/cryptosoft.h> 59091d81d1SSam Leffler #include <opencrypto/xform.h> 60091d81d1SSam Leffler 616810ad6fSSam Leffler #include <sys/kobj.h> 626810ad6fSSam Leffler #include <sys/bus.h> 636810ad6fSSam Leffler #include "cryptodev_if.h" 64091d81d1SSam Leffler 65*507281e5SSean Eric Fagan _Static_assert(AES_CCM_IV_LEN == AES_GCM_IV_LEN, 66*507281e5SSean Eric Fagan "AES_GCM_IV_LEN must currently be the same as AES_CCM_IV_LEN"); 67*507281e5SSean Eric Fagan 686810ad6fSSam Leffler static int32_t swcr_id; 696810ad6fSSam Leffler 706810ad6fSSam Leffler u_int8_t hmac_ipad_buffer[HMAC_MAX_BLOCK_LEN]; 716810ad6fSSam Leffler u_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN]; 72091d81d1SSam Leffler 73091d81d1SSam Leffler static int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); 74f34a967bSPawel Jakub Dawidek static int swcr_authcompute(struct cryptodesc *, struct swcr_data *, caddr_t, int); 7508fca7a5SJohn-Mark Gurney static int swcr_authenc(struct cryptop *crp); 76091d81d1SSam Leffler static int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); 771b0909d5SConrad Meyer static void swcr_freesession(device_t dev, crypto_session_t cses); 78091d81d1SSam Leffler 79091d81d1SSam Leffler /* 80091d81d1SSam Leffler * Apply a symmetric encryption/decryption algorithm. 81091d81d1SSam Leffler */ 82091d81d1SSam Leffler static int 83091d81d1SSam Leffler swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, 84f34a967bSPawel Jakub Dawidek int flags) 85091d81d1SSam Leffler { 865d7ae54aSConrad Meyer unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN]; 8708fca7a5SJohn-Mark Gurney unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN]; 88091d81d1SSam Leffler struct enc_xform *exf; 8908fca7a5SJohn-Mark Gurney int i, j, k, blks, ind, count, ivlen; 9008fca7a5SJohn-Mark Gurney struct uio *uio, uiolcl; 9108fca7a5SJohn-Mark Gurney struct iovec iovlcl[4]; 9208fca7a5SJohn-Mark Gurney struct iovec *iov; 9308fca7a5SJohn-Mark Gurney int iovcnt, iovalloc; 9408fca7a5SJohn-Mark Gurney int error; 9508fca7a5SJohn-Mark Gurney 9608fca7a5SJohn-Mark Gurney error = 0; 97091d81d1SSam Leffler 98091d81d1SSam Leffler exf = sw->sw_exf; 99091d81d1SSam Leffler blks = exf->blocksize; 10008fca7a5SJohn-Mark Gurney ivlen = exf->ivsize; 101091d81d1SSam Leffler 102091d81d1SSam Leffler /* Check for non-padded data */ 103091d81d1SSam Leffler if (crd->crd_len % blks) 104091d81d1SSam Leffler return EINVAL; 105091d81d1SSam Leffler 10608fca7a5SJohn-Mark Gurney if (crd->crd_alg == CRYPTO_AES_ICM && 10708fca7a5SJohn-Mark Gurney (crd->crd_flags & CRD_F_IV_EXPLICIT) == 0) 10808fca7a5SJohn-Mark Gurney return (EINVAL); 10908fca7a5SJohn-Mark Gurney 110091d81d1SSam Leffler /* Initialize the IV */ 111091d81d1SSam Leffler if (crd->crd_flags & CRD_F_ENCRYPT) { 112091d81d1SSam Leffler /* IV explicitly provided ? */ 113091d81d1SSam Leffler if (crd->crd_flags & CRD_F_IV_EXPLICIT) 11408fca7a5SJohn-Mark Gurney bcopy(crd->crd_iv, iv, ivlen); 11548b0f2e1SPawel Jakub Dawidek else 11608fca7a5SJohn-Mark Gurney arc4rand(iv, ivlen, 0); 117091d81d1SSam Leffler 118091d81d1SSam Leffler /* Do we need to write the IV */ 119f34a967bSPawel Jakub Dawidek if (!(crd->crd_flags & CRD_F_IV_PRESENT)) 12008fca7a5SJohn-Mark Gurney crypto_copyback(flags, buf, crd->crd_inject, ivlen, iv); 121091d81d1SSam Leffler 122091d81d1SSam Leffler } else { /* Decryption */ 123091d81d1SSam Leffler /* IV explicitly provided ? */ 124091d81d1SSam Leffler if (crd->crd_flags & CRD_F_IV_EXPLICIT) 12508fca7a5SJohn-Mark Gurney bcopy(crd->crd_iv, iv, ivlen); 126091d81d1SSam Leffler else { 127091d81d1SSam Leffler /* Get IV off buf */ 12808fca7a5SJohn-Mark Gurney crypto_copydata(flags, buf, crd->crd_inject, ivlen, iv); 129091d81d1SSam Leffler } 130091d81d1SSam Leffler } 131091d81d1SSam Leffler 132c740ae4bSPoul-Henning Kamp if (crd->crd_flags & CRD_F_KEY_EXPLICIT) { 133c740ae4bSPoul-Henning Kamp int error; 134c740ae4bSPoul-Henning Kamp 135c740ae4bSPoul-Henning Kamp if (sw->sw_kschedule) 136c740ae4bSPoul-Henning Kamp exf->zerokey(&(sw->sw_kschedule)); 13708fca7a5SJohn-Mark Gurney 138c740ae4bSPoul-Henning Kamp error = exf->setkey(&sw->sw_kschedule, 139c740ae4bSPoul-Henning Kamp crd->crd_key, crd->crd_klen / 8); 140c740ae4bSPoul-Henning Kamp if (error) 141c740ae4bSPoul-Henning Kamp return (error); 142c740ae4bSPoul-Henning Kamp } 143d295bdeeSPawel Jakub Dawidek 14408fca7a5SJohn-Mark Gurney iov = iovlcl; 14508fca7a5SJohn-Mark Gurney iovcnt = nitems(iovlcl); 14608fca7a5SJohn-Mark Gurney iovalloc = 0; 14708fca7a5SJohn-Mark Gurney uio = &uiolcl; 14808fca7a5SJohn-Mark Gurney if ((flags & CRYPTO_F_IMBUF) != 0) { 149748a12e2SJohn-Mark Gurney error = crypto_mbuftoiov((struct mbuf *)buf, &iov, &iovcnt, 15008fca7a5SJohn-Mark Gurney &iovalloc); 151748a12e2SJohn-Mark Gurney if (error) 152748a12e2SJohn-Mark Gurney return (error); 15308fca7a5SJohn-Mark Gurney uio->uio_iov = iov; 15408fca7a5SJohn-Mark Gurney uio->uio_iovcnt = iovcnt; 15508fca7a5SJohn-Mark Gurney } else if ((flags & CRYPTO_F_IOV) != 0) 15608fca7a5SJohn-Mark Gurney uio = (struct uio *)buf; 15708fca7a5SJohn-Mark Gurney else { 15808fca7a5SJohn-Mark Gurney iov[0].iov_base = buf; 15908fca7a5SJohn-Mark Gurney iov[0].iov_len = crd->crd_skip + crd->crd_len; 16008fca7a5SJohn-Mark Gurney uio->uio_iov = iov; 16108fca7a5SJohn-Mark Gurney uio->uio_iovcnt = 1; 16208fca7a5SJohn-Mark Gurney } 16308fca7a5SJohn-Mark Gurney 164091d81d1SSam Leffler ivp = iv; 165091d81d1SSam Leffler 16608fca7a5SJohn-Mark Gurney if (exf->reinit) { 167d295bdeeSPawel Jakub Dawidek /* 168d295bdeeSPawel Jakub Dawidek * xforms that provide a reinit method perform all IV 169d295bdeeSPawel Jakub Dawidek * handling themselves. 170d295bdeeSPawel Jakub Dawidek */ 171d295bdeeSPawel Jakub Dawidek exf->reinit(sw->sw_kschedule, iv); 172091d81d1SSam Leffler } 173091d81d1SSam Leffler 17408fca7a5SJohn-Mark Gurney count = crd->crd_skip; 17508fca7a5SJohn-Mark Gurney ind = cuio_getptr(uio, count, &k); 17608fca7a5SJohn-Mark Gurney if (ind == -1) { 17708fca7a5SJohn-Mark Gurney error = EINVAL; 17808fca7a5SJohn-Mark Gurney goto out; 179091d81d1SSam Leffler } 180091d81d1SSam Leffler 181091d81d1SSam Leffler i = crd->crd_len; 182091d81d1SSam Leffler 183091d81d1SSam Leffler while (i > 0) { 184091d81d1SSam Leffler /* 185091d81d1SSam Leffler * If there's insufficient data at the end of 186091d81d1SSam Leffler * an iovec, we have to do some copying. 187091d81d1SSam Leffler */ 18808fca7a5SJohn-Mark Gurney if (uio->uio_iov[ind].iov_len < k + blks && 18908fca7a5SJohn-Mark Gurney uio->uio_iov[ind].iov_len != k) { 19008fca7a5SJohn-Mark Gurney cuio_copydata(uio, count, blks, blk); 191091d81d1SSam Leffler 192091d81d1SSam Leffler /* Actual encryption/decryption */ 193d295bdeeSPawel Jakub Dawidek if (exf->reinit) { 194091d81d1SSam Leffler if (crd->crd_flags & CRD_F_ENCRYPT) { 195d295bdeeSPawel Jakub Dawidek exf->encrypt(sw->sw_kschedule, 196d295bdeeSPawel Jakub Dawidek blk); 197d295bdeeSPawel Jakub Dawidek } else { 198d295bdeeSPawel Jakub Dawidek exf->decrypt(sw->sw_kschedule, 199d295bdeeSPawel Jakub Dawidek blk); 200d295bdeeSPawel Jakub Dawidek } 201d295bdeeSPawel Jakub Dawidek } else if (crd->crd_flags & CRD_F_ENCRYPT) { 202091d81d1SSam Leffler /* XOR with previous block */ 203091d81d1SSam Leffler for (j = 0; j < blks; j++) 204091d81d1SSam Leffler blk[j] ^= ivp[j]; 205091d81d1SSam Leffler 206091d81d1SSam Leffler exf->encrypt(sw->sw_kschedule, blk); 207091d81d1SSam Leffler 208091d81d1SSam Leffler /* 209091d81d1SSam Leffler * Keep encrypted block for XOR'ing 210091d81d1SSam Leffler * with next block 211091d81d1SSam Leffler */ 212091d81d1SSam Leffler bcopy(blk, iv, blks); 213091d81d1SSam Leffler ivp = iv; 214091d81d1SSam Leffler } else { /* decrypt */ 215091d81d1SSam Leffler /* 216091d81d1SSam Leffler * Keep encrypted block for XOR'ing 217091d81d1SSam Leffler * with next block 218091d81d1SSam Leffler */ 21908fca7a5SJohn-Mark Gurney nivp = (ivp == iv) ? iv2 : iv; 22008fca7a5SJohn-Mark Gurney bcopy(blk, nivp, blks); 221091d81d1SSam Leffler 222091d81d1SSam Leffler exf->decrypt(sw->sw_kschedule, blk); 223091d81d1SSam Leffler 224091d81d1SSam Leffler /* XOR with previous block */ 225091d81d1SSam Leffler for (j = 0; j < blks; j++) 226091d81d1SSam Leffler blk[j] ^= ivp[j]; 227091d81d1SSam Leffler 22808fca7a5SJohn-Mark Gurney ivp = nivp; 229091d81d1SSam Leffler } 230091d81d1SSam Leffler 231091d81d1SSam Leffler /* Copy back decrypted block */ 23208fca7a5SJohn-Mark Gurney cuio_copyback(uio, count, blks, blk); 23308fca7a5SJohn-Mark Gurney 23408fca7a5SJohn-Mark Gurney count += blks; 235091d81d1SSam Leffler 236091d81d1SSam Leffler /* Advance pointer */ 23708fca7a5SJohn-Mark Gurney ind = cuio_getptr(uio, count, &k); 23808fca7a5SJohn-Mark Gurney if (ind == -1) { 23908fca7a5SJohn-Mark Gurney error = EINVAL; 24008fca7a5SJohn-Mark Gurney goto out; 24108fca7a5SJohn-Mark Gurney } 242091d81d1SSam Leffler 243091d81d1SSam Leffler i -= blks; 244091d81d1SSam Leffler 245091d81d1SSam Leffler /* Could be done... */ 246091d81d1SSam Leffler if (i == 0) 247091d81d1SSam Leffler break; 248091d81d1SSam Leffler } 249091d81d1SSam Leffler 2502f1f9cceSConrad Meyer while (uio->uio_iov[ind].iov_len >= k + blks && i > 0) { 2515d7ae54aSConrad Meyer uint8_t *idat; 2522f1f9cceSConrad Meyer size_t nb, rem; 2532f1f9cceSConrad Meyer 2542f1f9cceSConrad Meyer nb = blks; 255179b21e8SConrad Meyer rem = MIN((size_t)i, 256179b21e8SConrad Meyer uio->uio_iov[ind].iov_len - (size_t)k); 2575d7ae54aSConrad Meyer idat = (uint8_t *)uio->uio_iov[ind].iov_base + k; 258091d81d1SSam Leffler 259d295bdeeSPawel Jakub Dawidek if (exf->reinit) { 2602f1f9cceSConrad Meyer if ((crd->crd_flags & CRD_F_ENCRYPT) != 0 && 2612f1f9cceSConrad Meyer exf->encrypt_multi == NULL) 262d295bdeeSPawel Jakub Dawidek exf->encrypt(sw->sw_kschedule, 263d295bdeeSPawel Jakub Dawidek idat); 2642f1f9cceSConrad Meyer else if ((crd->crd_flags & CRD_F_ENCRYPT) != 0) { 2652f1f9cceSConrad Meyer nb = rounddown(rem, blks); 2662f1f9cceSConrad Meyer exf->encrypt_multi(sw->sw_kschedule, 2672f1f9cceSConrad Meyer idat, nb); 2682f1f9cceSConrad Meyer } else if (exf->decrypt_multi == NULL) 269d295bdeeSPawel Jakub Dawidek exf->decrypt(sw->sw_kschedule, 270d295bdeeSPawel Jakub Dawidek idat); 2712f1f9cceSConrad Meyer else { 2722f1f9cceSConrad Meyer nb = rounddown(rem, blks); 2732f1f9cceSConrad Meyer exf->decrypt_multi(sw->sw_kschedule, 2742f1f9cceSConrad Meyer idat, nb); 275d295bdeeSPawel Jakub Dawidek } 276d295bdeeSPawel Jakub Dawidek } else if (crd->crd_flags & CRD_F_ENCRYPT) { 277091d81d1SSam Leffler /* XOR with previous block/IV */ 278091d81d1SSam Leffler for (j = 0; j < blks; j++) 279091d81d1SSam Leffler idat[j] ^= ivp[j]; 280091d81d1SSam Leffler 281091d81d1SSam Leffler exf->encrypt(sw->sw_kschedule, idat); 282091d81d1SSam Leffler ivp = idat; 283091d81d1SSam Leffler } else { /* decrypt */ 284091d81d1SSam Leffler /* 285091d81d1SSam Leffler * Keep encrypted block to be used 286091d81d1SSam Leffler * in next block's processing. 287091d81d1SSam Leffler */ 28808fca7a5SJohn-Mark Gurney nivp = (ivp == iv) ? iv2 : iv; 28908fca7a5SJohn-Mark Gurney bcopy(idat, nivp, blks); 290091d81d1SSam Leffler 291091d81d1SSam Leffler exf->decrypt(sw->sw_kschedule, idat); 292091d81d1SSam Leffler 293091d81d1SSam Leffler /* XOR with previous block/IV */ 294091d81d1SSam Leffler for (j = 0; j < blks; j++) 295091d81d1SSam Leffler idat[j] ^= ivp[j]; 296091d81d1SSam Leffler 29708fca7a5SJohn-Mark Gurney ivp = nivp; 298091d81d1SSam Leffler } 299091d81d1SSam Leffler 3002f1f9cceSConrad Meyer count += nb; 3012f1f9cceSConrad Meyer k += nb; 3022f1f9cceSConrad Meyer i -= nb; 303091d81d1SSam Leffler } 304091d81d1SSam Leffler 305f34a967bSPawel Jakub Dawidek /* 30608fca7a5SJohn-Mark Gurney * Advance to the next iov if the end of the current iov 30708fca7a5SJohn-Mark Gurney * is aligned with the end of a cipher block. 30808fca7a5SJohn-Mark Gurney * Note that the code is equivalent to calling: 30908fca7a5SJohn-Mark Gurney * ind = cuio_getptr(uio, count, &k); 310f34a967bSPawel Jakub Dawidek */ 31108fca7a5SJohn-Mark Gurney if (i > 0 && k == uio->uio_iov[ind].iov_len) { 31208fca7a5SJohn-Mark Gurney k = 0; 31308fca7a5SJohn-Mark Gurney ind++; 31408fca7a5SJohn-Mark Gurney if (ind >= uio->uio_iovcnt) { 31508fca7a5SJohn-Mark Gurney error = EINVAL; 31608fca7a5SJohn-Mark Gurney goto out; 31708fca7a5SJohn-Mark Gurney } 318f34a967bSPawel Jakub Dawidek } 319f34a967bSPawel Jakub Dawidek } 320f34a967bSPawel Jakub Dawidek 32108fca7a5SJohn-Mark Gurney out: 32208fca7a5SJohn-Mark Gurney if (iovalloc) 32308fca7a5SJohn-Mark Gurney free(iov, M_CRYPTO_DATA); 324091d81d1SSam Leffler 32508fca7a5SJohn-Mark Gurney return (error); 326091d81d1SSam Leffler } 327091d81d1SSam Leffler 32825b7033bSConrad Meyer static int __result_use_check 329f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key, 330f6c4bc3bSPawel Jakub Dawidek int klen) 331f6c4bc3bSPawel Jakub Dawidek { 332f6c4bc3bSPawel Jakub Dawidek int k; 333f6c4bc3bSPawel Jakub Dawidek 334f6c4bc3bSPawel Jakub Dawidek klen /= 8; 335f6c4bc3bSPawel Jakub Dawidek 336f6c4bc3bSPawel Jakub Dawidek switch (axf->type) { 337f6c4bc3bSPawel Jakub Dawidek case CRYPTO_MD5_HMAC: 338f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA1_HMAC: 339c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 340f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 341f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 342f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 343f6c4bc3bSPawel Jakub Dawidek case CRYPTO_NULL_HMAC: 344f6c4bc3bSPawel Jakub Dawidek case CRYPTO_RIPEMD160_HMAC: 345f6c4bc3bSPawel Jakub Dawidek for (k = 0; k < klen; k++) 346f6c4bc3bSPawel Jakub Dawidek key[k] ^= HMAC_IPAD_VAL; 347f6c4bc3bSPawel Jakub Dawidek 348f6c4bc3bSPawel Jakub Dawidek axf->Init(sw->sw_ictx); 349f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_ictx, key, klen); 350f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_ictx, hmac_ipad_buffer, axf->blocksize - klen); 351f6c4bc3bSPawel Jakub Dawidek 352f6c4bc3bSPawel Jakub Dawidek for (k = 0; k < klen; k++) 353f6c4bc3bSPawel Jakub Dawidek key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 354f6c4bc3bSPawel Jakub Dawidek 355f6c4bc3bSPawel Jakub Dawidek axf->Init(sw->sw_octx); 356f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_octx, key, klen); 357f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_octx, hmac_opad_buffer, axf->blocksize - klen); 358f6c4bc3bSPawel Jakub Dawidek 359f6c4bc3bSPawel Jakub Dawidek for (k = 0; k < klen; k++) 360f6c4bc3bSPawel Jakub Dawidek key[k] ^= HMAC_OPAD_VAL; 361f6c4bc3bSPawel Jakub Dawidek break; 362f6c4bc3bSPawel Jakub Dawidek case CRYPTO_MD5_KPDK: 363f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA1_KPDK: 3641f4990a6SBjoern A. Zeeb { 36577680d96SBjoern A. Zeeb /* 36677680d96SBjoern A. Zeeb * We need a buffer that can hold an md5 and a sha1 result 36777680d96SBjoern A. Zeeb * just to throw it away. 36877680d96SBjoern A. Zeeb * What we do here is the initial part of: 36977680d96SBjoern A. Zeeb * ALGO( key, keyfill, .. ) 37077680d96SBjoern A. Zeeb * adding the key to sw_ictx and abusing Final() to get the 37177680d96SBjoern A. Zeeb * "keyfill" padding. 37277680d96SBjoern A. Zeeb * In addition we abuse the sw_octx to save the key to have 37377680d96SBjoern A. Zeeb * it to be able to append it at the end in swcr_authcompute(). 37477680d96SBjoern A. Zeeb */ 3751f4990a6SBjoern A. Zeeb u_char buf[SHA1_RESULTLEN]; 3761f4990a6SBjoern A. Zeeb 377f6c4bc3bSPawel Jakub Dawidek sw->sw_klen = klen; 378f6c4bc3bSPawel Jakub Dawidek bcopy(key, sw->sw_octx, klen); 379f6c4bc3bSPawel Jakub Dawidek axf->Init(sw->sw_ictx); 380f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_ictx, key, klen); 3811f4990a6SBjoern A. Zeeb axf->Final(buf, sw->sw_ictx); 382f6c4bc3bSPawel Jakub Dawidek break; 3831f4990a6SBjoern A. Zeeb } 38425b7033bSConrad Meyer case CRYPTO_POLY1305: 38525b7033bSConrad Meyer if (klen != POLY1305_KEY_LEN) { 38625b7033bSConrad Meyer CRYPTDEB("bad poly1305 key size %d", klen); 38725b7033bSConrad Meyer return EINVAL; 38825b7033bSConrad Meyer } 38925b7033bSConrad Meyer /* FALLTHROUGH */ 3900e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 3910e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 3920e33efe4SConrad Meyer axf->Setkey(sw->sw_ictx, key, klen); 3930e33efe4SConrad Meyer axf->Init(sw->sw_ictx); 3940e33efe4SConrad Meyer break; 395f6c4bc3bSPawel Jakub Dawidek default: 396f6c4bc3bSPawel Jakub Dawidek printf("%s: CRD_F_KEY_EXPLICIT flag given, but algorithm %d " 397f6c4bc3bSPawel Jakub Dawidek "doesn't use keys.\n", __func__, axf->type); 39825b7033bSConrad Meyer return EINVAL; 399f6c4bc3bSPawel Jakub Dawidek } 40025b7033bSConrad Meyer return 0; 401f6c4bc3bSPawel Jakub Dawidek } 402f6c4bc3bSPawel Jakub Dawidek 403091d81d1SSam Leffler /* 404091d81d1SSam Leffler * Compute keyed-hash authenticator. 405091d81d1SSam Leffler */ 406091d81d1SSam Leffler static int 40738d2f8d6SPawel Jakub Dawidek swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, 408f34a967bSPawel Jakub Dawidek int flags) 409091d81d1SSam Leffler { 4100bbc4bf9SPawel Jakub Dawidek unsigned char aalg[HASH_MAX_LEN]; 411091d81d1SSam Leffler struct auth_hash *axf; 412091d81d1SSam Leffler union authctx ctx; 413091d81d1SSam Leffler int err; 414091d81d1SSam Leffler 415091d81d1SSam Leffler if (sw->sw_ictx == 0) 416091d81d1SSam Leffler return EINVAL; 417091d81d1SSam Leffler 418091d81d1SSam Leffler axf = sw->sw_axf; 419091d81d1SSam Leffler 42025b7033bSConrad Meyer if (crd->crd_flags & CRD_F_KEY_EXPLICIT) { 42125b7033bSConrad Meyer err = swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen); 42225b7033bSConrad Meyer if (err != 0) 42325b7033bSConrad Meyer return err; 42425b7033bSConrad Meyer } 425f6c4bc3bSPawel Jakub Dawidek 426091d81d1SSam Leffler bcopy(sw->sw_ictx, &ctx, axf->ctxsize); 427091d81d1SSam Leffler 428f34a967bSPawel Jakub Dawidek err = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, 429f34a967bSPawel Jakub Dawidek (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); 430091d81d1SSam Leffler if (err) 431091d81d1SSam Leffler return err; 432091d81d1SSam Leffler 433091d81d1SSam Leffler switch (sw->sw_alg) { 434c4729f6eSConrad Meyer case CRYPTO_SHA1: 435c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 436c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 437c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 438c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 439c4729f6eSConrad Meyer axf->Final(aalg, &ctx); 440c4729f6eSConrad Meyer break; 441c4729f6eSConrad Meyer 442091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 443091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 444c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 445f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 446f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 447f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 448091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 449091d81d1SSam Leffler if (sw->sw_octx == NULL) 450091d81d1SSam Leffler return EINVAL; 451091d81d1SSam Leffler 452091d81d1SSam Leffler axf->Final(aalg, &ctx); 453091d81d1SSam Leffler bcopy(sw->sw_octx, &ctx, axf->ctxsize); 454091d81d1SSam Leffler axf->Update(&ctx, aalg, axf->hashsize); 455091d81d1SSam Leffler axf->Final(aalg, &ctx); 456091d81d1SSam Leffler break; 457091d81d1SSam Leffler 458091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 459091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 46077680d96SBjoern A. Zeeb /* If we have no key saved, return error. */ 461091d81d1SSam Leffler if (sw->sw_octx == NULL) 462091d81d1SSam Leffler return EINVAL; 463091d81d1SSam Leffler 46477680d96SBjoern A. Zeeb /* 46577680d96SBjoern A. Zeeb * Add the trailing copy of the key (see comment in 46677680d96SBjoern A. Zeeb * swcr_authprepare()) after the data: 46777680d96SBjoern A. Zeeb * ALGO( .., key, algofill ) 46877680d96SBjoern A. Zeeb * and let Final() do the proper, natural "algofill" 46977680d96SBjoern A. Zeeb * padding. 47077680d96SBjoern A. Zeeb */ 471091d81d1SSam Leffler axf->Update(&ctx, sw->sw_octx, sw->sw_klen); 472091d81d1SSam Leffler axf->Final(aalg, &ctx); 473091d81d1SSam Leffler break; 474091d81d1SSam Leffler 4750e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 4760e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 477091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 47825b7033bSConrad Meyer case CRYPTO_POLY1305: 479091d81d1SSam Leffler axf->Final(aalg, &ctx); 480091d81d1SSam Leffler break; 481091d81d1SSam Leffler } 482091d81d1SSam Leffler 483091d81d1SSam Leffler /* Inject the authentication data */ 484f34a967bSPawel Jakub Dawidek crypto_copyback(flags, buf, crd->crd_inject, 485f6c4bc3bSPawel Jakub Dawidek sw->sw_mlen == 0 ? axf->hashsize : sw->sw_mlen, aalg); 486091d81d1SSam Leffler return 0; 487091d81d1SSam Leffler } 488091d81d1SSam Leffler 48908fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256); /* GCM: plain text < 2^39-256 */ 49008fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1); /* GCM: associated data <= 2^64-1 */ 49108fca7a5SJohn-Mark Gurney 49208fca7a5SJohn-Mark Gurney /* 49308fca7a5SJohn-Mark Gurney * Apply a combined encryption-authentication transformation 49408fca7a5SJohn-Mark Gurney */ 49508fca7a5SJohn-Mark Gurney static int 49608fca7a5SJohn-Mark Gurney swcr_authenc(struct cryptop *crp) 49708fca7a5SJohn-Mark Gurney { 49808fca7a5SJohn-Mark Gurney uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; 49908fca7a5SJohn-Mark Gurney u_char *blk = (u_char *)blkbuf; 50008fca7a5SJohn-Mark Gurney u_char aalg[AALG_MAX_RESULT_LEN]; 50108fca7a5SJohn-Mark Gurney u_char uaalg[AALG_MAX_RESULT_LEN]; 50208fca7a5SJohn-Mark Gurney u_char iv[EALG_MAX_BLOCK_LEN]; 50308fca7a5SJohn-Mark Gurney union authctx ctx; 5049ebbebe4SConrad Meyer struct swcr_session *ses; 50508fca7a5SJohn-Mark Gurney struct cryptodesc *crd, *crda = NULL, *crde = NULL; 50608fca7a5SJohn-Mark Gurney struct swcr_data *sw, *swa, *swe = NULL; 50708fca7a5SJohn-Mark Gurney struct auth_hash *axf = NULL; 50808fca7a5SJohn-Mark Gurney struct enc_xform *exf = NULL; 50908fca7a5SJohn-Mark Gurney caddr_t buf = (caddr_t)crp->crp_buf; 51008fca7a5SJohn-Mark Gurney uint32_t *blkp; 51108fca7a5SJohn-Mark Gurney int aadlen, blksz, i, ivlen, len, iskip, oskip, r; 512*507281e5SSean Eric Fagan int isccm = 0; 51308fca7a5SJohn-Mark Gurney 51408fca7a5SJohn-Mark Gurney ivlen = blksz = iskip = oskip = 0; 51508fca7a5SJohn-Mark Gurney 5169ebbebe4SConrad Meyer ses = crypto_get_driver_session(crp->crp_session); 5179ebbebe4SConrad Meyer 51808fca7a5SJohn-Mark Gurney for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 5199ebbebe4SConrad Meyer for (i = 0; i < nitems(ses->swcr_algorithms) && 5209ebbebe4SConrad Meyer ses->swcr_algorithms[i].sw_alg != crd->crd_alg; i++) 52108fca7a5SJohn-Mark Gurney ; 5229ebbebe4SConrad Meyer if (i == nitems(ses->swcr_algorithms)) 52308fca7a5SJohn-Mark Gurney return (EINVAL); 52408fca7a5SJohn-Mark Gurney 5259ebbebe4SConrad Meyer sw = &ses->swcr_algorithms[i]; 52608fca7a5SJohn-Mark Gurney switch (sw->sw_alg) { 527*507281e5SSean Eric Fagan case CRYPTO_AES_CCM_16: 52808fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 52908fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 53008fca7a5SJohn-Mark Gurney swe = sw; 53108fca7a5SJohn-Mark Gurney crde = crd; 53208fca7a5SJohn-Mark Gurney exf = swe->sw_exf; 533*507281e5SSean Eric Fagan /* AES_CCM_IV_LEN and AES_GCM_IV_LEN are both 12 */ 534*507281e5SSean Eric Fagan ivlen = AES_CCM_IV_LEN; 53508fca7a5SJohn-Mark Gurney break; 536*507281e5SSean Eric Fagan case CRYPTO_AES_CCM_CBC_MAC: 537*507281e5SSean Eric Fagan isccm = 1; 538*507281e5SSean Eric Fagan /* FALLTHROUGH */ 53908fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 54008fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 54108fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 54208fca7a5SJohn-Mark Gurney swa = sw; 54308fca7a5SJohn-Mark Gurney crda = crd; 54408fca7a5SJohn-Mark Gurney axf = swa->sw_axf; 54508fca7a5SJohn-Mark Gurney if (swa->sw_ictx == 0) 54608fca7a5SJohn-Mark Gurney return (EINVAL); 54708fca7a5SJohn-Mark Gurney bcopy(swa->sw_ictx, &ctx, axf->ctxsize); 54808fca7a5SJohn-Mark Gurney blksz = axf->blocksize; 54908fca7a5SJohn-Mark Gurney break; 55008fca7a5SJohn-Mark Gurney default: 55108fca7a5SJohn-Mark Gurney return (EINVAL); 55208fca7a5SJohn-Mark Gurney } 55308fca7a5SJohn-Mark Gurney } 55408fca7a5SJohn-Mark Gurney if (crde == NULL || crda == NULL) 55508fca7a5SJohn-Mark Gurney return (EINVAL); 556*507281e5SSean Eric Fagan /* 557*507281e5SSean Eric Fagan * We need to make sure that the auth algorithm matches the 558*507281e5SSean Eric Fagan * encr algorithm. Specifically, for AES-GCM must go with 559*507281e5SSean Eric Fagan * AES NIST GMAC, and AES-CCM must go with CBC-MAC. 560*507281e5SSean Eric Fagan */ 561*507281e5SSean Eric Fagan if (crde->crd_alg == CRYPTO_AES_NIST_GCM_16) { 562*507281e5SSean Eric Fagan switch (crda->crd_alg) { 563*507281e5SSean Eric Fagan case CRYPTO_AES_128_NIST_GMAC: 564*507281e5SSean Eric Fagan case CRYPTO_AES_192_NIST_GMAC: 565*507281e5SSean Eric Fagan case CRYPTO_AES_256_NIST_GMAC: 566*507281e5SSean Eric Fagan break; /* Good! */ 567*507281e5SSean Eric Fagan default: 568*507281e5SSean Eric Fagan return (EINVAL); /* Not good! */ 569*507281e5SSean Eric Fagan } 570*507281e5SSean Eric Fagan } else if (crde->crd_alg == CRYPTO_AES_CCM_16 && 571*507281e5SSean Eric Fagan crda->crd_alg != CRYPTO_AES_CCM_CBC_MAC) 572*507281e5SSean Eric Fagan return (EINVAL); 57308fca7a5SJohn-Mark Gurney 574*507281e5SSean Eric Fagan if ((crde->crd_alg == CRYPTO_AES_NIST_GCM_16 || 575*507281e5SSean Eric Fagan crde->crd_alg == CRYPTO_AES_CCM_16) && 57608fca7a5SJohn-Mark Gurney (crde->crd_flags & CRD_F_IV_EXPLICIT) == 0) 57708fca7a5SJohn-Mark Gurney return (EINVAL); 57808fca7a5SJohn-Mark Gurney 57908fca7a5SJohn-Mark Gurney if (crde->crd_klen != crda->crd_klen) 58008fca7a5SJohn-Mark Gurney return (EINVAL); 58108fca7a5SJohn-Mark Gurney 58208fca7a5SJohn-Mark Gurney /* Initialize the IV */ 58308fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_ENCRYPT) { 58408fca7a5SJohn-Mark Gurney /* IV explicitly provided ? */ 58508fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_IV_EXPLICIT) 58608fca7a5SJohn-Mark Gurney bcopy(crde->crd_iv, iv, ivlen); 58708fca7a5SJohn-Mark Gurney else 58808fca7a5SJohn-Mark Gurney arc4rand(iv, ivlen, 0); 58908fca7a5SJohn-Mark Gurney 59008fca7a5SJohn-Mark Gurney /* Do we need to write the IV */ 59108fca7a5SJohn-Mark Gurney if (!(crde->crd_flags & CRD_F_IV_PRESENT)) 59208fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, crde->crd_inject, 59308fca7a5SJohn-Mark Gurney ivlen, iv); 59408fca7a5SJohn-Mark Gurney 59508fca7a5SJohn-Mark Gurney } else { /* Decryption */ 59608fca7a5SJohn-Mark Gurney /* IV explicitly provided ? */ 59708fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_IV_EXPLICIT) 59808fca7a5SJohn-Mark Gurney bcopy(crde->crd_iv, iv, ivlen); 59908fca7a5SJohn-Mark Gurney else { 60008fca7a5SJohn-Mark Gurney /* Get IV off buf */ 60108fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crde->crd_inject, 60208fca7a5SJohn-Mark Gurney ivlen, iv); 60308fca7a5SJohn-Mark Gurney } 60408fca7a5SJohn-Mark Gurney } 60508fca7a5SJohn-Mark Gurney 606*507281e5SSean Eric Fagan if (swa->sw_alg == CRYPTO_AES_CCM_CBC_MAC) { 607*507281e5SSean Eric Fagan /* 608*507281e5SSean Eric Fagan * AES CCM-CBC needs to know the length of 609*507281e5SSean Eric Fagan * both the auth data, and payload data, before 610*507281e5SSean Eric Fagan * doing the auth computation. 611*507281e5SSean Eric Fagan */ 612*507281e5SSean Eric Fagan ctx.aes_cbc_mac_ctx.authDataLength = crda->crd_len; 613*507281e5SSean Eric Fagan ctx.aes_cbc_mac_ctx.cryptDataLength = crde->crd_len; 614*507281e5SSean Eric Fagan } 61508fca7a5SJohn-Mark Gurney /* Supply MAC with IV */ 61608fca7a5SJohn-Mark Gurney if (axf->Reinit) 61708fca7a5SJohn-Mark Gurney axf->Reinit(&ctx, iv, ivlen); 61808fca7a5SJohn-Mark Gurney 61908fca7a5SJohn-Mark Gurney /* Supply MAC with AAD */ 62008fca7a5SJohn-Mark Gurney aadlen = crda->crd_len; 62108fca7a5SJohn-Mark Gurney 62208fca7a5SJohn-Mark Gurney for (i = iskip; i < crda->crd_len; i += blksz) { 62308fca7a5SJohn-Mark Gurney len = MIN(crda->crd_len - i, blksz - oskip); 62408fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crda->crd_skip + i, len, 62508fca7a5SJohn-Mark Gurney blk + oskip); 62608fca7a5SJohn-Mark Gurney bzero(blk + len + oskip, blksz - len - oskip); 62708fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, blksz); 62808fca7a5SJohn-Mark Gurney oskip = 0; /* reset initial output offset */ 62908fca7a5SJohn-Mark Gurney } 63008fca7a5SJohn-Mark Gurney 63108fca7a5SJohn-Mark Gurney if (exf->reinit) 63208fca7a5SJohn-Mark Gurney exf->reinit(swe->sw_kschedule, iv); 63308fca7a5SJohn-Mark Gurney 63408fca7a5SJohn-Mark Gurney /* Do encryption/decryption with MAC */ 6352f1f9cceSConrad Meyer for (i = 0; i < crde->crd_len; i += len) { 6362f1f9cceSConrad Meyer if (exf->encrypt_multi != NULL) { 6372f1f9cceSConrad Meyer len = rounddown(crde->crd_len - i, blksz); 6382f1f9cceSConrad Meyer if (len == 0) 6392f1f9cceSConrad Meyer len = blksz; 6402f1f9cceSConrad Meyer else 6412f1f9cceSConrad Meyer len = MIN(len, sizeof(blkbuf)); 6422f1f9cceSConrad Meyer } else 6432f1f9cceSConrad Meyer len = blksz; 6442f1f9cceSConrad Meyer len = MIN(crde->crd_len - i, len); 64508fca7a5SJohn-Mark Gurney if (len < blksz) 64608fca7a5SJohn-Mark Gurney bzero(blk, blksz); 64708fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crde->crd_skip + i, len, 64808fca7a5SJohn-Mark Gurney blk); 649*507281e5SSean Eric Fagan /* 650*507281e5SSean Eric Fagan * One of the problems with CCM+CBC is that the authentication 651*507281e5SSean Eric Fagan * is done on the unecncrypted data. As a result, we have 652*507281e5SSean Eric Fagan * to do the authentication update at different times, 653*507281e5SSean Eric Fagan * depending on whether it's CCM or not. 654*507281e5SSean Eric Fagan */ 65508fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_ENCRYPT) { 656*507281e5SSean Eric Fagan if (isccm) 657*507281e5SSean Eric Fagan axf->Update(&ctx, blk, len); 6582f1f9cceSConrad Meyer if (exf->encrypt_multi != NULL) 6592f1f9cceSConrad Meyer exf->encrypt_multi(swe->sw_kschedule, blk, 6602f1f9cceSConrad Meyer len); 6612f1f9cceSConrad Meyer else 66208fca7a5SJohn-Mark Gurney exf->encrypt(swe->sw_kschedule, blk); 663*507281e5SSean Eric Fagan if (!isccm) 66408fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, len); 66508fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, 66608fca7a5SJohn-Mark Gurney crde->crd_skip + i, len, blk); 66708fca7a5SJohn-Mark Gurney } else { 668*507281e5SSean Eric Fagan if (isccm) { 669*507281e5SSean Eric Fagan KASSERT(exf->encrypt_multi == NULL, 670*507281e5SSean Eric Fagan ("assume CCM is single-block only")); 671*507281e5SSean Eric Fagan exf->decrypt(swe->sw_kschedule, blk); 672*507281e5SSean Eric Fagan } 67308fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, len); 67408fca7a5SJohn-Mark Gurney } 67508fca7a5SJohn-Mark Gurney } 67608fca7a5SJohn-Mark Gurney 67708fca7a5SJohn-Mark Gurney /* Do any required special finalization */ 67808fca7a5SJohn-Mark Gurney switch (crda->crd_alg) { 67908fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 68008fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 68108fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 68208fca7a5SJohn-Mark Gurney /* length block */ 68308fca7a5SJohn-Mark Gurney bzero(blk, blksz); 68408fca7a5SJohn-Mark Gurney blkp = (uint32_t *)blk + 1; 68508fca7a5SJohn-Mark Gurney *blkp = htobe32(aadlen * 8); 68608fca7a5SJohn-Mark Gurney blkp = (uint32_t *)blk + 3; 68708fca7a5SJohn-Mark Gurney *blkp = htobe32(crde->crd_len * 8); 68808fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, blksz); 68908fca7a5SJohn-Mark Gurney break; 69008fca7a5SJohn-Mark Gurney } 69108fca7a5SJohn-Mark Gurney 69208fca7a5SJohn-Mark Gurney /* Finalize MAC */ 69308fca7a5SJohn-Mark Gurney axf->Final(aalg, &ctx); 69408fca7a5SJohn-Mark Gurney 69508fca7a5SJohn-Mark Gurney /* Validate tag */ 69608fca7a5SJohn-Mark Gurney if (!(crde->crd_flags & CRD_F_ENCRYPT)) { 69708fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crda->crd_inject, 69808fca7a5SJohn-Mark Gurney axf->hashsize, uaalg); 69908fca7a5SJohn-Mark Gurney 70008fca7a5SJohn-Mark Gurney r = timingsafe_bcmp(aalg, uaalg, axf->hashsize); 70108fca7a5SJohn-Mark Gurney if (r == 0) { 70208fca7a5SJohn-Mark Gurney /* tag matches, decrypt data */ 703*507281e5SSean Eric Fagan if (isccm) { 704*507281e5SSean Eric Fagan KASSERT(exf->reinit != NULL, 705*507281e5SSean Eric Fagan ("AES-CCM reinit function must be set")); 706*507281e5SSean Eric Fagan exf->reinit(swe->sw_kschedule, iv); 707*507281e5SSean Eric Fagan } 70808fca7a5SJohn-Mark Gurney for (i = 0; i < crde->crd_len; i += blksz) { 70908fca7a5SJohn-Mark Gurney len = MIN(crde->crd_len - i, blksz); 71008fca7a5SJohn-Mark Gurney if (len < blksz) 71108fca7a5SJohn-Mark Gurney bzero(blk, blksz); 71208fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, 71308fca7a5SJohn-Mark Gurney crde->crd_skip + i, len, blk); 71408fca7a5SJohn-Mark Gurney exf->decrypt(swe->sw_kschedule, blk); 71508fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, 71608fca7a5SJohn-Mark Gurney crde->crd_skip + i, len, blk); 71708fca7a5SJohn-Mark Gurney } 71808fca7a5SJohn-Mark Gurney } else 71908fca7a5SJohn-Mark Gurney return (EBADMSG); 72008fca7a5SJohn-Mark Gurney } else { 72108fca7a5SJohn-Mark Gurney /* Inject the authentication data */ 72208fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, crda->crd_inject, 72308fca7a5SJohn-Mark Gurney axf->hashsize, aalg); 72408fca7a5SJohn-Mark Gurney } 72508fca7a5SJohn-Mark Gurney 72608fca7a5SJohn-Mark Gurney return (0); 72708fca7a5SJohn-Mark Gurney } 72808fca7a5SJohn-Mark Gurney 729091d81d1SSam Leffler /* 730091d81d1SSam Leffler * Apply a compression/decompression algorithm 731091d81d1SSam Leffler */ 732091d81d1SSam Leffler static int 733091d81d1SSam Leffler swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw, 734f34a967bSPawel Jakub Dawidek caddr_t buf, int flags) 735091d81d1SSam Leffler { 736091d81d1SSam Leffler u_int8_t *data, *out; 737091d81d1SSam Leffler struct comp_algo *cxf; 738091d81d1SSam Leffler int adj; 739091d81d1SSam Leffler u_int32_t result; 740091d81d1SSam Leffler 741091d81d1SSam Leffler cxf = sw->sw_cxf; 742091d81d1SSam Leffler 743091d81d1SSam Leffler /* We must handle the whole buffer of data in one time 744091d81d1SSam Leffler * then if there is not all the data in the mbuf, we must 745091d81d1SSam Leffler * copy in a buffer. 746091d81d1SSam Leffler */ 747091d81d1SSam Leffler 7481ede983cSDag-Erling Smørgrav data = malloc(crd->crd_len, M_CRYPTO_DATA, M_NOWAIT); 749091d81d1SSam Leffler if (data == NULL) 750091d81d1SSam Leffler return (EINVAL); 751f34a967bSPawel Jakub Dawidek crypto_copydata(flags, buf, crd->crd_skip, crd->crd_len, data); 752091d81d1SSam Leffler 753091d81d1SSam Leffler if (crd->crd_flags & CRD_F_COMP) 754091d81d1SSam Leffler result = cxf->compress(data, crd->crd_len, &out); 755091d81d1SSam Leffler else 756091d81d1SSam Leffler result = cxf->decompress(data, crd->crd_len, &out); 757091d81d1SSam Leffler 7581ede983cSDag-Erling Smørgrav free(data, M_CRYPTO_DATA); 759091d81d1SSam Leffler if (result == 0) 760091d81d1SSam Leffler return EINVAL; 761091d81d1SSam Leffler 762091d81d1SSam Leffler /* Copy back the (de)compressed data. m_copyback is 763091d81d1SSam Leffler * extending the mbuf as necessary. 764091d81d1SSam Leffler */ 765091d81d1SSam Leffler sw->sw_size = result; 766091d81d1SSam Leffler /* Check the compressed size when doing compression */ 767091d81d1SSam Leffler if (crd->crd_flags & CRD_F_COMP) { 768df4dece1SBjoern A. Zeeb if (result >= crd->crd_len) { 769091d81d1SSam Leffler /* Compression was useless, we lost time */ 7701ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 771091d81d1SSam Leffler return 0; 772091d81d1SSam Leffler } 773091d81d1SSam Leffler } 774091d81d1SSam Leffler 775f34a967bSPawel Jakub Dawidek crypto_copyback(flags, buf, crd->crd_skip, result, out); 776091d81d1SSam Leffler if (result < crd->crd_len) { 777091d81d1SSam Leffler adj = result - crd->crd_len; 778f34a967bSPawel Jakub Dawidek if (flags & CRYPTO_F_IMBUF) { 779091d81d1SSam Leffler adj = result - crd->crd_len; 780091d81d1SSam Leffler m_adj((struct mbuf *)buf, adj); 781f34a967bSPawel Jakub Dawidek } else if (flags & CRYPTO_F_IOV) { 782091d81d1SSam Leffler struct uio *uio = (struct uio *)buf; 783091d81d1SSam Leffler int ind; 784091d81d1SSam Leffler 785091d81d1SSam Leffler adj = crd->crd_len - result; 786091d81d1SSam Leffler ind = uio->uio_iovcnt - 1; 787091d81d1SSam Leffler 788091d81d1SSam Leffler while (adj > 0 && ind >= 0) { 789091d81d1SSam Leffler if (adj < uio->uio_iov[ind].iov_len) { 790091d81d1SSam Leffler uio->uio_iov[ind].iov_len -= adj; 791091d81d1SSam Leffler break; 792091d81d1SSam Leffler } 793091d81d1SSam Leffler 794091d81d1SSam Leffler adj -= uio->uio_iov[ind].iov_len; 795091d81d1SSam Leffler uio->uio_iov[ind].iov_len = 0; 796091d81d1SSam Leffler ind--; 797091d81d1SSam Leffler uio->uio_iovcnt--; 798091d81d1SSam Leffler } 799091d81d1SSam Leffler } 800091d81d1SSam Leffler } 8011ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 802091d81d1SSam Leffler return 0; 803091d81d1SSam Leffler } 804091d81d1SSam Leffler 805091d81d1SSam Leffler /* 806091d81d1SSam Leffler * Generate a new software session. 807091d81d1SSam Leffler */ 808091d81d1SSam Leffler static int 8091b0909d5SConrad Meyer swcr_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) 810091d81d1SSam Leffler { 8119ebbebe4SConrad Meyer struct swcr_session *ses; 8129ebbebe4SConrad Meyer struct swcr_data *swd; 813091d81d1SSam Leffler struct auth_hash *axf; 814091d81d1SSam Leffler struct enc_xform *txf; 815091d81d1SSam Leffler struct comp_algo *cxf; 8169ebbebe4SConrad Meyer size_t i; 817a2bc81bfSJohn-Mark Gurney int len; 818f6c4bc3bSPawel Jakub Dawidek int error; 819091d81d1SSam Leffler 8201b0909d5SConrad Meyer if (cses == NULL || cri == NULL) 821091d81d1SSam Leffler return EINVAL; 822091d81d1SSam Leffler 8231b0909d5SConrad Meyer ses = crypto_get_driver_session(cses); 824a7fcb1afSSean Eric Fagan mtx_init(&ses->swcr_lock, "swcr session lock", NULL, MTX_DEF); 825091d81d1SSam Leffler 8269ebbebe4SConrad Meyer for (i = 0; cri != NULL && i < nitems(ses->swcr_algorithms); i++) { 8279ebbebe4SConrad Meyer swd = &ses->swcr_algorithms[i]; 828091d81d1SSam Leffler 829091d81d1SSam Leffler switch (cri->cri_alg) { 830091d81d1SSam Leffler case CRYPTO_DES_CBC: 831091d81d1SSam Leffler txf = &enc_xform_des; 832091d81d1SSam Leffler goto enccommon; 833091d81d1SSam Leffler case CRYPTO_3DES_CBC: 834091d81d1SSam Leffler txf = &enc_xform_3des; 835091d81d1SSam Leffler goto enccommon; 836091d81d1SSam Leffler case CRYPTO_BLF_CBC: 837091d81d1SSam Leffler txf = &enc_xform_blf; 838091d81d1SSam Leffler goto enccommon; 839091d81d1SSam Leffler case CRYPTO_CAST_CBC: 840091d81d1SSam Leffler txf = &enc_xform_cast5; 841091d81d1SSam Leffler goto enccommon; 842091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 843091d81d1SSam Leffler txf = &enc_xform_skipjack; 844091d81d1SSam Leffler goto enccommon; 845091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 846091d81d1SSam Leffler txf = &enc_xform_rijndael128; 847091d81d1SSam Leffler goto enccommon; 848d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 849d295bdeeSPawel Jakub Dawidek txf = &enc_xform_aes_xts; 850d295bdeeSPawel Jakub Dawidek goto enccommon; 85108fca7a5SJohn-Mark Gurney case CRYPTO_AES_ICM: 85208fca7a5SJohn-Mark Gurney txf = &enc_xform_aes_icm; 85308fca7a5SJohn-Mark Gurney goto enccommon; 85408fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 85508fca7a5SJohn-Mark Gurney txf = &enc_xform_aes_nist_gcm; 85608fca7a5SJohn-Mark Gurney goto enccommon; 857*507281e5SSean Eric Fagan case CRYPTO_AES_CCM_16: 858*507281e5SSean Eric Fagan txf = &enc_xform_ccm; 859*507281e5SSean Eric Fagan goto enccommon; 86008fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 86108fca7a5SJohn-Mark Gurney txf = &enc_xform_aes_nist_gmac; 8629ebbebe4SConrad Meyer swd->sw_exf = txf; 86308fca7a5SJohn-Mark Gurney break; 864559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 865559d3390SGeorge V. Neville-Neil txf = &enc_xform_camellia; 866559d3390SGeorge V. Neville-Neil goto enccommon; 867091d81d1SSam Leffler case CRYPTO_NULL_CBC: 868091d81d1SSam Leffler txf = &enc_xform_null; 869091d81d1SSam Leffler goto enccommon; 87061590291SConrad Meyer case CRYPTO_CHACHA20: 87161590291SConrad Meyer txf = &enc_xform_chacha20; 87261590291SConrad Meyer goto enccommon; 873091d81d1SSam Leffler enccommon: 874f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 8759ebbebe4SConrad Meyer error = txf->setkey(&swd->sw_kschedule, 876091d81d1SSam Leffler cri->cri_key, cri->cri_klen / 8); 877091d81d1SSam Leffler if (error) { 8781b0909d5SConrad Meyer swcr_freesession(dev, cses); 879091d81d1SSam Leffler return error; 880091d81d1SSam Leffler } 881f6c4bc3bSPawel Jakub Dawidek } 8829ebbebe4SConrad Meyer swd->sw_exf = txf; 883091d81d1SSam Leffler break; 884091d81d1SSam Leffler 885091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 886f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_md5; 887091d81d1SSam Leffler goto authcommon; 888091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 889f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_sha1; 890091d81d1SSam Leffler goto authcommon; 891c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 892c97f39ceSConrad Meyer axf = &auth_hash_hmac_sha2_224; 893c97f39ceSConrad Meyer goto authcommon; 894f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 895091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_256; 896f6c4bc3bSPawel Jakub Dawidek goto authcommon; 897f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 898091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_384; 899f6c4bc3bSPawel Jakub Dawidek goto authcommon; 900f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 901091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_512; 902091d81d1SSam Leffler goto authcommon; 903091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 904091d81d1SSam Leffler axf = &auth_hash_null; 905091d81d1SSam Leffler goto authcommon; 906091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 907f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_ripemd_160; 908091d81d1SSam Leffler authcommon: 9099ebbebe4SConrad Meyer swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 910091d81d1SSam Leffler M_NOWAIT); 9119ebbebe4SConrad Meyer if (swd->sw_ictx == NULL) { 9121b0909d5SConrad Meyer swcr_freesession(dev, cses); 913091d81d1SSam Leffler return ENOBUFS; 914091d81d1SSam Leffler } 915091d81d1SSam Leffler 9169ebbebe4SConrad Meyer swd->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, 917091d81d1SSam Leffler M_NOWAIT); 9189ebbebe4SConrad Meyer if (swd->sw_octx == NULL) { 9191b0909d5SConrad Meyer swcr_freesession(dev, cses); 920091d81d1SSam Leffler return ENOBUFS; 921091d81d1SSam Leffler } 922091d81d1SSam Leffler 923f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 9249ebbebe4SConrad Meyer error = swcr_authprepare(axf, swd, 92525b7033bSConrad Meyer cri->cri_key, cri->cri_klen); 92625b7033bSConrad Meyer if (error != 0) { 92725b7033bSConrad Meyer swcr_freesession(dev, cses); 92825b7033bSConrad Meyer return error; 92925b7033bSConrad Meyer } 930f6c4bc3bSPawel Jakub Dawidek } 931091d81d1SSam Leffler 9329ebbebe4SConrad Meyer swd->sw_mlen = cri->cri_mlen; 9339ebbebe4SConrad Meyer swd->sw_axf = axf; 934091d81d1SSam Leffler break; 935091d81d1SSam Leffler 936091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 937091d81d1SSam Leffler axf = &auth_hash_key_md5; 938091d81d1SSam Leffler goto auth2common; 939091d81d1SSam Leffler 940091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 941091d81d1SSam Leffler axf = &auth_hash_key_sha1; 942091d81d1SSam Leffler auth2common: 9439ebbebe4SConrad Meyer swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 944091d81d1SSam Leffler M_NOWAIT); 9459ebbebe4SConrad Meyer if (swd->sw_ictx == NULL) { 9461b0909d5SConrad Meyer swcr_freesession(dev, cses); 947091d81d1SSam Leffler return ENOBUFS; 948091d81d1SSam Leffler } 949091d81d1SSam Leffler 9509ebbebe4SConrad Meyer swd->sw_octx = malloc(cri->cri_klen / 8, 951f6c4bc3bSPawel Jakub Dawidek M_CRYPTO_DATA, M_NOWAIT); 9529ebbebe4SConrad Meyer if (swd->sw_octx == NULL) { 9531b0909d5SConrad Meyer swcr_freesession(dev, cses); 954091d81d1SSam Leffler return ENOBUFS; 955091d81d1SSam Leffler } 956091d81d1SSam Leffler 957f6c4bc3bSPawel Jakub Dawidek /* Store the key so we can "append" it to the payload */ 958f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 9599ebbebe4SConrad Meyer error = swcr_authprepare(axf, swd, 96025b7033bSConrad Meyer cri->cri_key, cri->cri_klen); 96125b7033bSConrad Meyer if (error != 0) { 96225b7033bSConrad Meyer swcr_freesession(dev, cses); 96325b7033bSConrad Meyer return error; 96425b7033bSConrad Meyer } 965f6c4bc3bSPawel Jakub Dawidek } 966f6c4bc3bSPawel Jakub Dawidek 9679ebbebe4SConrad Meyer swd->sw_mlen = cri->cri_mlen; 9689ebbebe4SConrad Meyer swd->sw_axf = axf; 969091d81d1SSam Leffler break; 970091d81d1SSam Leffler #ifdef notdef 971091d81d1SSam Leffler case CRYPTO_MD5: 972091d81d1SSam Leffler axf = &auth_hash_md5; 973091d81d1SSam Leffler goto auth3common; 974c4729f6eSConrad Meyer #endif 975091d81d1SSam Leffler 976091d81d1SSam Leffler case CRYPTO_SHA1: 977091d81d1SSam Leffler axf = &auth_hash_sha1; 978c4729f6eSConrad Meyer goto auth3common; 979c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 980c4729f6eSConrad Meyer axf = &auth_hash_sha2_224; 981c4729f6eSConrad Meyer goto auth3common; 982c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 983c4729f6eSConrad Meyer axf = &auth_hash_sha2_256; 984c4729f6eSConrad Meyer goto auth3common; 985c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 986c4729f6eSConrad Meyer axf = &auth_hash_sha2_384; 987c4729f6eSConrad Meyer goto auth3common; 988c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 989c4729f6eSConrad Meyer axf = &auth_hash_sha2_512; 990c4729f6eSConrad Meyer 991091d81d1SSam Leffler auth3common: 9929ebbebe4SConrad Meyer swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 993091d81d1SSam Leffler M_NOWAIT); 9949ebbebe4SConrad Meyer if (swd->sw_ictx == NULL) { 9951b0909d5SConrad Meyer swcr_freesession(dev, cses); 996091d81d1SSam Leffler return ENOBUFS; 997091d81d1SSam Leffler } 998091d81d1SSam Leffler 9999ebbebe4SConrad Meyer axf->Init(swd->sw_ictx); 10009ebbebe4SConrad Meyer swd->sw_mlen = cri->cri_mlen; 10019ebbebe4SConrad Meyer swd->sw_axf = axf; 1002091d81d1SSam Leffler break; 100308fca7a5SJohn-Mark Gurney 1004*507281e5SSean Eric Fagan case CRYPTO_AES_CCM_CBC_MAC: 1005*507281e5SSean Eric Fagan switch (cri->cri_klen) { 1006*507281e5SSean Eric Fagan case 128: 1007*507281e5SSean Eric Fagan axf = &auth_hash_ccm_cbc_mac_128; 1008*507281e5SSean Eric Fagan break; 1009*507281e5SSean Eric Fagan case 192: 1010*507281e5SSean Eric Fagan axf = &auth_hash_ccm_cbc_mac_192; 1011*507281e5SSean Eric Fagan break; 1012*507281e5SSean Eric Fagan case 256: 1013*507281e5SSean Eric Fagan axf = &auth_hash_ccm_cbc_mac_256; 1014*507281e5SSean Eric Fagan break; 1015*507281e5SSean Eric Fagan default: 1016*507281e5SSean Eric Fagan swcr_freesession(dev, cses); 1017*507281e5SSean Eric Fagan return EINVAL; 1018*507281e5SSean Eric Fagan } 1019*507281e5SSean Eric Fagan goto auth4common; 102008fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 102108fca7a5SJohn-Mark Gurney axf = &auth_hash_nist_gmac_aes_128; 102208fca7a5SJohn-Mark Gurney goto auth4common; 102308fca7a5SJohn-Mark Gurney 102408fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 102508fca7a5SJohn-Mark Gurney axf = &auth_hash_nist_gmac_aes_192; 102608fca7a5SJohn-Mark Gurney goto auth4common; 102708fca7a5SJohn-Mark Gurney 102808fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 102908fca7a5SJohn-Mark Gurney axf = &auth_hash_nist_gmac_aes_256; 103008fca7a5SJohn-Mark Gurney auth4common: 1031a2bc81bfSJohn-Mark Gurney len = cri->cri_klen / 8; 10322e2e26d1SJohn Baldwin if (len != 16 && len != 24 && len != 32) { 10331b0909d5SConrad Meyer swcr_freesession(dev, cses); 1034a2bc81bfSJohn-Mark Gurney return EINVAL; 10352e2e26d1SJohn Baldwin } 1036a2bc81bfSJohn-Mark Gurney 10379ebbebe4SConrad Meyer swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 103808fca7a5SJohn-Mark Gurney M_NOWAIT); 10399ebbebe4SConrad Meyer if (swd->sw_ictx == NULL) { 10401b0909d5SConrad Meyer swcr_freesession(dev, cses); 104108fca7a5SJohn-Mark Gurney return ENOBUFS; 104208fca7a5SJohn-Mark Gurney } 10439ebbebe4SConrad Meyer axf->Init(swd->sw_ictx); 10449ebbebe4SConrad Meyer axf->Setkey(swd->sw_ictx, cri->cri_key, len); 10459ebbebe4SConrad Meyer swd->sw_axf = axf; 104608fca7a5SJohn-Mark Gurney break; 104708fca7a5SJohn-Mark Gurney 10480e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 10490e33efe4SConrad Meyer axf = &auth_hash_blake2b; 10500e33efe4SConrad Meyer goto auth5common; 10510e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 10520e33efe4SConrad Meyer axf = &auth_hash_blake2s; 105325b7033bSConrad Meyer goto auth5common; 105425b7033bSConrad Meyer case CRYPTO_POLY1305: 105525b7033bSConrad Meyer axf = &auth_hash_poly1305; 10560e33efe4SConrad Meyer auth5common: 10579ebbebe4SConrad Meyer swd->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 10580e33efe4SConrad Meyer M_NOWAIT); 10599ebbebe4SConrad Meyer if (swd->sw_ictx == NULL) { 10601b0909d5SConrad Meyer swcr_freesession(dev, cses); 10610e33efe4SConrad Meyer return ENOBUFS; 10620e33efe4SConrad Meyer } 10639ebbebe4SConrad Meyer axf->Setkey(swd->sw_ictx, cri->cri_key, 10640e33efe4SConrad Meyer cri->cri_klen / 8); 10659ebbebe4SConrad Meyer axf->Init(swd->sw_ictx); 10669ebbebe4SConrad Meyer swd->sw_axf = axf; 10670e33efe4SConrad Meyer break; 10680e33efe4SConrad Meyer 1069091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 1070091d81d1SSam Leffler cxf = &comp_algo_deflate; 10719ebbebe4SConrad Meyer swd->sw_cxf = cxf; 1072091d81d1SSam Leffler break; 1073091d81d1SSam Leffler default: 10741b0909d5SConrad Meyer swcr_freesession(dev, cses); 1075091d81d1SSam Leffler return EINVAL; 1076091d81d1SSam Leffler } 1077091d81d1SSam Leffler 10789ebbebe4SConrad Meyer swd->sw_alg = cri->cri_alg; 1079091d81d1SSam Leffler cri = cri->cri_next; 10809ebbebe4SConrad Meyer ses->swcr_nalgs++; 10819ebbebe4SConrad Meyer } 10829ebbebe4SConrad Meyer 10839ebbebe4SConrad Meyer if (cri != NULL) { 10849ebbebe4SConrad Meyer CRYPTDEB("Bogus session request for three or more algorithms"); 10859ebbebe4SConrad Meyer return EINVAL; 1086091d81d1SSam Leffler } 1087091d81d1SSam Leffler return 0; 1088091d81d1SSam Leffler } 1089091d81d1SSam Leffler 10901b0909d5SConrad Meyer static void 10911b0909d5SConrad Meyer swcr_freesession(device_t dev, crypto_session_t cses) 1092109919c6SBenno Rice { 10939ebbebe4SConrad Meyer struct swcr_session *ses; 10949ebbebe4SConrad Meyer struct swcr_data *swd; 1095091d81d1SSam Leffler struct enc_xform *txf; 1096091d81d1SSam Leffler struct auth_hash *axf; 10979ebbebe4SConrad Meyer size_t i; 1098091d81d1SSam Leffler 10991b0909d5SConrad Meyer ses = crypto_get_driver_session(cses); 1100091d81d1SSam Leffler 1101a7fcb1afSSean Eric Fagan mtx_destroy(&ses->swcr_lock); 11029ebbebe4SConrad Meyer for (i = 0; i < nitems(ses->swcr_algorithms); i++) { 11039ebbebe4SConrad Meyer swd = &ses->swcr_algorithms[i]; 1104091d81d1SSam Leffler 1105091d81d1SSam Leffler switch (swd->sw_alg) { 1106091d81d1SSam Leffler case CRYPTO_DES_CBC: 1107091d81d1SSam Leffler case CRYPTO_3DES_CBC: 1108091d81d1SSam Leffler case CRYPTO_BLF_CBC: 1109091d81d1SSam Leffler case CRYPTO_CAST_CBC: 1110091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 1111091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 1112d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 111308fca7a5SJohn-Mark Gurney case CRYPTO_AES_ICM: 111408fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 111508fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 1116559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 1117091d81d1SSam Leffler case CRYPTO_NULL_CBC: 111861590291SConrad Meyer case CRYPTO_CHACHA20: 1119*507281e5SSean Eric Fagan case CRYPTO_AES_CCM_16: 1120091d81d1SSam Leffler txf = swd->sw_exf; 1121091d81d1SSam Leffler 1122091d81d1SSam Leffler if (swd->sw_kschedule) 1123091d81d1SSam Leffler txf->zerokey(&(swd->sw_kschedule)); 1124091d81d1SSam Leffler break; 1125091d81d1SSam Leffler 1126091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 1127091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1128c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1129f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1130f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1131f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1132091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 1133091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1134*507281e5SSean Eric Fagan case CRYPTO_AES_CCM_CBC_MAC: 1135091d81d1SSam Leffler axf = swd->sw_axf; 1136091d81d1SSam Leffler 1137091d81d1SSam Leffler if (swd->sw_ictx) { 1138091d81d1SSam Leffler bzero(swd->sw_ictx, axf->ctxsize); 1139091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 1140091d81d1SSam Leffler } 1141091d81d1SSam Leffler if (swd->sw_octx) { 1142091d81d1SSam Leffler bzero(swd->sw_octx, axf->ctxsize); 1143091d81d1SSam Leffler free(swd->sw_octx, M_CRYPTO_DATA); 1144091d81d1SSam Leffler } 1145091d81d1SSam Leffler break; 1146091d81d1SSam Leffler 1147091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 1148091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 1149091d81d1SSam Leffler axf = swd->sw_axf; 1150091d81d1SSam Leffler 1151091d81d1SSam Leffler if (swd->sw_ictx) { 1152091d81d1SSam Leffler bzero(swd->sw_ictx, axf->ctxsize); 1153091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 1154091d81d1SSam Leffler } 1155091d81d1SSam Leffler if (swd->sw_octx) { 1156091d81d1SSam Leffler bzero(swd->sw_octx, swd->sw_klen); 1157091d81d1SSam Leffler free(swd->sw_octx, M_CRYPTO_DATA); 1158091d81d1SSam Leffler } 1159091d81d1SSam Leffler break; 1160091d81d1SSam Leffler 11610e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 11620e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 1163091d81d1SSam Leffler case CRYPTO_MD5: 116425b7033bSConrad Meyer case CRYPTO_POLY1305: 1165091d81d1SSam Leffler case CRYPTO_SHA1: 1166c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 1167c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 1168c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 1169c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 11706062df03SAndrey V. Elsukov case CRYPTO_AES_128_NIST_GMAC: 11716062df03SAndrey V. Elsukov case CRYPTO_AES_192_NIST_GMAC: 11726062df03SAndrey V. Elsukov case CRYPTO_AES_256_NIST_GMAC: 1173091d81d1SSam Leffler axf = swd->sw_axf; 1174091d81d1SSam Leffler 11755fbc5b5aSConrad Meyer if (swd->sw_ictx) { 11765fbc5b5aSConrad Meyer explicit_bzero(swd->sw_ictx, axf->ctxsize); 1177091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 11785fbc5b5aSConrad Meyer } 1179091d81d1SSam Leffler break; 1180091d81d1SSam Leffler 1181091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 1182151ba793SAlexander Kabaev /* Nothing to do */ 1183091d81d1SSam Leffler break; 1184091d81d1SSam Leffler } 1185091d81d1SSam Leffler } 1186091d81d1SSam Leffler } 1187091d81d1SSam Leffler 1188091d81d1SSam Leffler /* 1189091d81d1SSam Leffler * Process a software request. 1190091d81d1SSam Leffler */ 1191091d81d1SSam Leffler static int 11926810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint) 1193091d81d1SSam Leffler { 1194a7fcb1afSSean Eric Fagan struct swcr_session *ses = NULL; 1195091d81d1SSam Leffler struct cryptodesc *crd; 11969ebbebe4SConrad Meyer struct swcr_data *sw; 11979ebbebe4SConrad Meyer size_t i; 1198091d81d1SSam Leffler 1199091d81d1SSam Leffler /* Sanity check */ 1200091d81d1SSam Leffler if (crp == NULL) 1201091d81d1SSam Leffler return EINVAL; 1202091d81d1SSam Leffler 1203091d81d1SSam Leffler if (crp->crp_desc == NULL || crp->crp_buf == NULL) { 1204091d81d1SSam Leffler crp->crp_etype = EINVAL; 1205091d81d1SSam Leffler goto done; 1206091d81d1SSam Leffler } 1207091d81d1SSam Leffler 12081b0909d5SConrad Meyer ses = crypto_get_driver_session(crp->crp_session); 1209a7fcb1afSSean Eric Fagan mtx_lock(&ses->swcr_lock); 1210091d81d1SSam Leffler 1211091d81d1SSam Leffler /* Go through crypto descriptors, processing as we go */ 1212091d81d1SSam Leffler for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 1213091d81d1SSam Leffler /* 1214091d81d1SSam Leffler * Find the crypto context. 1215091d81d1SSam Leffler * 1216091d81d1SSam Leffler * XXX Note that the logic here prevents us from having 1217091d81d1SSam Leffler * XXX the same algorithm multiple times in a session 1218091d81d1SSam Leffler * XXX (or rather, we can but it won't give us the right 1219091d81d1SSam Leffler * XXX results). To do that, we'd need some way of differentiating 1220091d81d1SSam Leffler * XXX between the various instances of an algorithm (so we can 1221091d81d1SSam Leffler * XXX locate the correct crypto context). 1222091d81d1SSam Leffler */ 12239ebbebe4SConrad Meyer for (i = 0; i < nitems(ses->swcr_algorithms) && 12249ebbebe4SConrad Meyer ses->swcr_algorithms[i].sw_alg != crd->crd_alg; i++) 1225091d81d1SSam Leffler ; 1226091d81d1SSam Leffler 1227091d81d1SSam Leffler /* No such context ? */ 12289ebbebe4SConrad Meyer if (i == nitems(ses->swcr_algorithms)) { 1229091d81d1SSam Leffler crp->crp_etype = EINVAL; 1230091d81d1SSam Leffler goto done; 1231091d81d1SSam Leffler } 12329ebbebe4SConrad Meyer sw = &ses->swcr_algorithms[i]; 1233091d81d1SSam Leffler switch (sw->sw_alg) { 1234091d81d1SSam Leffler case CRYPTO_DES_CBC: 1235091d81d1SSam Leffler case CRYPTO_3DES_CBC: 1236091d81d1SSam Leffler case CRYPTO_BLF_CBC: 1237091d81d1SSam Leffler case CRYPTO_CAST_CBC: 1238091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 1239091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 1240d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 124108fca7a5SJohn-Mark Gurney case CRYPTO_AES_ICM: 1242559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 124361590291SConrad Meyer case CRYPTO_CHACHA20: 1244091d81d1SSam Leffler if ((crp->crp_etype = swcr_encdec(crd, sw, 1245f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1246091d81d1SSam Leffler goto done; 1247091d81d1SSam Leffler break; 1248091d81d1SSam Leffler case CRYPTO_NULL_CBC: 1249091d81d1SSam Leffler crp->crp_etype = 0; 1250091d81d1SSam Leffler break; 1251091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 1252091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1253c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1254f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1255f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1256f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1257091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 1258091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1259091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 1260091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 1261091d81d1SSam Leffler case CRYPTO_MD5: 1262091d81d1SSam Leffler case CRYPTO_SHA1: 1263c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 1264c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 1265c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 1266c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 12670e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 12680e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 126925b7033bSConrad Meyer case CRYPTO_POLY1305: 127038d2f8d6SPawel Jakub Dawidek if ((crp->crp_etype = swcr_authcompute(crd, sw, 1271f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1272091d81d1SSam Leffler goto done; 1273091d81d1SSam Leffler break; 1274091d81d1SSam Leffler 127508fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 127608fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 127708fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 127808fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 127908fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 1280*507281e5SSean Eric Fagan case CRYPTO_AES_CCM_16: 1281*507281e5SSean Eric Fagan case CRYPTO_AES_CCM_CBC_MAC: 128208fca7a5SJohn-Mark Gurney crp->crp_etype = swcr_authenc(crp); 128308fca7a5SJohn-Mark Gurney goto done; 128408fca7a5SJohn-Mark Gurney 1285091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 1286091d81d1SSam Leffler if ((crp->crp_etype = swcr_compdec(crd, sw, 1287f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1288091d81d1SSam Leffler goto done; 1289091d81d1SSam Leffler else 1290091d81d1SSam Leffler crp->crp_olen = (int)sw->sw_size; 1291091d81d1SSam Leffler break; 1292091d81d1SSam Leffler 1293091d81d1SSam Leffler default: 1294091d81d1SSam Leffler /* Unknown/unsupported algorithm */ 1295091d81d1SSam Leffler crp->crp_etype = EINVAL; 1296091d81d1SSam Leffler goto done; 1297091d81d1SSam Leffler } 1298091d81d1SSam Leffler } 1299091d81d1SSam Leffler 1300091d81d1SSam Leffler done: 1301a7fcb1afSSean Eric Fagan if (ses) 1302a7fcb1afSSean Eric Fagan mtx_unlock(&ses->swcr_lock); 1303091d81d1SSam Leffler crypto_done(crp); 1304091d81d1SSam Leffler return 0; 1305091d81d1SSam Leffler } 1306091d81d1SSam Leffler 1307091d81d1SSam Leffler static void 13083f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent) 1309091d81d1SSam Leffler { 13106810ad6fSSam Leffler /* NB: order 10 is so we get attached after h/w devices */ 13116810ad6fSSam Leffler if (device_find_child(parent, "cryptosoft", -1) == NULL && 131286c585d9SMarius Strobl BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0) 13136810ad6fSSam Leffler panic("cryptosoft: could not attach"); 13146810ad6fSSam Leffler } 1315f6c4bc3bSPawel Jakub Dawidek 13166810ad6fSSam Leffler static int 13176810ad6fSSam Leffler swcr_probe(device_t dev) 13186810ad6fSSam Leffler { 13196810ad6fSSam Leffler device_set_desc(dev, "software crypto"); 132086c585d9SMarius Strobl return (BUS_PROBE_NOWILDCARD); 13216810ad6fSSam Leffler } 1322f6c4bc3bSPawel Jakub Dawidek 13236810ad6fSSam Leffler static int 13246810ad6fSSam Leffler swcr_attach(device_t dev) 13256810ad6fSSam Leffler { 13266810ad6fSSam Leffler memset(hmac_ipad_buffer, HMAC_IPAD_VAL, HMAC_MAX_BLOCK_LEN); 13276810ad6fSSam Leffler memset(hmac_opad_buffer, HMAC_OPAD_VAL, HMAC_MAX_BLOCK_LEN); 13286810ad6fSSam Leffler 13299ebbebe4SConrad Meyer swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_session), 13306810ad6fSSam Leffler CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); 13316810ad6fSSam Leffler if (swcr_id < 0) { 13326810ad6fSSam Leffler device_printf(dev, "cannot initialize!"); 13336810ad6fSSam Leffler return ENOMEM; 13346810ad6fSSam Leffler } 1335091d81d1SSam Leffler #define REGISTER(alg) \ 13366810ad6fSSam Leffler crypto_register(swcr_id, alg, 0,0) 13376810ad6fSSam Leffler REGISTER(CRYPTO_DES_CBC); 1338091d81d1SSam Leffler REGISTER(CRYPTO_3DES_CBC); 1339091d81d1SSam Leffler REGISTER(CRYPTO_BLF_CBC); 1340091d81d1SSam Leffler REGISTER(CRYPTO_CAST_CBC); 1341091d81d1SSam Leffler REGISTER(CRYPTO_SKIPJACK_CBC); 1342091d81d1SSam Leffler REGISTER(CRYPTO_NULL_CBC); 1343091d81d1SSam Leffler REGISTER(CRYPTO_MD5_HMAC); 1344091d81d1SSam Leffler REGISTER(CRYPTO_SHA1_HMAC); 1345c97f39ceSConrad Meyer REGISTER(CRYPTO_SHA2_224_HMAC); 1346f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_256_HMAC); 1347f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_384_HMAC); 1348f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_512_HMAC); 1349091d81d1SSam Leffler REGISTER(CRYPTO_RIPEMD160_HMAC); 1350091d81d1SSam Leffler REGISTER(CRYPTO_NULL_HMAC); 1351091d81d1SSam Leffler REGISTER(CRYPTO_MD5_KPDK); 1352091d81d1SSam Leffler REGISTER(CRYPTO_SHA1_KPDK); 1353091d81d1SSam Leffler REGISTER(CRYPTO_MD5); 1354091d81d1SSam Leffler REGISTER(CRYPTO_SHA1); 1355c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_224); 1356c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_256); 1357c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_384); 1358c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_512); 1359091d81d1SSam Leffler REGISTER(CRYPTO_RIJNDAEL128_CBC); 1360d295bdeeSPawel Jakub Dawidek REGISTER(CRYPTO_AES_XTS); 136108fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_ICM); 136208fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_NIST_GCM_16); 136308fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_NIST_GMAC); 136408fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_128_NIST_GMAC); 136508fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_192_NIST_GMAC); 136608fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_256_NIST_GMAC); 1367559d3390SGeorge V. Neville-Neil REGISTER(CRYPTO_CAMELLIA_CBC); 1368091d81d1SSam Leffler REGISTER(CRYPTO_DEFLATE_COMP); 13690e33efe4SConrad Meyer REGISTER(CRYPTO_BLAKE2B); 13700e33efe4SConrad Meyer REGISTER(CRYPTO_BLAKE2S); 137161590291SConrad Meyer REGISTER(CRYPTO_CHACHA20); 1372*507281e5SSean Eric Fagan REGISTER(CRYPTO_AES_CCM_16); 1373*507281e5SSean Eric Fagan REGISTER(CRYPTO_AES_CCM_CBC_MAC); 137425b7033bSConrad Meyer REGISTER(CRYPTO_POLY1305); 1375091d81d1SSam Leffler #undef REGISTER 13766810ad6fSSam Leffler 13776810ad6fSSam Leffler return 0; 1378091d81d1SSam Leffler } 13794b465da2SPawel Jakub Dawidek 13803f147ab2SWarner Losh static int 13816810ad6fSSam Leffler swcr_detach(device_t dev) 13824b465da2SPawel Jakub Dawidek { 13836810ad6fSSam Leffler crypto_unregister_all(swcr_id); 13843f147ab2SWarner Losh return 0; 13854b465da2SPawel Jakub Dawidek } 13866810ad6fSSam Leffler 13876810ad6fSSam Leffler static device_method_t swcr_methods[] = { 13886810ad6fSSam Leffler DEVMETHOD(device_identify, swcr_identify), 13896810ad6fSSam Leffler DEVMETHOD(device_probe, swcr_probe), 13906810ad6fSSam Leffler DEVMETHOD(device_attach, swcr_attach), 13916810ad6fSSam Leffler DEVMETHOD(device_detach, swcr_detach), 13926810ad6fSSam Leffler 13936810ad6fSSam Leffler DEVMETHOD(cryptodev_newsession, swcr_newsession), 13946810ad6fSSam Leffler DEVMETHOD(cryptodev_freesession,swcr_freesession), 13956810ad6fSSam Leffler DEVMETHOD(cryptodev_process, swcr_process), 13966810ad6fSSam Leffler 13976810ad6fSSam Leffler {0, 0}, 13986810ad6fSSam Leffler }; 13996810ad6fSSam Leffler 14006810ad6fSSam Leffler static driver_t swcr_driver = { 14016810ad6fSSam Leffler "cryptosoft", 14026810ad6fSSam Leffler swcr_methods, 14036810ad6fSSam Leffler 0, /* NB: no softc */ 14046810ad6fSSam Leffler }; 14056810ad6fSSam Leffler static devclass_t swcr_devclass; 14066810ad6fSSam Leffler 14076810ad6fSSam Leffler /* 14086810ad6fSSam Leffler * NB: We explicitly reference the crypto module so we 14096810ad6fSSam Leffler * get the necessary ordering when built as a loadable 14106810ad6fSSam Leffler * module. This is required because we bundle the crypto 14116810ad6fSSam Leffler * module code together with the cryptosoft driver (otherwise 14126810ad6fSSam Leffler * normal module dependencies would handle things). 14136810ad6fSSam Leffler */ 14146810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *); 14156810ad6fSSam Leffler /* XXX where to attach */ 14166810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0); 14176810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1); 14186810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1); 1419