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> 48091d81d1SSam Leffler 49091d81d1SSam Leffler #include <crypto/blowfish/blowfish.h> 50091d81d1SSam Leffler #include <crypto/sha1.h> 51091d81d1SSam Leffler #include <opencrypto/rmd160.h> 529f65b10bSHajimu UMEMOTO #include <opencrypto/cast.h> 53091d81d1SSam Leffler #include <opencrypto/skipjack.h> 54091d81d1SSam Leffler #include <sys/md5.h> 55091d81d1SSam Leffler 56091d81d1SSam Leffler #include <opencrypto/cryptodev.h> 57091d81d1SSam Leffler #include <opencrypto/cryptosoft.h> 58091d81d1SSam Leffler #include <opencrypto/xform.h> 59091d81d1SSam Leffler 606810ad6fSSam Leffler #include <sys/kobj.h> 616810ad6fSSam Leffler #include <sys/bus.h> 626810ad6fSSam Leffler #include "cryptodev_if.h" 63091d81d1SSam Leffler 646810ad6fSSam Leffler static int32_t swcr_id; 656810ad6fSSam Leffler 666810ad6fSSam Leffler u_int8_t hmac_ipad_buffer[HMAC_MAX_BLOCK_LEN]; 676810ad6fSSam Leffler u_int8_t hmac_opad_buffer[HMAC_MAX_BLOCK_LEN]; 68091d81d1SSam Leffler 69091d81d1SSam Leffler static int swcr_encdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); 70f34a967bSPawel Jakub Dawidek static int swcr_authcompute(struct cryptodesc *, struct swcr_data *, caddr_t, int); 7108fca7a5SJohn-Mark Gurney static int swcr_authenc(struct cryptop *crp); 72091d81d1SSam Leffler static int swcr_compdec(struct cryptodesc *, struct swcr_data *, caddr_t, int); 73*1b0909d5SConrad Meyer static void swcr_freesession(device_t dev, crypto_session_t cses); 74091d81d1SSam Leffler 75091d81d1SSam Leffler /* 76091d81d1SSam Leffler * Apply a symmetric encryption/decryption algorithm. 77091d81d1SSam Leffler */ 78091d81d1SSam Leffler static int 79091d81d1SSam Leffler swcr_encdec(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, 80f34a967bSPawel Jakub Dawidek int flags) 81091d81d1SSam Leffler { 825d7ae54aSConrad Meyer unsigned char iv[EALG_MAX_BLOCK_LEN], blk[EALG_MAX_BLOCK_LEN]; 8308fca7a5SJohn-Mark Gurney unsigned char *ivp, *nivp, iv2[EALG_MAX_BLOCK_LEN]; 84091d81d1SSam Leffler struct enc_xform *exf; 8508fca7a5SJohn-Mark Gurney int i, j, k, blks, ind, count, ivlen; 8608fca7a5SJohn-Mark Gurney struct uio *uio, uiolcl; 8708fca7a5SJohn-Mark Gurney struct iovec iovlcl[4]; 8808fca7a5SJohn-Mark Gurney struct iovec *iov; 8908fca7a5SJohn-Mark Gurney int iovcnt, iovalloc; 9008fca7a5SJohn-Mark Gurney int error; 9108fca7a5SJohn-Mark Gurney 9208fca7a5SJohn-Mark Gurney error = 0; 93091d81d1SSam Leffler 94091d81d1SSam Leffler exf = sw->sw_exf; 95091d81d1SSam Leffler blks = exf->blocksize; 9608fca7a5SJohn-Mark Gurney ivlen = exf->ivsize; 97091d81d1SSam Leffler 98091d81d1SSam Leffler /* Check for non-padded data */ 99091d81d1SSam Leffler if (crd->crd_len % blks) 100091d81d1SSam Leffler return EINVAL; 101091d81d1SSam Leffler 10208fca7a5SJohn-Mark Gurney if (crd->crd_alg == CRYPTO_AES_ICM && 10308fca7a5SJohn-Mark Gurney (crd->crd_flags & CRD_F_IV_EXPLICIT) == 0) 10408fca7a5SJohn-Mark Gurney return (EINVAL); 10508fca7a5SJohn-Mark Gurney 106091d81d1SSam Leffler /* Initialize the IV */ 107091d81d1SSam Leffler if (crd->crd_flags & CRD_F_ENCRYPT) { 108091d81d1SSam Leffler /* IV explicitly provided ? */ 109091d81d1SSam Leffler if (crd->crd_flags & CRD_F_IV_EXPLICIT) 11008fca7a5SJohn-Mark Gurney bcopy(crd->crd_iv, iv, ivlen); 11148b0f2e1SPawel Jakub Dawidek else 11208fca7a5SJohn-Mark Gurney arc4rand(iv, ivlen, 0); 113091d81d1SSam Leffler 114091d81d1SSam Leffler /* Do we need to write the IV */ 115f34a967bSPawel Jakub Dawidek if (!(crd->crd_flags & CRD_F_IV_PRESENT)) 11608fca7a5SJohn-Mark Gurney crypto_copyback(flags, buf, crd->crd_inject, ivlen, iv); 117091d81d1SSam Leffler 118091d81d1SSam Leffler } else { /* Decryption */ 119091d81d1SSam Leffler /* IV explicitly provided ? */ 120091d81d1SSam Leffler if (crd->crd_flags & CRD_F_IV_EXPLICIT) 12108fca7a5SJohn-Mark Gurney bcopy(crd->crd_iv, iv, ivlen); 122091d81d1SSam Leffler else { 123091d81d1SSam Leffler /* Get IV off buf */ 12408fca7a5SJohn-Mark Gurney crypto_copydata(flags, buf, crd->crd_inject, ivlen, iv); 125091d81d1SSam Leffler } 126091d81d1SSam Leffler } 127091d81d1SSam Leffler 128c740ae4bSPoul-Henning Kamp if (crd->crd_flags & CRD_F_KEY_EXPLICIT) { 129c740ae4bSPoul-Henning Kamp int error; 130c740ae4bSPoul-Henning Kamp 131c740ae4bSPoul-Henning Kamp if (sw->sw_kschedule) 132c740ae4bSPoul-Henning Kamp exf->zerokey(&(sw->sw_kschedule)); 13308fca7a5SJohn-Mark Gurney 134c740ae4bSPoul-Henning Kamp error = exf->setkey(&sw->sw_kschedule, 135c740ae4bSPoul-Henning Kamp crd->crd_key, crd->crd_klen / 8); 136c740ae4bSPoul-Henning Kamp if (error) 137c740ae4bSPoul-Henning Kamp return (error); 138c740ae4bSPoul-Henning Kamp } 139d295bdeeSPawel Jakub Dawidek 14008fca7a5SJohn-Mark Gurney iov = iovlcl; 14108fca7a5SJohn-Mark Gurney iovcnt = nitems(iovlcl); 14208fca7a5SJohn-Mark Gurney iovalloc = 0; 14308fca7a5SJohn-Mark Gurney uio = &uiolcl; 14408fca7a5SJohn-Mark Gurney if ((flags & CRYPTO_F_IMBUF) != 0) { 145748a12e2SJohn-Mark Gurney error = crypto_mbuftoiov((struct mbuf *)buf, &iov, &iovcnt, 14608fca7a5SJohn-Mark Gurney &iovalloc); 147748a12e2SJohn-Mark Gurney if (error) 148748a12e2SJohn-Mark Gurney return (error); 14908fca7a5SJohn-Mark Gurney uio->uio_iov = iov; 15008fca7a5SJohn-Mark Gurney uio->uio_iovcnt = iovcnt; 15108fca7a5SJohn-Mark Gurney } else if ((flags & CRYPTO_F_IOV) != 0) 15208fca7a5SJohn-Mark Gurney uio = (struct uio *)buf; 15308fca7a5SJohn-Mark Gurney else { 15408fca7a5SJohn-Mark Gurney iov[0].iov_base = buf; 15508fca7a5SJohn-Mark Gurney iov[0].iov_len = crd->crd_skip + crd->crd_len; 15608fca7a5SJohn-Mark Gurney uio->uio_iov = iov; 15708fca7a5SJohn-Mark Gurney uio->uio_iovcnt = 1; 15808fca7a5SJohn-Mark Gurney } 15908fca7a5SJohn-Mark Gurney 160091d81d1SSam Leffler ivp = iv; 161091d81d1SSam Leffler 16208fca7a5SJohn-Mark Gurney if (exf->reinit) { 163d295bdeeSPawel Jakub Dawidek /* 164d295bdeeSPawel Jakub Dawidek * xforms that provide a reinit method perform all IV 165d295bdeeSPawel Jakub Dawidek * handling themselves. 166d295bdeeSPawel Jakub Dawidek */ 167d295bdeeSPawel Jakub Dawidek exf->reinit(sw->sw_kschedule, iv); 168091d81d1SSam Leffler } 169091d81d1SSam Leffler 17008fca7a5SJohn-Mark Gurney count = crd->crd_skip; 17108fca7a5SJohn-Mark Gurney ind = cuio_getptr(uio, count, &k); 17208fca7a5SJohn-Mark Gurney if (ind == -1) { 17308fca7a5SJohn-Mark Gurney error = EINVAL; 17408fca7a5SJohn-Mark Gurney goto out; 175091d81d1SSam Leffler } 176091d81d1SSam Leffler 177091d81d1SSam Leffler i = crd->crd_len; 178091d81d1SSam Leffler 179091d81d1SSam Leffler while (i > 0) { 180091d81d1SSam Leffler /* 181091d81d1SSam Leffler * If there's insufficient data at the end of 182091d81d1SSam Leffler * an iovec, we have to do some copying. 183091d81d1SSam Leffler */ 18408fca7a5SJohn-Mark Gurney if (uio->uio_iov[ind].iov_len < k + blks && 18508fca7a5SJohn-Mark Gurney uio->uio_iov[ind].iov_len != k) { 18608fca7a5SJohn-Mark Gurney cuio_copydata(uio, count, blks, blk); 187091d81d1SSam Leffler 188091d81d1SSam Leffler /* Actual encryption/decryption */ 189d295bdeeSPawel Jakub Dawidek if (exf->reinit) { 190091d81d1SSam Leffler if (crd->crd_flags & CRD_F_ENCRYPT) { 191d295bdeeSPawel Jakub Dawidek exf->encrypt(sw->sw_kschedule, 192d295bdeeSPawel Jakub Dawidek blk); 193d295bdeeSPawel Jakub Dawidek } else { 194d295bdeeSPawel Jakub Dawidek exf->decrypt(sw->sw_kschedule, 195d295bdeeSPawel Jakub Dawidek blk); 196d295bdeeSPawel Jakub Dawidek } 197d295bdeeSPawel Jakub Dawidek } else if (crd->crd_flags & CRD_F_ENCRYPT) { 198091d81d1SSam Leffler /* XOR with previous block */ 199091d81d1SSam Leffler for (j = 0; j < blks; j++) 200091d81d1SSam Leffler blk[j] ^= ivp[j]; 201091d81d1SSam Leffler 202091d81d1SSam Leffler exf->encrypt(sw->sw_kschedule, blk); 203091d81d1SSam Leffler 204091d81d1SSam Leffler /* 205091d81d1SSam Leffler * Keep encrypted block for XOR'ing 206091d81d1SSam Leffler * with next block 207091d81d1SSam Leffler */ 208091d81d1SSam Leffler bcopy(blk, iv, blks); 209091d81d1SSam Leffler ivp = iv; 210091d81d1SSam Leffler } else { /* decrypt */ 211091d81d1SSam Leffler /* 212091d81d1SSam Leffler * Keep encrypted block for XOR'ing 213091d81d1SSam Leffler * with next block 214091d81d1SSam Leffler */ 21508fca7a5SJohn-Mark Gurney nivp = (ivp == iv) ? iv2 : iv; 21608fca7a5SJohn-Mark Gurney bcopy(blk, nivp, blks); 217091d81d1SSam Leffler 218091d81d1SSam Leffler exf->decrypt(sw->sw_kschedule, blk); 219091d81d1SSam Leffler 220091d81d1SSam Leffler /* XOR with previous block */ 221091d81d1SSam Leffler for (j = 0; j < blks; j++) 222091d81d1SSam Leffler blk[j] ^= ivp[j]; 223091d81d1SSam Leffler 22408fca7a5SJohn-Mark Gurney ivp = nivp; 225091d81d1SSam Leffler } 226091d81d1SSam Leffler 227091d81d1SSam Leffler /* Copy back decrypted block */ 22808fca7a5SJohn-Mark Gurney cuio_copyback(uio, count, blks, blk); 22908fca7a5SJohn-Mark Gurney 23008fca7a5SJohn-Mark Gurney count += blks; 231091d81d1SSam Leffler 232091d81d1SSam Leffler /* Advance pointer */ 23308fca7a5SJohn-Mark Gurney ind = cuio_getptr(uio, count, &k); 23408fca7a5SJohn-Mark Gurney if (ind == -1) { 23508fca7a5SJohn-Mark Gurney error = EINVAL; 23608fca7a5SJohn-Mark Gurney goto out; 23708fca7a5SJohn-Mark Gurney } 238091d81d1SSam Leffler 239091d81d1SSam Leffler i -= blks; 240091d81d1SSam Leffler 241091d81d1SSam Leffler /* Could be done... */ 242091d81d1SSam Leffler if (i == 0) 243091d81d1SSam Leffler break; 244091d81d1SSam Leffler } 245091d81d1SSam Leffler 2462f1f9cceSConrad Meyer while (uio->uio_iov[ind].iov_len >= k + blks && i > 0) { 2475d7ae54aSConrad Meyer uint8_t *idat; 2482f1f9cceSConrad Meyer size_t nb, rem; 2492f1f9cceSConrad Meyer 2502f1f9cceSConrad Meyer nb = blks; 251179b21e8SConrad Meyer rem = MIN((size_t)i, 252179b21e8SConrad Meyer uio->uio_iov[ind].iov_len - (size_t)k); 2535d7ae54aSConrad Meyer idat = (uint8_t *)uio->uio_iov[ind].iov_base + k; 254091d81d1SSam Leffler 255d295bdeeSPawel Jakub Dawidek if (exf->reinit) { 2562f1f9cceSConrad Meyer if ((crd->crd_flags & CRD_F_ENCRYPT) != 0 && 2572f1f9cceSConrad Meyer exf->encrypt_multi == NULL) 258d295bdeeSPawel Jakub Dawidek exf->encrypt(sw->sw_kschedule, 259d295bdeeSPawel Jakub Dawidek idat); 2602f1f9cceSConrad Meyer else if ((crd->crd_flags & CRD_F_ENCRYPT) != 0) { 2612f1f9cceSConrad Meyer nb = rounddown(rem, blks); 2622f1f9cceSConrad Meyer exf->encrypt_multi(sw->sw_kschedule, 2632f1f9cceSConrad Meyer idat, nb); 2642f1f9cceSConrad Meyer } else if (exf->decrypt_multi == NULL) 265d295bdeeSPawel Jakub Dawidek exf->decrypt(sw->sw_kschedule, 266d295bdeeSPawel Jakub Dawidek idat); 2672f1f9cceSConrad Meyer else { 2682f1f9cceSConrad Meyer nb = rounddown(rem, blks); 2692f1f9cceSConrad Meyer exf->decrypt_multi(sw->sw_kschedule, 2702f1f9cceSConrad Meyer idat, nb); 271d295bdeeSPawel Jakub Dawidek } 272d295bdeeSPawel Jakub Dawidek } else if (crd->crd_flags & CRD_F_ENCRYPT) { 273091d81d1SSam Leffler /* XOR with previous block/IV */ 274091d81d1SSam Leffler for (j = 0; j < blks; j++) 275091d81d1SSam Leffler idat[j] ^= ivp[j]; 276091d81d1SSam Leffler 277091d81d1SSam Leffler exf->encrypt(sw->sw_kschedule, idat); 278091d81d1SSam Leffler ivp = idat; 279091d81d1SSam Leffler } else { /* decrypt */ 280091d81d1SSam Leffler /* 281091d81d1SSam Leffler * Keep encrypted block to be used 282091d81d1SSam Leffler * in next block's processing. 283091d81d1SSam Leffler */ 28408fca7a5SJohn-Mark Gurney nivp = (ivp == iv) ? iv2 : iv; 28508fca7a5SJohn-Mark Gurney bcopy(idat, nivp, blks); 286091d81d1SSam Leffler 287091d81d1SSam Leffler exf->decrypt(sw->sw_kschedule, idat); 288091d81d1SSam Leffler 289091d81d1SSam Leffler /* XOR with previous block/IV */ 290091d81d1SSam Leffler for (j = 0; j < blks; j++) 291091d81d1SSam Leffler idat[j] ^= ivp[j]; 292091d81d1SSam Leffler 29308fca7a5SJohn-Mark Gurney ivp = nivp; 294091d81d1SSam Leffler } 295091d81d1SSam Leffler 2962f1f9cceSConrad Meyer count += nb; 2972f1f9cceSConrad Meyer k += nb; 2982f1f9cceSConrad Meyer i -= nb; 299091d81d1SSam Leffler } 300091d81d1SSam Leffler 301f34a967bSPawel Jakub Dawidek /* 30208fca7a5SJohn-Mark Gurney * Advance to the next iov if the end of the current iov 30308fca7a5SJohn-Mark Gurney * is aligned with the end of a cipher block. 30408fca7a5SJohn-Mark Gurney * Note that the code is equivalent to calling: 30508fca7a5SJohn-Mark Gurney * ind = cuio_getptr(uio, count, &k); 306f34a967bSPawel Jakub Dawidek */ 30708fca7a5SJohn-Mark Gurney if (i > 0 && k == uio->uio_iov[ind].iov_len) { 30808fca7a5SJohn-Mark Gurney k = 0; 30908fca7a5SJohn-Mark Gurney ind++; 31008fca7a5SJohn-Mark Gurney if (ind >= uio->uio_iovcnt) { 31108fca7a5SJohn-Mark Gurney error = EINVAL; 31208fca7a5SJohn-Mark Gurney goto out; 31308fca7a5SJohn-Mark Gurney } 314f34a967bSPawel Jakub Dawidek } 315f34a967bSPawel Jakub Dawidek } 316f34a967bSPawel Jakub Dawidek 31708fca7a5SJohn-Mark Gurney out: 31808fca7a5SJohn-Mark Gurney if (iovalloc) 31908fca7a5SJohn-Mark Gurney free(iov, M_CRYPTO_DATA); 320091d81d1SSam Leffler 32108fca7a5SJohn-Mark Gurney return (error); 322091d81d1SSam Leffler } 323091d81d1SSam Leffler 324f6c4bc3bSPawel Jakub Dawidek static void 325f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(struct auth_hash *axf, struct swcr_data *sw, u_char *key, 326f6c4bc3bSPawel Jakub Dawidek int klen) 327f6c4bc3bSPawel Jakub Dawidek { 328f6c4bc3bSPawel Jakub Dawidek int k; 329f6c4bc3bSPawel Jakub Dawidek 330f6c4bc3bSPawel Jakub Dawidek klen /= 8; 331f6c4bc3bSPawel Jakub Dawidek 332f6c4bc3bSPawel Jakub Dawidek switch (axf->type) { 333f6c4bc3bSPawel Jakub Dawidek case CRYPTO_MD5_HMAC: 334f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA1_HMAC: 335c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 336f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 337f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 338f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 339f6c4bc3bSPawel Jakub Dawidek case CRYPTO_NULL_HMAC: 340f6c4bc3bSPawel Jakub Dawidek case CRYPTO_RIPEMD160_HMAC: 341f6c4bc3bSPawel Jakub Dawidek for (k = 0; k < klen; k++) 342f6c4bc3bSPawel Jakub Dawidek key[k] ^= HMAC_IPAD_VAL; 343f6c4bc3bSPawel Jakub Dawidek 344f6c4bc3bSPawel Jakub Dawidek axf->Init(sw->sw_ictx); 345f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_ictx, key, klen); 346f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_ictx, hmac_ipad_buffer, axf->blocksize - klen); 347f6c4bc3bSPawel Jakub Dawidek 348f6c4bc3bSPawel Jakub Dawidek for (k = 0; k < klen; k++) 349f6c4bc3bSPawel Jakub Dawidek key[k] ^= (HMAC_IPAD_VAL ^ HMAC_OPAD_VAL); 350f6c4bc3bSPawel Jakub Dawidek 351f6c4bc3bSPawel Jakub Dawidek axf->Init(sw->sw_octx); 352f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_octx, key, klen); 353f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_octx, hmac_opad_buffer, axf->blocksize - klen); 354f6c4bc3bSPawel Jakub Dawidek 355f6c4bc3bSPawel Jakub Dawidek for (k = 0; k < klen; k++) 356f6c4bc3bSPawel Jakub Dawidek key[k] ^= HMAC_OPAD_VAL; 357f6c4bc3bSPawel Jakub Dawidek break; 358f6c4bc3bSPawel Jakub Dawidek case CRYPTO_MD5_KPDK: 359f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA1_KPDK: 3601f4990a6SBjoern A. Zeeb { 36177680d96SBjoern A. Zeeb /* 36277680d96SBjoern A. Zeeb * We need a buffer that can hold an md5 and a sha1 result 36377680d96SBjoern A. Zeeb * just to throw it away. 36477680d96SBjoern A. Zeeb * What we do here is the initial part of: 36577680d96SBjoern A. Zeeb * ALGO( key, keyfill, .. ) 36677680d96SBjoern A. Zeeb * adding the key to sw_ictx and abusing Final() to get the 36777680d96SBjoern A. Zeeb * "keyfill" padding. 36877680d96SBjoern A. Zeeb * In addition we abuse the sw_octx to save the key to have 36977680d96SBjoern A. Zeeb * it to be able to append it at the end in swcr_authcompute(). 37077680d96SBjoern A. Zeeb */ 3711f4990a6SBjoern A. Zeeb u_char buf[SHA1_RESULTLEN]; 3721f4990a6SBjoern A. Zeeb 373f6c4bc3bSPawel Jakub Dawidek sw->sw_klen = klen; 374f6c4bc3bSPawel Jakub Dawidek bcopy(key, sw->sw_octx, klen); 375f6c4bc3bSPawel Jakub Dawidek axf->Init(sw->sw_ictx); 376f6c4bc3bSPawel Jakub Dawidek axf->Update(sw->sw_ictx, key, klen); 3771f4990a6SBjoern A. Zeeb axf->Final(buf, sw->sw_ictx); 378f6c4bc3bSPawel Jakub Dawidek break; 3791f4990a6SBjoern A. Zeeb } 3800e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 3810e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 3820e33efe4SConrad Meyer axf->Setkey(sw->sw_ictx, key, klen); 3830e33efe4SConrad Meyer axf->Init(sw->sw_ictx); 3840e33efe4SConrad Meyer break; 385f6c4bc3bSPawel Jakub Dawidek default: 386f6c4bc3bSPawel Jakub Dawidek printf("%s: CRD_F_KEY_EXPLICIT flag given, but algorithm %d " 387f6c4bc3bSPawel Jakub Dawidek "doesn't use keys.\n", __func__, axf->type); 388f6c4bc3bSPawel Jakub Dawidek } 389f6c4bc3bSPawel Jakub Dawidek } 390f6c4bc3bSPawel Jakub Dawidek 391091d81d1SSam Leffler /* 392091d81d1SSam Leffler * Compute keyed-hash authenticator. 393091d81d1SSam Leffler */ 394091d81d1SSam Leffler static int 39538d2f8d6SPawel Jakub Dawidek swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, 396f34a967bSPawel Jakub Dawidek int flags) 397091d81d1SSam Leffler { 3980bbc4bf9SPawel Jakub Dawidek unsigned char aalg[HASH_MAX_LEN]; 399091d81d1SSam Leffler struct auth_hash *axf; 400091d81d1SSam Leffler union authctx ctx; 401091d81d1SSam Leffler int err; 402091d81d1SSam Leffler 403091d81d1SSam Leffler if (sw->sw_ictx == 0) 404091d81d1SSam Leffler return EINVAL; 405091d81d1SSam Leffler 406091d81d1SSam Leffler axf = sw->sw_axf; 407091d81d1SSam Leffler 408f6c4bc3bSPawel Jakub Dawidek if (crd->crd_flags & CRD_F_KEY_EXPLICIT) 409f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen); 410f6c4bc3bSPawel Jakub Dawidek 411091d81d1SSam Leffler bcopy(sw->sw_ictx, &ctx, axf->ctxsize); 412091d81d1SSam Leffler 413f34a967bSPawel Jakub Dawidek err = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, 414f34a967bSPawel Jakub Dawidek (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); 415091d81d1SSam Leffler if (err) 416091d81d1SSam Leffler return err; 417091d81d1SSam Leffler 418091d81d1SSam Leffler switch (sw->sw_alg) { 419c4729f6eSConrad Meyer case CRYPTO_SHA1: 420c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 421c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 422c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 423c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 424c4729f6eSConrad Meyer axf->Final(aalg, &ctx); 425c4729f6eSConrad Meyer break; 426c4729f6eSConrad Meyer 427091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 428091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 429c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 430f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 431f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 432f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 433091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 434091d81d1SSam Leffler if (sw->sw_octx == NULL) 435091d81d1SSam Leffler return EINVAL; 436091d81d1SSam Leffler 437091d81d1SSam Leffler axf->Final(aalg, &ctx); 438091d81d1SSam Leffler bcopy(sw->sw_octx, &ctx, axf->ctxsize); 439091d81d1SSam Leffler axf->Update(&ctx, aalg, axf->hashsize); 440091d81d1SSam Leffler axf->Final(aalg, &ctx); 441091d81d1SSam Leffler break; 442091d81d1SSam Leffler 443091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 444091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 44577680d96SBjoern A. Zeeb /* If we have no key saved, return error. */ 446091d81d1SSam Leffler if (sw->sw_octx == NULL) 447091d81d1SSam Leffler return EINVAL; 448091d81d1SSam Leffler 44977680d96SBjoern A. Zeeb /* 45077680d96SBjoern A. Zeeb * Add the trailing copy of the key (see comment in 45177680d96SBjoern A. Zeeb * swcr_authprepare()) after the data: 45277680d96SBjoern A. Zeeb * ALGO( .., key, algofill ) 45377680d96SBjoern A. Zeeb * and let Final() do the proper, natural "algofill" 45477680d96SBjoern A. Zeeb * padding. 45577680d96SBjoern A. Zeeb */ 456091d81d1SSam Leffler axf->Update(&ctx, sw->sw_octx, sw->sw_klen); 457091d81d1SSam Leffler axf->Final(aalg, &ctx); 458091d81d1SSam Leffler break; 459091d81d1SSam Leffler 4600e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 4610e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 462091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 463091d81d1SSam Leffler axf->Final(aalg, &ctx); 464091d81d1SSam Leffler break; 465091d81d1SSam Leffler } 466091d81d1SSam Leffler 467091d81d1SSam Leffler /* Inject the authentication data */ 468f34a967bSPawel Jakub Dawidek crypto_copyback(flags, buf, crd->crd_inject, 469f6c4bc3bSPawel Jakub Dawidek sw->sw_mlen == 0 ? axf->hashsize : sw->sw_mlen, aalg); 470091d81d1SSam Leffler return 0; 471091d81d1SSam Leffler } 472091d81d1SSam Leffler 47308fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256); /* GCM: plain text < 2^39-256 */ 47408fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1); /* GCM: associated data <= 2^64-1 */ 47508fca7a5SJohn-Mark Gurney 47608fca7a5SJohn-Mark Gurney /* 47708fca7a5SJohn-Mark Gurney * Apply a combined encryption-authentication transformation 47808fca7a5SJohn-Mark Gurney */ 47908fca7a5SJohn-Mark Gurney static int 48008fca7a5SJohn-Mark Gurney swcr_authenc(struct cryptop *crp) 48108fca7a5SJohn-Mark Gurney { 48208fca7a5SJohn-Mark Gurney uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; 48308fca7a5SJohn-Mark Gurney u_char *blk = (u_char *)blkbuf; 48408fca7a5SJohn-Mark Gurney u_char aalg[AALG_MAX_RESULT_LEN]; 48508fca7a5SJohn-Mark Gurney u_char uaalg[AALG_MAX_RESULT_LEN]; 48608fca7a5SJohn-Mark Gurney u_char iv[EALG_MAX_BLOCK_LEN]; 48708fca7a5SJohn-Mark Gurney union authctx ctx; 48808fca7a5SJohn-Mark Gurney struct cryptodesc *crd, *crda = NULL, *crde = NULL; 48908fca7a5SJohn-Mark Gurney struct swcr_data *sw, *swa, *swe = NULL; 49008fca7a5SJohn-Mark Gurney struct auth_hash *axf = NULL; 49108fca7a5SJohn-Mark Gurney struct enc_xform *exf = NULL; 49208fca7a5SJohn-Mark Gurney caddr_t buf = (caddr_t)crp->crp_buf; 49308fca7a5SJohn-Mark Gurney uint32_t *blkp; 49408fca7a5SJohn-Mark Gurney int aadlen, blksz, i, ivlen, len, iskip, oskip, r; 49508fca7a5SJohn-Mark Gurney 49608fca7a5SJohn-Mark Gurney ivlen = blksz = iskip = oskip = 0; 49708fca7a5SJohn-Mark Gurney 49808fca7a5SJohn-Mark Gurney for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 499*1b0909d5SConrad Meyer for (sw = crypto_get_driver_session(crp->crp_session); 50008fca7a5SJohn-Mark Gurney sw && sw->sw_alg != crd->crd_alg; 50108fca7a5SJohn-Mark Gurney sw = sw->sw_next) 50208fca7a5SJohn-Mark Gurney ; 50308fca7a5SJohn-Mark Gurney if (sw == NULL) 50408fca7a5SJohn-Mark Gurney return (EINVAL); 50508fca7a5SJohn-Mark Gurney 50608fca7a5SJohn-Mark Gurney switch (sw->sw_alg) { 50708fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 50808fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 50908fca7a5SJohn-Mark Gurney swe = sw; 51008fca7a5SJohn-Mark Gurney crde = crd; 51108fca7a5SJohn-Mark Gurney exf = swe->sw_exf; 51208fca7a5SJohn-Mark Gurney ivlen = 12; 51308fca7a5SJohn-Mark Gurney break; 51408fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 51508fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 51608fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 51708fca7a5SJohn-Mark Gurney swa = sw; 51808fca7a5SJohn-Mark Gurney crda = crd; 51908fca7a5SJohn-Mark Gurney axf = swa->sw_axf; 52008fca7a5SJohn-Mark Gurney if (swa->sw_ictx == 0) 52108fca7a5SJohn-Mark Gurney return (EINVAL); 52208fca7a5SJohn-Mark Gurney bcopy(swa->sw_ictx, &ctx, axf->ctxsize); 52308fca7a5SJohn-Mark Gurney blksz = axf->blocksize; 52408fca7a5SJohn-Mark Gurney break; 52508fca7a5SJohn-Mark Gurney default: 52608fca7a5SJohn-Mark Gurney return (EINVAL); 52708fca7a5SJohn-Mark Gurney } 52808fca7a5SJohn-Mark Gurney } 52908fca7a5SJohn-Mark Gurney if (crde == NULL || crda == NULL) 53008fca7a5SJohn-Mark Gurney return (EINVAL); 53108fca7a5SJohn-Mark Gurney 53208fca7a5SJohn-Mark Gurney if (crde->crd_alg == CRYPTO_AES_NIST_GCM_16 && 53308fca7a5SJohn-Mark Gurney (crde->crd_flags & CRD_F_IV_EXPLICIT) == 0) 53408fca7a5SJohn-Mark Gurney return (EINVAL); 53508fca7a5SJohn-Mark Gurney 53608fca7a5SJohn-Mark Gurney if (crde->crd_klen != crda->crd_klen) 53708fca7a5SJohn-Mark Gurney return (EINVAL); 53808fca7a5SJohn-Mark Gurney 53908fca7a5SJohn-Mark Gurney /* Initialize the IV */ 54008fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_ENCRYPT) { 54108fca7a5SJohn-Mark Gurney /* IV explicitly provided ? */ 54208fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_IV_EXPLICIT) 54308fca7a5SJohn-Mark Gurney bcopy(crde->crd_iv, iv, ivlen); 54408fca7a5SJohn-Mark Gurney else 54508fca7a5SJohn-Mark Gurney arc4rand(iv, ivlen, 0); 54608fca7a5SJohn-Mark Gurney 54708fca7a5SJohn-Mark Gurney /* Do we need to write the IV */ 54808fca7a5SJohn-Mark Gurney if (!(crde->crd_flags & CRD_F_IV_PRESENT)) 54908fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, crde->crd_inject, 55008fca7a5SJohn-Mark Gurney ivlen, iv); 55108fca7a5SJohn-Mark Gurney 55208fca7a5SJohn-Mark Gurney } else { /* Decryption */ 55308fca7a5SJohn-Mark Gurney /* IV explicitly provided ? */ 55408fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_IV_EXPLICIT) 55508fca7a5SJohn-Mark Gurney bcopy(crde->crd_iv, iv, ivlen); 55608fca7a5SJohn-Mark Gurney else { 55708fca7a5SJohn-Mark Gurney /* Get IV off buf */ 55808fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crde->crd_inject, 55908fca7a5SJohn-Mark Gurney ivlen, iv); 56008fca7a5SJohn-Mark Gurney } 56108fca7a5SJohn-Mark Gurney } 56208fca7a5SJohn-Mark Gurney 56308fca7a5SJohn-Mark Gurney /* Supply MAC with IV */ 56408fca7a5SJohn-Mark Gurney if (axf->Reinit) 56508fca7a5SJohn-Mark Gurney axf->Reinit(&ctx, iv, ivlen); 56608fca7a5SJohn-Mark Gurney 56708fca7a5SJohn-Mark Gurney /* Supply MAC with AAD */ 56808fca7a5SJohn-Mark Gurney aadlen = crda->crd_len; 56908fca7a5SJohn-Mark Gurney 57008fca7a5SJohn-Mark Gurney for (i = iskip; i < crda->crd_len; i += blksz) { 57108fca7a5SJohn-Mark Gurney len = MIN(crda->crd_len - i, blksz - oskip); 57208fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crda->crd_skip + i, len, 57308fca7a5SJohn-Mark Gurney blk + oskip); 57408fca7a5SJohn-Mark Gurney bzero(blk + len + oskip, blksz - len - oskip); 57508fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, blksz); 57608fca7a5SJohn-Mark Gurney oskip = 0; /* reset initial output offset */ 57708fca7a5SJohn-Mark Gurney } 57808fca7a5SJohn-Mark Gurney 57908fca7a5SJohn-Mark Gurney if (exf->reinit) 58008fca7a5SJohn-Mark Gurney exf->reinit(swe->sw_kschedule, iv); 58108fca7a5SJohn-Mark Gurney 58208fca7a5SJohn-Mark Gurney /* Do encryption/decryption with MAC */ 5832f1f9cceSConrad Meyer for (i = 0; i < crde->crd_len; i += len) { 5842f1f9cceSConrad Meyer if (exf->encrypt_multi != NULL) { 5852f1f9cceSConrad Meyer len = rounddown(crde->crd_len - i, blksz); 5862f1f9cceSConrad Meyer if (len == 0) 5872f1f9cceSConrad Meyer len = blksz; 5882f1f9cceSConrad Meyer else 5892f1f9cceSConrad Meyer len = MIN(len, sizeof(blkbuf)); 5902f1f9cceSConrad Meyer } else 5912f1f9cceSConrad Meyer len = blksz; 5922f1f9cceSConrad Meyer len = MIN(crde->crd_len - i, len); 59308fca7a5SJohn-Mark Gurney if (len < blksz) 59408fca7a5SJohn-Mark Gurney bzero(blk, blksz); 59508fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crde->crd_skip + i, len, 59608fca7a5SJohn-Mark Gurney blk); 59708fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_ENCRYPT) { 5982f1f9cceSConrad Meyer if (exf->encrypt_multi != NULL) 5992f1f9cceSConrad Meyer exf->encrypt_multi(swe->sw_kschedule, blk, 6002f1f9cceSConrad Meyer len); 6012f1f9cceSConrad Meyer else 60208fca7a5SJohn-Mark Gurney exf->encrypt(swe->sw_kschedule, blk); 60308fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, len); 60408fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, 60508fca7a5SJohn-Mark Gurney crde->crd_skip + i, len, blk); 60608fca7a5SJohn-Mark Gurney } else { 60708fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, len); 60808fca7a5SJohn-Mark Gurney } 60908fca7a5SJohn-Mark Gurney } 61008fca7a5SJohn-Mark Gurney 61108fca7a5SJohn-Mark Gurney /* Do any required special finalization */ 61208fca7a5SJohn-Mark Gurney switch (crda->crd_alg) { 61308fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 61408fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 61508fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 61608fca7a5SJohn-Mark Gurney /* length block */ 61708fca7a5SJohn-Mark Gurney bzero(blk, blksz); 61808fca7a5SJohn-Mark Gurney blkp = (uint32_t *)blk + 1; 61908fca7a5SJohn-Mark Gurney *blkp = htobe32(aadlen * 8); 62008fca7a5SJohn-Mark Gurney blkp = (uint32_t *)blk + 3; 62108fca7a5SJohn-Mark Gurney *blkp = htobe32(crde->crd_len * 8); 62208fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, blksz); 62308fca7a5SJohn-Mark Gurney break; 62408fca7a5SJohn-Mark Gurney } 62508fca7a5SJohn-Mark Gurney 62608fca7a5SJohn-Mark Gurney /* Finalize MAC */ 62708fca7a5SJohn-Mark Gurney axf->Final(aalg, &ctx); 62808fca7a5SJohn-Mark Gurney 62908fca7a5SJohn-Mark Gurney /* Validate tag */ 63008fca7a5SJohn-Mark Gurney if (!(crde->crd_flags & CRD_F_ENCRYPT)) { 63108fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crda->crd_inject, 63208fca7a5SJohn-Mark Gurney axf->hashsize, uaalg); 63308fca7a5SJohn-Mark Gurney 63408fca7a5SJohn-Mark Gurney r = timingsafe_bcmp(aalg, uaalg, axf->hashsize); 63508fca7a5SJohn-Mark Gurney if (r == 0) { 63608fca7a5SJohn-Mark Gurney /* tag matches, decrypt data */ 63708fca7a5SJohn-Mark Gurney for (i = 0; i < crde->crd_len; i += blksz) { 63808fca7a5SJohn-Mark Gurney len = MIN(crde->crd_len - i, blksz); 63908fca7a5SJohn-Mark Gurney if (len < blksz) 64008fca7a5SJohn-Mark Gurney bzero(blk, blksz); 64108fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, 64208fca7a5SJohn-Mark Gurney crde->crd_skip + i, len, blk); 64308fca7a5SJohn-Mark Gurney exf->decrypt(swe->sw_kschedule, blk); 64408fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, 64508fca7a5SJohn-Mark Gurney crde->crd_skip + i, len, blk); 64608fca7a5SJohn-Mark Gurney } 64708fca7a5SJohn-Mark Gurney } else 64808fca7a5SJohn-Mark Gurney return (EBADMSG); 64908fca7a5SJohn-Mark Gurney } else { 65008fca7a5SJohn-Mark Gurney /* Inject the authentication data */ 65108fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, crda->crd_inject, 65208fca7a5SJohn-Mark Gurney axf->hashsize, aalg); 65308fca7a5SJohn-Mark Gurney } 65408fca7a5SJohn-Mark Gurney 65508fca7a5SJohn-Mark Gurney return (0); 65608fca7a5SJohn-Mark Gurney } 65708fca7a5SJohn-Mark Gurney 658091d81d1SSam Leffler /* 659091d81d1SSam Leffler * Apply a compression/decompression algorithm 660091d81d1SSam Leffler */ 661091d81d1SSam Leffler static int 662091d81d1SSam Leffler swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw, 663f34a967bSPawel Jakub Dawidek caddr_t buf, int flags) 664091d81d1SSam Leffler { 665091d81d1SSam Leffler u_int8_t *data, *out; 666091d81d1SSam Leffler struct comp_algo *cxf; 667091d81d1SSam Leffler int adj; 668091d81d1SSam Leffler u_int32_t result; 669091d81d1SSam Leffler 670091d81d1SSam Leffler cxf = sw->sw_cxf; 671091d81d1SSam Leffler 672091d81d1SSam Leffler /* We must handle the whole buffer of data in one time 673091d81d1SSam Leffler * then if there is not all the data in the mbuf, we must 674091d81d1SSam Leffler * copy in a buffer. 675091d81d1SSam Leffler */ 676091d81d1SSam Leffler 6771ede983cSDag-Erling Smørgrav data = malloc(crd->crd_len, M_CRYPTO_DATA, M_NOWAIT); 678091d81d1SSam Leffler if (data == NULL) 679091d81d1SSam Leffler return (EINVAL); 680f34a967bSPawel Jakub Dawidek crypto_copydata(flags, buf, crd->crd_skip, crd->crd_len, data); 681091d81d1SSam Leffler 682091d81d1SSam Leffler if (crd->crd_flags & CRD_F_COMP) 683091d81d1SSam Leffler result = cxf->compress(data, crd->crd_len, &out); 684091d81d1SSam Leffler else 685091d81d1SSam Leffler result = cxf->decompress(data, crd->crd_len, &out); 686091d81d1SSam Leffler 6871ede983cSDag-Erling Smørgrav free(data, M_CRYPTO_DATA); 688091d81d1SSam Leffler if (result == 0) 689091d81d1SSam Leffler return EINVAL; 690091d81d1SSam Leffler 691091d81d1SSam Leffler /* Copy back the (de)compressed data. m_copyback is 692091d81d1SSam Leffler * extending the mbuf as necessary. 693091d81d1SSam Leffler */ 694091d81d1SSam Leffler sw->sw_size = result; 695091d81d1SSam Leffler /* Check the compressed size when doing compression */ 696091d81d1SSam Leffler if (crd->crd_flags & CRD_F_COMP) { 697df4dece1SBjoern A. Zeeb if (result >= crd->crd_len) { 698091d81d1SSam Leffler /* Compression was useless, we lost time */ 6991ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 700091d81d1SSam Leffler return 0; 701091d81d1SSam Leffler } 702091d81d1SSam Leffler } 703091d81d1SSam Leffler 704f34a967bSPawel Jakub Dawidek crypto_copyback(flags, buf, crd->crd_skip, result, out); 705091d81d1SSam Leffler if (result < crd->crd_len) { 706091d81d1SSam Leffler adj = result - crd->crd_len; 707f34a967bSPawel Jakub Dawidek if (flags & CRYPTO_F_IMBUF) { 708091d81d1SSam Leffler adj = result - crd->crd_len; 709091d81d1SSam Leffler m_adj((struct mbuf *)buf, adj); 710f34a967bSPawel Jakub Dawidek } else if (flags & CRYPTO_F_IOV) { 711091d81d1SSam Leffler struct uio *uio = (struct uio *)buf; 712091d81d1SSam Leffler int ind; 713091d81d1SSam Leffler 714091d81d1SSam Leffler adj = crd->crd_len - result; 715091d81d1SSam Leffler ind = uio->uio_iovcnt - 1; 716091d81d1SSam Leffler 717091d81d1SSam Leffler while (adj > 0 && ind >= 0) { 718091d81d1SSam Leffler if (adj < uio->uio_iov[ind].iov_len) { 719091d81d1SSam Leffler uio->uio_iov[ind].iov_len -= adj; 720091d81d1SSam Leffler break; 721091d81d1SSam Leffler } 722091d81d1SSam Leffler 723091d81d1SSam Leffler adj -= uio->uio_iov[ind].iov_len; 724091d81d1SSam Leffler uio->uio_iov[ind].iov_len = 0; 725091d81d1SSam Leffler ind--; 726091d81d1SSam Leffler uio->uio_iovcnt--; 727091d81d1SSam Leffler } 728091d81d1SSam Leffler } 729091d81d1SSam Leffler } 7301ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 731091d81d1SSam Leffler return 0; 732091d81d1SSam Leffler } 733091d81d1SSam Leffler 734091d81d1SSam Leffler /* 735091d81d1SSam Leffler * Generate a new software session. 736091d81d1SSam Leffler */ 737091d81d1SSam Leffler static int 738*1b0909d5SConrad Meyer swcr_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) 739091d81d1SSam Leffler { 740*1b0909d5SConrad Meyer struct swcr_data **swd, *ses; 741091d81d1SSam Leffler struct auth_hash *axf; 742091d81d1SSam Leffler struct enc_xform *txf; 743091d81d1SSam Leffler struct comp_algo *cxf; 744a2bc81bfSJohn-Mark Gurney int len; 745f6c4bc3bSPawel Jakub Dawidek int error; 746091d81d1SSam Leffler 747*1b0909d5SConrad Meyer if (cses == NULL || cri == NULL) 748091d81d1SSam Leffler return EINVAL; 749091d81d1SSam Leffler 750*1b0909d5SConrad Meyer ses = crypto_get_driver_session(cses); 751*1b0909d5SConrad Meyer swd = &ses; 752091d81d1SSam Leffler 753091d81d1SSam Leffler while (cri) { 754*1b0909d5SConrad Meyer if (*swd == NULL) 7551ede983cSDag-Erling Smørgrav *swd = malloc(sizeof(struct swcr_data), 756*1b0909d5SConrad Meyer M_CRYPTO_DATA, M_WAITOK | M_ZERO); 757091d81d1SSam Leffler if (*swd == NULL) { 758*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 759091d81d1SSam Leffler return ENOBUFS; 760091d81d1SSam Leffler } 761091d81d1SSam Leffler 762091d81d1SSam Leffler switch (cri->cri_alg) { 763091d81d1SSam Leffler case CRYPTO_DES_CBC: 764091d81d1SSam Leffler txf = &enc_xform_des; 765091d81d1SSam Leffler goto enccommon; 766091d81d1SSam Leffler case CRYPTO_3DES_CBC: 767091d81d1SSam Leffler txf = &enc_xform_3des; 768091d81d1SSam Leffler goto enccommon; 769091d81d1SSam Leffler case CRYPTO_BLF_CBC: 770091d81d1SSam Leffler txf = &enc_xform_blf; 771091d81d1SSam Leffler goto enccommon; 772091d81d1SSam Leffler case CRYPTO_CAST_CBC: 773091d81d1SSam Leffler txf = &enc_xform_cast5; 774091d81d1SSam Leffler goto enccommon; 775091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 776091d81d1SSam Leffler txf = &enc_xform_skipjack; 777091d81d1SSam Leffler goto enccommon; 778091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 779091d81d1SSam Leffler txf = &enc_xform_rijndael128; 780091d81d1SSam Leffler goto enccommon; 781d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 782d295bdeeSPawel Jakub Dawidek txf = &enc_xform_aes_xts; 783d295bdeeSPawel Jakub Dawidek goto enccommon; 78408fca7a5SJohn-Mark Gurney case CRYPTO_AES_ICM: 78508fca7a5SJohn-Mark Gurney txf = &enc_xform_aes_icm; 78608fca7a5SJohn-Mark Gurney goto enccommon; 78708fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 78808fca7a5SJohn-Mark Gurney txf = &enc_xform_aes_nist_gcm; 78908fca7a5SJohn-Mark Gurney goto enccommon; 79008fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 79108fca7a5SJohn-Mark Gurney txf = &enc_xform_aes_nist_gmac; 79208fca7a5SJohn-Mark Gurney (*swd)->sw_exf = txf; 79308fca7a5SJohn-Mark Gurney break; 794559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 795559d3390SGeorge V. Neville-Neil txf = &enc_xform_camellia; 796559d3390SGeorge V. Neville-Neil goto enccommon; 797091d81d1SSam Leffler case CRYPTO_NULL_CBC: 798091d81d1SSam Leffler txf = &enc_xform_null; 799091d81d1SSam Leffler goto enccommon; 80061590291SConrad Meyer case CRYPTO_CHACHA20: 80161590291SConrad Meyer txf = &enc_xform_chacha20; 80261590291SConrad Meyer goto enccommon; 803091d81d1SSam Leffler enccommon: 804f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 805091d81d1SSam Leffler error = txf->setkey(&((*swd)->sw_kschedule), 806091d81d1SSam Leffler cri->cri_key, cri->cri_klen / 8); 807091d81d1SSam Leffler if (error) { 808*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 809091d81d1SSam Leffler return error; 810091d81d1SSam Leffler } 811f6c4bc3bSPawel Jakub Dawidek } 812091d81d1SSam Leffler (*swd)->sw_exf = txf; 813091d81d1SSam Leffler break; 814091d81d1SSam Leffler 815091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 816f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_md5; 817091d81d1SSam Leffler goto authcommon; 818091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 819f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_sha1; 820091d81d1SSam Leffler goto authcommon; 821c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 822c97f39ceSConrad Meyer axf = &auth_hash_hmac_sha2_224; 823c97f39ceSConrad Meyer goto authcommon; 824f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 825091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_256; 826f6c4bc3bSPawel Jakub Dawidek goto authcommon; 827f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 828091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_384; 829f6c4bc3bSPawel Jakub Dawidek goto authcommon; 830f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 831091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_512; 832091d81d1SSam Leffler goto authcommon; 833091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 834091d81d1SSam Leffler axf = &auth_hash_null; 835091d81d1SSam Leffler goto authcommon; 836091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 837f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_ripemd_160; 838091d81d1SSam Leffler authcommon: 839091d81d1SSam Leffler (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 840091d81d1SSam Leffler M_NOWAIT); 841091d81d1SSam Leffler if ((*swd)->sw_ictx == NULL) { 842*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 843091d81d1SSam Leffler return ENOBUFS; 844091d81d1SSam Leffler } 845091d81d1SSam Leffler 846091d81d1SSam Leffler (*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, 847091d81d1SSam Leffler M_NOWAIT); 848091d81d1SSam Leffler if ((*swd)->sw_octx == NULL) { 849*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 850091d81d1SSam Leffler return ENOBUFS; 851091d81d1SSam Leffler } 852091d81d1SSam Leffler 853f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 854f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(axf, *swd, cri->cri_key, 855f6c4bc3bSPawel Jakub Dawidek cri->cri_klen); 856f6c4bc3bSPawel Jakub Dawidek } 857091d81d1SSam Leffler 858f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_mlen = cri->cri_mlen; 859091d81d1SSam Leffler (*swd)->sw_axf = axf; 860091d81d1SSam Leffler break; 861091d81d1SSam Leffler 862091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 863091d81d1SSam Leffler axf = &auth_hash_key_md5; 864091d81d1SSam Leffler goto auth2common; 865091d81d1SSam Leffler 866091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 867091d81d1SSam Leffler axf = &auth_hash_key_sha1; 868091d81d1SSam Leffler auth2common: 869091d81d1SSam Leffler (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 870091d81d1SSam Leffler M_NOWAIT); 871091d81d1SSam Leffler if ((*swd)->sw_ictx == NULL) { 872*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 873091d81d1SSam Leffler return ENOBUFS; 874091d81d1SSam Leffler } 875091d81d1SSam Leffler 876f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_octx = malloc(cri->cri_klen / 8, 877f6c4bc3bSPawel Jakub Dawidek M_CRYPTO_DATA, M_NOWAIT); 878091d81d1SSam Leffler if ((*swd)->sw_octx == NULL) { 879*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 880091d81d1SSam Leffler return ENOBUFS; 881091d81d1SSam Leffler } 882091d81d1SSam Leffler 883f6c4bc3bSPawel Jakub Dawidek /* Store the key so we can "append" it to the payload */ 884f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 885f6c4bc3bSPawel Jakub Dawidek swcr_authprepare(axf, *swd, cri->cri_key, 886f6c4bc3bSPawel Jakub Dawidek cri->cri_klen); 887f6c4bc3bSPawel Jakub Dawidek } 888f6c4bc3bSPawel Jakub Dawidek 889f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_mlen = cri->cri_mlen; 890091d81d1SSam Leffler (*swd)->sw_axf = axf; 891091d81d1SSam Leffler break; 892091d81d1SSam Leffler #ifdef notdef 893091d81d1SSam Leffler case CRYPTO_MD5: 894091d81d1SSam Leffler axf = &auth_hash_md5; 895091d81d1SSam Leffler goto auth3common; 896c4729f6eSConrad Meyer #endif 897091d81d1SSam Leffler 898091d81d1SSam Leffler case CRYPTO_SHA1: 899091d81d1SSam Leffler axf = &auth_hash_sha1; 900c4729f6eSConrad Meyer goto auth3common; 901c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 902c4729f6eSConrad Meyer axf = &auth_hash_sha2_224; 903c4729f6eSConrad Meyer goto auth3common; 904c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 905c4729f6eSConrad Meyer axf = &auth_hash_sha2_256; 906c4729f6eSConrad Meyer goto auth3common; 907c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 908c4729f6eSConrad Meyer axf = &auth_hash_sha2_384; 909c4729f6eSConrad Meyer goto auth3common; 910c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 911c4729f6eSConrad Meyer axf = &auth_hash_sha2_512; 912c4729f6eSConrad Meyer 913091d81d1SSam Leffler auth3common: 914091d81d1SSam Leffler (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 915091d81d1SSam Leffler M_NOWAIT); 916091d81d1SSam Leffler if ((*swd)->sw_ictx == NULL) { 917*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 918091d81d1SSam Leffler return ENOBUFS; 919091d81d1SSam Leffler } 920091d81d1SSam Leffler 921091d81d1SSam Leffler axf->Init((*swd)->sw_ictx); 922f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_mlen = cri->cri_mlen; 923091d81d1SSam Leffler (*swd)->sw_axf = axf; 924091d81d1SSam Leffler break; 92508fca7a5SJohn-Mark Gurney 92608fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 92708fca7a5SJohn-Mark Gurney axf = &auth_hash_nist_gmac_aes_128; 92808fca7a5SJohn-Mark Gurney goto auth4common; 92908fca7a5SJohn-Mark Gurney 93008fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 93108fca7a5SJohn-Mark Gurney axf = &auth_hash_nist_gmac_aes_192; 93208fca7a5SJohn-Mark Gurney goto auth4common; 93308fca7a5SJohn-Mark Gurney 93408fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 93508fca7a5SJohn-Mark Gurney axf = &auth_hash_nist_gmac_aes_256; 93608fca7a5SJohn-Mark Gurney auth4common: 937a2bc81bfSJohn-Mark Gurney len = cri->cri_klen / 8; 9382e2e26d1SJohn Baldwin if (len != 16 && len != 24 && len != 32) { 939*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 940a2bc81bfSJohn-Mark Gurney return EINVAL; 9412e2e26d1SJohn Baldwin } 942a2bc81bfSJohn-Mark Gurney 94308fca7a5SJohn-Mark Gurney (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 94408fca7a5SJohn-Mark Gurney M_NOWAIT); 94508fca7a5SJohn-Mark Gurney if ((*swd)->sw_ictx == NULL) { 946*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 94708fca7a5SJohn-Mark Gurney return ENOBUFS; 94808fca7a5SJohn-Mark Gurney } 94908fca7a5SJohn-Mark Gurney axf->Init((*swd)->sw_ictx); 950a2bc81bfSJohn-Mark Gurney axf->Setkey((*swd)->sw_ictx, cri->cri_key, len); 95108fca7a5SJohn-Mark Gurney (*swd)->sw_axf = axf; 95208fca7a5SJohn-Mark Gurney break; 95308fca7a5SJohn-Mark Gurney 9540e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 9550e33efe4SConrad Meyer axf = &auth_hash_blake2b; 9560e33efe4SConrad Meyer goto auth5common; 9570e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 9580e33efe4SConrad Meyer axf = &auth_hash_blake2s; 9590e33efe4SConrad Meyer auth5common: 9600e33efe4SConrad Meyer (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 9610e33efe4SConrad Meyer M_NOWAIT); 9620e33efe4SConrad Meyer if ((*swd)->sw_ictx == NULL) { 963*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 9640e33efe4SConrad Meyer return ENOBUFS; 9650e33efe4SConrad Meyer } 9660e33efe4SConrad Meyer axf->Setkey((*swd)->sw_ictx, cri->cri_key, 9670e33efe4SConrad Meyer cri->cri_klen / 8); 9680e33efe4SConrad Meyer axf->Init((*swd)->sw_ictx); 9690e33efe4SConrad Meyer (*swd)->sw_axf = axf; 9700e33efe4SConrad Meyer break; 9710e33efe4SConrad Meyer 972091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 973091d81d1SSam Leffler cxf = &comp_algo_deflate; 974091d81d1SSam Leffler (*swd)->sw_cxf = cxf; 975091d81d1SSam Leffler break; 976091d81d1SSam Leffler default: 977*1b0909d5SConrad Meyer swcr_freesession(dev, cses); 978091d81d1SSam Leffler return EINVAL; 979091d81d1SSam Leffler } 980091d81d1SSam Leffler 981091d81d1SSam Leffler (*swd)->sw_alg = cri->cri_alg; 982091d81d1SSam Leffler cri = cri->cri_next; 983091d81d1SSam Leffler swd = &((*swd)->sw_next); 984091d81d1SSam Leffler } 985091d81d1SSam Leffler return 0; 986091d81d1SSam Leffler } 987091d81d1SSam Leffler 988*1b0909d5SConrad Meyer static void 989*1b0909d5SConrad Meyer swcr_freesession(device_t dev, crypto_session_t cses) 990109919c6SBenno Rice { 991*1b0909d5SConrad Meyer struct swcr_data *ses, *swd, *next; 992091d81d1SSam Leffler struct enc_xform *txf; 993091d81d1SSam Leffler struct auth_hash *axf; 994091d81d1SSam Leffler 995*1b0909d5SConrad Meyer ses = crypto_get_driver_session(cses); 996091d81d1SSam Leffler 997*1b0909d5SConrad Meyer for (swd = ses; swd != NULL; swd = next) { 998*1b0909d5SConrad Meyer next = swd->sw_next; 999091d81d1SSam Leffler 1000091d81d1SSam Leffler switch (swd->sw_alg) { 1001091d81d1SSam Leffler case CRYPTO_DES_CBC: 1002091d81d1SSam Leffler case CRYPTO_3DES_CBC: 1003091d81d1SSam Leffler case CRYPTO_BLF_CBC: 1004091d81d1SSam Leffler case CRYPTO_CAST_CBC: 1005091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 1006091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 1007d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 100808fca7a5SJohn-Mark Gurney case CRYPTO_AES_ICM: 100908fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 101008fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 1011559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 1012091d81d1SSam Leffler case CRYPTO_NULL_CBC: 101361590291SConrad Meyer case CRYPTO_CHACHA20: 1014091d81d1SSam Leffler txf = swd->sw_exf; 1015091d81d1SSam Leffler 1016091d81d1SSam Leffler if (swd->sw_kschedule) 1017091d81d1SSam Leffler txf->zerokey(&(swd->sw_kschedule)); 1018091d81d1SSam Leffler break; 1019091d81d1SSam Leffler 1020091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 1021091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1022c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1023f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1024f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1025f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1026091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 1027091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1028091d81d1SSam Leffler axf = swd->sw_axf; 1029091d81d1SSam Leffler 1030091d81d1SSam Leffler if (swd->sw_ictx) { 1031091d81d1SSam Leffler bzero(swd->sw_ictx, axf->ctxsize); 1032091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 1033091d81d1SSam Leffler } 1034091d81d1SSam Leffler if (swd->sw_octx) { 1035091d81d1SSam Leffler bzero(swd->sw_octx, axf->ctxsize); 1036091d81d1SSam Leffler free(swd->sw_octx, M_CRYPTO_DATA); 1037091d81d1SSam Leffler } 1038091d81d1SSam Leffler break; 1039091d81d1SSam Leffler 1040091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 1041091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 1042091d81d1SSam Leffler axf = swd->sw_axf; 1043091d81d1SSam Leffler 1044091d81d1SSam Leffler if (swd->sw_ictx) { 1045091d81d1SSam Leffler bzero(swd->sw_ictx, axf->ctxsize); 1046091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 1047091d81d1SSam Leffler } 1048091d81d1SSam Leffler if (swd->sw_octx) { 1049091d81d1SSam Leffler bzero(swd->sw_octx, swd->sw_klen); 1050091d81d1SSam Leffler free(swd->sw_octx, M_CRYPTO_DATA); 1051091d81d1SSam Leffler } 1052091d81d1SSam Leffler break; 1053091d81d1SSam Leffler 10540e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 10550e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 1056091d81d1SSam Leffler case CRYPTO_MD5: 1057091d81d1SSam Leffler case CRYPTO_SHA1: 1058c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 1059c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 1060c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 1061c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 1062091d81d1SSam Leffler axf = swd->sw_axf; 1063091d81d1SSam Leffler 10645fbc5b5aSConrad Meyer if (swd->sw_ictx) { 10655fbc5b5aSConrad Meyer explicit_bzero(swd->sw_ictx, axf->ctxsize); 1066091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 10675fbc5b5aSConrad Meyer } 1068091d81d1SSam Leffler break; 1069091d81d1SSam Leffler 1070091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 1071151ba793SAlexander Kabaev /* Nothing to do */ 1072091d81d1SSam Leffler break; 1073091d81d1SSam Leffler } 1074091d81d1SSam Leffler 1075*1b0909d5SConrad Meyer /* OCF owns and frees the primary session object */ 1076*1b0909d5SConrad Meyer if (swd != ses) 10771ede983cSDag-Erling Smørgrav free(swd, M_CRYPTO_DATA); 1078091d81d1SSam Leffler } 1079091d81d1SSam Leffler } 1080091d81d1SSam Leffler 1081091d81d1SSam Leffler /* 1082091d81d1SSam Leffler * Process a software request. 1083091d81d1SSam Leffler */ 1084091d81d1SSam Leffler static int 10856810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint) 1086091d81d1SSam Leffler { 1087091d81d1SSam Leffler struct cryptodesc *crd; 1088*1b0909d5SConrad Meyer struct swcr_data *sw, *ses; 1089091d81d1SSam Leffler 1090091d81d1SSam Leffler /* Sanity check */ 1091091d81d1SSam Leffler if (crp == NULL) 1092091d81d1SSam Leffler return EINVAL; 1093091d81d1SSam Leffler 1094091d81d1SSam Leffler if (crp->crp_desc == NULL || crp->crp_buf == NULL) { 1095091d81d1SSam Leffler crp->crp_etype = EINVAL; 1096091d81d1SSam Leffler goto done; 1097091d81d1SSam Leffler } 1098091d81d1SSam Leffler 1099*1b0909d5SConrad Meyer ses = crypto_get_driver_session(crp->crp_session); 1100091d81d1SSam Leffler 1101091d81d1SSam Leffler /* Go through crypto descriptors, processing as we go */ 1102091d81d1SSam Leffler for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 1103091d81d1SSam Leffler /* 1104091d81d1SSam Leffler * Find the crypto context. 1105091d81d1SSam Leffler * 1106091d81d1SSam Leffler * XXX Note that the logic here prevents us from having 1107091d81d1SSam Leffler * XXX the same algorithm multiple times in a session 1108091d81d1SSam Leffler * XXX (or rather, we can but it won't give us the right 1109091d81d1SSam Leffler * XXX results). To do that, we'd need some way of differentiating 1110091d81d1SSam Leffler * XXX between the various instances of an algorithm (so we can 1111091d81d1SSam Leffler * XXX locate the correct crypto context). 1112091d81d1SSam Leffler */ 1113*1b0909d5SConrad Meyer for (sw = ses; sw && sw->sw_alg != crd->crd_alg; 1114091d81d1SSam Leffler sw = sw->sw_next) 1115091d81d1SSam Leffler ; 1116091d81d1SSam Leffler 1117091d81d1SSam Leffler /* No such context ? */ 1118091d81d1SSam Leffler if (sw == NULL) { 1119091d81d1SSam Leffler crp->crp_etype = EINVAL; 1120091d81d1SSam Leffler goto done; 1121091d81d1SSam Leffler } 1122091d81d1SSam Leffler switch (sw->sw_alg) { 1123091d81d1SSam Leffler case CRYPTO_DES_CBC: 1124091d81d1SSam Leffler case CRYPTO_3DES_CBC: 1125091d81d1SSam Leffler case CRYPTO_BLF_CBC: 1126091d81d1SSam Leffler case CRYPTO_CAST_CBC: 1127091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 1128091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 1129d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 113008fca7a5SJohn-Mark Gurney case CRYPTO_AES_ICM: 1131559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 113261590291SConrad Meyer case CRYPTO_CHACHA20: 1133091d81d1SSam Leffler if ((crp->crp_etype = swcr_encdec(crd, sw, 1134f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1135091d81d1SSam Leffler goto done; 1136091d81d1SSam Leffler break; 1137091d81d1SSam Leffler case CRYPTO_NULL_CBC: 1138091d81d1SSam Leffler crp->crp_etype = 0; 1139091d81d1SSam Leffler break; 1140091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 1141091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1142c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1143f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1144f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1145f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1146091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 1147091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1148091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 1149091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 1150091d81d1SSam Leffler case CRYPTO_MD5: 1151091d81d1SSam Leffler case CRYPTO_SHA1: 1152c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 1153c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 1154c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 1155c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 11560e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 11570e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 115838d2f8d6SPawel Jakub Dawidek if ((crp->crp_etype = swcr_authcompute(crd, sw, 1159f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1160091d81d1SSam Leffler goto done; 1161091d81d1SSam Leffler break; 1162091d81d1SSam Leffler 116308fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 116408fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 116508fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 116608fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 116708fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 116808fca7a5SJohn-Mark Gurney crp->crp_etype = swcr_authenc(crp); 116908fca7a5SJohn-Mark Gurney goto done; 117008fca7a5SJohn-Mark Gurney 1171091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 1172091d81d1SSam Leffler if ((crp->crp_etype = swcr_compdec(crd, sw, 1173f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1174091d81d1SSam Leffler goto done; 1175091d81d1SSam Leffler else 1176091d81d1SSam Leffler crp->crp_olen = (int)sw->sw_size; 1177091d81d1SSam Leffler break; 1178091d81d1SSam Leffler 1179091d81d1SSam Leffler default: 1180091d81d1SSam Leffler /* Unknown/unsupported algorithm */ 1181091d81d1SSam Leffler crp->crp_etype = EINVAL; 1182091d81d1SSam Leffler goto done; 1183091d81d1SSam Leffler } 1184091d81d1SSam Leffler } 1185091d81d1SSam Leffler 1186091d81d1SSam Leffler done: 1187091d81d1SSam Leffler crypto_done(crp); 1188091d81d1SSam Leffler return 0; 1189091d81d1SSam Leffler } 1190091d81d1SSam Leffler 1191091d81d1SSam Leffler static void 11923f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent) 1193091d81d1SSam Leffler { 11946810ad6fSSam Leffler /* NB: order 10 is so we get attached after h/w devices */ 11956810ad6fSSam Leffler if (device_find_child(parent, "cryptosoft", -1) == NULL && 119686c585d9SMarius Strobl BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0) 11976810ad6fSSam Leffler panic("cryptosoft: could not attach"); 11986810ad6fSSam Leffler } 1199f6c4bc3bSPawel Jakub Dawidek 12006810ad6fSSam Leffler static int 12016810ad6fSSam Leffler swcr_probe(device_t dev) 12026810ad6fSSam Leffler { 12036810ad6fSSam Leffler device_set_desc(dev, "software crypto"); 120486c585d9SMarius Strobl return (BUS_PROBE_NOWILDCARD); 12056810ad6fSSam Leffler } 1206f6c4bc3bSPawel Jakub Dawidek 12076810ad6fSSam Leffler static int 12086810ad6fSSam Leffler swcr_attach(device_t dev) 12096810ad6fSSam Leffler { 12106810ad6fSSam Leffler memset(hmac_ipad_buffer, HMAC_IPAD_VAL, HMAC_MAX_BLOCK_LEN); 12116810ad6fSSam Leffler memset(hmac_opad_buffer, HMAC_OPAD_VAL, HMAC_MAX_BLOCK_LEN); 12126810ad6fSSam Leffler 1213*1b0909d5SConrad Meyer swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_data), 12146810ad6fSSam Leffler CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); 12156810ad6fSSam Leffler if (swcr_id < 0) { 12166810ad6fSSam Leffler device_printf(dev, "cannot initialize!"); 12176810ad6fSSam Leffler return ENOMEM; 12186810ad6fSSam Leffler } 1219091d81d1SSam Leffler #define REGISTER(alg) \ 12206810ad6fSSam Leffler crypto_register(swcr_id, alg, 0,0) 12216810ad6fSSam Leffler REGISTER(CRYPTO_DES_CBC); 1222091d81d1SSam Leffler REGISTER(CRYPTO_3DES_CBC); 1223091d81d1SSam Leffler REGISTER(CRYPTO_BLF_CBC); 1224091d81d1SSam Leffler REGISTER(CRYPTO_CAST_CBC); 1225091d81d1SSam Leffler REGISTER(CRYPTO_SKIPJACK_CBC); 1226091d81d1SSam Leffler REGISTER(CRYPTO_NULL_CBC); 1227091d81d1SSam Leffler REGISTER(CRYPTO_MD5_HMAC); 1228091d81d1SSam Leffler REGISTER(CRYPTO_SHA1_HMAC); 1229c97f39ceSConrad Meyer REGISTER(CRYPTO_SHA2_224_HMAC); 1230f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_256_HMAC); 1231f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_384_HMAC); 1232f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_512_HMAC); 1233091d81d1SSam Leffler REGISTER(CRYPTO_RIPEMD160_HMAC); 1234091d81d1SSam Leffler REGISTER(CRYPTO_NULL_HMAC); 1235091d81d1SSam Leffler REGISTER(CRYPTO_MD5_KPDK); 1236091d81d1SSam Leffler REGISTER(CRYPTO_SHA1_KPDK); 1237091d81d1SSam Leffler REGISTER(CRYPTO_MD5); 1238091d81d1SSam Leffler REGISTER(CRYPTO_SHA1); 1239c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_224); 1240c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_256); 1241c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_384); 1242c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_512); 1243091d81d1SSam Leffler REGISTER(CRYPTO_RIJNDAEL128_CBC); 1244d295bdeeSPawel Jakub Dawidek REGISTER(CRYPTO_AES_XTS); 124508fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_ICM); 124608fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_NIST_GCM_16); 124708fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_NIST_GMAC); 124808fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_128_NIST_GMAC); 124908fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_192_NIST_GMAC); 125008fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_256_NIST_GMAC); 1251559d3390SGeorge V. Neville-Neil REGISTER(CRYPTO_CAMELLIA_CBC); 1252091d81d1SSam Leffler REGISTER(CRYPTO_DEFLATE_COMP); 12530e33efe4SConrad Meyer REGISTER(CRYPTO_BLAKE2B); 12540e33efe4SConrad Meyer REGISTER(CRYPTO_BLAKE2S); 125561590291SConrad Meyer REGISTER(CRYPTO_CHACHA20); 1256091d81d1SSam Leffler #undef REGISTER 12576810ad6fSSam Leffler 12586810ad6fSSam Leffler return 0; 1259091d81d1SSam Leffler } 12604b465da2SPawel Jakub Dawidek 12613f147ab2SWarner Losh static int 12626810ad6fSSam Leffler swcr_detach(device_t dev) 12634b465da2SPawel Jakub Dawidek { 12646810ad6fSSam Leffler crypto_unregister_all(swcr_id); 12653f147ab2SWarner Losh return 0; 12664b465da2SPawel Jakub Dawidek } 12676810ad6fSSam Leffler 12686810ad6fSSam Leffler static device_method_t swcr_methods[] = { 12696810ad6fSSam Leffler DEVMETHOD(device_identify, swcr_identify), 12706810ad6fSSam Leffler DEVMETHOD(device_probe, swcr_probe), 12716810ad6fSSam Leffler DEVMETHOD(device_attach, swcr_attach), 12726810ad6fSSam Leffler DEVMETHOD(device_detach, swcr_detach), 12736810ad6fSSam Leffler 12746810ad6fSSam Leffler DEVMETHOD(cryptodev_newsession, swcr_newsession), 12756810ad6fSSam Leffler DEVMETHOD(cryptodev_freesession,swcr_freesession), 12766810ad6fSSam Leffler DEVMETHOD(cryptodev_process, swcr_process), 12776810ad6fSSam Leffler 12786810ad6fSSam Leffler {0, 0}, 12796810ad6fSSam Leffler }; 12806810ad6fSSam Leffler 12816810ad6fSSam Leffler static driver_t swcr_driver = { 12826810ad6fSSam Leffler "cryptosoft", 12836810ad6fSSam Leffler swcr_methods, 12846810ad6fSSam Leffler 0, /* NB: no softc */ 12856810ad6fSSam Leffler }; 12866810ad6fSSam Leffler static devclass_t swcr_devclass; 12876810ad6fSSam Leffler 12886810ad6fSSam Leffler /* 12896810ad6fSSam Leffler * NB: We explicitly reference the crypto module so we 12906810ad6fSSam Leffler * get the necessary ordering when built as a loadable 12916810ad6fSSam Leffler * module. This is required because we bundle the crypto 12926810ad6fSSam Leffler * module code together with the cryptosoft driver (otherwise 12936810ad6fSSam Leffler * normal module dependencies would handle things). 12946810ad6fSSam Leffler */ 12956810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *); 12966810ad6fSSam Leffler /* XXX where to attach */ 12976810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0); 12986810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1); 12996810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1); 1300