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); 731b0909d5SConrad 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 32425b7033bSConrad Meyer static int __result_use_check 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 } 38025b7033bSConrad Meyer case CRYPTO_POLY1305: 38125b7033bSConrad Meyer if (klen != POLY1305_KEY_LEN) { 38225b7033bSConrad Meyer CRYPTDEB("bad poly1305 key size %d", klen); 38325b7033bSConrad Meyer return EINVAL; 38425b7033bSConrad Meyer } 38525b7033bSConrad Meyer /* FALLTHROUGH */ 3860e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 3870e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 3880e33efe4SConrad Meyer axf->Setkey(sw->sw_ictx, key, klen); 3890e33efe4SConrad Meyer axf->Init(sw->sw_ictx); 3900e33efe4SConrad Meyer break; 391f6c4bc3bSPawel Jakub Dawidek default: 392f6c4bc3bSPawel Jakub Dawidek printf("%s: CRD_F_KEY_EXPLICIT flag given, but algorithm %d " 393f6c4bc3bSPawel Jakub Dawidek "doesn't use keys.\n", __func__, axf->type); 39425b7033bSConrad Meyer return EINVAL; 395f6c4bc3bSPawel Jakub Dawidek } 39625b7033bSConrad Meyer return 0; 397f6c4bc3bSPawel Jakub Dawidek } 398f6c4bc3bSPawel Jakub Dawidek 399091d81d1SSam Leffler /* 400091d81d1SSam Leffler * Compute keyed-hash authenticator. 401091d81d1SSam Leffler */ 402091d81d1SSam Leffler static int 40338d2f8d6SPawel Jakub Dawidek swcr_authcompute(struct cryptodesc *crd, struct swcr_data *sw, caddr_t buf, 404f34a967bSPawel Jakub Dawidek int flags) 405091d81d1SSam Leffler { 4060bbc4bf9SPawel Jakub Dawidek unsigned char aalg[HASH_MAX_LEN]; 407091d81d1SSam Leffler struct auth_hash *axf; 408091d81d1SSam Leffler union authctx ctx; 409091d81d1SSam Leffler int err; 410091d81d1SSam Leffler 411091d81d1SSam Leffler if (sw->sw_ictx == 0) 412091d81d1SSam Leffler return EINVAL; 413091d81d1SSam Leffler 414091d81d1SSam Leffler axf = sw->sw_axf; 415091d81d1SSam Leffler 41625b7033bSConrad Meyer if (crd->crd_flags & CRD_F_KEY_EXPLICIT) { 41725b7033bSConrad Meyer err = swcr_authprepare(axf, sw, crd->crd_key, crd->crd_klen); 41825b7033bSConrad Meyer if (err != 0) 41925b7033bSConrad Meyer return err; 42025b7033bSConrad Meyer } 421f6c4bc3bSPawel Jakub Dawidek 422091d81d1SSam Leffler bcopy(sw->sw_ictx, &ctx, axf->ctxsize); 423091d81d1SSam Leffler 424f34a967bSPawel Jakub Dawidek err = crypto_apply(flags, buf, crd->crd_skip, crd->crd_len, 425f34a967bSPawel Jakub Dawidek (int (*)(void *, void *, unsigned int))axf->Update, (caddr_t)&ctx); 426091d81d1SSam Leffler if (err) 427091d81d1SSam Leffler return err; 428091d81d1SSam Leffler 429091d81d1SSam Leffler switch (sw->sw_alg) { 430c4729f6eSConrad Meyer case CRYPTO_SHA1: 431c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 432c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 433c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 434c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 435c4729f6eSConrad Meyer axf->Final(aalg, &ctx); 436c4729f6eSConrad Meyer break; 437c4729f6eSConrad Meyer 438091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 439091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 440c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 441f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 442f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 443f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 444091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 445091d81d1SSam Leffler if (sw->sw_octx == NULL) 446091d81d1SSam Leffler return EINVAL; 447091d81d1SSam Leffler 448091d81d1SSam Leffler axf->Final(aalg, &ctx); 449091d81d1SSam Leffler bcopy(sw->sw_octx, &ctx, axf->ctxsize); 450091d81d1SSam Leffler axf->Update(&ctx, aalg, axf->hashsize); 451091d81d1SSam Leffler axf->Final(aalg, &ctx); 452091d81d1SSam Leffler break; 453091d81d1SSam Leffler 454091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 455091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 45677680d96SBjoern A. Zeeb /* If we have no key saved, return error. */ 457091d81d1SSam Leffler if (sw->sw_octx == NULL) 458091d81d1SSam Leffler return EINVAL; 459091d81d1SSam Leffler 46077680d96SBjoern A. Zeeb /* 46177680d96SBjoern A. Zeeb * Add the trailing copy of the key (see comment in 46277680d96SBjoern A. Zeeb * swcr_authprepare()) after the data: 46377680d96SBjoern A. Zeeb * ALGO( .., key, algofill ) 46477680d96SBjoern A. Zeeb * and let Final() do the proper, natural "algofill" 46577680d96SBjoern A. Zeeb * padding. 46677680d96SBjoern A. Zeeb */ 467091d81d1SSam Leffler axf->Update(&ctx, sw->sw_octx, sw->sw_klen); 468091d81d1SSam Leffler axf->Final(aalg, &ctx); 469091d81d1SSam Leffler break; 470091d81d1SSam Leffler 4710e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 4720e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 473091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 47425b7033bSConrad Meyer case CRYPTO_POLY1305: 475091d81d1SSam Leffler axf->Final(aalg, &ctx); 476091d81d1SSam Leffler break; 477091d81d1SSam Leffler } 478091d81d1SSam Leffler 479091d81d1SSam Leffler /* Inject the authentication data */ 480f34a967bSPawel Jakub Dawidek crypto_copyback(flags, buf, crd->crd_inject, 481f6c4bc3bSPawel Jakub Dawidek sw->sw_mlen == 0 ? axf->hashsize : sw->sw_mlen, aalg); 482091d81d1SSam Leffler return 0; 483091d81d1SSam Leffler } 484091d81d1SSam Leffler 48508fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (1ll<<39) - 256); /* GCM: plain text < 2^39-256 */ 48608fca7a5SJohn-Mark Gurney CTASSERT(INT_MAX <= (uint64_t)-1); /* GCM: associated data <= 2^64-1 */ 48708fca7a5SJohn-Mark Gurney 48808fca7a5SJohn-Mark Gurney /* 48908fca7a5SJohn-Mark Gurney * Apply a combined encryption-authentication transformation 49008fca7a5SJohn-Mark Gurney */ 49108fca7a5SJohn-Mark Gurney static int 49208fca7a5SJohn-Mark Gurney swcr_authenc(struct cryptop *crp) 49308fca7a5SJohn-Mark Gurney { 49408fca7a5SJohn-Mark Gurney uint32_t blkbuf[howmany(EALG_MAX_BLOCK_LEN, sizeof(uint32_t))]; 49508fca7a5SJohn-Mark Gurney u_char *blk = (u_char *)blkbuf; 49608fca7a5SJohn-Mark Gurney u_char aalg[AALG_MAX_RESULT_LEN]; 49708fca7a5SJohn-Mark Gurney u_char uaalg[AALG_MAX_RESULT_LEN]; 49808fca7a5SJohn-Mark Gurney u_char iv[EALG_MAX_BLOCK_LEN]; 49908fca7a5SJohn-Mark Gurney union authctx ctx; 50008fca7a5SJohn-Mark Gurney struct cryptodesc *crd, *crda = NULL, *crde = NULL; 50108fca7a5SJohn-Mark Gurney struct swcr_data *sw, *swa, *swe = NULL; 50208fca7a5SJohn-Mark Gurney struct auth_hash *axf = NULL; 50308fca7a5SJohn-Mark Gurney struct enc_xform *exf = NULL; 50408fca7a5SJohn-Mark Gurney caddr_t buf = (caddr_t)crp->crp_buf; 50508fca7a5SJohn-Mark Gurney uint32_t *blkp; 50608fca7a5SJohn-Mark Gurney int aadlen, blksz, i, ivlen, len, iskip, oskip, r; 50708fca7a5SJohn-Mark Gurney 50808fca7a5SJohn-Mark Gurney ivlen = blksz = iskip = oskip = 0; 50908fca7a5SJohn-Mark Gurney 51008fca7a5SJohn-Mark Gurney for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 5111b0909d5SConrad Meyer for (sw = crypto_get_driver_session(crp->crp_session); 51208fca7a5SJohn-Mark Gurney sw && sw->sw_alg != crd->crd_alg; 51308fca7a5SJohn-Mark Gurney sw = sw->sw_next) 51408fca7a5SJohn-Mark Gurney ; 51508fca7a5SJohn-Mark Gurney if (sw == NULL) 51608fca7a5SJohn-Mark Gurney return (EINVAL); 51708fca7a5SJohn-Mark Gurney 51808fca7a5SJohn-Mark Gurney switch (sw->sw_alg) { 51908fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 52008fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 52108fca7a5SJohn-Mark Gurney swe = sw; 52208fca7a5SJohn-Mark Gurney crde = crd; 52308fca7a5SJohn-Mark Gurney exf = swe->sw_exf; 52408fca7a5SJohn-Mark Gurney ivlen = 12; 52508fca7a5SJohn-Mark Gurney break; 52608fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 52708fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 52808fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 52908fca7a5SJohn-Mark Gurney swa = sw; 53008fca7a5SJohn-Mark Gurney crda = crd; 53108fca7a5SJohn-Mark Gurney axf = swa->sw_axf; 53208fca7a5SJohn-Mark Gurney if (swa->sw_ictx == 0) 53308fca7a5SJohn-Mark Gurney return (EINVAL); 53408fca7a5SJohn-Mark Gurney bcopy(swa->sw_ictx, &ctx, axf->ctxsize); 53508fca7a5SJohn-Mark Gurney blksz = axf->blocksize; 53608fca7a5SJohn-Mark Gurney break; 53708fca7a5SJohn-Mark Gurney default: 53808fca7a5SJohn-Mark Gurney return (EINVAL); 53908fca7a5SJohn-Mark Gurney } 54008fca7a5SJohn-Mark Gurney } 54108fca7a5SJohn-Mark Gurney if (crde == NULL || crda == NULL) 54208fca7a5SJohn-Mark Gurney return (EINVAL); 54308fca7a5SJohn-Mark Gurney 54408fca7a5SJohn-Mark Gurney if (crde->crd_alg == CRYPTO_AES_NIST_GCM_16 && 54508fca7a5SJohn-Mark Gurney (crde->crd_flags & CRD_F_IV_EXPLICIT) == 0) 54608fca7a5SJohn-Mark Gurney return (EINVAL); 54708fca7a5SJohn-Mark Gurney 54808fca7a5SJohn-Mark Gurney if (crde->crd_klen != crda->crd_klen) 54908fca7a5SJohn-Mark Gurney return (EINVAL); 55008fca7a5SJohn-Mark Gurney 55108fca7a5SJohn-Mark Gurney /* Initialize the IV */ 55208fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_ENCRYPT) { 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 arc4rand(iv, ivlen, 0); 55808fca7a5SJohn-Mark Gurney 55908fca7a5SJohn-Mark Gurney /* Do we need to write the IV */ 56008fca7a5SJohn-Mark Gurney if (!(crde->crd_flags & CRD_F_IV_PRESENT)) 56108fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, crde->crd_inject, 56208fca7a5SJohn-Mark Gurney ivlen, iv); 56308fca7a5SJohn-Mark Gurney 56408fca7a5SJohn-Mark Gurney } else { /* Decryption */ 56508fca7a5SJohn-Mark Gurney /* IV explicitly provided ? */ 56608fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_IV_EXPLICIT) 56708fca7a5SJohn-Mark Gurney bcopy(crde->crd_iv, iv, ivlen); 56808fca7a5SJohn-Mark Gurney else { 56908fca7a5SJohn-Mark Gurney /* Get IV off buf */ 57008fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crde->crd_inject, 57108fca7a5SJohn-Mark Gurney ivlen, iv); 57208fca7a5SJohn-Mark Gurney } 57308fca7a5SJohn-Mark Gurney } 57408fca7a5SJohn-Mark Gurney 57508fca7a5SJohn-Mark Gurney /* Supply MAC with IV */ 57608fca7a5SJohn-Mark Gurney if (axf->Reinit) 57708fca7a5SJohn-Mark Gurney axf->Reinit(&ctx, iv, ivlen); 57808fca7a5SJohn-Mark Gurney 57908fca7a5SJohn-Mark Gurney /* Supply MAC with AAD */ 58008fca7a5SJohn-Mark Gurney aadlen = crda->crd_len; 58108fca7a5SJohn-Mark Gurney 58208fca7a5SJohn-Mark Gurney for (i = iskip; i < crda->crd_len; i += blksz) { 58308fca7a5SJohn-Mark Gurney len = MIN(crda->crd_len - i, blksz - oskip); 58408fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crda->crd_skip + i, len, 58508fca7a5SJohn-Mark Gurney blk + oskip); 58608fca7a5SJohn-Mark Gurney bzero(blk + len + oskip, blksz - len - oskip); 58708fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, blksz); 58808fca7a5SJohn-Mark Gurney oskip = 0; /* reset initial output offset */ 58908fca7a5SJohn-Mark Gurney } 59008fca7a5SJohn-Mark Gurney 59108fca7a5SJohn-Mark Gurney if (exf->reinit) 59208fca7a5SJohn-Mark Gurney exf->reinit(swe->sw_kschedule, iv); 59308fca7a5SJohn-Mark Gurney 59408fca7a5SJohn-Mark Gurney /* Do encryption/decryption with MAC */ 5952f1f9cceSConrad Meyer for (i = 0; i < crde->crd_len; i += len) { 5962f1f9cceSConrad Meyer if (exf->encrypt_multi != NULL) { 5972f1f9cceSConrad Meyer len = rounddown(crde->crd_len - i, blksz); 5982f1f9cceSConrad Meyer if (len == 0) 5992f1f9cceSConrad Meyer len = blksz; 6002f1f9cceSConrad Meyer else 6012f1f9cceSConrad Meyer len = MIN(len, sizeof(blkbuf)); 6022f1f9cceSConrad Meyer } else 6032f1f9cceSConrad Meyer len = blksz; 6042f1f9cceSConrad Meyer len = MIN(crde->crd_len - i, len); 60508fca7a5SJohn-Mark Gurney if (len < blksz) 60608fca7a5SJohn-Mark Gurney bzero(blk, blksz); 60708fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crde->crd_skip + i, len, 60808fca7a5SJohn-Mark Gurney blk); 60908fca7a5SJohn-Mark Gurney if (crde->crd_flags & CRD_F_ENCRYPT) { 6102f1f9cceSConrad Meyer if (exf->encrypt_multi != NULL) 6112f1f9cceSConrad Meyer exf->encrypt_multi(swe->sw_kschedule, blk, 6122f1f9cceSConrad Meyer len); 6132f1f9cceSConrad Meyer else 61408fca7a5SJohn-Mark Gurney exf->encrypt(swe->sw_kschedule, blk); 61508fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, len); 61608fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, 61708fca7a5SJohn-Mark Gurney crde->crd_skip + i, len, blk); 61808fca7a5SJohn-Mark Gurney } else { 61908fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, len); 62008fca7a5SJohn-Mark Gurney } 62108fca7a5SJohn-Mark Gurney } 62208fca7a5SJohn-Mark Gurney 62308fca7a5SJohn-Mark Gurney /* Do any required special finalization */ 62408fca7a5SJohn-Mark Gurney switch (crda->crd_alg) { 62508fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 62608fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 62708fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 62808fca7a5SJohn-Mark Gurney /* length block */ 62908fca7a5SJohn-Mark Gurney bzero(blk, blksz); 63008fca7a5SJohn-Mark Gurney blkp = (uint32_t *)blk + 1; 63108fca7a5SJohn-Mark Gurney *blkp = htobe32(aadlen * 8); 63208fca7a5SJohn-Mark Gurney blkp = (uint32_t *)blk + 3; 63308fca7a5SJohn-Mark Gurney *blkp = htobe32(crde->crd_len * 8); 63408fca7a5SJohn-Mark Gurney axf->Update(&ctx, blk, blksz); 63508fca7a5SJohn-Mark Gurney break; 63608fca7a5SJohn-Mark Gurney } 63708fca7a5SJohn-Mark Gurney 63808fca7a5SJohn-Mark Gurney /* Finalize MAC */ 63908fca7a5SJohn-Mark Gurney axf->Final(aalg, &ctx); 64008fca7a5SJohn-Mark Gurney 64108fca7a5SJohn-Mark Gurney /* Validate tag */ 64208fca7a5SJohn-Mark Gurney if (!(crde->crd_flags & CRD_F_ENCRYPT)) { 64308fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, crda->crd_inject, 64408fca7a5SJohn-Mark Gurney axf->hashsize, uaalg); 64508fca7a5SJohn-Mark Gurney 64608fca7a5SJohn-Mark Gurney r = timingsafe_bcmp(aalg, uaalg, axf->hashsize); 64708fca7a5SJohn-Mark Gurney if (r == 0) { 64808fca7a5SJohn-Mark Gurney /* tag matches, decrypt data */ 64908fca7a5SJohn-Mark Gurney for (i = 0; i < crde->crd_len; i += blksz) { 65008fca7a5SJohn-Mark Gurney len = MIN(crde->crd_len - i, blksz); 65108fca7a5SJohn-Mark Gurney if (len < blksz) 65208fca7a5SJohn-Mark Gurney bzero(blk, blksz); 65308fca7a5SJohn-Mark Gurney crypto_copydata(crp->crp_flags, buf, 65408fca7a5SJohn-Mark Gurney crde->crd_skip + i, len, blk); 65508fca7a5SJohn-Mark Gurney exf->decrypt(swe->sw_kschedule, blk); 65608fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, 65708fca7a5SJohn-Mark Gurney crde->crd_skip + i, len, blk); 65808fca7a5SJohn-Mark Gurney } 65908fca7a5SJohn-Mark Gurney } else 66008fca7a5SJohn-Mark Gurney return (EBADMSG); 66108fca7a5SJohn-Mark Gurney } else { 66208fca7a5SJohn-Mark Gurney /* Inject the authentication data */ 66308fca7a5SJohn-Mark Gurney crypto_copyback(crp->crp_flags, buf, crda->crd_inject, 66408fca7a5SJohn-Mark Gurney axf->hashsize, aalg); 66508fca7a5SJohn-Mark Gurney } 66608fca7a5SJohn-Mark Gurney 66708fca7a5SJohn-Mark Gurney return (0); 66808fca7a5SJohn-Mark Gurney } 66908fca7a5SJohn-Mark Gurney 670091d81d1SSam Leffler /* 671091d81d1SSam Leffler * Apply a compression/decompression algorithm 672091d81d1SSam Leffler */ 673091d81d1SSam Leffler static int 674091d81d1SSam Leffler swcr_compdec(struct cryptodesc *crd, struct swcr_data *sw, 675f34a967bSPawel Jakub Dawidek caddr_t buf, int flags) 676091d81d1SSam Leffler { 677091d81d1SSam Leffler u_int8_t *data, *out; 678091d81d1SSam Leffler struct comp_algo *cxf; 679091d81d1SSam Leffler int adj; 680091d81d1SSam Leffler u_int32_t result; 681091d81d1SSam Leffler 682091d81d1SSam Leffler cxf = sw->sw_cxf; 683091d81d1SSam Leffler 684091d81d1SSam Leffler /* We must handle the whole buffer of data in one time 685091d81d1SSam Leffler * then if there is not all the data in the mbuf, we must 686091d81d1SSam Leffler * copy in a buffer. 687091d81d1SSam Leffler */ 688091d81d1SSam Leffler 6891ede983cSDag-Erling Smørgrav data = malloc(crd->crd_len, M_CRYPTO_DATA, M_NOWAIT); 690091d81d1SSam Leffler if (data == NULL) 691091d81d1SSam Leffler return (EINVAL); 692f34a967bSPawel Jakub Dawidek crypto_copydata(flags, buf, crd->crd_skip, crd->crd_len, data); 693091d81d1SSam Leffler 694091d81d1SSam Leffler if (crd->crd_flags & CRD_F_COMP) 695091d81d1SSam Leffler result = cxf->compress(data, crd->crd_len, &out); 696091d81d1SSam Leffler else 697091d81d1SSam Leffler result = cxf->decompress(data, crd->crd_len, &out); 698091d81d1SSam Leffler 6991ede983cSDag-Erling Smørgrav free(data, M_CRYPTO_DATA); 700091d81d1SSam Leffler if (result == 0) 701091d81d1SSam Leffler return EINVAL; 702091d81d1SSam Leffler 703091d81d1SSam Leffler /* Copy back the (de)compressed data. m_copyback is 704091d81d1SSam Leffler * extending the mbuf as necessary. 705091d81d1SSam Leffler */ 706091d81d1SSam Leffler sw->sw_size = result; 707091d81d1SSam Leffler /* Check the compressed size when doing compression */ 708091d81d1SSam Leffler if (crd->crd_flags & CRD_F_COMP) { 709df4dece1SBjoern A. Zeeb if (result >= crd->crd_len) { 710091d81d1SSam Leffler /* Compression was useless, we lost time */ 7111ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 712091d81d1SSam Leffler return 0; 713091d81d1SSam Leffler } 714091d81d1SSam Leffler } 715091d81d1SSam Leffler 716f34a967bSPawel Jakub Dawidek crypto_copyback(flags, buf, crd->crd_skip, result, out); 717091d81d1SSam Leffler if (result < crd->crd_len) { 718091d81d1SSam Leffler adj = result - crd->crd_len; 719f34a967bSPawel Jakub Dawidek if (flags & CRYPTO_F_IMBUF) { 720091d81d1SSam Leffler adj = result - crd->crd_len; 721091d81d1SSam Leffler m_adj((struct mbuf *)buf, adj); 722f34a967bSPawel Jakub Dawidek } else if (flags & CRYPTO_F_IOV) { 723091d81d1SSam Leffler struct uio *uio = (struct uio *)buf; 724091d81d1SSam Leffler int ind; 725091d81d1SSam Leffler 726091d81d1SSam Leffler adj = crd->crd_len - result; 727091d81d1SSam Leffler ind = uio->uio_iovcnt - 1; 728091d81d1SSam Leffler 729091d81d1SSam Leffler while (adj > 0 && ind >= 0) { 730091d81d1SSam Leffler if (adj < uio->uio_iov[ind].iov_len) { 731091d81d1SSam Leffler uio->uio_iov[ind].iov_len -= adj; 732091d81d1SSam Leffler break; 733091d81d1SSam Leffler } 734091d81d1SSam Leffler 735091d81d1SSam Leffler adj -= uio->uio_iov[ind].iov_len; 736091d81d1SSam Leffler uio->uio_iov[ind].iov_len = 0; 737091d81d1SSam Leffler ind--; 738091d81d1SSam Leffler uio->uio_iovcnt--; 739091d81d1SSam Leffler } 740091d81d1SSam Leffler } 741091d81d1SSam Leffler } 7421ede983cSDag-Erling Smørgrav free(out, M_CRYPTO_DATA); 743091d81d1SSam Leffler return 0; 744091d81d1SSam Leffler } 745091d81d1SSam Leffler 746091d81d1SSam Leffler /* 747091d81d1SSam Leffler * Generate a new software session. 748091d81d1SSam Leffler */ 749091d81d1SSam Leffler static int 7501b0909d5SConrad Meyer swcr_newsession(device_t dev, crypto_session_t cses, struct cryptoini *cri) 751091d81d1SSam Leffler { 7521b0909d5SConrad Meyer struct swcr_data **swd, *ses; 753091d81d1SSam Leffler struct auth_hash *axf; 754091d81d1SSam Leffler struct enc_xform *txf; 755091d81d1SSam Leffler struct comp_algo *cxf; 756a2bc81bfSJohn-Mark Gurney int len; 757f6c4bc3bSPawel Jakub Dawidek int error; 758091d81d1SSam Leffler 7591b0909d5SConrad Meyer if (cses == NULL || cri == NULL) 760091d81d1SSam Leffler return EINVAL; 761091d81d1SSam Leffler 7621b0909d5SConrad Meyer ses = crypto_get_driver_session(cses); 7631b0909d5SConrad Meyer swd = &ses; 764091d81d1SSam Leffler 765091d81d1SSam Leffler while (cri) { 7661b0909d5SConrad Meyer if (*swd == NULL) 7671ede983cSDag-Erling Smørgrav *swd = malloc(sizeof(struct swcr_data), 7681b0909d5SConrad Meyer M_CRYPTO_DATA, M_WAITOK | M_ZERO); 769091d81d1SSam Leffler if (*swd == NULL) { 7701b0909d5SConrad Meyer swcr_freesession(dev, cses); 771091d81d1SSam Leffler return ENOBUFS; 772091d81d1SSam Leffler } 773091d81d1SSam Leffler 774091d81d1SSam Leffler switch (cri->cri_alg) { 775091d81d1SSam Leffler case CRYPTO_DES_CBC: 776091d81d1SSam Leffler txf = &enc_xform_des; 777091d81d1SSam Leffler goto enccommon; 778091d81d1SSam Leffler case CRYPTO_3DES_CBC: 779091d81d1SSam Leffler txf = &enc_xform_3des; 780091d81d1SSam Leffler goto enccommon; 781091d81d1SSam Leffler case CRYPTO_BLF_CBC: 782091d81d1SSam Leffler txf = &enc_xform_blf; 783091d81d1SSam Leffler goto enccommon; 784091d81d1SSam Leffler case CRYPTO_CAST_CBC: 785091d81d1SSam Leffler txf = &enc_xform_cast5; 786091d81d1SSam Leffler goto enccommon; 787091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 788091d81d1SSam Leffler txf = &enc_xform_skipjack; 789091d81d1SSam Leffler goto enccommon; 790091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 791091d81d1SSam Leffler txf = &enc_xform_rijndael128; 792091d81d1SSam Leffler goto enccommon; 793d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 794d295bdeeSPawel Jakub Dawidek txf = &enc_xform_aes_xts; 795d295bdeeSPawel Jakub Dawidek goto enccommon; 79608fca7a5SJohn-Mark Gurney case CRYPTO_AES_ICM: 79708fca7a5SJohn-Mark Gurney txf = &enc_xform_aes_icm; 79808fca7a5SJohn-Mark Gurney goto enccommon; 79908fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 80008fca7a5SJohn-Mark Gurney txf = &enc_xform_aes_nist_gcm; 80108fca7a5SJohn-Mark Gurney goto enccommon; 80208fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 80308fca7a5SJohn-Mark Gurney txf = &enc_xform_aes_nist_gmac; 80408fca7a5SJohn-Mark Gurney (*swd)->sw_exf = txf; 80508fca7a5SJohn-Mark Gurney break; 806559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 807559d3390SGeorge V. Neville-Neil txf = &enc_xform_camellia; 808559d3390SGeorge V. Neville-Neil goto enccommon; 809091d81d1SSam Leffler case CRYPTO_NULL_CBC: 810091d81d1SSam Leffler txf = &enc_xform_null; 811091d81d1SSam Leffler goto enccommon; 81261590291SConrad Meyer case CRYPTO_CHACHA20: 81361590291SConrad Meyer txf = &enc_xform_chacha20; 81461590291SConrad Meyer goto enccommon; 815091d81d1SSam Leffler enccommon: 816f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 817091d81d1SSam Leffler error = txf->setkey(&((*swd)->sw_kschedule), 818091d81d1SSam Leffler cri->cri_key, cri->cri_klen / 8); 819091d81d1SSam Leffler if (error) { 8201b0909d5SConrad Meyer swcr_freesession(dev, cses); 821091d81d1SSam Leffler return error; 822091d81d1SSam Leffler } 823f6c4bc3bSPawel Jakub Dawidek } 824091d81d1SSam Leffler (*swd)->sw_exf = txf; 825091d81d1SSam Leffler break; 826091d81d1SSam Leffler 827091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 828f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_md5; 829091d81d1SSam Leffler goto authcommon; 830091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 831f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_sha1; 832091d81d1SSam Leffler goto authcommon; 833c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 834c97f39ceSConrad Meyer axf = &auth_hash_hmac_sha2_224; 835c97f39ceSConrad Meyer goto authcommon; 836f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 837091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_256; 838f6c4bc3bSPawel Jakub Dawidek goto authcommon; 839f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 840091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_384; 841f6c4bc3bSPawel Jakub Dawidek goto authcommon; 842f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 843091d81d1SSam Leffler axf = &auth_hash_hmac_sha2_512; 844091d81d1SSam Leffler goto authcommon; 845091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 846091d81d1SSam Leffler axf = &auth_hash_null; 847091d81d1SSam Leffler goto authcommon; 848091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 849f6c4bc3bSPawel Jakub Dawidek axf = &auth_hash_hmac_ripemd_160; 850091d81d1SSam Leffler authcommon: 851091d81d1SSam Leffler (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 852091d81d1SSam Leffler M_NOWAIT); 853091d81d1SSam Leffler if ((*swd)->sw_ictx == NULL) { 8541b0909d5SConrad Meyer swcr_freesession(dev, cses); 855091d81d1SSam Leffler return ENOBUFS; 856091d81d1SSam Leffler } 857091d81d1SSam Leffler 858091d81d1SSam Leffler (*swd)->sw_octx = malloc(axf->ctxsize, M_CRYPTO_DATA, 859091d81d1SSam Leffler M_NOWAIT); 860091d81d1SSam Leffler if ((*swd)->sw_octx == NULL) { 8611b0909d5SConrad Meyer swcr_freesession(dev, cses); 862091d81d1SSam Leffler return ENOBUFS; 863091d81d1SSam Leffler } 864091d81d1SSam Leffler 865f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 86625b7033bSConrad Meyer error = swcr_authprepare(axf, *swd, 86725b7033bSConrad Meyer cri->cri_key, cri->cri_klen); 86825b7033bSConrad Meyer if (error != 0) { 86925b7033bSConrad Meyer swcr_freesession(dev, cses); 87025b7033bSConrad Meyer return error; 87125b7033bSConrad Meyer } 872f6c4bc3bSPawel Jakub Dawidek } 873091d81d1SSam Leffler 874f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_mlen = cri->cri_mlen; 875091d81d1SSam Leffler (*swd)->sw_axf = axf; 876091d81d1SSam Leffler break; 877091d81d1SSam Leffler 878091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 879091d81d1SSam Leffler axf = &auth_hash_key_md5; 880091d81d1SSam Leffler goto auth2common; 881091d81d1SSam Leffler 882091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 883091d81d1SSam Leffler axf = &auth_hash_key_sha1; 884091d81d1SSam Leffler auth2common: 885091d81d1SSam Leffler (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 886091d81d1SSam Leffler M_NOWAIT); 887091d81d1SSam Leffler if ((*swd)->sw_ictx == NULL) { 8881b0909d5SConrad Meyer swcr_freesession(dev, cses); 889091d81d1SSam Leffler return ENOBUFS; 890091d81d1SSam Leffler } 891091d81d1SSam Leffler 892f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_octx = malloc(cri->cri_klen / 8, 893f6c4bc3bSPawel Jakub Dawidek M_CRYPTO_DATA, M_NOWAIT); 894091d81d1SSam Leffler if ((*swd)->sw_octx == NULL) { 8951b0909d5SConrad Meyer swcr_freesession(dev, cses); 896091d81d1SSam Leffler return ENOBUFS; 897091d81d1SSam Leffler } 898091d81d1SSam Leffler 899f6c4bc3bSPawel Jakub Dawidek /* Store the key so we can "append" it to the payload */ 900f6c4bc3bSPawel Jakub Dawidek if (cri->cri_key != NULL) { 90125b7033bSConrad Meyer error = swcr_authprepare(axf, *swd, 90225b7033bSConrad Meyer cri->cri_key, cri->cri_klen); 90325b7033bSConrad Meyer if (error != 0) { 90425b7033bSConrad Meyer swcr_freesession(dev, cses); 90525b7033bSConrad Meyer return error; 90625b7033bSConrad Meyer } 907f6c4bc3bSPawel Jakub Dawidek } 908f6c4bc3bSPawel Jakub Dawidek 909f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_mlen = cri->cri_mlen; 910091d81d1SSam Leffler (*swd)->sw_axf = axf; 911091d81d1SSam Leffler break; 912091d81d1SSam Leffler #ifdef notdef 913091d81d1SSam Leffler case CRYPTO_MD5: 914091d81d1SSam Leffler axf = &auth_hash_md5; 915091d81d1SSam Leffler goto auth3common; 916c4729f6eSConrad Meyer #endif 917091d81d1SSam Leffler 918091d81d1SSam Leffler case CRYPTO_SHA1: 919091d81d1SSam Leffler axf = &auth_hash_sha1; 920c4729f6eSConrad Meyer goto auth3common; 921c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 922c4729f6eSConrad Meyer axf = &auth_hash_sha2_224; 923c4729f6eSConrad Meyer goto auth3common; 924c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 925c4729f6eSConrad Meyer axf = &auth_hash_sha2_256; 926c4729f6eSConrad Meyer goto auth3common; 927c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 928c4729f6eSConrad Meyer axf = &auth_hash_sha2_384; 929c4729f6eSConrad Meyer goto auth3common; 930c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 931c4729f6eSConrad Meyer axf = &auth_hash_sha2_512; 932c4729f6eSConrad Meyer 933091d81d1SSam Leffler auth3common: 934091d81d1SSam Leffler (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 935091d81d1SSam Leffler M_NOWAIT); 936091d81d1SSam Leffler if ((*swd)->sw_ictx == NULL) { 9371b0909d5SConrad Meyer swcr_freesession(dev, cses); 938091d81d1SSam Leffler return ENOBUFS; 939091d81d1SSam Leffler } 940091d81d1SSam Leffler 941091d81d1SSam Leffler axf->Init((*swd)->sw_ictx); 942f6c4bc3bSPawel Jakub Dawidek (*swd)->sw_mlen = cri->cri_mlen; 943091d81d1SSam Leffler (*swd)->sw_axf = axf; 944091d81d1SSam Leffler break; 94508fca7a5SJohn-Mark Gurney 94608fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 94708fca7a5SJohn-Mark Gurney axf = &auth_hash_nist_gmac_aes_128; 94808fca7a5SJohn-Mark Gurney goto auth4common; 94908fca7a5SJohn-Mark Gurney 95008fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 95108fca7a5SJohn-Mark Gurney axf = &auth_hash_nist_gmac_aes_192; 95208fca7a5SJohn-Mark Gurney goto auth4common; 95308fca7a5SJohn-Mark Gurney 95408fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 95508fca7a5SJohn-Mark Gurney axf = &auth_hash_nist_gmac_aes_256; 95608fca7a5SJohn-Mark Gurney auth4common: 957a2bc81bfSJohn-Mark Gurney len = cri->cri_klen / 8; 9582e2e26d1SJohn Baldwin if (len != 16 && len != 24 && len != 32) { 9591b0909d5SConrad Meyer swcr_freesession(dev, cses); 960a2bc81bfSJohn-Mark Gurney return EINVAL; 9612e2e26d1SJohn Baldwin } 962a2bc81bfSJohn-Mark Gurney 96308fca7a5SJohn-Mark Gurney (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 96408fca7a5SJohn-Mark Gurney M_NOWAIT); 96508fca7a5SJohn-Mark Gurney if ((*swd)->sw_ictx == NULL) { 9661b0909d5SConrad Meyer swcr_freesession(dev, cses); 96708fca7a5SJohn-Mark Gurney return ENOBUFS; 96808fca7a5SJohn-Mark Gurney } 96908fca7a5SJohn-Mark Gurney axf->Init((*swd)->sw_ictx); 970a2bc81bfSJohn-Mark Gurney axf->Setkey((*swd)->sw_ictx, cri->cri_key, len); 97108fca7a5SJohn-Mark Gurney (*swd)->sw_axf = axf; 97208fca7a5SJohn-Mark Gurney break; 97308fca7a5SJohn-Mark Gurney 9740e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 9750e33efe4SConrad Meyer axf = &auth_hash_blake2b; 9760e33efe4SConrad Meyer goto auth5common; 9770e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 9780e33efe4SConrad Meyer axf = &auth_hash_blake2s; 97925b7033bSConrad Meyer goto auth5common; 98025b7033bSConrad Meyer case CRYPTO_POLY1305: 98125b7033bSConrad Meyer axf = &auth_hash_poly1305; 9820e33efe4SConrad Meyer auth5common: 9830e33efe4SConrad Meyer (*swd)->sw_ictx = malloc(axf->ctxsize, M_CRYPTO_DATA, 9840e33efe4SConrad Meyer M_NOWAIT); 9850e33efe4SConrad Meyer if ((*swd)->sw_ictx == NULL) { 9861b0909d5SConrad Meyer swcr_freesession(dev, cses); 9870e33efe4SConrad Meyer return ENOBUFS; 9880e33efe4SConrad Meyer } 9890e33efe4SConrad Meyer axf->Setkey((*swd)->sw_ictx, cri->cri_key, 9900e33efe4SConrad Meyer cri->cri_klen / 8); 9910e33efe4SConrad Meyer axf->Init((*swd)->sw_ictx); 9920e33efe4SConrad Meyer (*swd)->sw_axf = axf; 9930e33efe4SConrad Meyer break; 9940e33efe4SConrad Meyer 995091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 996091d81d1SSam Leffler cxf = &comp_algo_deflate; 997091d81d1SSam Leffler (*swd)->sw_cxf = cxf; 998091d81d1SSam Leffler break; 999091d81d1SSam Leffler default: 10001b0909d5SConrad Meyer swcr_freesession(dev, cses); 1001091d81d1SSam Leffler return EINVAL; 1002091d81d1SSam Leffler } 1003091d81d1SSam Leffler 1004091d81d1SSam Leffler (*swd)->sw_alg = cri->cri_alg; 1005091d81d1SSam Leffler cri = cri->cri_next; 1006091d81d1SSam Leffler swd = &((*swd)->sw_next); 1007091d81d1SSam Leffler } 1008091d81d1SSam Leffler return 0; 1009091d81d1SSam Leffler } 1010091d81d1SSam Leffler 10111b0909d5SConrad Meyer static void 10121b0909d5SConrad Meyer swcr_freesession(device_t dev, crypto_session_t cses) 1013109919c6SBenno Rice { 10141b0909d5SConrad Meyer struct swcr_data *ses, *swd, *next; 1015091d81d1SSam Leffler struct enc_xform *txf; 1016091d81d1SSam Leffler struct auth_hash *axf; 1017091d81d1SSam Leffler 10181b0909d5SConrad Meyer ses = crypto_get_driver_session(cses); 1019091d81d1SSam Leffler 10201b0909d5SConrad Meyer for (swd = ses; swd != NULL; swd = next) { 10211b0909d5SConrad Meyer next = swd->sw_next; 1022091d81d1SSam Leffler 1023091d81d1SSam Leffler switch (swd->sw_alg) { 1024091d81d1SSam Leffler case CRYPTO_DES_CBC: 1025091d81d1SSam Leffler case CRYPTO_3DES_CBC: 1026091d81d1SSam Leffler case CRYPTO_BLF_CBC: 1027091d81d1SSam Leffler case CRYPTO_CAST_CBC: 1028091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 1029091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 1030d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 103108fca7a5SJohn-Mark Gurney case CRYPTO_AES_ICM: 103208fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 103308fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 1034559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 1035091d81d1SSam Leffler case CRYPTO_NULL_CBC: 103661590291SConrad Meyer case CRYPTO_CHACHA20: 1037091d81d1SSam Leffler txf = swd->sw_exf; 1038091d81d1SSam Leffler 1039091d81d1SSam Leffler if (swd->sw_kschedule) 1040091d81d1SSam Leffler txf->zerokey(&(swd->sw_kschedule)); 1041091d81d1SSam Leffler break; 1042091d81d1SSam Leffler 1043091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 1044091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1045c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1046f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1047f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1048f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1049091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 1050091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1051091d81d1SSam Leffler axf = swd->sw_axf; 1052091d81d1SSam Leffler 1053091d81d1SSam Leffler if (swd->sw_ictx) { 1054091d81d1SSam Leffler bzero(swd->sw_ictx, axf->ctxsize); 1055091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 1056091d81d1SSam Leffler } 1057091d81d1SSam Leffler if (swd->sw_octx) { 1058091d81d1SSam Leffler bzero(swd->sw_octx, axf->ctxsize); 1059091d81d1SSam Leffler free(swd->sw_octx, M_CRYPTO_DATA); 1060091d81d1SSam Leffler } 1061091d81d1SSam Leffler break; 1062091d81d1SSam Leffler 1063091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 1064091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 1065091d81d1SSam Leffler axf = swd->sw_axf; 1066091d81d1SSam Leffler 1067091d81d1SSam Leffler if (swd->sw_ictx) { 1068091d81d1SSam Leffler bzero(swd->sw_ictx, axf->ctxsize); 1069091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 1070091d81d1SSam Leffler } 1071091d81d1SSam Leffler if (swd->sw_octx) { 1072091d81d1SSam Leffler bzero(swd->sw_octx, swd->sw_klen); 1073091d81d1SSam Leffler free(swd->sw_octx, M_CRYPTO_DATA); 1074091d81d1SSam Leffler } 1075091d81d1SSam Leffler break; 1076091d81d1SSam Leffler 10770e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 10780e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 1079091d81d1SSam Leffler case CRYPTO_MD5: 108025b7033bSConrad Meyer case CRYPTO_POLY1305: 1081091d81d1SSam Leffler case CRYPTO_SHA1: 1082c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 1083c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 1084c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 1085c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 1086091d81d1SSam Leffler axf = swd->sw_axf; 1087091d81d1SSam Leffler 10885fbc5b5aSConrad Meyer if (swd->sw_ictx) { 10895fbc5b5aSConrad Meyer explicit_bzero(swd->sw_ictx, axf->ctxsize); 1090091d81d1SSam Leffler free(swd->sw_ictx, M_CRYPTO_DATA); 10915fbc5b5aSConrad Meyer } 1092091d81d1SSam Leffler break; 1093091d81d1SSam Leffler 1094091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 1095151ba793SAlexander Kabaev /* Nothing to do */ 1096091d81d1SSam Leffler break; 1097091d81d1SSam Leffler } 1098091d81d1SSam Leffler 10991b0909d5SConrad Meyer /* OCF owns and frees the primary session object */ 11001b0909d5SConrad Meyer if (swd != ses) 11011ede983cSDag-Erling Smørgrav free(swd, M_CRYPTO_DATA); 1102091d81d1SSam Leffler } 1103091d81d1SSam Leffler } 1104091d81d1SSam Leffler 1105091d81d1SSam Leffler /* 1106091d81d1SSam Leffler * Process a software request. 1107091d81d1SSam Leffler */ 1108091d81d1SSam Leffler static int 11096810ad6fSSam Leffler swcr_process(device_t dev, struct cryptop *crp, int hint) 1110091d81d1SSam Leffler { 1111091d81d1SSam Leffler struct cryptodesc *crd; 11121b0909d5SConrad Meyer struct swcr_data *sw, *ses; 1113091d81d1SSam Leffler 1114091d81d1SSam Leffler /* Sanity check */ 1115091d81d1SSam Leffler if (crp == NULL) 1116091d81d1SSam Leffler return EINVAL; 1117091d81d1SSam Leffler 1118091d81d1SSam Leffler if (crp->crp_desc == NULL || crp->crp_buf == NULL) { 1119091d81d1SSam Leffler crp->crp_etype = EINVAL; 1120091d81d1SSam Leffler goto done; 1121091d81d1SSam Leffler } 1122091d81d1SSam Leffler 11231b0909d5SConrad Meyer ses = crypto_get_driver_session(crp->crp_session); 1124091d81d1SSam Leffler 1125091d81d1SSam Leffler /* Go through crypto descriptors, processing as we go */ 1126091d81d1SSam Leffler for (crd = crp->crp_desc; crd; crd = crd->crd_next) { 1127091d81d1SSam Leffler /* 1128091d81d1SSam Leffler * Find the crypto context. 1129091d81d1SSam Leffler * 1130091d81d1SSam Leffler * XXX Note that the logic here prevents us from having 1131091d81d1SSam Leffler * XXX the same algorithm multiple times in a session 1132091d81d1SSam Leffler * XXX (or rather, we can but it won't give us the right 1133091d81d1SSam Leffler * XXX results). To do that, we'd need some way of differentiating 1134091d81d1SSam Leffler * XXX between the various instances of an algorithm (so we can 1135091d81d1SSam Leffler * XXX locate the correct crypto context). 1136091d81d1SSam Leffler */ 11371b0909d5SConrad Meyer for (sw = ses; sw && sw->sw_alg != crd->crd_alg; 1138091d81d1SSam Leffler sw = sw->sw_next) 1139091d81d1SSam Leffler ; 1140091d81d1SSam Leffler 1141091d81d1SSam Leffler /* No such context ? */ 1142091d81d1SSam Leffler if (sw == NULL) { 1143091d81d1SSam Leffler crp->crp_etype = EINVAL; 1144091d81d1SSam Leffler goto done; 1145091d81d1SSam Leffler } 1146091d81d1SSam Leffler switch (sw->sw_alg) { 1147091d81d1SSam Leffler case CRYPTO_DES_CBC: 1148091d81d1SSam Leffler case CRYPTO_3DES_CBC: 1149091d81d1SSam Leffler case CRYPTO_BLF_CBC: 1150091d81d1SSam Leffler case CRYPTO_CAST_CBC: 1151091d81d1SSam Leffler case CRYPTO_SKIPJACK_CBC: 1152091d81d1SSam Leffler case CRYPTO_RIJNDAEL128_CBC: 1153d295bdeeSPawel Jakub Dawidek case CRYPTO_AES_XTS: 115408fca7a5SJohn-Mark Gurney case CRYPTO_AES_ICM: 1155559d3390SGeorge V. Neville-Neil case CRYPTO_CAMELLIA_CBC: 115661590291SConrad Meyer case CRYPTO_CHACHA20: 1157091d81d1SSam Leffler if ((crp->crp_etype = swcr_encdec(crd, sw, 1158f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1159091d81d1SSam Leffler goto done; 1160091d81d1SSam Leffler break; 1161091d81d1SSam Leffler case CRYPTO_NULL_CBC: 1162091d81d1SSam Leffler crp->crp_etype = 0; 1163091d81d1SSam Leffler break; 1164091d81d1SSam Leffler case CRYPTO_MD5_HMAC: 1165091d81d1SSam Leffler case CRYPTO_SHA1_HMAC: 1166c97f39ceSConrad Meyer case CRYPTO_SHA2_224_HMAC: 1167f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_256_HMAC: 1168f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_384_HMAC: 1169f6c4bc3bSPawel Jakub Dawidek case CRYPTO_SHA2_512_HMAC: 1170091d81d1SSam Leffler case CRYPTO_RIPEMD160_HMAC: 1171091d81d1SSam Leffler case CRYPTO_NULL_HMAC: 1172091d81d1SSam Leffler case CRYPTO_MD5_KPDK: 1173091d81d1SSam Leffler case CRYPTO_SHA1_KPDK: 1174091d81d1SSam Leffler case CRYPTO_MD5: 1175091d81d1SSam Leffler case CRYPTO_SHA1: 1176c4729f6eSConrad Meyer case CRYPTO_SHA2_224: 1177c4729f6eSConrad Meyer case CRYPTO_SHA2_256: 1178c4729f6eSConrad Meyer case CRYPTO_SHA2_384: 1179c4729f6eSConrad Meyer case CRYPTO_SHA2_512: 11800e33efe4SConrad Meyer case CRYPTO_BLAKE2B: 11810e33efe4SConrad Meyer case CRYPTO_BLAKE2S: 118225b7033bSConrad Meyer case CRYPTO_POLY1305: 118338d2f8d6SPawel Jakub Dawidek if ((crp->crp_etype = swcr_authcompute(crd, sw, 1184f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1185091d81d1SSam Leffler goto done; 1186091d81d1SSam Leffler break; 1187091d81d1SSam Leffler 118808fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GCM_16: 118908fca7a5SJohn-Mark Gurney case CRYPTO_AES_NIST_GMAC: 119008fca7a5SJohn-Mark Gurney case CRYPTO_AES_128_NIST_GMAC: 119108fca7a5SJohn-Mark Gurney case CRYPTO_AES_192_NIST_GMAC: 119208fca7a5SJohn-Mark Gurney case CRYPTO_AES_256_NIST_GMAC: 119308fca7a5SJohn-Mark Gurney crp->crp_etype = swcr_authenc(crp); 119408fca7a5SJohn-Mark Gurney goto done; 119508fca7a5SJohn-Mark Gurney 1196091d81d1SSam Leffler case CRYPTO_DEFLATE_COMP: 1197091d81d1SSam Leffler if ((crp->crp_etype = swcr_compdec(crd, sw, 1198f34a967bSPawel Jakub Dawidek crp->crp_buf, crp->crp_flags)) != 0) 1199091d81d1SSam Leffler goto done; 1200091d81d1SSam Leffler else 1201091d81d1SSam Leffler crp->crp_olen = (int)sw->sw_size; 1202091d81d1SSam Leffler break; 1203091d81d1SSam Leffler 1204091d81d1SSam Leffler default: 1205091d81d1SSam Leffler /* Unknown/unsupported algorithm */ 1206091d81d1SSam Leffler crp->crp_etype = EINVAL; 1207091d81d1SSam Leffler goto done; 1208091d81d1SSam Leffler } 1209091d81d1SSam Leffler } 1210091d81d1SSam Leffler 1211091d81d1SSam Leffler done: 1212091d81d1SSam Leffler crypto_done(crp); 1213091d81d1SSam Leffler return 0; 1214091d81d1SSam Leffler } 1215091d81d1SSam Leffler 1216091d81d1SSam Leffler static void 12173f147ab2SWarner Losh swcr_identify(driver_t *drv, device_t parent) 1218091d81d1SSam Leffler { 12196810ad6fSSam Leffler /* NB: order 10 is so we get attached after h/w devices */ 12206810ad6fSSam Leffler if (device_find_child(parent, "cryptosoft", -1) == NULL && 122186c585d9SMarius Strobl BUS_ADD_CHILD(parent, 10, "cryptosoft", 0) == 0) 12226810ad6fSSam Leffler panic("cryptosoft: could not attach"); 12236810ad6fSSam Leffler } 1224f6c4bc3bSPawel Jakub Dawidek 12256810ad6fSSam Leffler static int 12266810ad6fSSam Leffler swcr_probe(device_t dev) 12276810ad6fSSam Leffler { 12286810ad6fSSam Leffler device_set_desc(dev, "software crypto"); 122986c585d9SMarius Strobl return (BUS_PROBE_NOWILDCARD); 12306810ad6fSSam Leffler } 1231f6c4bc3bSPawel Jakub Dawidek 12326810ad6fSSam Leffler static int 12336810ad6fSSam Leffler swcr_attach(device_t dev) 12346810ad6fSSam Leffler { 12356810ad6fSSam Leffler memset(hmac_ipad_buffer, HMAC_IPAD_VAL, HMAC_MAX_BLOCK_LEN); 12366810ad6fSSam Leffler memset(hmac_opad_buffer, HMAC_OPAD_VAL, HMAC_MAX_BLOCK_LEN); 12376810ad6fSSam Leffler 12381b0909d5SConrad Meyer swcr_id = crypto_get_driverid(dev, sizeof(struct swcr_data), 12396810ad6fSSam Leffler CRYPTOCAP_F_SOFTWARE | CRYPTOCAP_F_SYNC); 12406810ad6fSSam Leffler if (swcr_id < 0) { 12416810ad6fSSam Leffler device_printf(dev, "cannot initialize!"); 12426810ad6fSSam Leffler return ENOMEM; 12436810ad6fSSam Leffler } 1244091d81d1SSam Leffler #define REGISTER(alg) \ 12456810ad6fSSam Leffler crypto_register(swcr_id, alg, 0,0) 12466810ad6fSSam Leffler REGISTER(CRYPTO_DES_CBC); 1247091d81d1SSam Leffler REGISTER(CRYPTO_3DES_CBC); 1248091d81d1SSam Leffler REGISTER(CRYPTO_BLF_CBC); 1249091d81d1SSam Leffler REGISTER(CRYPTO_CAST_CBC); 1250091d81d1SSam Leffler REGISTER(CRYPTO_SKIPJACK_CBC); 1251091d81d1SSam Leffler REGISTER(CRYPTO_NULL_CBC); 1252091d81d1SSam Leffler REGISTER(CRYPTO_MD5_HMAC); 1253091d81d1SSam Leffler REGISTER(CRYPTO_SHA1_HMAC); 1254c97f39ceSConrad Meyer REGISTER(CRYPTO_SHA2_224_HMAC); 1255f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_256_HMAC); 1256f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_384_HMAC); 1257f6c4bc3bSPawel Jakub Dawidek REGISTER(CRYPTO_SHA2_512_HMAC); 1258091d81d1SSam Leffler REGISTER(CRYPTO_RIPEMD160_HMAC); 1259091d81d1SSam Leffler REGISTER(CRYPTO_NULL_HMAC); 1260091d81d1SSam Leffler REGISTER(CRYPTO_MD5_KPDK); 1261091d81d1SSam Leffler REGISTER(CRYPTO_SHA1_KPDK); 1262091d81d1SSam Leffler REGISTER(CRYPTO_MD5); 1263091d81d1SSam Leffler REGISTER(CRYPTO_SHA1); 1264c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_224); 1265c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_256); 1266c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_384); 1267c4729f6eSConrad Meyer REGISTER(CRYPTO_SHA2_512); 1268091d81d1SSam Leffler REGISTER(CRYPTO_RIJNDAEL128_CBC); 1269d295bdeeSPawel Jakub Dawidek REGISTER(CRYPTO_AES_XTS); 127008fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_ICM); 127108fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_NIST_GCM_16); 127208fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_NIST_GMAC); 127308fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_128_NIST_GMAC); 127408fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_192_NIST_GMAC); 127508fca7a5SJohn-Mark Gurney REGISTER(CRYPTO_AES_256_NIST_GMAC); 1276559d3390SGeorge V. Neville-Neil REGISTER(CRYPTO_CAMELLIA_CBC); 1277091d81d1SSam Leffler REGISTER(CRYPTO_DEFLATE_COMP); 12780e33efe4SConrad Meyer REGISTER(CRYPTO_BLAKE2B); 12790e33efe4SConrad Meyer REGISTER(CRYPTO_BLAKE2S); 128061590291SConrad Meyer REGISTER(CRYPTO_CHACHA20); 128125b7033bSConrad Meyer REGISTER(CRYPTO_POLY1305); 1282091d81d1SSam Leffler #undef REGISTER 12836810ad6fSSam Leffler 12846810ad6fSSam Leffler return 0; 1285091d81d1SSam Leffler } 12864b465da2SPawel Jakub Dawidek 12873f147ab2SWarner Losh static int 12886810ad6fSSam Leffler swcr_detach(device_t dev) 12894b465da2SPawel Jakub Dawidek { 12906810ad6fSSam Leffler crypto_unregister_all(swcr_id); 12913f147ab2SWarner Losh return 0; 12924b465da2SPawel Jakub Dawidek } 12936810ad6fSSam Leffler 12946810ad6fSSam Leffler static device_method_t swcr_methods[] = { 12956810ad6fSSam Leffler DEVMETHOD(device_identify, swcr_identify), 12966810ad6fSSam Leffler DEVMETHOD(device_probe, swcr_probe), 12976810ad6fSSam Leffler DEVMETHOD(device_attach, swcr_attach), 12986810ad6fSSam Leffler DEVMETHOD(device_detach, swcr_detach), 12996810ad6fSSam Leffler 13006810ad6fSSam Leffler DEVMETHOD(cryptodev_newsession, swcr_newsession), 13016810ad6fSSam Leffler DEVMETHOD(cryptodev_freesession,swcr_freesession), 13026810ad6fSSam Leffler DEVMETHOD(cryptodev_process, swcr_process), 13036810ad6fSSam Leffler 13046810ad6fSSam Leffler {0, 0}, 13056810ad6fSSam Leffler }; 13066810ad6fSSam Leffler 13076810ad6fSSam Leffler static driver_t swcr_driver = { 13086810ad6fSSam Leffler "cryptosoft", 13096810ad6fSSam Leffler swcr_methods, 13106810ad6fSSam Leffler 0, /* NB: no softc */ 13116810ad6fSSam Leffler }; 13126810ad6fSSam Leffler static devclass_t swcr_devclass; 13136810ad6fSSam Leffler 13146810ad6fSSam Leffler /* 13156810ad6fSSam Leffler * NB: We explicitly reference the crypto module so we 13166810ad6fSSam Leffler * get the necessary ordering when built as a loadable 13176810ad6fSSam Leffler * module. This is required because we bundle the crypto 13186810ad6fSSam Leffler * module code together with the cryptosoft driver (otherwise 13196810ad6fSSam Leffler * normal module dependencies would handle things). 13206810ad6fSSam Leffler */ 13216810ad6fSSam Leffler extern int crypto_modevent(struct module *, int, void *); 13226810ad6fSSam Leffler /* XXX where to attach */ 13236810ad6fSSam Leffler DRIVER_MODULE(cryptosoft, nexus, swcr_driver, swcr_devclass, crypto_modevent,0); 13246810ad6fSSam Leffler MODULE_VERSION(cryptosoft, 1); 13256810ad6fSSam Leffler MODULE_DEPEND(cryptosoft, crypto, 1, 1, 1); 1326