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 44 #include <opencrypto/cryptodev.h> 45 46 /* 47 * This macro is only for avoiding code duplication, as we need to skip 48 * given number of bytes in the same way in three functions below. 49 */ 50 #define CUIO_SKIP() do { \ 51 KASSERT(off >= 0, ("%s: off %d < 0", __func__, off)); \ 52 KASSERT(len >= 0, ("%s: len %d < 0", __func__, len)); \ 53 while (off > 0) { \ 54 KASSERT(iol >= 0, ("%s: empty in skip", __func__)); \ 55 if (off < iov->iov_len) \ 56 break; \ 57 off -= iov->iov_len; \ 58 iol--; \ 59 iov++; \ 60 } \ 61 } while (0) 62 63 static void 64 cuio_copydata(struct uio* uio, int off, int len, caddr_t cp) 65 { 66 struct iovec *iov = uio->uio_iov; 67 int iol = uio->uio_iovcnt; 68 unsigned count; 69 70 CUIO_SKIP(); 71 while (len > 0) { 72 KASSERT(iol >= 0, ("%s: empty", __func__)); 73 count = min(iov->iov_len - off, len); 74 bcopy(((caddr_t)iov->iov_base) + off, cp, count); 75 len -= count; 76 cp += count; 77 off = 0; 78 iol--; 79 iov++; 80 } 81 } 82 83 static void 84 cuio_copyback(struct uio* uio, int off, int len, c_caddr_t cp) 85 { 86 struct iovec *iov = uio->uio_iov; 87 int iol = uio->uio_iovcnt; 88 unsigned count; 89 90 CUIO_SKIP(); 91 while (len > 0) { 92 KASSERT(iol >= 0, ("%s: empty", __func__)); 93 count = min(iov->iov_len - off, len); 94 bcopy(cp, ((caddr_t)iov->iov_base) + off, count); 95 len -= count; 96 cp += count; 97 off = 0; 98 iol--; 99 iov++; 100 } 101 } 102 103 /* 104 * Return the index and offset of location in iovec list. 105 */ 106 static int 107 cuio_getptr(struct uio *uio, int loc, int *off) 108 { 109 int ind, len; 110 111 ind = 0; 112 while (loc >= 0 && ind < uio->uio_iovcnt) { 113 len = uio->uio_iov[ind].iov_len; 114 if (len > loc) { 115 *off = loc; 116 return (ind); 117 } 118 loc -= len; 119 ind++; 120 } 121 122 if (ind > 0 && loc == 0) { 123 ind--; 124 *off = uio->uio_iov[ind].iov_len; 125 return (ind); 126 } 127 128 return (-1); 129 } 130 131 void 132 crypto_cursor_init(struct crypto_buffer_cursor *cc, 133 const struct crypto_buffer *cb) 134 { 135 memset(cc, 0, sizeof(*cc)); 136 cc->cc_type = cb->cb_type; 137 switch (cc->cc_type) { 138 case CRYPTO_BUF_CONTIG: 139 cc->cc_buf = cb->cb_buf; 140 cc->cc_buf_len = cb->cb_buf_len; 141 break; 142 case CRYPTO_BUF_MBUF: 143 cc->cc_mbuf = cb->cb_mbuf; 144 break; 145 case CRYPTO_BUF_UIO: 146 cc->cc_iov = cb->cb_uio->uio_iov; 147 break; 148 default: 149 #ifdef INVARIANTS 150 panic("%s: invalid buffer type %d", __func__, cb->cb_type); 151 #endif 152 break; 153 } 154 } 155 156 void 157 crypto_cursor_advance(struct crypto_buffer_cursor *cc, size_t amount) 158 { 159 size_t remain; 160 161 switch (cc->cc_type) { 162 case CRYPTO_BUF_CONTIG: 163 MPASS(cc->cc_buf_len >= amount); 164 cc->cc_buf += amount; 165 cc->cc_buf_len -= amount; 166 break; 167 case CRYPTO_BUF_MBUF: 168 for (;;) { 169 remain = cc->cc_mbuf->m_len - cc->cc_offset; 170 if (amount < remain) { 171 cc->cc_offset += amount; 172 break; 173 } 174 amount -= remain; 175 cc->cc_mbuf = cc->cc_mbuf->m_next; 176 cc->cc_offset = 0; 177 if (amount == 0) 178 break; 179 } 180 break; 181 case CRYPTO_BUF_UIO: 182 for (;;) { 183 remain = cc->cc_iov->iov_len - cc->cc_offset; 184 if (amount < remain) { 185 cc->cc_offset += amount; 186 break; 187 } 188 amount -= remain; 189 cc->cc_iov++; 190 cc->cc_offset = 0; 191 if (amount == 0) 192 break; 193 } 194 break; 195 default: 196 #ifdef INVARIANTS 197 panic("%s: invalid buffer type %d", __func__, cc->cc_type); 198 #endif 199 break; 200 } 201 } 202 203 void * 204 crypto_cursor_segbase(struct crypto_buffer_cursor *cc) 205 { 206 switch (cc->cc_type) { 207 case CRYPTO_BUF_CONTIG: 208 return (cc->cc_buf); 209 case CRYPTO_BUF_MBUF: 210 if (cc->cc_mbuf == NULL) 211 return (NULL); 212 KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0, 213 ("%s: not supported for unmapped mbufs", __func__)); 214 return (mtod(cc->cc_mbuf, char *) + cc->cc_offset); 215 case CRYPTO_BUF_UIO: 216 return ((char *)cc->cc_iov->iov_base + cc->cc_offset); 217 default: 218 #ifdef INVARIANTS 219 panic("%s: invalid buffer type %d", __func__, cc->cc_type); 220 #endif 221 return (NULL); 222 } 223 } 224 225 size_t 226 crypto_cursor_seglen(struct crypto_buffer_cursor *cc) 227 { 228 switch (cc->cc_type) { 229 case CRYPTO_BUF_CONTIG: 230 return (cc->cc_buf_len); 231 case CRYPTO_BUF_MBUF: 232 if (cc->cc_mbuf == NULL) 233 return (0); 234 return (cc->cc_mbuf->m_len - cc->cc_offset); 235 case CRYPTO_BUF_UIO: 236 return (cc->cc_iov->iov_len - cc->cc_offset); 237 default: 238 #ifdef INVARIANTS 239 panic("%s: invalid buffer type %d", __func__, cc->cc_type); 240 #endif 241 return (0); 242 } 243 } 244 245 void 246 crypto_cursor_copyback(struct crypto_buffer_cursor *cc, int size, 247 const void *vsrc) 248 { 249 size_t remain, todo; 250 const char *src; 251 char *dst; 252 253 src = vsrc; 254 switch (cc->cc_type) { 255 case CRYPTO_BUF_CONTIG: 256 MPASS(cc->cc_buf_len >= size); 257 memcpy(cc->cc_buf, src, size); 258 cc->cc_buf += size; 259 cc->cc_buf_len -= size; 260 break; 261 case CRYPTO_BUF_MBUF: 262 for (;;) { 263 KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0, 264 ("%s: not supported for unmapped mbufs", __func__)); 265 dst = mtod(cc->cc_mbuf, char *) + cc->cc_offset; 266 remain = cc->cc_mbuf->m_len - cc->cc_offset; 267 todo = MIN(remain, size); 268 memcpy(dst, src, todo); 269 src += todo; 270 if (todo < remain) { 271 cc->cc_offset += todo; 272 break; 273 } 274 size -= todo; 275 cc->cc_mbuf = cc->cc_mbuf->m_next; 276 cc->cc_offset = 0; 277 if (size == 0) 278 break; 279 } 280 break; 281 case CRYPTO_BUF_UIO: 282 for (;;) { 283 dst = (char *)cc->cc_iov->iov_base + cc->cc_offset; 284 remain = cc->cc_iov->iov_len - cc->cc_offset; 285 todo = MIN(remain, size); 286 memcpy(dst, src, todo); 287 src += todo; 288 if (todo < remain) { 289 cc->cc_offset += todo; 290 break; 291 } 292 size -= todo; 293 cc->cc_iov++; 294 cc->cc_offset = 0; 295 if (size == 0) 296 break; 297 } 298 break; 299 default: 300 #ifdef INVARIANTS 301 panic("%s: invalid buffer type %d", __func__, cc->cc_type); 302 #endif 303 break; 304 } 305 } 306 307 void 308 crypto_cursor_copydata(struct crypto_buffer_cursor *cc, int size, void *vdst) 309 { 310 size_t remain, todo; 311 const char *src; 312 char *dst; 313 314 dst = vdst; 315 switch (cc->cc_type) { 316 case CRYPTO_BUF_CONTIG: 317 MPASS(cc->cc_buf_len >= size); 318 memcpy(dst, cc->cc_buf, size); 319 cc->cc_buf += size; 320 cc->cc_buf_len -= size; 321 break; 322 case CRYPTO_BUF_MBUF: 323 for (;;) { 324 KASSERT((cc->cc_mbuf->m_flags & M_EXTPG) == 0, 325 ("%s: not supported for unmapped mbufs", __func__)); 326 src = mtod(cc->cc_mbuf, const char *) + cc->cc_offset; 327 remain = cc->cc_mbuf->m_len - cc->cc_offset; 328 todo = MIN(remain, size); 329 memcpy(dst, src, todo); 330 dst += todo; 331 if (todo < remain) { 332 cc->cc_offset += todo; 333 break; 334 } 335 size -= todo; 336 cc->cc_mbuf = cc->cc_mbuf->m_next; 337 cc->cc_offset = 0; 338 if (size == 0) 339 break; 340 } 341 break; 342 case CRYPTO_BUF_UIO: 343 for (;;) { 344 src = (const char *)cc->cc_iov->iov_base + 345 cc->cc_offset; 346 remain = cc->cc_iov->iov_len - cc->cc_offset; 347 todo = MIN(remain, size); 348 memcpy(dst, src, todo); 349 dst += todo; 350 if (todo < remain) { 351 cc->cc_offset += todo; 352 break; 353 } 354 size -= todo; 355 cc->cc_iov++; 356 cc->cc_offset = 0; 357 if (size == 0) 358 break; 359 } 360 break; 361 default: 362 #ifdef INVARIANTS 363 panic("%s: invalid buffer type %d", __func__, cc->cc_type); 364 #endif 365 break; 366 } 367 } 368 369 /* 370 * To avoid advancing 'cursor', make a local copy that gets advanced 371 * instead. 372 */ 373 void 374 crypto_cursor_copydata_noadv(struct crypto_buffer_cursor *cc, int size, 375 void *vdst) 376 { 377 struct crypto_buffer_cursor copy; 378 379 copy = *cc; 380 crypto_cursor_copydata(©, size, vdst); 381 } 382 383 /* 384 * Apply function f to the data in an iovec list starting "off" bytes from 385 * the beginning, continuing for "len" bytes. 386 */ 387 static int 388 cuio_apply(struct uio *uio, int off, int len, 389 int (*f)(void *, const void *, u_int), void *arg) 390 { 391 struct iovec *iov = uio->uio_iov; 392 int iol = uio->uio_iovcnt; 393 unsigned count; 394 int rval; 395 396 CUIO_SKIP(); 397 while (len > 0) { 398 KASSERT(iol >= 0, ("%s: empty", __func__)); 399 count = min(iov->iov_len - off, len); 400 rval = (*f)(arg, ((caddr_t)iov->iov_base) + off, count); 401 if (rval) 402 return (rval); 403 len -= count; 404 off = 0; 405 iol--; 406 iov++; 407 } 408 return (0); 409 } 410 411 void 412 crypto_copyback(struct cryptop *crp, int off, int size, const void *src) 413 { 414 struct crypto_buffer *cb; 415 416 if (crp->crp_obuf.cb_type != CRYPTO_BUF_NONE) 417 cb = &crp->crp_obuf; 418 else 419 cb = &crp->crp_buf; 420 switch (cb->cb_type) { 421 case CRYPTO_BUF_MBUF: 422 m_copyback(cb->cb_mbuf, off, size, src); 423 break; 424 case CRYPTO_BUF_UIO: 425 cuio_copyback(cb->cb_uio, off, size, src); 426 break; 427 case CRYPTO_BUF_CONTIG: 428 MPASS(off + size <= cb->cb_buf_len); 429 bcopy(src, cb->cb_buf + off, size); 430 break; 431 default: 432 #ifdef INVARIANTS 433 panic("invalid crp buf type %d", cb->cb_type); 434 #endif 435 break; 436 } 437 } 438 439 void 440 crypto_copydata(struct cryptop *crp, int off, int size, void *dst) 441 { 442 443 switch (crp->crp_buf.cb_type) { 444 case CRYPTO_BUF_MBUF: 445 m_copydata(crp->crp_buf.cb_mbuf, off, size, dst); 446 break; 447 case CRYPTO_BUF_UIO: 448 cuio_copydata(crp->crp_buf.cb_uio, off, size, dst); 449 break; 450 case CRYPTO_BUF_CONTIG: 451 MPASS(off + size <= crp->crp_buf.cb_buf_len); 452 bcopy(crp->crp_buf.cb_buf + off, dst, size); 453 break; 454 default: 455 #ifdef INVARIANTS 456 panic("invalid crp buf type %d", crp->crp_buf.cb_type); 457 #endif 458 break; 459 } 460 } 461 462 int 463 crypto_apply_buf(struct crypto_buffer *cb, int off, int len, 464 int (*f)(void *, const void *, u_int), void *arg) 465 { 466 int error; 467 468 switch (cb->cb_type) { 469 case CRYPTO_BUF_MBUF: 470 error = m_apply(cb->cb_mbuf, off, len, 471 (int (*)(void *, void *, u_int))f, arg); 472 break; 473 case CRYPTO_BUF_UIO: 474 error = cuio_apply(cb->cb_uio, off, len, f, arg); 475 break; 476 case CRYPTO_BUF_CONTIG: 477 MPASS(off + len <= cb->cb_buf_len); 478 error = (*f)(arg, cb->cb_buf + off, len); 479 break; 480 default: 481 #ifdef INVARIANTS 482 panic("invalid crypto buf type %d", cb->cb_type); 483 #endif 484 error = 0; 485 break; 486 } 487 return (error); 488 } 489 490 int 491 crypto_apply(struct cryptop *crp, int off, int len, 492 int (*f)(void *, const void *, u_int), void *arg) 493 { 494 return (crypto_apply_buf(&crp->crp_buf, off, len, f, arg)); 495 } 496 497 static inline void * 498 m_contiguous_subsegment(struct mbuf *m, size_t skip, size_t len) 499 { 500 int rel_off; 501 502 MPASS(skip <= INT_MAX); 503 504 m = m_getptr(m, (int)skip, &rel_off); 505 if (m == NULL) 506 return (NULL); 507 508 MPASS(rel_off >= 0); 509 skip = rel_off; 510 if (skip + len > m->m_len) 511 return (NULL); 512 513 return (mtod(m, char*) + skip); 514 } 515 516 static inline void * 517 cuio_contiguous_segment(struct uio *uio, size_t skip, size_t len) 518 { 519 int rel_off, idx; 520 521 MPASS(skip <= INT_MAX); 522 idx = cuio_getptr(uio, (int)skip, &rel_off); 523 if (idx < 0) 524 return (NULL); 525 526 MPASS(rel_off >= 0); 527 skip = rel_off; 528 if (skip + len > uio->uio_iov[idx].iov_len) 529 return (NULL); 530 return ((char *)uio->uio_iov[idx].iov_base + skip); 531 } 532 533 void * 534 crypto_buffer_contiguous_subsegment(struct crypto_buffer *cb, size_t skip, 535 size_t len) 536 { 537 538 switch (cb->cb_type) { 539 case CRYPTO_BUF_MBUF: 540 return (m_contiguous_subsegment(cb->cb_mbuf, skip, len)); 541 case CRYPTO_BUF_UIO: 542 return (cuio_contiguous_segment(cb->cb_uio, skip, len)); 543 case CRYPTO_BUF_CONTIG: 544 MPASS(skip + len <= cb->cb_buf_len); 545 return (cb->cb_buf + skip); 546 default: 547 #ifdef INVARIANTS 548 panic("invalid crp buf type %d", cb->cb_type); 549 #endif 550 return (NULL); 551 } 552 } 553 554 void * 555 crypto_contiguous_subsegment(struct cryptop *crp, size_t skip, size_t len) 556 { 557 return (crypto_buffer_contiguous_subsegment(&crp->crp_buf, skip, len)); 558 } 559