1091d81d1SSam Leffler /* $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $ */ 2091d81d1SSam Leffler 360727d8bSWarner Losh /*- 4091d81d1SSam Leffler * Copyright (c) 1999 Theo de Raadt 5091d81d1SSam Leffler * 6091d81d1SSam Leffler * Redistribution and use in source and binary forms, with or without 7091d81d1SSam Leffler * modification, are permitted provided that the following conditions 8091d81d1SSam Leffler * are met: 9091d81d1SSam Leffler * 10091d81d1SSam Leffler * 1. Redistributions of source code must retain the above copyright 11091d81d1SSam Leffler * notice, this list of conditions and the following disclaimer. 12091d81d1SSam Leffler * 2. Redistributions in binary form must reproduce the above copyright 13091d81d1SSam Leffler * notice, this list of conditions and the following disclaimer in the 14091d81d1SSam Leffler * documentation and/or other materials provided with the distribution. 15091d81d1SSam Leffler * 3. The name of the author may not be used to endorse or promote products 16091d81d1SSam Leffler * derived from this software without specific prior written permission. 17091d81d1SSam Leffler * 18091d81d1SSam Leffler * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19091d81d1SSam Leffler * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20091d81d1SSam Leffler * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21091d81d1SSam Leffler * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22091d81d1SSam Leffler * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23091d81d1SSam Leffler * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24091d81d1SSam Leffler * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25091d81d1SSam Leffler * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26091d81d1SSam Leffler * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27091d81d1SSam Leffler * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28091d81d1SSam Leffler */ 29091d81d1SSam Leffler 302c446514SDavid E. O'Brien #include <sys/cdefs.h> 312c446514SDavid E. O'Brien __FBSDID("$FreeBSD$"); 322c446514SDavid E. O'Brien 33091d81d1SSam Leffler #include <sys/param.h> 34091d81d1SSam Leffler #include <sys/systm.h> 35091d81d1SSam Leffler #include <sys/proc.h> 36091d81d1SSam Leffler #include <sys/errno.h> 37091d81d1SSam Leffler #include <sys/malloc.h> 38091d81d1SSam Leffler #include <sys/kernel.h> 3911d2e1e8SPawel Jakub Dawidek #include <sys/mbuf.h> 40091d81d1SSam Leffler #include <sys/uio.h> 41ff2038a9SMatt Macy #include <sys/limits.h> 42ff2038a9SMatt Macy #include <sys/lock.h> 43091d81d1SSam Leffler 44091d81d1SSam Leffler #include <opencrypto/cryptodev.h> 45091d81d1SSam Leffler 468f91d4abSPawel Jakub Dawidek /* 478f91d4abSPawel Jakub Dawidek * This macro is only for avoiding code duplication, as we need to skip 488f91d4abSPawel Jakub Dawidek * given number of bytes in the same way in three functions below. 498f91d4abSPawel Jakub Dawidek */ 508f91d4abSPawel Jakub Dawidek #define CUIO_SKIP() do { \ 518f91d4abSPawel Jakub Dawidek KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \ 528f91d4abSPawel Jakub Dawidek KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \ 538f91d4abSPawel Jakub Dawidek while (off > 0) { \ 548f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty in skip", __func__)); \ 558f91d4abSPawel Jakub Dawidek if (off < iov->iov_len) \ 568f91d4abSPawel Jakub Dawidek break; \ 578f91d4abSPawel Jakub Dawidek off -= iov->iov_len; \ 588f91d4abSPawel Jakub Dawidek iol--; \ 598f91d4abSPawel Jakub Dawidek iov++; \ 608f91d4abSPawel Jakub Dawidek } \ 618f91d4abSPawel Jakub Dawidek } while (0) 628f91d4abSPawel Jakub Dawidek 63*9c0e3d3aSJohn Baldwin static void 64091d81d1SSam Leffler cuio_copydata(struct uio* uio, int off, int len, caddr_t cp) 65091d81d1SSam Leffler { 66091d81d1SSam Leffler struct iovec *iov = uio->uio_iov; 67091d81d1SSam Leffler int iol = uio->uio_iovcnt; 68091d81d1SSam Leffler unsigned count; 69091d81d1SSam Leffler 708f91d4abSPawel Jakub Dawidek CUIO_SKIP(); 71091d81d1SSam Leffler while (len > 0) { 728f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty", __func__)); 73091d81d1SSam Leffler count = min(iov->iov_len - off, len); 74091d81d1SSam Leffler bcopy(((caddr_t)iov->iov_base) + off, cp, count); 75091d81d1SSam Leffler len -= count; 76091d81d1SSam Leffler cp += count; 77091d81d1SSam Leffler off = 0; 78091d81d1SSam Leffler iol--; 79091d81d1SSam Leffler iov++; 80091d81d1SSam Leffler } 81091d81d1SSam Leffler } 82091d81d1SSam Leffler 83*9c0e3d3aSJohn Baldwin static void 847dd10fdeSJohn Baldwin cuio_copyback(struct uio* uio, int off, int len, c_caddr_t cp) 85091d81d1SSam Leffler { 86091d81d1SSam Leffler struct iovec *iov = uio->uio_iov; 87091d81d1SSam Leffler int iol = uio->uio_iovcnt; 88091d81d1SSam Leffler unsigned count; 89091d81d1SSam Leffler 908f91d4abSPawel Jakub Dawidek CUIO_SKIP(); 91091d81d1SSam Leffler while (len > 0) { 928f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty", __func__)); 93091d81d1SSam Leffler count = min(iov->iov_len - off, len); 94091d81d1SSam Leffler bcopy(cp, ((caddr_t)iov->iov_base) + off, count); 95091d81d1SSam Leffler len -= count; 96091d81d1SSam Leffler cp += count; 97091d81d1SSam Leffler off = 0; 98091d81d1SSam Leffler iol--; 99091d81d1SSam Leffler iov++; 100091d81d1SSam Leffler } 101091d81d1SSam Leffler } 102091d81d1SSam Leffler 103091d81d1SSam Leffler /* 10408fca7a5SJohn-Mark Gurney * Return the index and offset of location in iovec list. 105091d81d1SSam Leffler */ 106*9c0e3d3aSJohn Baldwin static int 107091d81d1SSam Leffler cuio_getptr(struct uio *uio, int loc, int *off) 108091d81d1SSam Leffler { 10908fca7a5SJohn-Mark Gurney int ind, len; 110091d81d1SSam Leffler 11108fca7a5SJohn-Mark Gurney ind = 0; 11208fca7a5SJohn-Mark Gurney while (loc >= 0 && ind < uio->uio_iovcnt) { 11308fca7a5SJohn-Mark Gurney len = uio->uio_iov[ind].iov_len; 11408fca7a5SJohn-Mark Gurney if (len > loc) { 115091d81d1SSam Leffler *off = loc; 11608fca7a5SJohn-Mark Gurney return (ind); 11708fca7a5SJohn-Mark Gurney } 11808fca7a5SJohn-Mark Gurney loc -= len; 11908fca7a5SJohn-Mark Gurney ind++; 120091d81d1SSam Leffler } 121091d81d1SSam Leffler 12208fca7a5SJohn-Mark Gurney if (ind > 0 && loc == 0) { 12308fca7a5SJohn-Mark Gurney ind--; 12408fca7a5SJohn-Mark Gurney *off = uio->uio_iov[ind].iov_len; 12508fca7a5SJohn-Mark Gurney return (ind); 126091d81d1SSam Leffler } 127091d81d1SSam Leffler 12808fca7a5SJohn-Mark Gurney return (-1); 129091d81d1SSam Leffler } 1308f91d4abSPawel Jakub Dawidek 131*9c0e3d3aSJohn Baldwin void 132*9c0e3d3aSJohn Baldwin crypto_cursor_init(struct crypto_buffer_cursor *cc, 133*9c0e3d3aSJohn Baldwin const struct crypto_buffer *cb) 134*9c0e3d3aSJohn Baldwin { 135*9c0e3d3aSJohn Baldwin memset(cc, 0, sizeof(*cc)); 136*9c0e3d3aSJohn Baldwin cc->cc_type = cb->cb_type; 137*9c0e3d3aSJohn Baldwin switch (cc->cc_type) { 138*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 139*9c0e3d3aSJohn Baldwin cc->cc_buf = cb->cb_buf; 140*9c0e3d3aSJohn Baldwin cc->cc_buf_len = cb->cb_buf_len; 141*9c0e3d3aSJohn Baldwin break; 142*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 143*9c0e3d3aSJohn Baldwin cc->cc_mbuf = cb->cb_mbuf; 144*9c0e3d3aSJohn Baldwin break; 145*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 146*9c0e3d3aSJohn Baldwin cc->cc_iov = cb->cb_uio->uio_iov; 147*9c0e3d3aSJohn Baldwin break; 148*9c0e3d3aSJohn Baldwin default: 149*9c0e3d3aSJohn Baldwin #ifdef INVARIANTS 150*9c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cb->cb_type); 151*9c0e3d3aSJohn Baldwin #endif 152*9c0e3d3aSJohn Baldwin break; 153*9c0e3d3aSJohn Baldwin } 154*9c0e3d3aSJohn Baldwin } 155*9c0e3d3aSJohn Baldwin 156*9c0e3d3aSJohn Baldwin void 157*9c0e3d3aSJohn Baldwin crypto_cursor_advance(struct crypto_buffer_cursor *cc, size_t amount) 158*9c0e3d3aSJohn Baldwin { 159*9c0e3d3aSJohn Baldwin size_t remain; 160*9c0e3d3aSJohn Baldwin 161*9c0e3d3aSJohn Baldwin switch (cc->cc_type) { 162*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 163*9c0e3d3aSJohn Baldwin MPASS(cc->cc_buf_len >= amount); 164*9c0e3d3aSJohn Baldwin cc->cc_buf += amount; 165*9c0e3d3aSJohn Baldwin cc->cc_buf_len -= amount; 166*9c0e3d3aSJohn Baldwin break; 167*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 168*9c0e3d3aSJohn Baldwin for (;;) { 169*9c0e3d3aSJohn Baldwin remain = cc->cc_mbuf->m_len - cc->cc_offset; 170*9c0e3d3aSJohn Baldwin if (amount < remain) { 171*9c0e3d3aSJohn Baldwin cc->cc_offset += amount; 172*9c0e3d3aSJohn Baldwin break; 173*9c0e3d3aSJohn Baldwin } 174*9c0e3d3aSJohn Baldwin amount -= remain; 175*9c0e3d3aSJohn Baldwin cc->cc_mbuf = cc->cc_mbuf->m_next; 176*9c0e3d3aSJohn Baldwin cc->cc_offset = 0; 177*9c0e3d3aSJohn Baldwin if (amount == 0) 178*9c0e3d3aSJohn Baldwin break; 179*9c0e3d3aSJohn Baldwin } 180*9c0e3d3aSJohn Baldwin break; 181*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 182*9c0e3d3aSJohn Baldwin for (;;) { 183*9c0e3d3aSJohn Baldwin remain = cc->cc_iov->iov_len - cc->cc_offset; 184*9c0e3d3aSJohn Baldwin if (amount < remain) { 185*9c0e3d3aSJohn Baldwin cc->cc_offset += amount; 186*9c0e3d3aSJohn Baldwin break; 187*9c0e3d3aSJohn Baldwin } 188*9c0e3d3aSJohn Baldwin amount -= remain; 189*9c0e3d3aSJohn Baldwin cc->cc_iov++; 190*9c0e3d3aSJohn Baldwin cc->cc_offset = 0; 191*9c0e3d3aSJohn Baldwin if (amount == 0) 192*9c0e3d3aSJohn Baldwin break; 193*9c0e3d3aSJohn Baldwin } 194*9c0e3d3aSJohn Baldwin break; 195*9c0e3d3aSJohn Baldwin default: 196*9c0e3d3aSJohn Baldwin #ifdef INVARIANTS 197*9c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cc->cc_type); 198*9c0e3d3aSJohn Baldwin #endif 199*9c0e3d3aSJohn Baldwin break; 200*9c0e3d3aSJohn Baldwin } 201*9c0e3d3aSJohn Baldwin } 202*9c0e3d3aSJohn Baldwin 203*9c0e3d3aSJohn Baldwin void * 204*9c0e3d3aSJohn Baldwin crypto_cursor_segbase(struct crypto_buffer_cursor *cc) 205*9c0e3d3aSJohn Baldwin { 206*9c0e3d3aSJohn Baldwin switch (cc->cc_type) { 207*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 208*9c0e3d3aSJohn Baldwin return (cc->cc_buf); 209*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 210*9c0e3d3aSJohn Baldwin if (cc->cc_mbuf == NULL) 211*9c0e3d3aSJohn Baldwin return (NULL); 212*9c0e3d3aSJohn Baldwin KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0, 213*9c0e3d3aSJohn Baldwin ("%s: not supported for unmapped mbufs", __func__)); 214*9c0e3d3aSJohn Baldwin return (mtod(cc->cc_mbuf, char *) + cc->cc_offset); 215*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 216*9c0e3d3aSJohn Baldwin return ((char *)cc->cc_iov->iov_base + cc->cc_offset); 217*9c0e3d3aSJohn Baldwin default: 218*9c0e3d3aSJohn Baldwin #ifdef INVARIANTS 219*9c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cc->cc_type); 220*9c0e3d3aSJohn Baldwin #endif 221*9c0e3d3aSJohn Baldwin return (NULL); 222*9c0e3d3aSJohn Baldwin } 223*9c0e3d3aSJohn Baldwin } 224*9c0e3d3aSJohn Baldwin 225*9c0e3d3aSJohn Baldwin size_t 226*9c0e3d3aSJohn Baldwin crypto_cursor_seglen(struct crypto_buffer_cursor *cc) 227*9c0e3d3aSJohn Baldwin { 228*9c0e3d3aSJohn Baldwin switch (cc->cc_type) { 229*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 230*9c0e3d3aSJohn Baldwin return (cc->cc_buf_len); 231*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 232*9c0e3d3aSJohn Baldwin if (cc->cc_mbuf == NULL) 233*9c0e3d3aSJohn Baldwin return (0); 234*9c0e3d3aSJohn Baldwin return (cc->cc_mbuf->m_len - cc->cc_offset); 235*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 236*9c0e3d3aSJohn Baldwin return (cc->cc_iov->iov_len - cc->cc_offset); 237*9c0e3d3aSJohn Baldwin default: 238*9c0e3d3aSJohn Baldwin #ifdef INVARIANTS 239*9c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cc->cc_type); 240*9c0e3d3aSJohn Baldwin #endif 241*9c0e3d3aSJohn Baldwin return (0); 242*9c0e3d3aSJohn Baldwin } 243*9c0e3d3aSJohn Baldwin } 244*9c0e3d3aSJohn Baldwin 245*9c0e3d3aSJohn Baldwin void 246*9c0e3d3aSJohn Baldwin crypto_cursor_copyback(struct crypto_buffer_cursor *cc, int size, 247*9c0e3d3aSJohn Baldwin const void *vsrc) 248*9c0e3d3aSJohn Baldwin { 249*9c0e3d3aSJohn Baldwin size_t remain, todo; 250*9c0e3d3aSJohn Baldwin const char *src; 251*9c0e3d3aSJohn Baldwin char *dst; 252*9c0e3d3aSJohn Baldwin 253*9c0e3d3aSJohn Baldwin src = vsrc; 254*9c0e3d3aSJohn Baldwin switch (cc->cc_type) { 255*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 256*9c0e3d3aSJohn Baldwin MPASS(cc->cc_buf_len >= size); 257*9c0e3d3aSJohn Baldwin memcpy(cc->cc_buf, src, size); 258*9c0e3d3aSJohn Baldwin cc->cc_buf += size; 259*9c0e3d3aSJohn Baldwin cc->cc_buf_len -= size; 260*9c0e3d3aSJohn Baldwin break; 261*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 262*9c0e3d3aSJohn Baldwin for (;;) { 263*9c0e3d3aSJohn Baldwin KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0, 264*9c0e3d3aSJohn Baldwin ("%s: not supported for unmapped mbufs", __func__)); 265*9c0e3d3aSJohn Baldwin dst = mtod(cc->cc_mbuf, char *) + cc->cc_offset; 266*9c0e3d3aSJohn Baldwin remain = cc->cc_mbuf->m_len - cc->cc_offset; 267*9c0e3d3aSJohn Baldwin todo = MIN(remain, size); 268*9c0e3d3aSJohn Baldwin memcpy(dst, src, todo); 269*9c0e3d3aSJohn Baldwin dst += todo; 270*9c0e3d3aSJohn Baldwin if (todo < remain) { 271*9c0e3d3aSJohn Baldwin cc->cc_offset += todo; 272*9c0e3d3aSJohn Baldwin break; 273*9c0e3d3aSJohn Baldwin } 274*9c0e3d3aSJohn Baldwin size -= todo; 275*9c0e3d3aSJohn Baldwin cc->cc_mbuf = cc->cc_mbuf->m_next; 276*9c0e3d3aSJohn Baldwin cc->cc_offset = 0; 277*9c0e3d3aSJohn Baldwin if (size == 0) 278*9c0e3d3aSJohn Baldwin break; 279*9c0e3d3aSJohn Baldwin } 280*9c0e3d3aSJohn Baldwin break; 281*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 282*9c0e3d3aSJohn Baldwin for (;;) { 283*9c0e3d3aSJohn Baldwin dst = (char *)cc->cc_iov->iov_base + cc->cc_offset; 284*9c0e3d3aSJohn Baldwin remain = cc->cc_iov->iov_len - cc->cc_offset; 285*9c0e3d3aSJohn Baldwin todo = MIN(remain, size); 286*9c0e3d3aSJohn Baldwin memcpy(dst, src, todo); 287*9c0e3d3aSJohn Baldwin dst += todo; 288*9c0e3d3aSJohn Baldwin if (todo < remain) { 289*9c0e3d3aSJohn Baldwin cc->cc_offset += todo; 290*9c0e3d3aSJohn Baldwin break; 291*9c0e3d3aSJohn Baldwin } 292*9c0e3d3aSJohn Baldwin size -= todo; 293*9c0e3d3aSJohn Baldwin cc->cc_iov++; 294*9c0e3d3aSJohn Baldwin cc->cc_offset = 0; 295*9c0e3d3aSJohn Baldwin if (size == 0) 296*9c0e3d3aSJohn Baldwin break; 297*9c0e3d3aSJohn Baldwin } 298*9c0e3d3aSJohn Baldwin break; 299*9c0e3d3aSJohn Baldwin default: 300*9c0e3d3aSJohn Baldwin #ifdef INVARIANTS 301*9c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cc->cc_type); 302*9c0e3d3aSJohn Baldwin #endif 303*9c0e3d3aSJohn Baldwin break; 304*9c0e3d3aSJohn Baldwin } 305*9c0e3d3aSJohn Baldwin } 306*9c0e3d3aSJohn Baldwin 307*9c0e3d3aSJohn Baldwin void 308*9c0e3d3aSJohn Baldwin crypto_cursor_copydata(struct crypto_buffer_cursor *cc, int size, void *vdst) 309*9c0e3d3aSJohn Baldwin { 310*9c0e3d3aSJohn Baldwin size_t remain, todo; 311*9c0e3d3aSJohn Baldwin const char *src; 312*9c0e3d3aSJohn Baldwin char *dst; 313*9c0e3d3aSJohn Baldwin 314*9c0e3d3aSJohn Baldwin dst = vdst; 315*9c0e3d3aSJohn Baldwin switch (cc->cc_type) { 316*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 317*9c0e3d3aSJohn Baldwin MPASS(cc->cc_buf_len >= size); 318*9c0e3d3aSJohn Baldwin memcpy(dst, cc->cc_buf, size); 319*9c0e3d3aSJohn Baldwin cc->cc_buf += size; 320*9c0e3d3aSJohn Baldwin cc->cc_buf_len -= size; 321*9c0e3d3aSJohn Baldwin break; 322*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 323*9c0e3d3aSJohn Baldwin for (;;) { 324*9c0e3d3aSJohn Baldwin KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0, 325*9c0e3d3aSJohn Baldwin ("%s: not supported for unmapped mbufs", __func__)); 326*9c0e3d3aSJohn Baldwin src = mtod(cc->cc_mbuf, const char *) + cc->cc_offset; 327*9c0e3d3aSJohn Baldwin remain = cc->cc_mbuf->m_len - cc->cc_offset; 328*9c0e3d3aSJohn Baldwin todo = MIN(remain, size); 329*9c0e3d3aSJohn Baldwin memcpy(dst, src, todo); 330*9c0e3d3aSJohn Baldwin dst += todo; 331*9c0e3d3aSJohn Baldwin if (todo < remain) { 332*9c0e3d3aSJohn Baldwin cc->cc_offset += todo; 333*9c0e3d3aSJohn Baldwin break; 334*9c0e3d3aSJohn Baldwin } 335*9c0e3d3aSJohn Baldwin size -= todo; 336*9c0e3d3aSJohn Baldwin cc->cc_mbuf = cc->cc_mbuf->m_next; 337*9c0e3d3aSJohn Baldwin cc->cc_offset = 0; 338*9c0e3d3aSJohn Baldwin if (size == 0) 339*9c0e3d3aSJohn Baldwin break; 340*9c0e3d3aSJohn Baldwin } 341*9c0e3d3aSJohn Baldwin break; 342*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 343*9c0e3d3aSJohn Baldwin for (;;) { 344*9c0e3d3aSJohn Baldwin src = (const char *)cc->cc_iov->iov_base + 345*9c0e3d3aSJohn Baldwin cc->cc_offset; 346*9c0e3d3aSJohn Baldwin remain = cc->cc_iov->iov_len - cc->cc_offset; 347*9c0e3d3aSJohn Baldwin todo = MIN(remain, size); 348*9c0e3d3aSJohn Baldwin memcpy(dst, src, todo); 349*9c0e3d3aSJohn Baldwin dst += todo; 350*9c0e3d3aSJohn Baldwin if (todo < remain) { 351*9c0e3d3aSJohn Baldwin cc->cc_offset += todo; 352*9c0e3d3aSJohn Baldwin break; 353*9c0e3d3aSJohn Baldwin } 354*9c0e3d3aSJohn Baldwin size -= todo; 355*9c0e3d3aSJohn Baldwin cc->cc_iov++; 356*9c0e3d3aSJohn Baldwin cc->cc_offset = 0; 357*9c0e3d3aSJohn Baldwin if (size == 0) 358*9c0e3d3aSJohn Baldwin break; 359*9c0e3d3aSJohn Baldwin } 360*9c0e3d3aSJohn Baldwin break; 361*9c0e3d3aSJohn Baldwin default: 362*9c0e3d3aSJohn Baldwin #ifdef INVARIANTS 363*9c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cc->cc_type); 364*9c0e3d3aSJohn Baldwin #endif 365*9c0e3d3aSJohn Baldwin break; 366*9c0e3d3aSJohn Baldwin } 367*9c0e3d3aSJohn Baldwin } 368*9c0e3d3aSJohn Baldwin 369*9c0e3d3aSJohn Baldwin /* 370*9c0e3d3aSJohn Baldwin * To avoid advancing 'cursor', make a local copy that gets advanced 371*9c0e3d3aSJohn Baldwin * instead. 372*9c0e3d3aSJohn Baldwin */ 373*9c0e3d3aSJohn Baldwin void 374*9c0e3d3aSJohn Baldwin crypto_cursor_copydata_noadv(struct crypto_buffer_cursor *cc, int size, 375*9c0e3d3aSJohn Baldwin void *vdst) 376*9c0e3d3aSJohn Baldwin { 377*9c0e3d3aSJohn Baldwin struct crypto_buffer_cursor copy; 378*9c0e3d3aSJohn Baldwin 379*9c0e3d3aSJohn Baldwin copy = *cc; 380*9c0e3d3aSJohn Baldwin crypto_cursor_copydata(©, size, vdst); 381*9c0e3d3aSJohn Baldwin } 382*9c0e3d3aSJohn Baldwin 3838f91d4abSPawel Jakub Dawidek /* 3848f91d4abSPawel Jakub Dawidek * Apply function f to the data in an iovec list starting "off" bytes from 3858f91d4abSPawel Jakub Dawidek * the beginning, continuing for "len" bytes. 3868f91d4abSPawel Jakub Dawidek */ 387*9c0e3d3aSJohn Baldwin static int 3888f91d4abSPawel Jakub Dawidek cuio_apply(struct uio *uio, int off, int len, int (*f)(void *, void *, u_int), 3898f91d4abSPawel Jakub Dawidek void *arg) 3908f91d4abSPawel Jakub Dawidek { 3918f91d4abSPawel Jakub Dawidek struct iovec *iov = uio->uio_iov; 3928f91d4abSPawel Jakub Dawidek int iol = uio->uio_iovcnt; 3938f91d4abSPawel Jakub Dawidek unsigned count; 3948f91d4abSPawel Jakub Dawidek int rval; 3958f91d4abSPawel Jakub Dawidek 3968f91d4abSPawel Jakub Dawidek CUIO_SKIP(); 3978f91d4abSPawel Jakub Dawidek while (len > 0) { 3988f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty", __func__)); 3998f91d4abSPawel Jakub Dawidek count = min(iov->iov_len - off, len); 4008f91d4abSPawel Jakub Dawidek rval = (*f)(arg, ((caddr_t)iov->iov_base) + off, count); 4018f91d4abSPawel Jakub Dawidek if (rval) 4028f91d4abSPawel Jakub Dawidek return (rval); 4038f91d4abSPawel Jakub Dawidek len -= count; 4048f91d4abSPawel Jakub Dawidek off = 0; 4058f91d4abSPawel Jakub Dawidek iol--; 4068f91d4abSPawel Jakub Dawidek iov++; 4078f91d4abSPawel Jakub Dawidek } 4088f91d4abSPawel Jakub Dawidek return (0); 4098f91d4abSPawel Jakub Dawidek } 41011d2e1e8SPawel Jakub Dawidek 41111d2e1e8SPawel Jakub Dawidek void 412c0341432SJohn Baldwin crypto_copyback(struct cryptop *crp, int off, int size, const void *src) 41311d2e1e8SPawel Jakub Dawidek { 414*9c0e3d3aSJohn Baldwin struct crypto_buffer *cb; 41511d2e1e8SPawel Jakub Dawidek 416*9c0e3d3aSJohn Baldwin if (crp->crp_obuf.cb_type != CRYPTO_BUF_NONE) 417*9c0e3d3aSJohn Baldwin cb = &crp->crp_obuf; 418*9c0e3d3aSJohn Baldwin else 419*9c0e3d3aSJohn Baldwin cb = &crp->crp_buf; 420*9c0e3d3aSJohn Baldwin switch (cb->cb_type) { 421c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 422*9c0e3d3aSJohn Baldwin m_copyback(cb->cb_mbuf, off, size, src); 423c0341432SJohn Baldwin break; 424c0341432SJohn Baldwin case CRYPTO_BUF_UIO: 425*9c0e3d3aSJohn Baldwin cuio_copyback(cb->cb_uio, off, size, src); 426c0341432SJohn Baldwin break; 427c0341432SJohn Baldwin case CRYPTO_BUF_CONTIG: 428*9c0e3d3aSJohn Baldwin MPASS(off + size <= cb->cb_buf_len); 429*9c0e3d3aSJohn Baldwin bcopy(src, cb->cb_buf + off, size); 430c0341432SJohn Baldwin break; 431c0341432SJohn Baldwin default: 432*9c0e3d3aSJohn Baldwin #ifdef INVARIANTS 433*9c0e3d3aSJohn Baldwin panic("invalid crp buf type %d", cb->cb_type); 434*9c0e3d3aSJohn Baldwin #endif 435*9c0e3d3aSJohn Baldwin break; 436c0341432SJohn Baldwin } 43711d2e1e8SPawel Jakub Dawidek } 43811d2e1e8SPawel Jakub Dawidek 43911d2e1e8SPawel Jakub Dawidek void 440c0341432SJohn Baldwin crypto_copydata(struct cryptop *crp, int off, int size, void *dst) 44111d2e1e8SPawel Jakub Dawidek { 44211d2e1e8SPawel Jakub Dawidek 443*9c0e3d3aSJohn Baldwin switch (crp->crp_buf.cb_type) { 444c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 445*9c0e3d3aSJohn Baldwin m_copydata(crp->crp_buf.cb_mbuf, off, size, dst); 446c0341432SJohn Baldwin break; 447c0341432SJohn Baldwin case CRYPTO_BUF_UIO: 448*9c0e3d3aSJohn Baldwin cuio_copydata(crp->crp_buf.cb_uio, off, size, dst); 449c0341432SJohn Baldwin break; 450c0341432SJohn Baldwin case CRYPTO_BUF_CONTIG: 451*9c0e3d3aSJohn Baldwin MPASS(off + size <= crp->crp_buf.cb_buf_len); 452*9c0e3d3aSJohn Baldwin bcopy(crp->crp_buf.cb_buf + off, dst, size); 453c0341432SJohn Baldwin break; 454c0341432SJohn Baldwin default: 455*9c0e3d3aSJohn Baldwin #ifdef INVARIANTS 456*9c0e3d3aSJohn Baldwin panic("invalid crp buf type %d", crp->crp_buf.cb_type); 457*9c0e3d3aSJohn Baldwin #endif 458*9c0e3d3aSJohn Baldwin break; 459c0341432SJohn Baldwin } 46011d2e1e8SPawel Jakub Dawidek } 46111d2e1e8SPawel Jakub Dawidek 46211d2e1e8SPawel Jakub Dawidek int 463*9c0e3d3aSJohn Baldwin crypto_apply_buf(struct crypto_buffer *cb, int off, int len, 464*9c0e3d3aSJohn Baldwin int (*f)(void *, void *, u_int), void *arg) 465*9c0e3d3aSJohn Baldwin { 466*9c0e3d3aSJohn Baldwin int error; 467*9c0e3d3aSJohn Baldwin 468*9c0e3d3aSJohn Baldwin switch (cb->cb_type) { 469*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 470*9c0e3d3aSJohn Baldwin error = m_apply(cb->cb_mbuf, off, len, f, arg); 471*9c0e3d3aSJohn Baldwin break; 472*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 473*9c0e3d3aSJohn Baldwin error = cuio_apply(cb->cb_uio, off, len, f, arg); 474*9c0e3d3aSJohn Baldwin break; 475*9c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 476*9c0e3d3aSJohn Baldwin MPASS(off + len <= cb->cb_buf_len); 477*9c0e3d3aSJohn Baldwin error = (*f)(arg, cb->cb_buf + off, len); 478*9c0e3d3aSJohn Baldwin break; 479*9c0e3d3aSJohn Baldwin default: 480*9c0e3d3aSJohn Baldwin #ifdef INVARIANTS 481*9c0e3d3aSJohn Baldwin panic("invalid crypto buf type %d", cb->cb_type); 482*9c0e3d3aSJohn Baldwin #endif 483*9c0e3d3aSJohn Baldwin error = 0; 484*9c0e3d3aSJohn Baldwin break; 485*9c0e3d3aSJohn Baldwin } 486*9c0e3d3aSJohn Baldwin return (error); 487*9c0e3d3aSJohn Baldwin } 488*9c0e3d3aSJohn Baldwin 489*9c0e3d3aSJohn Baldwin int 490c0341432SJohn Baldwin crypto_apply(struct cryptop *crp, int off, int len, 49111d2e1e8SPawel Jakub Dawidek int (*f)(void *, void *, u_int), void *arg) 49211d2e1e8SPawel Jakub Dawidek { 493*9c0e3d3aSJohn Baldwin return (crypto_apply_buf(&crp->crp_buf, off, len, f, arg)); 49408fca7a5SJohn-Mark Gurney } 495ff2038a9SMatt Macy 496ff2038a9SMatt Macy static inline void * 497ff2038a9SMatt Macy m_contiguous_subsegment(struct mbuf *m, size_t skip, size_t len) 498ff2038a9SMatt Macy { 499ff2038a9SMatt Macy int rel_off; 500ff2038a9SMatt Macy 501ff2038a9SMatt Macy MPASS(skip <= INT_MAX); 502ff2038a9SMatt Macy 503ff2038a9SMatt Macy m = m_getptr(m, (int)skip, &rel_off); 504ff2038a9SMatt Macy if (m == NULL) 505ff2038a9SMatt Macy return (NULL); 506ff2038a9SMatt Macy 507ff2038a9SMatt Macy MPASS(rel_off >= 0); 508ff2038a9SMatt Macy skip = rel_off; 509ff2038a9SMatt Macy if (skip + len > m->m_len) 510ff2038a9SMatt Macy return (NULL); 511ff2038a9SMatt Macy 512ff2038a9SMatt Macy return (mtod(m, char*) + skip); 513ff2038a9SMatt Macy } 514ff2038a9SMatt Macy 515ff2038a9SMatt Macy static inline void * 516ff2038a9SMatt Macy cuio_contiguous_segment(struct uio *uio, size_t skip, size_t len) 517ff2038a9SMatt Macy { 518ff2038a9SMatt Macy int rel_off, idx; 519ff2038a9SMatt Macy 520ff2038a9SMatt Macy MPASS(skip <= INT_MAX); 521ff2038a9SMatt Macy idx = cuio_getptr(uio, (int)skip, &rel_off); 522ff2038a9SMatt Macy if (idx < 0) 523ff2038a9SMatt Macy return (NULL); 524ff2038a9SMatt Macy 525ff2038a9SMatt Macy MPASS(rel_off >= 0); 526ff2038a9SMatt Macy skip = rel_off; 527ff2038a9SMatt Macy if (skip + len > uio->uio_iov[idx].iov_len) 528ff2038a9SMatt Macy return (NULL); 529ff2038a9SMatt Macy return ((char *)uio->uio_iov[idx].iov_base + skip); 530ff2038a9SMatt Macy } 531ff2038a9SMatt Macy 532ff2038a9SMatt Macy void * 533*9c0e3d3aSJohn Baldwin crypto_buffer_contiguous_subsegment(struct crypto_buffer *cb, size_t skip, 534*9c0e3d3aSJohn Baldwin size_t len) 535ff2038a9SMatt Macy { 536ff2038a9SMatt Macy 537*9c0e3d3aSJohn Baldwin switch (cb->cb_type) { 538c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 539*9c0e3d3aSJohn Baldwin return (m_contiguous_subsegment(cb->cb_mbuf, skip, len)); 540c0341432SJohn Baldwin case CRYPTO_BUF_UIO: 541*9c0e3d3aSJohn Baldwin return (cuio_contiguous_segment(cb->cb_uio, skip, len)); 542c0341432SJohn Baldwin case CRYPTO_BUF_CONTIG: 543*9c0e3d3aSJohn Baldwin MPASS(skip + len <= cb->cb_buf_len); 544*9c0e3d3aSJohn Baldwin return (cb->cb_buf + skip); 545c0341432SJohn Baldwin default: 546*9c0e3d3aSJohn Baldwin #ifdef INVARIANTS 547*9c0e3d3aSJohn Baldwin panic("invalid crp buf type %d", cb->cb_type); 548*9c0e3d3aSJohn Baldwin #endif 549*9c0e3d3aSJohn Baldwin return (NULL); 550c0341432SJohn Baldwin } 551c0341432SJohn Baldwin } 552*9c0e3d3aSJohn Baldwin 553*9c0e3d3aSJohn Baldwin void * 554*9c0e3d3aSJohn Baldwin crypto_contiguous_subsegment(struct cryptop *crp, size_t skip, size_t len) 555*9c0e3d3aSJohn Baldwin { 556*9c0e3d3aSJohn Baldwin return (crypto_buffer_contiguous_subsegment(&crp->crp_buf, skip, len)); 557*9c0e3d3aSJohn Baldwin } 558