1 /* $OpenBSD: criov.c,v 1.9 2002/01/29 15:48:29 jason Exp $ */
2
3 /*-
4 * Copyright (c) 1999 Theo de Raadt
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/proc.h>
36 #include <sys/errno.h>
37 #include <sys/malloc.h>
38 #include <sys/kernel.h>
39 #include <sys/mbuf.h>
40 #include <sys/uio.h>
41 #include <sys/limits.h>
42 #include <sys/lock.h>
43 #include <sys/sdt.h>
44
45 #include <machine/vmparam.h>
46
47 #include <vm/vm.h>
48 #include <vm/vm_page.h>
49 #include <vm/pmap.h>
50
51 #include <opencrypto/cryptodev.h>
52
53 SDT_PROVIDER_DECLARE(opencrypto);
54
55 /*
56 * These macros are only for avoiding code duplication, as we need to skip
57 * given number of bytes in the same way in several functions below.
58 */
59 #define CUIO_SKIP() do { \
60 KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \
61 KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \
62 while (off > 0) { \
63 KASSERT(iol >= 0, ("%s: empty in skip", __func__)); \
64 if (off < iov->iov_len) \
65 break; \
66 off -= iov->iov_len; \
67 iol--; \
68 iov++; \
69 } \
70 } while (0)
71
72 #define CVM_PAGE_SKIP() do { \
73 KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \
74 KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \
75 while (off > 0) { \
76 if (off < PAGE_SIZE) \
77 break; \
78 processed += PAGE_SIZE - off; \
79 off -= PAGE_SIZE - off; \
80 pages++; \
81 } \
82 } while (0)
83
84 static void
85 cuio_copydata(struct uio* uio, int off, int len, caddr_t cp)
86 {
87 struct iovec *iov = uio->uio_iov;
88 int iol = uio->uio_iovcnt;
89 unsigned count;
90
91 CUIO_SKIP();
92 while (len > 0) {
93 KASSERT(iol >= 0, ("%s: empty", __func__));
94 count = min(iov->iov_len - off, len);
95 bcopy(((caddr_t)iov->iov_base) + off, cp, count);
96 len -= count;
97 cp += count;
98 off = 0;
99 iol--;
100 iov++;
101 }
102 }
103
104 static void
105 cuio_copyback(struct uio* uio, int off, int len, c_caddr_t cp)
106 {
107 struct iovec *iov = uio->uio_iov;
108 int iol = uio->uio_iovcnt;
109 unsigned count;
110
111 CUIO_SKIP();
112 while (len > 0) {
113 KASSERT(iol >= 0, ("%s: empty", __func__));
114 count = min(iov->iov_len - off, len);
115 bcopy(cp, ((caddr_t)iov->iov_base) + off, count);
116 len -= count;
117 cp += count;
118 off = 0;
119 iol--;
120 iov++;
121 }
122 }
123
124 /*
125 * Return the index and offset of location in iovec list.
126 */
127 static int
128 cuio_getptr(struct uio *uio, int loc, int *off)
129 {
130 int ind, len;
131
132 ind = 0;
133 while (loc >= 0 && ind < uio->uio_iovcnt) {
134 len = uio->uio_iov[ind].iov_len;
135 if (len > loc) {
136 *off = loc;
137 return (ind);
138 }
139 loc -= len;
140 ind++;
141 }
142
143 if (ind > 0 && loc == 0) {
144 ind--;
145 *off = uio->uio_iov[ind].iov_len;
146 return (ind);
147 }
148
149 return (-1);
150 }
151
152 #if CRYPTO_MAY_HAVE_VMPAGE
153 /*
154 * Apply function f to the data in a vm_page_t list starting "off" bytes from
155 * the beginning, continuing for "len" bytes.
156 */
157 static int
158 cvm_page_apply(vm_page_t *pages, int off, int len,
159 int (*f)(void *, const void *, u_int), void *arg)
160 {
161 int processed = 0;
162 unsigned count;
163 int rval;
164
165 CVM_PAGE_SKIP();
166 while (len > 0) {
167 char *kaddr = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages));
168 count = min(PAGE_SIZE - off, len);
169 rval = (*f)(arg, kaddr + off, count);
170 if (rval)
171 return (rval);
172 len -= count;
173 processed += count;
174 off = 0;
175 pages++;
176 }
177 return (0);
178 }
179
180 static inline void *
181 cvm_page_contiguous_segment(vm_page_t *pages, size_t skip, int len)
182 {
183 if ((skip + len - 1) / PAGE_SIZE > skip / PAGE_SIZE)
184 return (NULL);
185
186 pages += (skip / PAGE_SIZE);
187 skip -= rounddown(skip, PAGE_SIZE);
188 return (((char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages))) + skip);
189 }
190
191 /*
192 * Copy len bytes of data from the vm_page_t array, skipping the first off
193 * bytes, into the pointer cp. Return the number of bytes skipped and copied.
194 * Does not verify the length of the array.
195 */
196 static int
197 cvm_page_copyback(vm_page_t *pages, int off, int len, c_caddr_t cp)
198 {
199 int processed = 0;
200 unsigned count;
201
202 CVM_PAGE_SKIP();
203 while (len > 0) {
204 count = min(PAGE_SIZE - off, len);
205 bcopy(cp, (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages)) + off,
206 count);
207 len -= count;
208 cp += count;
209 processed += count;
210 off = 0;
211 pages++;
212 }
213 return (processed);
214 }
215
216 /*
217 * Copy len bytes of data from the pointer cp into the vm_page_t array,
218 * skipping the first off bytes, Return the number of bytes skipped and copied.
219 * Does not verify the length of the array.
220 */
221 static int
222 cvm_page_copydata(vm_page_t *pages, int off, int len, caddr_t cp)
223 {
224 int processed = 0;
225 unsigned count;
226
227 CVM_PAGE_SKIP();
228 while (len > 0) {
229 count = min(PAGE_SIZE - off, len);
230 bcopy(((char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages)) + off), cp,
231 count);
232 len -= count;
233 cp += count;
234 processed += count;
235 off = 0;
236 pages++;
237 }
238 return processed;
239 }
240 #endif /* CRYPTO_MAY_HAVE_VMPAGE */
241
242 void
243 crypto_cursor_init(struct crypto_buffer_cursor *cc,
244 const struct crypto_buffer *cb)
245 {
246 memset(cc, 0, sizeof(*cc));
247 cc->cc_type = cb->cb_type;
248 switch (cc->cc_type) {
249 case CRYPTO_BUF_CONTIG:
250 cc->cc_buf = cb->cb_buf;
251 cc->cc_buf_len = cb->cb_buf_len;
252 break;
253 case CRYPTO_BUF_MBUF:
254 cc->cc_mbuf = cb->cb_mbuf;
255 break;
256 case CRYPTO_BUF_VMPAGE:
257 cc->cc_vmpage = cb->cb_vm_page;
258 cc->cc_buf_len = cb->cb_vm_page_len;
259 cc->cc_offset = cb->cb_vm_page_offset;
260 break;
261 case CRYPTO_BUF_UIO:
262 cc->cc_iov = cb->cb_uio->uio_iov;
263 break;
264 default:
265 #ifdef INVARIANTS
266 panic("%s: invalid buffer type %d", __func__, cb->cb_type);
267 #endif
268 break;
269 }
270 }
271
272 SDT_PROBE_DEFINE2(opencrypto, criov, cursor_advance, vmpage, "struct crypto_buffer_cursor*", "size_t");
273
274 void
275 crypto_cursor_advance(struct crypto_buffer_cursor *cc, size_t amount)
276 {
277 size_t remain;
278
279 switch (cc->cc_type) {
280 case CRYPTO_BUF_CONTIG:
281 MPASS(cc->cc_buf_len >= amount);
282 cc->cc_buf += amount;
283 cc->cc_buf_len -= amount;
284 break;
285 case CRYPTO_BUF_MBUF:
286 for (;;) {
287 remain = cc->cc_mbuf->m_len - cc->cc_offset;
288 if (amount < remain) {
289 cc->cc_offset += amount;
290 break;
291 }
292 amount -= remain;
293 cc->cc_mbuf = cc->cc_mbuf->m_next;
294 cc->cc_offset = 0;
295 if (amount == 0)
296 break;
297 }
298 break;
299 case CRYPTO_BUF_VMPAGE:
300 for (;;) {
301 SDT_PROBE2(opencrypto, criov, cursor_advance, vmpage,
302 cc, amount);
303 remain = MIN(PAGE_SIZE - cc->cc_offset, cc->cc_buf_len);
304 if (amount < remain) {
305 cc->cc_buf_len -= amount;
306 cc->cc_offset += amount;
307 break;
308 }
309 cc->cc_buf_len -= remain;
310 amount -= remain;
311 cc->cc_vmpage++;
312 cc->cc_offset = 0;
313 if (amount == 0 || cc->cc_buf_len == 0)
314 break;
315 }
316 break;
317 case CRYPTO_BUF_UIO:
318 for (;;) {
319 remain = cc->cc_iov->iov_len - cc->cc_offset;
320 if (amount < remain) {
321 cc->cc_offset += amount;
322 break;
323 }
324 amount -= remain;
325 cc->cc_iov++;
326 cc->cc_offset = 0;
327 if (amount == 0)
328 break;
329 }
330 break;
331 default:
332 #ifdef INVARIANTS
333 panic("%s: invalid buffer type %d", __func__, cc->cc_type);
334 #endif
335 break;
336 }
337 }
338
339 void *
340 crypto_cursor_segbase(struct crypto_buffer_cursor *cc)
341 {
342 switch (cc->cc_type) {
343 case CRYPTO_BUF_CONTIG:
344 return (cc->cc_buf);
345 case CRYPTO_BUF_MBUF:
346 if (cc->cc_mbuf == NULL)
347 return (NULL);
348 KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0,
349 ("%s: not supported for unmapped mbufs", __func__));
350 return (mtod(cc->cc_mbuf, char *) + cc->cc_offset);
351 case CRYPTO_BUF_VMPAGE:
352 return ((char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(
353 *cc->cc_vmpage)) + cc->cc_offset);
354 case CRYPTO_BUF_UIO:
355 return ((char *)cc->cc_iov->iov_base + cc->cc_offset);
356 default:
357 #ifdef INVARIANTS
358 panic("%s: invalid buffer type %d", __func__, cc->cc_type);
359 #endif
360 return (NULL);
361 }
362 }
363
364 size_t
365 crypto_cursor_seglen(struct crypto_buffer_cursor *cc)
366 {
367 switch (cc->cc_type) {
368 case CRYPTO_BUF_CONTIG:
369 return (cc->cc_buf_len);
370 case CRYPTO_BUF_VMPAGE:
371 return (PAGE_SIZE - cc->cc_offset);
372 case CRYPTO_BUF_MBUF:
373 if (cc->cc_mbuf == NULL)
374 return (0);
375 return (cc->cc_mbuf->m_len - cc->cc_offset);
376 case CRYPTO_BUF_UIO:
377 return (cc->cc_iov->iov_len - cc->cc_offset);
378 default:
379 #ifdef INVARIANTS
380 panic("%s: invalid buffer type %d", __func__, cc->cc_type);
381 #endif
382 return (0);
383 }
384 }
385
386 void
387 crypto_cursor_copyback(struct crypto_buffer_cursor *cc, int size,
388 const void *vsrc)
389 {
390 size_t remain, todo;
391 const char *src;
392 char *dst;
393
394 src = vsrc;
395 switch (cc->cc_type) {
396 case CRYPTO_BUF_CONTIG:
397 MPASS(cc->cc_buf_len >= size);
398 memcpy(cc->cc_buf, src, size);
399 cc->cc_buf += size;
400 cc->cc_buf_len -= size;
401 break;
402 case CRYPTO_BUF_MBUF:
403 for (;;) {
404 KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0,
405 ("%s: not supported for unmapped mbufs", __func__));
406 dst = mtod(cc->cc_mbuf, char *) + cc->cc_offset;
407 remain = cc->cc_mbuf->m_len - cc->cc_offset;
408 todo = MIN(remain, size);
409 memcpy(dst, src, todo);
410 src += todo;
411 if (todo < remain) {
412 cc->cc_offset += todo;
413 break;
414 }
415 size -= todo;
416 cc->cc_mbuf = cc->cc_mbuf->m_next;
417 cc->cc_offset = 0;
418 if (size == 0)
419 break;
420 }
421 break;
422 case CRYPTO_BUF_VMPAGE:
423 for (;;) {
424 dst = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(
425 *cc->cc_vmpage)) + cc->cc_offset;
426 remain = MIN(PAGE_SIZE - cc->cc_offset, cc->cc_buf_len);
427 todo = MIN(remain, size);
428 memcpy(dst, src, todo);
429 src += todo;
430 cc->cc_buf_len -= todo;
431 if (todo < remain) {
432 cc->cc_offset += todo;
433 break;
434 }
435 size -= todo;
436 cc->cc_vmpage++;
437 cc->cc_offset = 0;
438 if (size == 0)
439 break;
440 }
441 break;
442 case CRYPTO_BUF_UIO:
443 for (;;) {
444 dst = (char *)cc->cc_iov->iov_base + cc->cc_offset;
445 remain = cc->cc_iov->iov_len - cc->cc_offset;
446 todo = MIN(remain, size);
447 memcpy(dst, src, todo);
448 src += todo;
449 if (todo < remain) {
450 cc->cc_offset += todo;
451 break;
452 }
453 size -= todo;
454 cc->cc_iov++;
455 cc->cc_offset = 0;
456 if (size == 0)
457 break;
458 }
459 break;
460 default:
461 #ifdef INVARIANTS
462 panic("%s: invalid buffer type %d", __func__, cc->cc_type);
463 #endif
464 break;
465 }
466 }
467
468 void
469 crypto_cursor_copydata(struct crypto_buffer_cursor *cc, int size, void *vdst)
470 {
471 size_t remain, todo;
472 const char *src;
473 char *dst;
474
475 dst = vdst;
476 switch (cc->cc_type) {
477 case CRYPTO_BUF_CONTIG:
478 MPASS(cc->cc_buf_len >= size);
479 memcpy(dst, cc->cc_buf, size);
480 cc->cc_buf += size;
481 cc->cc_buf_len -= size;
482 break;
483 case CRYPTO_BUF_MBUF:
484 for (;;) {
485 KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0,
486 ("%s: not supported for unmapped mbufs", __func__));
487 src = mtod(cc->cc_mbuf, const char *) + cc->cc_offset;
488 remain = cc->cc_mbuf->m_len - cc->cc_offset;
489 todo = MIN(remain, size);
490 memcpy(dst, src, todo);
491 dst += todo;
492 if (todo < remain) {
493 cc->cc_offset += todo;
494 break;
495 }
496 size -= todo;
497 cc->cc_mbuf = cc->cc_mbuf->m_next;
498 cc->cc_offset = 0;
499 if (size == 0)
500 break;
501 }
502 break;
503 case CRYPTO_BUF_VMPAGE:
504 for (;;) {
505 src = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(
506 *cc->cc_vmpage)) + cc->cc_offset;
507 remain = MIN(PAGE_SIZE - cc->cc_offset, cc->cc_buf_len);
508 todo = MIN(remain, size);
509 memcpy(dst, src, todo);
510 src += todo;
511 cc->cc_buf_len -= todo;
512 if (todo < remain) {
513 cc->cc_offset += todo;
514 break;
515 }
516 size -= todo;
517 cc->cc_vmpage++;
518 cc->cc_offset = 0;
519 if (size == 0)
520 break;
521 }
522 break;
523 case CRYPTO_BUF_UIO:
524 for (;;) {
525 src = (const char *)cc->cc_iov->iov_base +
526 cc->cc_offset;
527 remain = cc->cc_iov->iov_len - cc->cc_offset;
528 todo = MIN(remain, size);
529 memcpy(dst, src, todo);
530 dst += todo;
531 if (todo < remain) {
532 cc->cc_offset += todo;
533 break;
534 }
535 size -= todo;
536 cc->cc_iov++;
537 cc->cc_offset = 0;
538 if (size == 0)
539 break;
540 }
541 break;
542 default:
543 #ifdef INVARIANTS
544 panic("%s: invalid buffer type %d", __func__, cc->cc_type);
545 #endif
546 break;
547 }
548 }
549
550 /*
551 * To avoid advancing 'cursor', make a local copy that gets advanced
552 * instead.
553 */
554 void
555 crypto_cursor_copydata_noadv(struct crypto_buffer_cursor *cc, int size,
556 void *vdst)
557 {
558 struct crypto_buffer_cursor copy;
559
560 copy = *cc;
561 crypto_cursor_copydata(©, size, vdst);
562 }
563
564 /*
565 * Apply function f to the data in an iovec list starting "off" bytes from
566 * the beginning, continuing for "len" bytes.
567 */
568 static int
569 cuio_apply(struct uio *uio, int off, int len,
570 int (*f)(void *, const void *, u_int), void *arg)
571 {
572 struct iovec *iov = uio->uio_iov;
573 int iol = uio->uio_iovcnt;
574 unsigned count;
575 int rval;
576
577 CUIO_SKIP();
578 while (len > 0) {
579 KASSERT(iol >= 0, ("%s: empty", __func__));
580 count = min(iov->iov_len - off, len);
581 rval = (*f)(arg, ((caddr_t)iov->iov_base) + off, count);
582 if (rval)
583 return (rval);
584 len -= count;
585 off = 0;
586 iol--;
587 iov++;
588 }
589 return (0);
590 }
591
592 void
593 crypto_copyback(struct cryptop *crp, int off, int size, const void *src)
594 {
595 struct crypto_buffer *cb;
596
597 if (crp->crp_obuf.cb_type != CRYPTO_BUF_NONE)
598 cb = &crp->crp_obuf;
599 else
600 cb = &crp->crp_buf;
601 switch (cb->cb_type) {
602 case CRYPTO_BUF_MBUF:
603 m_copyback(cb->cb_mbuf, off, size, src);
604 break;
605 #if CRYPTO_MAY_HAVE_VMPAGE
606 case CRYPTO_BUF_VMPAGE:
607 MPASS(size <= cb->cb_vm_page_len);
608 MPASS(size + off <=
609 cb->cb_vm_page_len + cb->cb_vm_page_offset);
610 cvm_page_copyback(cb->cb_vm_page,
611 off + cb->cb_vm_page_offset, size, src);
612 break;
613 #endif /* CRYPTO_MAY_HAVE_VMPAGE */
614 case CRYPTO_BUF_UIO:
615 cuio_copyback(cb->cb_uio, off, size, src);
616 break;
617 case CRYPTO_BUF_CONTIG:
618 MPASS(off + size <= cb->cb_buf_len);
619 bcopy(src, cb->cb_buf + off, size);
620 break;
621 default:
622 #ifdef INVARIANTS
623 panic("invalid crp buf type %d", cb->cb_type);
624 #endif
625 break;
626 }
627 }
628
629 void
630 crypto_copydata(struct cryptop *crp, int off, int size, void *dst)
631 {
632
633 switch (crp->crp_buf.cb_type) {
634 case CRYPTO_BUF_MBUF:
635 m_copydata(crp->crp_buf.cb_mbuf, off, size, dst);
636 break;
637 #if CRYPTO_MAY_HAVE_VMPAGE
638 case CRYPTO_BUF_VMPAGE:
639 MPASS(size <= crp->crp_buf.cb_vm_page_len);
640 MPASS(size + off <= crp->crp_buf.cb_vm_page_len +
641 crp->crp_buf.cb_vm_page_offset);
642 cvm_page_copydata(crp->crp_buf.cb_vm_page,
643 off + crp->crp_buf.cb_vm_page_offset, size, dst);
644 break;
645 #endif /* CRYPTO_MAY_HAVE_VMPAGE */
646 case CRYPTO_BUF_UIO:
647 cuio_copydata(crp->crp_buf.cb_uio, off, size, dst);
648 break;
649 case CRYPTO_BUF_CONTIG:
650 MPASS(off + size <= crp->crp_buf.cb_buf_len);
651 bcopy(crp->crp_buf.cb_buf + off, dst, size);
652 break;
653 default:
654 #ifdef INVARIANTS
655 panic("invalid crp buf type %d", crp->crp_buf.cb_type);
656 #endif
657 break;
658 }
659 }
660
661 int
662 crypto_apply_buf(struct crypto_buffer *cb, int off, int len,
663 int (*f)(void *, const void *, u_int), void *arg)
664 {
665 int error;
666
667 switch (cb->cb_type) {
668 case CRYPTO_BUF_MBUF:
669 error = m_apply(cb->cb_mbuf, off, len,
670 (int (*)(void *, void *, u_int))f, arg);
671 break;
672 case CRYPTO_BUF_UIO:
673 error = cuio_apply(cb->cb_uio, off, len, f, arg);
674 break;
675 #if CRYPTO_MAY_HAVE_VMPAGE
676 case CRYPTO_BUF_VMPAGE:
677 error = cvm_page_apply(cb->cb_vm_page,
678 off + cb->cb_vm_page_offset, len, f, arg);
679 break;
680 #endif /* CRYPTO_MAY_HAVE_VMPAGE */
681 case CRYPTO_BUF_CONTIG:
682 MPASS(off + len <= cb->cb_buf_len);
683 error = (*f)(arg, cb->cb_buf + off, len);
684 break;
685 default:
686 #ifdef INVARIANTS
687 panic("invalid crypto buf type %d", cb->cb_type);
688 #endif
689 error = 0;
690 break;
691 }
692 return (error);
693 }
694
695 int
696 crypto_apply(struct cryptop *crp, int off, int len,
697 int (*f)(void *, const void *, u_int), void *arg)
698 {
699 return (crypto_apply_buf(&crp->crp_buf, off, len, f, arg));
700 }
701
702 static inline void *
703 m_contiguous_subsegment(struct mbuf *m, size_t skip, size_t len)
704 {
705 int rel_off;
706
707 MPASS(skip <= INT_MAX);
708
709 m = m_getptr(m, (int)skip, &rel_off);
710 if (m == NULL)
711 return (NULL);
712
713 MPASS(rel_off >= 0);
714 skip = rel_off;
715 if (skip + len > m->m_len)
716 return (NULL);
717
718 return (mtod(m, char*) + skip);
719 }
720
721 static inline void *
722 cuio_contiguous_segment(struct uio *uio, size_t skip, size_t len)
723 {
724 int rel_off, idx;
725
726 MPASS(skip <= INT_MAX);
727 idx = cuio_getptr(uio, (int)skip, &rel_off);
728 if (idx < 0)
729 return (NULL);
730
731 MPASS(rel_off >= 0);
732 skip = rel_off;
733 if (skip + len > uio->uio_iov[idx].iov_len)
734 return (NULL);
735 return ((char *)uio->uio_iov[idx].iov_base + skip);
736 }
737
738 void *
739 crypto_buffer_contiguous_subsegment(struct crypto_buffer *cb, size_t skip,
740 size_t len)
741 {
742
743 switch (cb->cb_type) {
744 case CRYPTO_BUF_MBUF:
745 return (m_contiguous_subsegment(cb->cb_mbuf, skip, len));
746 case CRYPTO_BUF_UIO:
747 return (cuio_contiguous_segment(cb->cb_uio, skip, len));
748 #if CRYPTO_MAY_HAVE_VMPAGE
749 case CRYPTO_BUF_VMPAGE:
750 MPASS(skip + len <= cb->cb_vm_page_len);
751 return (cvm_page_contiguous_segment(cb->cb_vm_page,
752 skip + cb->cb_vm_page_offset, len));
753 #endif /* CRYPTO_MAY_HAVE_VMPAGE */
754 case CRYPTO_BUF_CONTIG:
755 MPASS(skip + len <= cb->cb_buf_len);
756 return (cb->cb_buf + skip);
757 default:
758 #ifdef INVARIANTS
759 panic("invalid crp buf type %d", cb->cb_type);
760 #endif
761 return (NULL);
762 }
763 }
764
765 void *
766 crypto_contiguous_subsegment(struct cryptop *crp, size_t skip, size_t len)
767 {
768 return (crypto_buffer_contiguous_subsegment(&crp->crp_buf, skip, len));
769 }
Cache object: 3c3cda63e5691e7faa92a2c2d38b4e43
|