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> 43e6f6d0c9SAlan Somers #include <sys/sdt.h> 44e6f6d0c9SAlan Somers 45e6f6d0c9SAlan Somers #include <machine/vmparam.h> 46e6f6d0c9SAlan Somers 47e6f6d0c9SAlan Somers #include <vm/vm.h> 48e6f6d0c9SAlan Somers #include <vm/vm_page.h> 49e6f6d0c9SAlan Somers #include <vm/pmap.h> 50091d81d1SSam Leffler 51091d81d1SSam Leffler #include <opencrypto/cryptodev.h> 52091d81d1SSam Leffler 53e6f6d0c9SAlan Somers SDT_PROVIDER_DECLARE(opencrypto); 54e6f6d0c9SAlan Somers 558f91d4abSPawel Jakub Dawidek /* 56e6f6d0c9SAlan Somers * These macros are only for avoiding code duplication, as we need to skip 57e6f6d0c9SAlan Somers * given number of bytes in the same way in several functions below. 588f91d4abSPawel Jakub Dawidek */ 598f91d4abSPawel Jakub Dawidek #define CUIO_SKIP() do { \ 608f91d4abSPawel Jakub Dawidek KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \ 618f91d4abSPawel Jakub Dawidek KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \ 628f91d4abSPawel Jakub Dawidek while (off > 0) { \ 638f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty in skip", __func__)); \ 648f91d4abSPawel Jakub Dawidek if (off < iov->iov_len) \ 658f91d4abSPawel Jakub Dawidek break; \ 668f91d4abSPawel Jakub Dawidek off -= iov->iov_len; \ 678f91d4abSPawel Jakub Dawidek iol--; \ 688f91d4abSPawel Jakub Dawidek iov++; \ 698f91d4abSPawel Jakub Dawidek } \ 708f91d4abSPawel Jakub Dawidek } while (0) 718f91d4abSPawel Jakub Dawidek 72e6f6d0c9SAlan Somers #define CVM_PAGE_SKIP() do { \ 73e6f6d0c9SAlan Somers KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \ 74e6f6d0c9SAlan Somers KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \ 75e6f6d0c9SAlan Somers while (off > 0) { \ 76e6f6d0c9SAlan Somers if (off < PAGE_SIZE) \ 77e6f6d0c9SAlan Somers break; \ 78e6f6d0c9SAlan Somers processed += PAGE_SIZE - off; \ 79e6f6d0c9SAlan Somers off -= PAGE_SIZE - off; \ 80e6f6d0c9SAlan Somers pages++; \ 81e6f6d0c9SAlan Somers } \ 82e6f6d0c9SAlan Somers } while (0) 83e6f6d0c9SAlan Somers 849c0e3d3aSJohn Baldwin static void 85091d81d1SSam Leffler cuio_copydata(struct uio* uio, int off, int len, caddr_t cp) 86091d81d1SSam Leffler { 87091d81d1SSam Leffler struct iovec *iov = uio->uio_iov; 88091d81d1SSam Leffler int iol = uio->uio_iovcnt; 89091d81d1SSam Leffler unsigned count; 90091d81d1SSam Leffler 918f91d4abSPawel Jakub Dawidek CUIO_SKIP(); 92091d81d1SSam Leffler while (len > 0) { 938f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty", __func__)); 94091d81d1SSam Leffler count = min(iov->iov_len - off, len); 95091d81d1SSam Leffler bcopy(((caddr_t)iov->iov_base) + off, cp, count); 96091d81d1SSam Leffler len -= count; 97091d81d1SSam Leffler cp += count; 98091d81d1SSam Leffler off = 0; 99091d81d1SSam Leffler iol--; 100091d81d1SSam Leffler iov++; 101091d81d1SSam Leffler } 102091d81d1SSam Leffler } 103091d81d1SSam Leffler 1049c0e3d3aSJohn Baldwin static void 1057dd10fdeSJohn Baldwin cuio_copyback(struct uio* uio, int off, int len, c_caddr_t cp) 106091d81d1SSam Leffler { 107091d81d1SSam Leffler struct iovec *iov = uio->uio_iov; 108091d81d1SSam Leffler int iol = uio->uio_iovcnt; 109091d81d1SSam Leffler unsigned count; 110091d81d1SSam Leffler 1118f91d4abSPawel Jakub Dawidek CUIO_SKIP(); 112091d81d1SSam Leffler while (len > 0) { 1138f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty", __func__)); 114091d81d1SSam Leffler count = min(iov->iov_len - off, len); 115091d81d1SSam Leffler bcopy(cp, ((caddr_t)iov->iov_base) + off, count); 116091d81d1SSam Leffler len -= count; 117091d81d1SSam Leffler cp += count; 118091d81d1SSam Leffler off = 0; 119091d81d1SSam Leffler iol--; 120091d81d1SSam Leffler iov++; 121091d81d1SSam Leffler } 122091d81d1SSam Leffler } 123091d81d1SSam Leffler 124091d81d1SSam Leffler /* 12508fca7a5SJohn-Mark Gurney * Return the index and offset of location in iovec list. 126091d81d1SSam Leffler */ 1279c0e3d3aSJohn Baldwin static int 128091d81d1SSam Leffler cuio_getptr(struct uio *uio, int loc, int *off) 129091d81d1SSam Leffler { 13008fca7a5SJohn-Mark Gurney int ind, len; 131091d81d1SSam Leffler 13208fca7a5SJohn-Mark Gurney ind = 0; 13308fca7a5SJohn-Mark Gurney while (loc >= 0 && ind < uio->uio_iovcnt) { 13408fca7a5SJohn-Mark Gurney len = uio->uio_iov[ind].iov_len; 13508fca7a5SJohn-Mark Gurney if (len > loc) { 136091d81d1SSam Leffler *off = loc; 13708fca7a5SJohn-Mark Gurney return (ind); 13808fca7a5SJohn-Mark Gurney } 13908fca7a5SJohn-Mark Gurney loc -= len; 14008fca7a5SJohn-Mark Gurney ind++; 141091d81d1SSam Leffler } 142091d81d1SSam Leffler 14308fca7a5SJohn-Mark Gurney if (ind > 0 && loc == 0) { 14408fca7a5SJohn-Mark Gurney ind--; 14508fca7a5SJohn-Mark Gurney *off = uio->uio_iov[ind].iov_len; 14608fca7a5SJohn-Mark Gurney return (ind); 147091d81d1SSam Leffler } 148091d81d1SSam Leffler 14908fca7a5SJohn-Mark Gurney return (-1); 150091d81d1SSam Leffler } 1518f91d4abSPawel Jakub Dawidek 152e6f6d0c9SAlan Somers #if CRYPTO_MAY_HAVE_VMPAGE 153e6f6d0c9SAlan Somers /* 154e6f6d0c9SAlan Somers * Apply function f to the data in a vm_page_t list starting "off" bytes from 155e6f6d0c9SAlan Somers * the beginning, continuing for "len" bytes. 156e6f6d0c9SAlan Somers */ 157e6f6d0c9SAlan Somers static int 158e6f6d0c9SAlan Somers cvm_page_apply(vm_page_t *pages, int off, int len, 159e6f6d0c9SAlan Somers int (*f)(void *, const void *, u_int), void *arg) 160e6f6d0c9SAlan Somers { 161e6f6d0c9SAlan Somers int processed = 0; 162e6f6d0c9SAlan Somers unsigned count; 163e6f6d0c9SAlan Somers int rval; 164e6f6d0c9SAlan Somers 165e6f6d0c9SAlan Somers CVM_PAGE_SKIP(); 166e6f6d0c9SAlan Somers while (len > 0) { 167e6f6d0c9SAlan Somers char *kaddr = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages)); 168e6f6d0c9SAlan Somers count = min(PAGE_SIZE - off, len); 169e6f6d0c9SAlan Somers rval = (*f)(arg, kaddr + off, count); 170e6f6d0c9SAlan Somers if (rval) 171e6f6d0c9SAlan Somers return (rval); 172e6f6d0c9SAlan Somers len -= count; 173e6f6d0c9SAlan Somers processed += count; 174e6f6d0c9SAlan Somers off = 0; 175e6f6d0c9SAlan Somers pages++; 176e6f6d0c9SAlan Somers } 177e6f6d0c9SAlan Somers return (0); 178e6f6d0c9SAlan Somers } 179e6f6d0c9SAlan Somers 180e6f6d0c9SAlan Somers static inline void * 181e6f6d0c9SAlan Somers cvm_page_contiguous_segment(vm_page_t *pages, size_t skip, int len) 182e6f6d0c9SAlan Somers { 183e6f6d0c9SAlan Somers if ((skip + len - 1) / PAGE_SIZE > skip / PAGE_SIZE) 184e6f6d0c9SAlan Somers return (NULL); 185e6f6d0c9SAlan Somers 186e6f6d0c9SAlan Somers pages += (skip / PAGE_SIZE); 187e6f6d0c9SAlan Somers skip -= rounddown(skip, PAGE_SIZE); 188e6f6d0c9SAlan Somers return (((char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages))) + skip); 189e6f6d0c9SAlan Somers } 190e6f6d0c9SAlan Somers 191e6f6d0c9SAlan Somers /* 192e6f6d0c9SAlan Somers * Copy len bytes of data from the vm_page_t array, skipping the first off 193e6f6d0c9SAlan Somers * bytes, into the pointer cp. Return the number of bytes skipped and copied. 194e6f6d0c9SAlan Somers * Does not verify the length of the array. 195e6f6d0c9SAlan Somers */ 196e6f6d0c9SAlan Somers static int 197e6f6d0c9SAlan Somers cvm_page_copyback(vm_page_t *pages, int off, int len, c_caddr_t cp) 198e6f6d0c9SAlan Somers { 199e6f6d0c9SAlan Somers int processed = 0; 200e6f6d0c9SAlan Somers unsigned count; 201e6f6d0c9SAlan Somers 202e6f6d0c9SAlan Somers CVM_PAGE_SKIP(); 203e6f6d0c9SAlan Somers while (len > 0) { 204e6f6d0c9SAlan Somers count = min(PAGE_SIZE - off, len); 205e6f6d0c9SAlan Somers bcopy(cp, (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages)) + off, 206e6f6d0c9SAlan Somers count); 207e6f6d0c9SAlan Somers len -= count; 208e6f6d0c9SAlan Somers cp += count; 209e6f6d0c9SAlan Somers processed += count; 210e6f6d0c9SAlan Somers off = 0; 211e6f6d0c9SAlan Somers pages++; 212e6f6d0c9SAlan Somers } 213e6f6d0c9SAlan Somers return (processed); 214e6f6d0c9SAlan Somers } 215e6f6d0c9SAlan Somers 216e6f6d0c9SAlan Somers /* 217e6f6d0c9SAlan Somers * Copy len bytes of data from the pointer cp into the vm_page_t array, 218e6f6d0c9SAlan Somers * skipping the first off bytes, Return the number of bytes skipped and copied. 219e6f6d0c9SAlan Somers * Does not verify the length of the array. 220e6f6d0c9SAlan Somers */ 221e6f6d0c9SAlan Somers static int 222e6f6d0c9SAlan Somers cvm_page_copydata(vm_page_t *pages, int off, int len, caddr_t cp) 223e6f6d0c9SAlan Somers { 224e6f6d0c9SAlan Somers int processed = 0; 225e6f6d0c9SAlan Somers unsigned count; 226e6f6d0c9SAlan Somers 227e6f6d0c9SAlan Somers CVM_PAGE_SKIP(); 228e6f6d0c9SAlan Somers while (len > 0) { 229e6f6d0c9SAlan Somers count = min(PAGE_SIZE - off, len); 230e6f6d0c9SAlan Somers bcopy(((char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages)) + off), cp, 231e6f6d0c9SAlan Somers count); 232e6f6d0c9SAlan Somers len -= count; 233e6f6d0c9SAlan Somers cp += count; 234e6f6d0c9SAlan Somers processed += count; 235e6f6d0c9SAlan Somers off = 0; 236e6f6d0c9SAlan Somers pages++; 237e6f6d0c9SAlan Somers } 238e6f6d0c9SAlan Somers return processed; 239e6f6d0c9SAlan Somers } 240e6f6d0c9SAlan Somers #endif /* CRYPTO_MAY_HAVE_VMPAGE */ 241e6f6d0c9SAlan Somers 2421c8f4b3cSJohn Baldwin /* 2431c8f4b3cSJohn Baldwin * Given a starting page in an m_epg, determine the length of the 2441c8f4b3cSJohn Baldwin * current physically contiguous segment. 2451c8f4b3cSJohn Baldwin */ 2461c8f4b3cSJohn Baldwin static __inline size_t 2471c8f4b3cSJohn Baldwin m_epg_pages_extent(struct mbuf *m, int idx, u_int pglen) 2481c8f4b3cSJohn Baldwin { 2491c8f4b3cSJohn Baldwin size_t len; 2501c8f4b3cSJohn Baldwin u_int i; 2511c8f4b3cSJohn Baldwin 2521c8f4b3cSJohn Baldwin len = pglen; 2531c8f4b3cSJohn Baldwin for (i = idx + 1; i < m->m_epg_npgs; i++) { 2541c8f4b3cSJohn Baldwin if (m->m_epg_pa[i - 1] + PAGE_SIZE != m->m_epg_pa[i]) 2551c8f4b3cSJohn Baldwin break; 2561c8f4b3cSJohn Baldwin len += m_epg_pagelen(m, i, 0); 2571c8f4b3cSJohn Baldwin } 2581c8f4b3cSJohn Baldwin return (len); 2591c8f4b3cSJohn Baldwin } 2601c8f4b3cSJohn Baldwin 2611c8f4b3cSJohn Baldwin static __inline void * 2621c8f4b3cSJohn Baldwin m_epg_segbase(struct mbuf *m, size_t offset) 2631c8f4b3cSJohn Baldwin { 2641c8f4b3cSJohn Baldwin u_int i, pglen, pgoff; 2651c8f4b3cSJohn Baldwin 2661c8f4b3cSJohn Baldwin offset += mtod(m, vm_offset_t); 2671c8f4b3cSJohn Baldwin if (offset < m->m_epg_hdrlen) 2681c8f4b3cSJohn Baldwin return (m->m_epg_hdr + offset); 2691c8f4b3cSJohn Baldwin offset -= m->m_epg_hdrlen; 2701c8f4b3cSJohn Baldwin pgoff = m->m_epg_1st_off; 2711c8f4b3cSJohn Baldwin for (i = 0; i < m->m_epg_npgs; i++) { 2721c8f4b3cSJohn Baldwin pglen = m_epg_pagelen(m, i, pgoff); 2731c8f4b3cSJohn Baldwin if (offset < pglen) 2741c8f4b3cSJohn Baldwin return ((void *)PHYS_TO_DMAP(m->m_epg_pa[i] + pgoff + 2751c8f4b3cSJohn Baldwin offset)); 2761c8f4b3cSJohn Baldwin offset -= pglen; 2771c8f4b3cSJohn Baldwin pgoff = 0; 2781c8f4b3cSJohn Baldwin } 2791c8f4b3cSJohn Baldwin KASSERT(offset <= m->m_epg_trllen, ("%s: offset beyond trailer", 2801c8f4b3cSJohn Baldwin __func__)); 2811c8f4b3cSJohn Baldwin return (m->m_epg_trail + offset); 2821c8f4b3cSJohn Baldwin } 2831c8f4b3cSJohn Baldwin 2841c8f4b3cSJohn Baldwin static __inline size_t 2851c8f4b3cSJohn Baldwin m_epg_seglen(struct mbuf *m, size_t offset) 2861c8f4b3cSJohn Baldwin { 2871c8f4b3cSJohn Baldwin u_int i, pglen, pgoff; 2881c8f4b3cSJohn Baldwin 2891c8f4b3cSJohn Baldwin offset += mtod(m, vm_offset_t); 2901c8f4b3cSJohn Baldwin if (offset < m->m_epg_hdrlen) 2911c8f4b3cSJohn Baldwin return (m->m_epg_hdrlen - offset); 2921c8f4b3cSJohn Baldwin offset -= m->m_epg_hdrlen; 2931c8f4b3cSJohn Baldwin pgoff = m->m_epg_1st_off; 2941c8f4b3cSJohn Baldwin for (i = 0; i < m->m_epg_npgs; i++) { 2951c8f4b3cSJohn Baldwin pglen = m_epg_pagelen(m, i, pgoff); 2961c8f4b3cSJohn Baldwin if (offset < pglen) 2971c8f4b3cSJohn Baldwin return (m_epg_pages_extent(m, i, pglen) - offset); 2981c8f4b3cSJohn Baldwin offset -= pglen; 2991c8f4b3cSJohn Baldwin pgoff = 0; 3001c8f4b3cSJohn Baldwin } 3011c8f4b3cSJohn Baldwin KASSERT(offset <= m->m_epg_trllen, ("%s: offset beyond trailer", 3021c8f4b3cSJohn Baldwin __func__)); 3031c8f4b3cSJohn Baldwin return (m->m_epg_trllen - offset); 3041c8f4b3cSJohn Baldwin } 3051c8f4b3cSJohn Baldwin 3061c8f4b3cSJohn Baldwin static __inline void * 3071c8f4b3cSJohn Baldwin m_epg_contiguous_subsegment(struct mbuf *m, size_t skip, size_t len) 3081c8f4b3cSJohn Baldwin { 3091c8f4b3cSJohn Baldwin u_int i, pglen, pgoff; 3101c8f4b3cSJohn Baldwin 3111c8f4b3cSJohn Baldwin skip += mtod(m, vm_offset_t); 3121c8f4b3cSJohn Baldwin if (skip < m->m_epg_hdrlen) { 3131c8f4b3cSJohn Baldwin if (len > m->m_epg_hdrlen - skip) 3141c8f4b3cSJohn Baldwin return (NULL); 3151c8f4b3cSJohn Baldwin return (m->m_epg_hdr + skip); 3161c8f4b3cSJohn Baldwin } 3171c8f4b3cSJohn Baldwin skip -= m->m_epg_hdrlen; 3181c8f4b3cSJohn Baldwin pgoff = m->m_epg_1st_off; 3191c8f4b3cSJohn Baldwin for (i = 0; i < m->m_epg_npgs; i++) { 3201c8f4b3cSJohn Baldwin pglen = m_epg_pagelen(m, i, pgoff); 3211c8f4b3cSJohn Baldwin if (skip < pglen) { 3221c8f4b3cSJohn Baldwin if (len > m_epg_pages_extent(m, i, pglen) - skip) 3231c8f4b3cSJohn Baldwin return (NULL); 3241c8f4b3cSJohn Baldwin return ((void *)PHYS_TO_DMAP(m->m_epg_pa[i] + pgoff + 3251c8f4b3cSJohn Baldwin skip)); 3261c8f4b3cSJohn Baldwin } 3271c8f4b3cSJohn Baldwin skip -= pglen; 3281c8f4b3cSJohn Baldwin pgoff = 0; 3291c8f4b3cSJohn Baldwin } 3301c8f4b3cSJohn Baldwin KASSERT(skip <= m->m_epg_trllen && len <= m->m_epg_trllen - skip, 3311c8f4b3cSJohn Baldwin ("%s: segment beyond trailer", __func__)); 3321c8f4b3cSJohn Baldwin return (m->m_epg_trail + skip); 3331c8f4b3cSJohn Baldwin } 3341c8f4b3cSJohn Baldwin 3359c0e3d3aSJohn Baldwin void 3369c0e3d3aSJohn Baldwin crypto_cursor_init(struct crypto_buffer_cursor *cc, 3379c0e3d3aSJohn Baldwin const struct crypto_buffer *cb) 3389c0e3d3aSJohn Baldwin { 3399c0e3d3aSJohn Baldwin memset(cc, 0, sizeof(*cc)); 3409c0e3d3aSJohn Baldwin cc->cc_type = cb->cb_type; 3419c0e3d3aSJohn Baldwin switch (cc->cc_type) { 3429c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 3439c0e3d3aSJohn Baldwin cc->cc_buf = cb->cb_buf; 3449c0e3d3aSJohn Baldwin cc->cc_buf_len = cb->cb_buf_len; 3459c0e3d3aSJohn Baldwin break; 3469c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 347*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 3489c0e3d3aSJohn Baldwin cc->cc_mbuf = cb->cb_mbuf; 3499c0e3d3aSJohn Baldwin break; 350e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 351e6f6d0c9SAlan Somers cc->cc_vmpage = cb->cb_vm_page; 352e6f6d0c9SAlan Somers cc->cc_buf_len = cb->cb_vm_page_len; 353e6f6d0c9SAlan Somers cc->cc_offset = cb->cb_vm_page_offset; 354e6f6d0c9SAlan Somers break; 3559c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 3569c0e3d3aSJohn Baldwin cc->cc_iov = cb->cb_uio->uio_iov; 3579c0e3d3aSJohn Baldwin break; 3589c0e3d3aSJohn Baldwin default: 3599c0e3d3aSJohn Baldwin #ifdef INVARIANTS 3609c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cb->cb_type); 3619c0e3d3aSJohn Baldwin #endif 3629c0e3d3aSJohn Baldwin break; 3639c0e3d3aSJohn Baldwin } 3649c0e3d3aSJohn Baldwin } 3659c0e3d3aSJohn Baldwin 366e6f6d0c9SAlan Somers SDT_PROBE_DEFINE2(opencrypto, criov, cursor_advance, vmpage, "struct crypto_buffer_cursor*", "size_t"); 367e6f6d0c9SAlan Somers 3689c0e3d3aSJohn Baldwin void 3699c0e3d3aSJohn Baldwin crypto_cursor_advance(struct crypto_buffer_cursor *cc, size_t amount) 3709c0e3d3aSJohn Baldwin { 3719c0e3d3aSJohn Baldwin size_t remain; 3729c0e3d3aSJohn Baldwin 3739c0e3d3aSJohn Baldwin switch (cc->cc_type) { 3749c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 3759c0e3d3aSJohn Baldwin MPASS(cc->cc_buf_len >= amount); 3769c0e3d3aSJohn Baldwin cc->cc_buf += amount; 3779c0e3d3aSJohn Baldwin cc->cc_buf_len -= amount; 3789c0e3d3aSJohn Baldwin break; 3799c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 3809c0e3d3aSJohn Baldwin for (;;) { 3819c0e3d3aSJohn Baldwin remain = cc->cc_mbuf->m_len - cc->cc_offset; 3829c0e3d3aSJohn Baldwin if (amount < remain) { 3839c0e3d3aSJohn Baldwin cc->cc_offset += amount; 3849c0e3d3aSJohn Baldwin break; 3859c0e3d3aSJohn Baldwin } 3869c0e3d3aSJohn Baldwin amount -= remain; 3879c0e3d3aSJohn Baldwin cc->cc_mbuf = cc->cc_mbuf->m_next; 3889c0e3d3aSJohn Baldwin cc->cc_offset = 0; 3899c0e3d3aSJohn Baldwin if (amount == 0) 3909c0e3d3aSJohn Baldwin break; 3919c0e3d3aSJohn Baldwin } 3929c0e3d3aSJohn Baldwin break; 393*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 394*883a0196SJohn Baldwin MPASS(cc->cc_mbuf->m_len >= cc->cc_offset + amount); 395*883a0196SJohn Baldwin cc->cc_offset += amount; 396*883a0196SJohn Baldwin break; 397e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 398e6f6d0c9SAlan Somers for (;;) { 399e6f6d0c9SAlan Somers SDT_PROBE2(opencrypto, criov, cursor_advance, vmpage, 400e6f6d0c9SAlan Somers cc, amount); 401e6f6d0c9SAlan Somers remain = MIN(PAGE_SIZE - cc->cc_offset, cc->cc_buf_len); 402e6f6d0c9SAlan Somers if (amount < remain) { 403e6f6d0c9SAlan Somers cc->cc_buf_len -= amount; 404e6f6d0c9SAlan Somers cc->cc_offset += amount; 405e6f6d0c9SAlan Somers break; 406e6f6d0c9SAlan Somers } 407e6f6d0c9SAlan Somers cc->cc_buf_len -= remain; 408e6f6d0c9SAlan Somers amount -= remain; 409e6f6d0c9SAlan Somers cc->cc_vmpage++; 410e6f6d0c9SAlan Somers cc->cc_offset = 0; 411e6f6d0c9SAlan Somers if (amount == 0 || cc->cc_buf_len == 0) 412e6f6d0c9SAlan Somers break; 413e6f6d0c9SAlan Somers } 414e6f6d0c9SAlan Somers break; 4159c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 4169c0e3d3aSJohn Baldwin for (;;) { 4179c0e3d3aSJohn Baldwin remain = cc->cc_iov->iov_len - cc->cc_offset; 4189c0e3d3aSJohn Baldwin if (amount < remain) { 4199c0e3d3aSJohn Baldwin cc->cc_offset += amount; 4209c0e3d3aSJohn Baldwin break; 4219c0e3d3aSJohn Baldwin } 4229c0e3d3aSJohn Baldwin amount -= remain; 4239c0e3d3aSJohn Baldwin cc->cc_iov++; 4249c0e3d3aSJohn Baldwin cc->cc_offset = 0; 4259c0e3d3aSJohn Baldwin if (amount == 0) 4269c0e3d3aSJohn Baldwin break; 4279c0e3d3aSJohn Baldwin } 4289c0e3d3aSJohn Baldwin break; 4299c0e3d3aSJohn Baldwin default: 4309c0e3d3aSJohn Baldwin #ifdef INVARIANTS 4319c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cc->cc_type); 4329c0e3d3aSJohn Baldwin #endif 4339c0e3d3aSJohn Baldwin break; 4349c0e3d3aSJohn Baldwin } 4359c0e3d3aSJohn Baldwin } 4369c0e3d3aSJohn Baldwin 4379c0e3d3aSJohn Baldwin void * 4389c0e3d3aSJohn Baldwin crypto_cursor_segbase(struct crypto_buffer_cursor *cc) 4399c0e3d3aSJohn Baldwin { 4409c0e3d3aSJohn Baldwin switch (cc->cc_type) { 4419c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 4429c0e3d3aSJohn Baldwin return (cc->cc_buf); 4439c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 444*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 4459c0e3d3aSJohn Baldwin if (cc->cc_mbuf == NULL) 4469c0e3d3aSJohn Baldwin return (NULL); 4471c8f4b3cSJohn Baldwin if (cc->cc_mbuf->m_flags & M_EXTPG) 4481c8f4b3cSJohn Baldwin return (m_epg_segbase(cc->cc_mbuf, cc->cc_offset)); 4499c0e3d3aSJohn Baldwin return (mtod(cc->cc_mbuf, char *) + cc->cc_offset); 450e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 451e6f6d0c9SAlan Somers return ((char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS( 452e6f6d0c9SAlan Somers *cc->cc_vmpage)) + cc->cc_offset); 4539c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 4549c0e3d3aSJohn Baldwin return ((char *)cc->cc_iov->iov_base + cc->cc_offset); 4559c0e3d3aSJohn Baldwin default: 4569c0e3d3aSJohn Baldwin #ifdef INVARIANTS 4579c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cc->cc_type); 4589c0e3d3aSJohn Baldwin #endif 4599c0e3d3aSJohn Baldwin return (NULL); 4609c0e3d3aSJohn Baldwin } 4619c0e3d3aSJohn Baldwin } 4629c0e3d3aSJohn Baldwin 4639c0e3d3aSJohn Baldwin size_t 4649c0e3d3aSJohn Baldwin crypto_cursor_seglen(struct crypto_buffer_cursor *cc) 4659c0e3d3aSJohn Baldwin { 4669c0e3d3aSJohn Baldwin switch (cc->cc_type) { 4679c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 4689c0e3d3aSJohn Baldwin return (cc->cc_buf_len); 469e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 470e6f6d0c9SAlan Somers return (PAGE_SIZE - cc->cc_offset); 4719c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 472*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 4739c0e3d3aSJohn Baldwin if (cc->cc_mbuf == NULL) 4749c0e3d3aSJohn Baldwin return (0); 4751c8f4b3cSJohn Baldwin if (cc->cc_mbuf->m_flags & M_EXTPG) 4761c8f4b3cSJohn Baldwin return (m_epg_seglen(cc->cc_mbuf, cc->cc_offset)); 4779c0e3d3aSJohn Baldwin return (cc->cc_mbuf->m_len - cc->cc_offset); 4789c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 4799c0e3d3aSJohn Baldwin return (cc->cc_iov->iov_len - cc->cc_offset); 4809c0e3d3aSJohn Baldwin default: 4819c0e3d3aSJohn Baldwin #ifdef INVARIANTS 4829c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cc->cc_type); 4839c0e3d3aSJohn Baldwin #endif 4849c0e3d3aSJohn Baldwin return (0); 4859c0e3d3aSJohn Baldwin } 4869c0e3d3aSJohn Baldwin } 4879c0e3d3aSJohn Baldwin 4889c0e3d3aSJohn Baldwin void 4899c0e3d3aSJohn Baldwin crypto_cursor_copyback(struct crypto_buffer_cursor *cc, int size, 4909c0e3d3aSJohn Baldwin const void *vsrc) 4919c0e3d3aSJohn Baldwin { 4929c0e3d3aSJohn Baldwin size_t remain, todo; 4939c0e3d3aSJohn Baldwin const char *src; 4949c0e3d3aSJohn Baldwin char *dst; 4959c0e3d3aSJohn Baldwin 4969c0e3d3aSJohn Baldwin src = vsrc; 4979c0e3d3aSJohn Baldwin switch (cc->cc_type) { 4989c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 4999c0e3d3aSJohn Baldwin MPASS(cc->cc_buf_len >= size); 5009c0e3d3aSJohn Baldwin memcpy(cc->cc_buf, src, size); 5019c0e3d3aSJohn Baldwin cc->cc_buf += size; 5029c0e3d3aSJohn Baldwin cc->cc_buf_len -= size; 5039c0e3d3aSJohn Baldwin break; 5049c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 5059c0e3d3aSJohn Baldwin for (;;) { 5061c8f4b3cSJohn Baldwin /* 5071c8f4b3cSJohn Baldwin * This uses m_copyback() for individual 5081c8f4b3cSJohn Baldwin * mbufs so that cc_mbuf and cc_offset are 5091c8f4b3cSJohn Baldwin * updated. 5101c8f4b3cSJohn Baldwin */ 5119c0e3d3aSJohn Baldwin remain = cc->cc_mbuf->m_len - cc->cc_offset; 5129c0e3d3aSJohn Baldwin todo = MIN(remain, size); 5131c8f4b3cSJohn Baldwin m_copyback(cc->cc_mbuf, cc->cc_offset, todo, src); 5144542cd93SJohn Baldwin src += todo; 5159c0e3d3aSJohn Baldwin if (todo < remain) { 5169c0e3d3aSJohn Baldwin cc->cc_offset += todo; 5179c0e3d3aSJohn Baldwin break; 5189c0e3d3aSJohn Baldwin } 5199c0e3d3aSJohn Baldwin size -= todo; 5209c0e3d3aSJohn Baldwin cc->cc_mbuf = cc->cc_mbuf->m_next; 5219c0e3d3aSJohn Baldwin cc->cc_offset = 0; 5229c0e3d3aSJohn Baldwin if (size == 0) 5239c0e3d3aSJohn Baldwin break; 5249c0e3d3aSJohn Baldwin } 5259c0e3d3aSJohn Baldwin break; 526*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 527*883a0196SJohn Baldwin MPASS(cc->cc_mbuf->m_len >= cc->cc_offset + size); 528*883a0196SJohn Baldwin m_copyback(cc->cc_mbuf, cc->cc_offset, size, src); 529*883a0196SJohn Baldwin cc->cc_offset += size; 530*883a0196SJohn Baldwin break; 531e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 532e6f6d0c9SAlan Somers for (;;) { 533e6f6d0c9SAlan Somers dst = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS( 534e6f6d0c9SAlan Somers *cc->cc_vmpage)) + cc->cc_offset; 535e6f6d0c9SAlan Somers remain = MIN(PAGE_SIZE - cc->cc_offset, cc->cc_buf_len); 536e6f6d0c9SAlan Somers todo = MIN(remain, size); 537e6f6d0c9SAlan Somers memcpy(dst, src, todo); 538e6f6d0c9SAlan Somers src += todo; 539e6f6d0c9SAlan Somers cc->cc_buf_len -= todo; 540e6f6d0c9SAlan Somers if (todo < remain) { 541e6f6d0c9SAlan Somers cc->cc_offset += todo; 542e6f6d0c9SAlan Somers break; 543e6f6d0c9SAlan Somers } 544e6f6d0c9SAlan Somers size -= todo; 545e6f6d0c9SAlan Somers cc->cc_vmpage++; 546e6f6d0c9SAlan Somers cc->cc_offset = 0; 547e6f6d0c9SAlan Somers if (size == 0) 548e6f6d0c9SAlan Somers break; 549e6f6d0c9SAlan Somers } 550e6f6d0c9SAlan Somers break; 5519c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 5529c0e3d3aSJohn Baldwin for (;;) { 5539c0e3d3aSJohn Baldwin dst = (char *)cc->cc_iov->iov_base + cc->cc_offset; 5549c0e3d3aSJohn Baldwin remain = cc->cc_iov->iov_len - cc->cc_offset; 5559c0e3d3aSJohn Baldwin todo = MIN(remain, size); 5569c0e3d3aSJohn Baldwin memcpy(dst, src, todo); 5574542cd93SJohn Baldwin src += todo; 5589c0e3d3aSJohn Baldwin if (todo < remain) { 5599c0e3d3aSJohn Baldwin cc->cc_offset += todo; 5609c0e3d3aSJohn Baldwin break; 5619c0e3d3aSJohn Baldwin } 5629c0e3d3aSJohn Baldwin size -= todo; 5639c0e3d3aSJohn Baldwin cc->cc_iov++; 5649c0e3d3aSJohn Baldwin cc->cc_offset = 0; 5659c0e3d3aSJohn Baldwin if (size == 0) 5669c0e3d3aSJohn Baldwin break; 5679c0e3d3aSJohn Baldwin } 5689c0e3d3aSJohn Baldwin break; 5699c0e3d3aSJohn Baldwin default: 5709c0e3d3aSJohn Baldwin #ifdef INVARIANTS 5719c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cc->cc_type); 5729c0e3d3aSJohn Baldwin #endif 5739c0e3d3aSJohn Baldwin break; 5749c0e3d3aSJohn Baldwin } 5759c0e3d3aSJohn Baldwin } 5769c0e3d3aSJohn Baldwin 5779c0e3d3aSJohn Baldwin void 5789c0e3d3aSJohn Baldwin crypto_cursor_copydata(struct crypto_buffer_cursor *cc, int size, void *vdst) 5799c0e3d3aSJohn Baldwin { 5809c0e3d3aSJohn Baldwin size_t remain, todo; 5819c0e3d3aSJohn Baldwin const char *src; 5829c0e3d3aSJohn Baldwin char *dst; 5839c0e3d3aSJohn Baldwin 5849c0e3d3aSJohn Baldwin dst = vdst; 5859c0e3d3aSJohn Baldwin switch (cc->cc_type) { 5869c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 5879c0e3d3aSJohn Baldwin MPASS(cc->cc_buf_len >= size); 5889c0e3d3aSJohn Baldwin memcpy(dst, cc->cc_buf, size); 5899c0e3d3aSJohn Baldwin cc->cc_buf += size; 5909c0e3d3aSJohn Baldwin cc->cc_buf_len -= size; 5919c0e3d3aSJohn Baldwin break; 5929c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 5939c0e3d3aSJohn Baldwin for (;;) { 5941c8f4b3cSJohn Baldwin /* 5951c8f4b3cSJohn Baldwin * This uses m_copydata() for individual 5961c8f4b3cSJohn Baldwin * mbufs so that cc_mbuf and cc_offset are 5971c8f4b3cSJohn Baldwin * updated. 5981c8f4b3cSJohn Baldwin */ 5999c0e3d3aSJohn Baldwin remain = cc->cc_mbuf->m_len - cc->cc_offset; 6009c0e3d3aSJohn Baldwin todo = MIN(remain, size); 6011c8f4b3cSJohn Baldwin m_copydata(cc->cc_mbuf, cc->cc_offset, todo, dst); 6029c0e3d3aSJohn Baldwin dst += todo; 6039c0e3d3aSJohn Baldwin if (todo < remain) { 6049c0e3d3aSJohn Baldwin cc->cc_offset += todo; 6059c0e3d3aSJohn Baldwin break; 6069c0e3d3aSJohn Baldwin } 6079c0e3d3aSJohn Baldwin size -= todo; 6089c0e3d3aSJohn Baldwin cc->cc_mbuf = cc->cc_mbuf->m_next; 6099c0e3d3aSJohn Baldwin cc->cc_offset = 0; 6109c0e3d3aSJohn Baldwin if (size == 0) 6119c0e3d3aSJohn Baldwin break; 6129c0e3d3aSJohn Baldwin } 6139c0e3d3aSJohn Baldwin break; 614*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 615*883a0196SJohn Baldwin MPASS(cc->cc_mbuf->m_len >= cc->cc_offset + size); 616*883a0196SJohn Baldwin m_copydata(cc->cc_mbuf, cc->cc_offset, size, dst); 617*883a0196SJohn Baldwin cc->cc_offset += size; 618*883a0196SJohn Baldwin break; 619e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 620e6f6d0c9SAlan Somers for (;;) { 621e6f6d0c9SAlan Somers src = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS( 622e6f6d0c9SAlan Somers *cc->cc_vmpage)) + cc->cc_offset; 623e6f6d0c9SAlan Somers remain = MIN(PAGE_SIZE - cc->cc_offset, cc->cc_buf_len); 624e6f6d0c9SAlan Somers todo = MIN(remain, size); 625e6f6d0c9SAlan Somers memcpy(dst, src, todo); 626e6f6d0c9SAlan Somers src += todo; 627e6f6d0c9SAlan Somers cc->cc_buf_len -= todo; 628e6f6d0c9SAlan Somers if (todo < remain) { 629e6f6d0c9SAlan Somers cc->cc_offset += todo; 630e6f6d0c9SAlan Somers break; 631e6f6d0c9SAlan Somers } 632e6f6d0c9SAlan Somers size -= todo; 633e6f6d0c9SAlan Somers cc->cc_vmpage++; 634e6f6d0c9SAlan Somers cc->cc_offset = 0; 635e6f6d0c9SAlan Somers if (size == 0) 636e6f6d0c9SAlan Somers break; 637e6f6d0c9SAlan Somers } 638e6f6d0c9SAlan Somers break; 6399c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 6409c0e3d3aSJohn Baldwin for (;;) { 6419c0e3d3aSJohn Baldwin src = (const char *)cc->cc_iov->iov_base + 6429c0e3d3aSJohn Baldwin cc->cc_offset; 6439c0e3d3aSJohn Baldwin remain = cc->cc_iov->iov_len - cc->cc_offset; 6449c0e3d3aSJohn Baldwin todo = MIN(remain, size); 6459c0e3d3aSJohn Baldwin memcpy(dst, src, todo); 6469c0e3d3aSJohn Baldwin dst += todo; 6479c0e3d3aSJohn Baldwin if (todo < remain) { 6489c0e3d3aSJohn Baldwin cc->cc_offset += todo; 6499c0e3d3aSJohn Baldwin break; 6509c0e3d3aSJohn Baldwin } 6519c0e3d3aSJohn Baldwin size -= todo; 6529c0e3d3aSJohn Baldwin cc->cc_iov++; 6539c0e3d3aSJohn Baldwin cc->cc_offset = 0; 6549c0e3d3aSJohn Baldwin if (size == 0) 6559c0e3d3aSJohn Baldwin break; 6569c0e3d3aSJohn Baldwin } 6579c0e3d3aSJohn Baldwin break; 6589c0e3d3aSJohn Baldwin default: 6599c0e3d3aSJohn Baldwin #ifdef INVARIANTS 6609c0e3d3aSJohn Baldwin panic("%s: invalid buffer type %d", __func__, cc->cc_type); 6619c0e3d3aSJohn Baldwin #endif 6629c0e3d3aSJohn Baldwin break; 6639c0e3d3aSJohn Baldwin } 6649c0e3d3aSJohn Baldwin } 6659c0e3d3aSJohn Baldwin 6669c0e3d3aSJohn Baldwin /* 6679c0e3d3aSJohn Baldwin * To avoid advancing 'cursor', make a local copy that gets advanced 6689c0e3d3aSJohn Baldwin * instead. 6699c0e3d3aSJohn Baldwin */ 6709c0e3d3aSJohn Baldwin void 6719c0e3d3aSJohn Baldwin crypto_cursor_copydata_noadv(struct crypto_buffer_cursor *cc, int size, 6729c0e3d3aSJohn Baldwin void *vdst) 6739c0e3d3aSJohn Baldwin { 6749c0e3d3aSJohn Baldwin struct crypto_buffer_cursor copy; 6759c0e3d3aSJohn Baldwin 6769c0e3d3aSJohn Baldwin copy = *cc; 6779c0e3d3aSJohn Baldwin crypto_cursor_copydata(©, size, vdst); 6789c0e3d3aSJohn Baldwin } 6799c0e3d3aSJohn Baldwin 6808f91d4abSPawel Jakub Dawidek /* 6818f91d4abSPawel Jakub Dawidek * Apply function f to the data in an iovec list starting "off" bytes from 6828f91d4abSPawel Jakub Dawidek * the beginning, continuing for "len" bytes. 6838f91d4abSPawel Jakub Dawidek */ 6849c0e3d3aSJohn Baldwin static int 6859b6b2f86SJohn Baldwin cuio_apply(struct uio *uio, int off, int len, 6869b6b2f86SJohn Baldwin int (*f)(void *, const void *, u_int), void *arg) 6878f91d4abSPawel Jakub Dawidek { 6888f91d4abSPawel Jakub Dawidek struct iovec *iov = uio->uio_iov; 6898f91d4abSPawel Jakub Dawidek int iol = uio->uio_iovcnt; 6908f91d4abSPawel Jakub Dawidek unsigned count; 6918f91d4abSPawel Jakub Dawidek int rval; 6928f91d4abSPawel Jakub Dawidek 6938f91d4abSPawel Jakub Dawidek CUIO_SKIP(); 6948f91d4abSPawel Jakub Dawidek while (len > 0) { 6958f91d4abSPawel Jakub Dawidek KASSERT(iol >= 0, ("%s: empty", __func__)); 6968f91d4abSPawel Jakub Dawidek count = min(iov->iov_len - off, len); 6978f91d4abSPawel Jakub Dawidek rval = (*f)(arg, ((caddr_t)iov->iov_base) + off, count); 6988f91d4abSPawel Jakub Dawidek if (rval) 6998f91d4abSPawel Jakub Dawidek return (rval); 7008f91d4abSPawel Jakub Dawidek len -= count; 7018f91d4abSPawel Jakub Dawidek off = 0; 7028f91d4abSPawel Jakub Dawidek iol--; 7038f91d4abSPawel Jakub Dawidek iov++; 7048f91d4abSPawel Jakub Dawidek } 7058f91d4abSPawel Jakub Dawidek return (0); 7068f91d4abSPawel Jakub Dawidek } 70711d2e1e8SPawel Jakub Dawidek 70811d2e1e8SPawel Jakub Dawidek void 709c0341432SJohn Baldwin crypto_copyback(struct cryptop *crp, int off, int size, const void *src) 71011d2e1e8SPawel Jakub Dawidek { 7119c0e3d3aSJohn Baldwin struct crypto_buffer *cb; 71211d2e1e8SPawel Jakub Dawidek 7139c0e3d3aSJohn Baldwin if (crp->crp_obuf.cb_type != CRYPTO_BUF_NONE) 7149c0e3d3aSJohn Baldwin cb = &crp->crp_obuf; 7159c0e3d3aSJohn Baldwin else 7169c0e3d3aSJohn Baldwin cb = &crp->crp_buf; 7179c0e3d3aSJohn Baldwin switch (cb->cb_type) { 718c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 719*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 7209c0e3d3aSJohn Baldwin m_copyback(cb->cb_mbuf, off, size, src); 721c0341432SJohn Baldwin break; 722e6f6d0c9SAlan Somers #if CRYPTO_MAY_HAVE_VMPAGE 723e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 724e6f6d0c9SAlan Somers MPASS(size <= cb->cb_vm_page_len); 725e6f6d0c9SAlan Somers MPASS(size + off <= 726e6f6d0c9SAlan Somers cb->cb_vm_page_len + cb->cb_vm_page_offset); 727e6f6d0c9SAlan Somers cvm_page_copyback(cb->cb_vm_page, 728e6f6d0c9SAlan Somers off + cb->cb_vm_page_offset, size, src); 729e6f6d0c9SAlan Somers break; 730e6f6d0c9SAlan Somers #endif /* CRYPTO_MAY_HAVE_VMPAGE */ 731c0341432SJohn Baldwin case CRYPTO_BUF_UIO: 7329c0e3d3aSJohn Baldwin cuio_copyback(cb->cb_uio, off, size, src); 733c0341432SJohn Baldwin break; 734c0341432SJohn Baldwin case CRYPTO_BUF_CONTIG: 7359c0e3d3aSJohn Baldwin MPASS(off + size <= cb->cb_buf_len); 7369c0e3d3aSJohn Baldwin bcopy(src, cb->cb_buf + off, size); 737c0341432SJohn Baldwin break; 738c0341432SJohn Baldwin default: 7399c0e3d3aSJohn Baldwin #ifdef INVARIANTS 7409c0e3d3aSJohn Baldwin panic("invalid crp buf type %d", cb->cb_type); 7419c0e3d3aSJohn Baldwin #endif 7429c0e3d3aSJohn Baldwin break; 743c0341432SJohn Baldwin } 74411d2e1e8SPawel Jakub Dawidek } 74511d2e1e8SPawel Jakub Dawidek 74611d2e1e8SPawel Jakub Dawidek void 747c0341432SJohn Baldwin crypto_copydata(struct cryptop *crp, int off, int size, void *dst) 74811d2e1e8SPawel Jakub Dawidek { 74911d2e1e8SPawel Jakub Dawidek 7509c0e3d3aSJohn Baldwin switch (crp->crp_buf.cb_type) { 751c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 752*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 7539c0e3d3aSJohn Baldwin m_copydata(crp->crp_buf.cb_mbuf, off, size, dst); 754c0341432SJohn Baldwin break; 755e6f6d0c9SAlan Somers #if CRYPTO_MAY_HAVE_VMPAGE 756e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 757e6f6d0c9SAlan Somers MPASS(size <= crp->crp_buf.cb_vm_page_len); 758e6f6d0c9SAlan Somers MPASS(size + off <= crp->crp_buf.cb_vm_page_len + 759e6f6d0c9SAlan Somers crp->crp_buf.cb_vm_page_offset); 760e6f6d0c9SAlan Somers cvm_page_copydata(crp->crp_buf.cb_vm_page, 761e6f6d0c9SAlan Somers off + crp->crp_buf.cb_vm_page_offset, size, dst); 762e6f6d0c9SAlan Somers break; 763e6f6d0c9SAlan Somers #endif /* CRYPTO_MAY_HAVE_VMPAGE */ 764c0341432SJohn Baldwin case CRYPTO_BUF_UIO: 7659c0e3d3aSJohn Baldwin cuio_copydata(crp->crp_buf.cb_uio, off, size, dst); 766c0341432SJohn Baldwin break; 767c0341432SJohn Baldwin case CRYPTO_BUF_CONTIG: 7689c0e3d3aSJohn Baldwin MPASS(off + size <= crp->crp_buf.cb_buf_len); 7699c0e3d3aSJohn Baldwin bcopy(crp->crp_buf.cb_buf + off, dst, size); 770c0341432SJohn Baldwin break; 771c0341432SJohn Baldwin default: 7729c0e3d3aSJohn Baldwin #ifdef INVARIANTS 7739c0e3d3aSJohn Baldwin panic("invalid crp buf type %d", crp->crp_buf.cb_type); 7749c0e3d3aSJohn Baldwin #endif 7759c0e3d3aSJohn Baldwin break; 776c0341432SJohn Baldwin } 77711d2e1e8SPawel Jakub Dawidek } 77811d2e1e8SPawel Jakub Dawidek 77911d2e1e8SPawel Jakub Dawidek int 7809c0e3d3aSJohn Baldwin crypto_apply_buf(struct crypto_buffer *cb, int off, int len, 7819b6b2f86SJohn Baldwin int (*f)(void *, const void *, u_int), void *arg) 7829c0e3d3aSJohn Baldwin { 7839c0e3d3aSJohn Baldwin int error; 7849c0e3d3aSJohn Baldwin 7859c0e3d3aSJohn Baldwin switch (cb->cb_type) { 7869c0e3d3aSJohn Baldwin case CRYPTO_BUF_MBUF: 787*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 7889b6b2f86SJohn Baldwin error = m_apply(cb->cb_mbuf, off, len, 7899b6b2f86SJohn Baldwin (int (*)(void *, void *, u_int))f, arg); 7909c0e3d3aSJohn Baldwin break; 7919c0e3d3aSJohn Baldwin case CRYPTO_BUF_UIO: 7929c0e3d3aSJohn Baldwin error = cuio_apply(cb->cb_uio, off, len, f, arg); 7939c0e3d3aSJohn Baldwin break; 794e6f6d0c9SAlan Somers #if CRYPTO_MAY_HAVE_VMPAGE 795e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 796e6f6d0c9SAlan Somers error = cvm_page_apply(cb->cb_vm_page, 797e6f6d0c9SAlan Somers off + cb->cb_vm_page_offset, len, f, arg); 798e6f6d0c9SAlan Somers break; 799e6f6d0c9SAlan Somers #endif /* CRYPTO_MAY_HAVE_VMPAGE */ 8009c0e3d3aSJohn Baldwin case CRYPTO_BUF_CONTIG: 8019c0e3d3aSJohn Baldwin MPASS(off + len <= cb->cb_buf_len); 8029c0e3d3aSJohn Baldwin error = (*f)(arg, cb->cb_buf + off, len); 8039c0e3d3aSJohn Baldwin break; 8049c0e3d3aSJohn Baldwin default: 8059c0e3d3aSJohn Baldwin #ifdef INVARIANTS 8069c0e3d3aSJohn Baldwin panic("invalid crypto buf type %d", cb->cb_type); 8079c0e3d3aSJohn Baldwin #endif 8089c0e3d3aSJohn Baldwin error = 0; 8099c0e3d3aSJohn Baldwin break; 8109c0e3d3aSJohn Baldwin } 8119c0e3d3aSJohn Baldwin return (error); 8129c0e3d3aSJohn Baldwin } 8139c0e3d3aSJohn Baldwin 8149c0e3d3aSJohn Baldwin int 815c0341432SJohn Baldwin crypto_apply(struct cryptop *crp, int off, int len, 8169b6b2f86SJohn Baldwin int (*f)(void *, const void *, u_int), void *arg) 81711d2e1e8SPawel Jakub Dawidek { 8189c0e3d3aSJohn Baldwin return (crypto_apply_buf(&crp->crp_buf, off, len, f, arg)); 81908fca7a5SJohn-Mark Gurney } 820ff2038a9SMatt Macy 821ff2038a9SMatt Macy static inline void * 822ff2038a9SMatt Macy m_contiguous_subsegment(struct mbuf *m, size_t skip, size_t len) 823ff2038a9SMatt Macy { 824ff2038a9SMatt Macy int rel_off; 825ff2038a9SMatt Macy 826ff2038a9SMatt Macy MPASS(skip <= INT_MAX); 827ff2038a9SMatt Macy 828ff2038a9SMatt Macy m = m_getptr(m, (int)skip, &rel_off); 829ff2038a9SMatt Macy if (m == NULL) 830ff2038a9SMatt Macy return (NULL); 831ff2038a9SMatt Macy 832ff2038a9SMatt Macy MPASS(rel_off >= 0); 833ff2038a9SMatt Macy skip = rel_off; 834ff2038a9SMatt Macy if (skip + len > m->m_len) 835ff2038a9SMatt Macy return (NULL); 836ff2038a9SMatt Macy 8371c8f4b3cSJohn Baldwin if (m->m_flags & M_EXTPG) 8381c8f4b3cSJohn Baldwin return (m_epg_contiguous_subsegment(m, skip, len)); 839ff2038a9SMatt Macy return (mtod(m, char*) + skip); 840ff2038a9SMatt Macy } 841ff2038a9SMatt Macy 842ff2038a9SMatt Macy static inline void * 843ff2038a9SMatt Macy cuio_contiguous_segment(struct uio *uio, size_t skip, size_t len) 844ff2038a9SMatt Macy { 845ff2038a9SMatt Macy int rel_off, idx; 846ff2038a9SMatt Macy 847ff2038a9SMatt Macy MPASS(skip <= INT_MAX); 848ff2038a9SMatt Macy idx = cuio_getptr(uio, (int)skip, &rel_off); 849ff2038a9SMatt Macy if (idx < 0) 850ff2038a9SMatt Macy return (NULL); 851ff2038a9SMatt Macy 852ff2038a9SMatt Macy MPASS(rel_off >= 0); 853ff2038a9SMatt Macy skip = rel_off; 854ff2038a9SMatt Macy if (skip + len > uio->uio_iov[idx].iov_len) 855ff2038a9SMatt Macy return (NULL); 856ff2038a9SMatt Macy return ((char *)uio->uio_iov[idx].iov_base + skip); 857ff2038a9SMatt Macy } 858ff2038a9SMatt Macy 859ff2038a9SMatt Macy void * 8609c0e3d3aSJohn Baldwin crypto_buffer_contiguous_subsegment(struct crypto_buffer *cb, size_t skip, 8619c0e3d3aSJohn Baldwin size_t len) 862ff2038a9SMatt Macy { 863ff2038a9SMatt Macy 8649c0e3d3aSJohn Baldwin switch (cb->cb_type) { 865c0341432SJohn Baldwin case CRYPTO_BUF_MBUF: 866*883a0196SJohn Baldwin case CRYPTO_BUF_SINGLE_MBUF: 8679c0e3d3aSJohn Baldwin return (m_contiguous_subsegment(cb->cb_mbuf, skip, len)); 868c0341432SJohn Baldwin case CRYPTO_BUF_UIO: 8699c0e3d3aSJohn Baldwin return (cuio_contiguous_segment(cb->cb_uio, skip, len)); 870e6f6d0c9SAlan Somers #if CRYPTO_MAY_HAVE_VMPAGE 871e6f6d0c9SAlan Somers case CRYPTO_BUF_VMPAGE: 872e6f6d0c9SAlan Somers MPASS(skip + len <= cb->cb_vm_page_len); 873e6f6d0c9SAlan Somers return (cvm_page_contiguous_segment(cb->cb_vm_page, 874e6f6d0c9SAlan Somers skip + cb->cb_vm_page_offset, len)); 875e6f6d0c9SAlan Somers #endif /* CRYPTO_MAY_HAVE_VMPAGE */ 876c0341432SJohn Baldwin case CRYPTO_BUF_CONTIG: 8779c0e3d3aSJohn Baldwin MPASS(skip + len <= cb->cb_buf_len); 8789c0e3d3aSJohn Baldwin return (cb->cb_buf + skip); 879c0341432SJohn Baldwin default: 8809c0e3d3aSJohn Baldwin #ifdef INVARIANTS 8819c0e3d3aSJohn Baldwin panic("invalid crp buf type %d", cb->cb_type); 8829c0e3d3aSJohn Baldwin #endif 8839c0e3d3aSJohn Baldwin return (NULL); 884c0341432SJohn Baldwin } 885c0341432SJohn Baldwin } 8869c0e3d3aSJohn Baldwin 8879c0e3d3aSJohn Baldwin void * 8889c0e3d3aSJohn Baldwin crypto_contiguous_subsegment(struct cryptop *crp, size_t skip, size_t len) 8899c0e3d3aSJohn Baldwin { 8909c0e3d3aSJohn Baldwin return (crypto_buffer_contiguous_subsegment(&crp->crp_buf, skip, len)); 8919c0e3d3aSJohn Baldwin } 892