cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

scatterwalk.c (2065B)


      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
     18static inline void memcpy_dir(void *buf, void *sgdata, size_t nbytes, int out)
     19{
     20	void *src = out ? buf : sgdata;
     21	void *dst = out ? sgdata : buf;
     22
     23	memcpy(dst, src, nbytes);
     24}
     25
     26void 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		if (len_this_page > nbytes)
     34			len_this_page = nbytes;
     35
     36		if (out != 2) {
     37			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		if (nbytes == len_this_page)
     45			break;
     46
     47		buf += len_this_page;
     48		nbytes -= len_this_page;
     49
     50		scatterwalk_pagedone(walk, out & 1, 1);
     51	}
     52}
     53EXPORT_SYMBOL_GPL(scatterwalk_copychunks);
     54
     55void 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	if (!nbytes)
     62		return;
     63
     64	sg = scatterwalk_ffwd(tmp, sg, start);
     65
     66	scatterwalk_start(&walk, sg);
     67	scatterwalk_copychunks(buf, &walk, nbytes, out);
     68	scatterwalk_done(&walk, out, 0);
     69}
     70EXPORT_SYMBOL_GPL(scatterwalk_map_and_copy);
     71
     72struct scatterlist *scatterwalk_ffwd(struct scatterlist dst[2],
     73				     struct scatterlist *src,
     74				     unsigned int len)
     75{
     76	for (;;) {
     77		if (!len)
     78			return src;
     79
     80		if (src->length > len)
     81			break;
     82
     83		len -= src->length;
     84		src = sg_next(src);
     85	}
     86
     87	sg_init_table(dst, 2);
     88	sg_set_page(dst, sg_page(src), src->length - len, src->offset + len);
     89	scatterwalk_crypto_chain(dst, sg_next(src), 2);
     90
     91	return dst;
     92}
     93EXPORT_SYMBOL_GPL(scatterwalk_ffwd);