xref: /freebsd/sys/opencrypto/criov.c (revision 9c0e3d3a534c3e3e7f6bfce0a150ed2a0841685a)
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(&copy, 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