The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/opencrypto/criov.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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(&copy, 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


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.