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 0 : 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 0 : for (;;) {
30 0 : unsigned int len_this_page = scatterwalk_pagelen(walk);
31 0 : u8 *vaddr;
32 :
33 0 : if (len_this_page > nbytes)
34 0 : len_this_page = nbytes;
35 :
36 0 : if (out != 2) {
37 0 : vaddr = scatterwalk_map(walk);
38 0 : memcpy_dir(buf, vaddr, len_this_page, out);
39 0 : scatterwalk_unmap(vaddr);
40 : }
41 :
42 0 : 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 : }
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 0 : struct scatter_walk walk;
59 0 : struct scatterlist tmp[2];
60 :
61 0 : if (!nbytes)
62 0 : return;
63 :
64 0 : sg = scatterwalk_ffwd(tmp, sg, start);
65 :
66 0 : 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 0 : 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 : }
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);
|