Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later 2 : : /* 3 : : * Cryptographic API. 4 : : * 5 : : * Cipher operations. 6 : : * 7 : : * Copyright (c) 2002 James Morris <jmorris@intercode.com.au> 8 : : * 2002 Adam J. Richter <adam@yggdrasil.com> 9 : : * 2004 Jean-Luc Cooke <jlcooke@certainkey.com> 10 : : */ 11 : : 12 : : #include <crypto/scatterwalk.h> 13 : : #include <linux/kernel.h> 14 : : #include <linux/mm.h> 15 : : #include <linux/module.h> 16 : : #include <linux/scatterlist.h> 17 : : 18 : : static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out) 19 : : { 20 : 0 : void *src = out ? buf : sgdata; 21 : 0 : void *dst = out ? sgdata : buf; 22 : : 23 : 0 : memcpy(dst, src, nbytes); 24 : : } 25 : : 26 : 0 : void scatterwalk_copychunks(void *buf, struct scatter_walk *walk, 27 : : size_t nbytes, int out) 28 : : { 29 : : for (;;) { 30 : : unsigned int len_this_page = scatterwalk_pagelen(walk); 31 : : u8 *vaddr; 32 : : 33 : 0 : if (len_this_page > nbytes) 34 : : len_this_page = nbytes; 35 : : 36 : 0 : if (out != 2) { 37 : 0 : vaddr = scatterwalk_map(walk); 38 : : memcpy_dir(buf, vaddr, len_this_page, out); 39 : : scatterwalk_unmap(vaddr); 40 : : } 41 : : 42 : : scatterwalk_advance(walk, len_this_page); 43 : : 44 : 0 : if (nbytes == len_this_page) 45 : : break; 46 : : 47 : 0 : buf += len_this_page; 48 : 0 : nbytes -= len_this_page; 49 : : 50 : 0 : scatterwalk_pagedone(walk, out & 1, 1); 51 : 0 : } 52 : 0 : } 53 : : EXPORT_SYMBOL_GPL(scatterwalk_copychunks); 54 : : 55 : 0 : void scatterwalk_map_and_copy(void *buf, struct scatterlist *sg, 56 : : unsigned int start, unsigned int nbytes, int out) 57 : : { 58 : : struct scatter_walk walk; 59 : : struct scatterlist tmp[2]; 60 : : 61 : 0 : if (!nbytes) 62 : 0 : return; 63 : : 64 : 0 : sg = scatterwalk_ffwd(tmp, sg, start); 65 : : 66 : : scatterwalk_start(&walk, sg); 67 : 0 : scatterwalk_copychunks(buf, &walk, nbytes, out); 68 : 0 : scatterwalk_done(&walk, out, 0); 69 : : } 70 : : EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy); 71 : : 72 : 0 : struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2], 73 : : struct scatterlist *src, 74 : : unsigned int len) 75 : : { 76 : : for (;;) { 77 : 0 : if (!len) 78 : 0 : return src; 79 : : 80 : 0 : if (src->length > len) 81 : : break; 82 : : 83 : 0 : len -= src->length; 84 : 0 : src = sg_next(src); 85 : 0 : } 86 : : 87 : 0 : sg_init_table(dst, 2); 88 : 0 : sg_set_page(dst, sg_page(src), src->length - len, src->offset + len); 89 : 0 : scatterwalk_crypto_chain(dst, sg_next(src), 2); 90 : : 91 : 0 : return dst; 92 : : } 93 : : EXPORT_SYMBOL_GPL(scatterwalk_ffwd);