]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/opencrypto/criov.c
GMAC: Reset initial hash value and counter in AES_GMAC_Reinit().
[FreeBSD/FreeBSD.git] / sys / opencrypto / criov.c
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 __unused;
162         unsigned count;
163         int rval;
164
165         processed = 0;
166         CVM_PAGE_SKIP();
167         while (len > 0) {
168                 char *kaddr = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages));
169                 count = min(PAGE_SIZE - off, len);
170                 rval = (*f)(arg, kaddr + off, count);
171                 if (rval)
172                         return (rval);
173                 len -= count;
174                 processed += count;
175                 off = 0;
176                 pages++;
177         }
178         return (0);
179 }
180
181 static inline void *
182 cvm_page_contiguous_segment(vm_page_t *pages, size_t skip, int len)
183 {
184         if ((skip + len - 1) / PAGE_SIZE > skip / PAGE_SIZE)
185                 return (NULL);
186
187         pages += (skip / PAGE_SIZE);
188         skip -= rounddown(skip, PAGE_SIZE);
189         return (((char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages))) + skip);
190 }
191
192 /*
193  * Copy len bytes of data from the vm_page_t array, skipping the first off
194  * bytes, into the pointer cp.  Return the number of bytes skipped and copied.
195  * Does not verify the length of the array.
196  */
197 static int
198 cvm_page_copyback(vm_page_t *pages, int off, int len, c_caddr_t cp)
199 {
200         int processed = 0;
201         unsigned count;
202
203         CVM_PAGE_SKIP();
204         while (len > 0) {
205                 count = min(PAGE_SIZE - off, len);
206                 bcopy(cp, (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages)) + off,
207                     count);
208                 len -= count;
209                 cp += count;
210                 processed += count;
211                 off = 0;
212                 pages++;
213         }
214         return (processed);
215 }
216
217 /*
218  * Copy len bytes of data from the pointer cp into the vm_page_t array,
219  * skipping the first off bytes, Return the number of bytes skipped and copied.
220  * Does not verify the length of the array.
221  */
222 static int
223 cvm_page_copydata(vm_page_t *pages, int off, int len, caddr_t cp)
224 {
225         int processed = 0;
226         unsigned count;
227
228         CVM_PAGE_SKIP();
229         while (len > 0) {
230                 count = min(PAGE_SIZE - off, len);
231                 bcopy(((char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(*pages)) + off), cp,
232                     count);
233                 len -= count;
234                 cp += count;
235                 processed += count;
236                 off = 0;
237                 pages++;
238         }
239         return processed;
240 }
241 #endif /* CRYPTO_MAY_HAVE_VMPAGE */
242
243 /*
244  * Given a starting page in an m_epg, determine the length of the
245  * current physically contiguous segment.
246  */
247 static __inline size_t
248 m_epg_pages_extent(struct mbuf *m, int idx, u_int pglen)
249 {
250         size_t len;
251         u_int i;
252
253         len = pglen;
254         for (i = idx + 1; i < m->m_epg_npgs; i++) {
255                 if (m->m_epg_pa[i - 1] + PAGE_SIZE != m->m_epg_pa[i])
256                         break;
257                 len += m_epg_pagelen(m, i, 0);
258         }
259         return (len);
260 }
261
262 static void *
263 m_epg_segment(struct mbuf *m, size_t offset, size_t *len)
264 {
265         u_int i, pglen, pgoff;
266
267         offset += mtod(m, vm_offset_t);
268         if (offset < m->m_epg_hdrlen) {
269                 *len = m->m_epg_hdrlen - offset;
270                 return (m->m_epg_hdr + offset);
271         }
272         offset -= m->m_epg_hdrlen;
273         pgoff = m->m_epg_1st_off;
274         for (i = 0; i < m->m_epg_npgs; i++) {
275                 pglen = m_epg_pagelen(m, i, pgoff);
276                 if (offset < pglen) {
277                         *len = m_epg_pages_extent(m, i, pglen) - offset;
278                         return ((void *)PHYS_TO_DMAP(m->m_epg_pa[i] + pgoff +
279                             offset));
280                 }
281                 offset -= pglen;
282                 pgoff = 0;
283         }
284         KASSERT(offset <= m->m_epg_trllen, ("%s: offset beyond trailer",
285             __func__));
286         *len = m->m_epg_trllen - offset;
287         return (m->m_epg_trail + offset);
288 }
289
290 static __inline void *
291 m_epg_contiguous_subsegment(struct mbuf *m, size_t skip, size_t len)
292 {
293         void *base;
294         size_t seglen;
295
296         base = m_epg_segment(m, skip, &seglen);
297         if (len > seglen)
298                 return (NULL);
299         return (base);
300 }
301
302 void
303 crypto_cursor_init(struct crypto_buffer_cursor *cc,
304     const struct crypto_buffer *cb)
305 {
306         memset(cc, 0, sizeof(*cc));
307         cc->cc_type = cb->cb_type;
308         switch (cc->cc_type) {
309         case CRYPTO_BUF_CONTIG:
310                 cc->cc_buf = cb->cb_buf;
311                 cc->cc_buf_len = cb->cb_buf_len;
312                 break;
313         case CRYPTO_BUF_MBUF:
314         case CRYPTO_BUF_SINGLE_MBUF:
315                 cc->cc_mbuf = cb->cb_mbuf;
316                 break;
317         case CRYPTO_BUF_VMPAGE:
318                 cc->cc_vmpage = cb->cb_vm_page;
319                 cc->cc_buf_len = cb->cb_vm_page_len;
320                 cc->cc_offset = cb->cb_vm_page_offset;
321                 break;
322         case CRYPTO_BUF_UIO:
323                 cc->cc_iov = cb->cb_uio->uio_iov;
324                 break;
325         default:
326 #ifdef INVARIANTS
327                 panic("%s: invalid buffer type %d", __func__, cb->cb_type);
328 #endif
329                 break;
330         }
331 }
332
333 SDT_PROBE_DEFINE2(opencrypto, criov, cursor_advance, vmpage, "struct crypto_buffer_cursor*", "size_t");
334
335 void
336 crypto_cursor_advance(struct crypto_buffer_cursor *cc, size_t amount)
337 {
338         size_t remain;
339
340         switch (cc->cc_type) {
341         case CRYPTO_BUF_CONTIG:
342                 MPASS(cc->cc_buf_len >= amount);
343                 cc->cc_buf += amount;
344                 cc->cc_buf_len -= amount;
345                 break;
346         case CRYPTO_BUF_MBUF:
347                 for (;;) {
348                         remain = cc->cc_mbuf->m_len - cc->cc_offset;
349                         if (amount < remain) {
350                                 cc->cc_offset += amount;
351                                 break;
352                         }
353                         amount -= remain;
354                         cc->cc_mbuf = cc->cc_mbuf->m_next;
355                         cc->cc_offset = 0;
356                         if (amount == 0)
357                                 break;
358                 }
359                 break;
360         case CRYPTO_BUF_SINGLE_MBUF:
361                 MPASS(cc->cc_mbuf->m_len >= cc->cc_offset + amount);
362                 cc->cc_offset += amount;
363                 break;
364         case CRYPTO_BUF_VMPAGE:
365                 for (;;) {
366                         SDT_PROBE2(opencrypto, criov, cursor_advance, vmpage,
367                             cc, amount);
368                         remain = MIN(PAGE_SIZE - cc->cc_offset, cc->cc_buf_len);
369                         if (amount < remain) {
370                                 cc->cc_buf_len -= amount;
371                                 cc->cc_offset += amount;
372                                 break;
373                         }
374                         cc->cc_buf_len -= remain;
375                         amount -= remain;
376                         cc->cc_vmpage++;
377                         cc->cc_offset = 0;
378                         if (amount == 0 || cc->cc_buf_len == 0)
379                                 break;
380                 }
381                 break;
382         case CRYPTO_BUF_UIO:
383                 for (;;) {
384                         remain = cc->cc_iov->iov_len - cc->cc_offset;
385                         if (amount < remain) {
386                                 cc->cc_offset += amount;
387                                 break;
388                         }
389                         amount -= remain;
390                         cc->cc_iov++;
391                         cc->cc_offset = 0;
392                         if (amount == 0)
393                                 break;
394                 }
395                 break;
396         default:
397 #ifdef INVARIANTS
398                 panic("%s: invalid buffer type %d", __func__, cc->cc_type);
399 #endif
400                 break;
401         }
402 }
403
404 void *
405 crypto_cursor_segment(struct crypto_buffer_cursor *cc, size_t *len)
406 {
407         switch (cc->cc_type) {
408         case CRYPTO_BUF_CONTIG:
409                 *len = cc->cc_buf_len;
410                 return (cc->cc_buf);
411         case CRYPTO_BUF_MBUF:
412         case CRYPTO_BUF_SINGLE_MBUF:
413                 if (cc->cc_mbuf == NULL) {
414                         *len = 0;
415                         return (NULL);
416                 }
417                 if (cc->cc_mbuf->m_flags & M_EXTPG)
418                         return (m_epg_segment(cc->cc_mbuf, cc->cc_offset, len));
419                 *len = cc->cc_mbuf->m_len - cc->cc_offset;
420                 return (mtod(cc->cc_mbuf, char *) + cc->cc_offset);
421         case CRYPTO_BUF_VMPAGE:
422                 *len = PAGE_SIZE - cc->cc_offset;
423                 return ((char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(
424                     *cc->cc_vmpage)) + cc->cc_offset);
425         case CRYPTO_BUF_UIO:
426                 *len = cc->cc_iov->iov_len - cc->cc_offset;
427                 return ((char *)cc->cc_iov->iov_base + cc->cc_offset);
428         default:
429 #ifdef INVARIANTS
430                 panic("%s: invalid buffer type %d", __func__, cc->cc_type);
431 #endif
432                 *len = 0;
433                 return (NULL);
434         }
435 }
436
437 void
438 crypto_cursor_copyback(struct crypto_buffer_cursor *cc, int size,
439     const void *vsrc)
440 {
441         size_t remain, todo;
442         const char *src;
443         char *dst;
444
445         src = vsrc;
446         switch (cc->cc_type) {
447         case CRYPTO_BUF_CONTIG:
448                 MPASS(cc->cc_buf_len >= size);
449                 memcpy(cc->cc_buf, src, size);
450                 cc->cc_buf += size;
451                 cc->cc_buf_len -= size;
452                 break;
453         case CRYPTO_BUF_MBUF:
454                 for (;;) {
455                         /*
456                          * This uses m_copyback() for individual
457                          * mbufs so that cc_mbuf and cc_offset are
458                          * updated.
459                          */
460                         remain = cc->cc_mbuf->m_len - cc->cc_offset;
461                         todo = MIN(remain, size);
462                         m_copyback(cc->cc_mbuf, cc->cc_offset, todo, src);
463                         src += todo;
464                         if (todo < remain) {
465                                 cc->cc_offset += todo;
466                                 break;
467                         }
468                         size -= todo;   
469                         cc->cc_mbuf = cc->cc_mbuf->m_next;
470                         cc->cc_offset = 0;
471                         if (size == 0)
472                                 break;
473                 }
474                 break;
475         case CRYPTO_BUF_SINGLE_MBUF:
476                 MPASS(cc->cc_mbuf->m_len >= cc->cc_offset + size);
477                 m_copyback(cc->cc_mbuf, cc->cc_offset, size, src);
478                 cc->cc_offset += size;
479                 break;
480         case CRYPTO_BUF_VMPAGE:
481                 for (;;) {
482                         dst = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(
483                             *cc->cc_vmpage)) + cc->cc_offset;
484                         remain = MIN(PAGE_SIZE - cc->cc_offset, cc->cc_buf_len);
485                         todo = MIN(remain, size);
486                         memcpy(dst, src, todo);
487                         src += todo;
488                         cc->cc_buf_len -= todo;
489                         if (todo < remain) {
490                                 cc->cc_offset += todo;
491                                 break;
492                         }
493                         size -= todo;
494                         cc->cc_vmpage++;
495                         cc->cc_offset = 0;
496                         if (size == 0)
497                                 break;
498                 }
499                 break;
500         case CRYPTO_BUF_UIO:
501                 for (;;) {
502                         dst = (char *)cc->cc_iov->iov_base + cc->cc_offset;
503                         remain = cc->cc_iov->iov_len - cc->cc_offset;
504                         todo = MIN(remain, size);
505                         memcpy(dst, src, todo);
506                         src += todo;
507                         if (todo < remain) {
508                                 cc->cc_offset += todo;
509                                 break;
510                         }
511                         size -= todo;   
512                         cc->cc_iov++;
513                         cc->cc_offset = 0;
514                         if (size == 0)
515                                 break;
516                 }
517                 break;
518         default:
519 #ifdef INVARIANTS
520                 panic("%s: invalid buffer type %d", __func__, cc->cc_type);
521 #endif
522                 break;
523         }
524 }
525
526 void
527 crypto_cursor_copydata(struct crypto_buffer_cursor *cc, int size, void *vdst)
528 {
529         size_t remain, todo;
530         const char *src;
531         char *dst;
532
533         dst = vdst;
534         switch (cc->cc_type) {
535         case CRYPTO_BUF_CONTIG:
536                 MPASS(cc->cc_buf_len >= size);
537                 memcpy(dst, cc->cc_buf, size);
538                 cc->cc_buf += size;
539                 cc->cc_buf_len -= size;
540                 break;
541         case CRYPTO_BUF_MBUF:
542                 for (;;) {
543                         /*
544                          * This uses m_copydata() for individual
545                          * mbufs so that cc_mbuf and cc_offset are
546                          * updated.
547                          */
548                         remain = cc->cc_mbuf->m_len - cc->cc_offset;
549                         todo = MIN(remain, size);
550                         m_copydata(cc->cc_mbuf, cc->cc_offset, todo, dst);
551                         dst += todo;
552                         if (todo < remain) {
553                                 cc->cc_offset += todo;
554                                 break;
555                         }
556                         size -= todo;
557                         cc->cc_mbuf = cc->cc_mbuf->m_next;
558                         cc->cc_offset = 0;
559                         if (size == 0)
560                                 break;
561                 }
562                 break;
563         case CRYPTO_BUF_SINGLE_MBUF:
564                 MPASS(cc->cc_mbuf->m_len >= cc->cc_offset + size);
565                 m_copydata(cc->cc_mbuf, cc->cc_offset, size, dst);
566                 cc->cc_offset += size;
567                 break;
568         case CRYPTO_BUF_VMPAGE:
569                 for (;;) {
570                         src = (char *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(
571                             *cc->cc_vmpage)) + cc->cc_offset;
572                         remain = MIN(PAGE_SIZE - cc->cc_offset, cc->cc_buf_len);
573                         todo = MIN(remain, size);
574                         memcpy(dst, src, todo);
575                         src += todo;
576                         cc->cc_buf_len -= todo;
577                         if (todo < remain) {
578                                 cc->cc_offset += todo;
579                                 break;
580                         }
581                         size -= todo;
582                         cc->cc_vmpage++;
583                         cc->cc_offset = 0;
584                         if (size == 0)
585                                 break;
586                 }
587                 break;
588         case CRYPTO_BUF_UIO:
589                 for (;;) {
590                         src = (const char *)cc->cc_iov->iov_base +
591                             cc->cc_offset;
592                         remain = cc->cc_iov->iov_len - cc->cc_offset;
593                         todo = MIN(remain, size);
594                         memcpy(dst, src, todo);
595                         dst += todo;
596                         if (todo < remain) {
597                                 cc->cc_offset += todo;
598                                 break;
599                         }
600                         size -= todo;
601                         cc->cc_iov++;
602                         cc->cc_offset = 0;
603                         if (size == 0)
604                                 break;
605                 }
606                 break;
607         default:
608 #ifdef INVARIANTS
609                 panic("%s: invalid buffer type %d", __func__, cc->cc_type);
610 #endif
611                 break;
612         }
613 }
614
615 /*
616  * To avoid advancing 'cursor', make a local copy that gets advanced
617  * instead.
618  */
619 void
620 crypto_cursor_copydata_noadv(struct crypto_buffer_cursor *cc, int size,
621     void *vdst)
622 {
623         struct crypto_buffer_cursor copy;
624
625         copy = *cc;
626         crypto_cursor_copydata(&copy, size, vdst);
627 }
628
629 /*
630  * Apply function f to the data in an iovec list starting "off" bytes from
631  * the beginning, continuing for "len" bytes.
632  */
633 static int
634 cuio_apply(struct uio *uio, int off, int len,
635     int (*f)(void *, const void *, u_int), void *arg)
636 {
637         struct iovec *iov = uio->uio_iov;
638         int iol = uio->uio_iovcnt;
639         unsigned count;
640         int rval;
641
642         CUIO_SKIP();
643         while (len > 0) {
644                 KASSERT(iol >= 0, ("%s: empty", __func__));
645                 count = min(iov->iov_len - off, len);
646                 rval = (*f)(arg, ((caddr_t)iov->iov_base) + off, count);
647                 if (rval)
648                         return (rval);
649                 len -= count;
650                 off = 0;
651                 iol--;
652                 iov++;
653         }
654         return (0);
655 }
656
657 void
658 crypto_copyback(struct cryptop *crp, int off, int size, const void *src)
659 {
660         struct crypto_buffer *cb;
661
662         if (crp->crp_obuf.cb_type != CRYPTO_BUF_NONE)
663                 cb = &crp->crp_obuf;
664         else
665                 cb = &crp->crp_buf;
666         switch (cb->cb_type) {
667         case CRYPTO_BUF_MBUF:
668         case CRYPTO_BUF_SINGLE_MBUF:
669                 m_copyback(cb->cb_mbuf, off, size, src);
670                 break;
671 #if CRYPTO_MAY_HAVE_VMPAGE
672         case CRYPTO_BUF_VMPAGE:
673                 MPASS(size <= cb->cb_vm_page_len);
674                 MPASS(size + off <=
675                     cb->cb_vm_page_len + cb->cb_vm_page_offset);
676                 cvm_page_copyback(cb->cb_vm_page,
677                     off + cb->cb_vm_page_offset, size, src);
678                 break;
679 #endif /* CRYPTO_MAY_HAVE_VMPAGE */
680         case CRYPTO_BUF_UIO:
681                 cuio_copyback(cb->cb_uio, off, size, src);
682                 break;
683         case CRYPTO_BUF_CONTIG:
684                 MPASS(off + size <= cb->cb_buf_len);
685                 bcopy(src, cb->cb_buf + off, size);
686                 break;
687         default:
688 #ifdef INVARIANTS
689                 panic("invalid crp buf type %d", cb->cb_type);
690 #endif
691                 break;
692         }
693 }
694
695 void
696 crypto_copydata(struct cryptop *crp, int off, int size, void *dst)
697 {
698
699         switch (crp->crp_buf.cb_type) {
700         case CRYPTO_BUF_MBUF:
701         case CRYPTO_BUF_SINGLE_MBUF:
702                 m_copydata(crp->crp_buf.cb_mbuf, off, size, dst);
703                 break;
704 #if CRYPTO_MAY_HAVE_VMPAGE
705         case CRYPTO_BUF_VMPAGE:
706                 MPASS(size <= crp->crp_buf.cb_vm_page_len);
707                 MPASS(size + off <= crp->crp_buf.cb_vm_page_len +
708                     crp->crp_buf.cb_vm_page_offset);
709                 cvm_page_copydata(crp->crp_buf.cb_vm_page,
710                     off + crp->crp_buf.cb_vm_page_offset, size, dst);
711                 break;
712 #endif /* CRYPTO_MAY_HAVE_VMPAGE */
713         case CRYPTO_BUF_UIO:
714                 cuio_copydata(crp->crp_buf.cb_uio, off, size, dst);
715                 break;
716         case CRYPTO_BUF_CONTIG:
717                 MPASS(off + size <= crp->crp_buf.cb_buf_len);
718                 bcopy(crp->crp_buf.cb_buf + off, dst, size);
719                 break;
720         default:
721 #ifdef INVARIANTS
722                 panic("invalid crp buf type %d", crp->crp_buf.cb_type);
723 #endif
724                 break;
725         }
726 }
727
728 int
729 crypto_apply_buf(struct crypto_buffer *cb, int off, int len,
730     int (*f)(void *, const void *, u_int), void *arg)
731 {
732         int error;
733
734         switch (cb->cb_type) {
735         case CRYPTO_BUF_MBUF:
736         case CRYPTO_BUF_SINGLE_MBUF:
737                 error = m_apply(cb->cb_mbuf, off, len,
738                     (int (*)(void *, void *, u_int))f, arg);
739                 break;
740         case CRYPTO_BUF_UIO:
741                 error = cuio_apply(cb->cb_uio, off, len, f, arg);
742                 break;
743 #if CRYPTO_MAY_HAVE_VMPAGE
744         case CRYPTO_BUF_VMPAGE:
745                 error = cvm_page_apply(cb->cb_vm_page,
746                     off + cb->cb_vm_page_offset, len, f, arg);
747                 break;
748 #endif /* CRYPTO_MAY_HAVE_VMPAGE */
749         case CRYPTO_BUF_CONTIG:
750                 MPASS(off + len <= cb->cb_buf_len);
751                 error = (*f)(arg, cb->cb_buf + off, len);
752                 break;
753         default:
754 #ifdef INVARIANTS
755                 panic("invalid crypto buf type %d", cb->cb_type);
756 #endif
757                 error = 0;
758                 break;
759         }
760         return (error);
761 }
762
763 int
764 crypto_apply(struct cryptop *crp, int off, int len,
765     int (*f)(void *, const void *, u_int), void *arg)
766 {
767         return (crypto_apply_buf(&crp->crp_buf, off, len, f, arg));
768 }
769
770 static inline void *
771 m_contiguous_subsegment(struct mbuf *m, size_t skip, size_t len)
772 {
773         int rel_off;
774
775         MPASS(skip <= INT_MAX);
776
777         m = m_getptr(m, (int)skip, &rel_off);
778         if (m == NULL)
779                 return (NULL);
780
781         MPASS(rel_off >= 0);
782         skip = rel_off;
783         if (skip + len > m->m_len)
784                 return (NULL);
785
786         if (m->m_flags & M_EXTPG)
787                 return (m_epg_contiguous_subsegment(m, skip, len));
788         return (mtod(m, char*) + skip);
789 }
790
791 static inline void *
792 cuio_contiguous_segment(struct uio *uio, size_t skip, size_t len)
793 {
794         int rel_off, idx;
795
796         MPASS(skip <= INT_MAX);
797         idx = cuio_getptr(uio, (int)skip, &rel_off);
798         if (idx < 0)
799                 return (NULL);
800
801         MPASS(rel_off >= 0);
802         skip = rel_off;
803         if (skip + len > uio->uio_iov[idx].iov_len)
804                 return (NULL);
805         return ((char *)uio->uio_iov[idx].iov_base + skip);
806 }
807
808 void *
809 crypto_buffer_contiguous_subsegment(struct crypto_buffer *cb, size_t skip,
810     size_t len)
811 {
812
813         switch (cb->cb_type) {
814         case CRYPTO_BUF_MBUF:
815         case CRYPTO_BUF_SINGLE_MBUF:
816                 return (m_contiguous_subsegment(cb->cb_mbuf, skip, len));
817         case CRYPTO_BUF_UIO:
818                 return (cuio_contiguous_segment(cb->cb_uio, skip, len));
819 #if CRYPTO_MAY_HAVE_VMPAGE
820         case CRYPTO_BUF_VMPAGE:
821                 MPASS(skip + len <= cb->cb_vm_page_len);
822                 return (cvm_page_contiguous_segment(cb->cb_vm_page,
823                     skip + cb->cb_vm_page_offset, len));
824 #endif /* CRYPTO_MAY_HAVE_VMPAGE */
825         case CRYPTO_BUF_CONTIG:
826                 MPASS(skip + len <= cb->cb_buf_len);
827                 return (cb->cb_buf + skip);
828         default:
829 #ifdef INVARIANTS
830                 panic("invalid crp buf type %d", cb->cb_type);
831 #endif
832                 return (NULL);
833         }
834 }
835
836 void *
837 crypto_contiguous_subsegment(struct cryptop *crp, size_t skip, size_t len)
838 {
839         return (crypto_buffer_contiguous_subsegment(&crp->crp_buf, skip, len));
840 }