Date: Tue, 27 Mar 2018 17:58:00 +0000 (UTC) From: Conrad Meyer <cem@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r331639 - head/sys/opencrypto Message-ID: <201803271758.w2RHw0qX075515@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: cem Date: Tue Mar 27 17:58:00 2018 New Revision: 331639 URL: https://svnweb.freebsd.org/changeset/base/331639 Log: opencrypto: Add mechanism to pass multiple crypto blocks to some ciphers xforms that support processing of multiple blocks at a time (to support more efficient modes, for example) can define the encrypt_ and decrypt_multi interfaces. If these interfaces are not present, the generic cryptosoft code falls back on the block-at-a-time encrypt/decrypt interfaces. Stream ciphers may support arbitrarily sized inputs (equivalent to an input block size of 1 byte) but may be more efficient if a larger block is passed. Sponsored by: Dell EMC Isilon Modified: head/sys/opencrypto/cryptosoft.c head/sys/opencrypto/xform_enc.h Modified: head/sys/opencrypto/cryptosoft.c ============================================================================== --- head/sys/opencrypto/cryptosoft.c Tue Mar 27 17:54:46 2018 (r331638) +++ head/sys/opencrypto/cryptosoft.c Tue Mar 27 17:58:00 2018 (r331639) @@ -248,21 +248,29 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data * break; } - /* - * Warning: idat may point to garbage here, but - * we only use it in the while() loop, only if - * there are indeed enough data. - */ - idat = (char *)uio->uio_iov[ind].iov_base + k; - while (uio->uio_iov[ind].iov_len >= k + blks && i > 0) { + size_t nb, rem; + + nb = blks; + rem = uio->uio_iov[ind].iov_len - k; + idat = (char *)uio->uio_iov[ind].iov_base + k; + if (exf->reinit) { - if (crd->crd_flags & CRD_F_ENCRYPT) { + if ((crd->crd_flags & CRD_F_ENCRYPT) != 0 && + exf->encrypt_multi == NULL) exf->encrypt(sw->sw_kschedule, idat); - } else { + else if ((crd->crd_flags & CRD_F_ENCRYPT) != 0) { + nb = rounddown(rem, blks); + exf->encrypt_multi(sw->sw_kschedule, + idat, nb); + } else if (exf->decrypt_multi == NULL) exf->decrypt(sw->sw_kschedule, idat); + else { + nb = rounddown(rem, blks); + exf->decrypt_multi(sw->sw_kschedule, + idat, nb); } } else if (crd->crd_flags & CRD_F_ENCRYPT) { /* XOR with previous block/IV */ @@ -288,10 +296,10 @@ swcr_encdec(struct cryptodesc *crd, struct swcr_data * ivp = nivp; } - idat += blks; - count += blks; - k += blks; - i -= blks; + idat += nb; + count += nb; + k += nb; + i -= nb; } /* @@ -566,14 +574,26 @@ swcr_authenc(struct cryptop *crp) exf->reinit(swe->sw_kschedule, iv); /* Do encryption/decryption with MAC */ - for (i = 0; i < crde->crd_len; i += blksz) { - len = MIN(crde->crd_len - i, blksz); + for (i = 0; i < crde->crd_len; i += len) { + if (exf->encrypt_multi != NULL) { + len = rounddown(crde->crd_len - i, blksz); + if (len == 0) + len = blksz; + else + len = MIN(len, sizeof(blkbuf)); + } else + len = blksz; + len = MIN(crde->crd_len - i, len); if (len < blksz) bzero(blk, blksz); crypto_copydata(crp->crp_flags, buf, crde->crd_skip + i, len, blk); if (crde->crd_flags & CRD_F_ENCRYPT) { - exf->encrypt(swe->sw_kschedule, blk); + if (exf->encrypt_multi != NULL) + exf->encrypt_multi(swe->sw_kschedule, blk, + len); + else + exf->encrypt(swe->sw_kschedule, blk); axf->Update(&ctx, blk, len); crypto_copyback(crp->crp_flags, buf, crde->crd_skip + i, len, blk); Modified: head/sys/opencrypto/xform_enc.h ============================================================================== --- head/sys/opencrypto/xform_enc.h Tue Mar 27 17:54:46 2018 (r331638) +++ head/sys/opencrypto/xform_enc.h Tue Mar 27 17:58:00 2018 (r331639) @@ -59,6 +59,14 @@ struct enc_xform { int (*setkey) (u_int8_t **, u_int8_t *, int len); void (*zerokey) (u_int8_t **); void (*reinit) (caddr_t, u_int8_t *); + /* + * Encrypt/decrypt 1+ blocks of input -- total size is 'len' bytes. + * Len is guaranteed to be a multiple of the defined 'blocksize'. + * Optional interface -- most useful for stream ciphers with a small + * blocksize (1). + */ + void (*encrypt_multi) (void *, uint8_t *, size_t len); + void (*decrypt_multi) (void *, uint8_t *, size_t len); };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803271758.w2RHw0qX075515>