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 } 770