18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * The ChaCha stream cipher (RFC7539)
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Martin Willi
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/kernel.h>
98c2ecf20Sopenharmony_ci#include <linux/export.h>
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <crypto/algapi.h> // for crypto_xor_cpy
138c2ecf20Sopenharmony_ci#include <crypto/chacha.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_civoid chacha_crypt_generic(u32 *state, u8 *dst, const u8 *src,
168c2ecf20Sopenharmony_ci			  unsigned int bytes, int nrounds)
178c2ecf20Sopenharmony_ci{
188c2ecf20Sopenharmony_ci	/* aligned to potentially speed up crypto_xor() */
198c2ecf20Sopenharmony_ci	u8 stream[CHACHA_BLOCK_SIZE] __aligned(sizeof(long));
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci	while (bytes >= CHACHA_BLOCK_SIZE) {
228c2ecf20Sopenharmony_ci		chacha_block_generic(state, stream, nrounds);
238c2ecf20Sopenharmony_ci		crypto_xor_cpy(dst, src, stream, CHACHA_BLOCK_SIZE);
248c2ecf20Sopenharmony_ci		bytes -= CHACHA_BLOCK_SIZE;
258c2ecf20Sopenharmony_ci		dst += CHACHA_BLOCK_SIZE;
268c2ecf20Sopenharmony_ci		src += CHACHA_BLOCK_SIZE;
278c2ecf20Sopenharmony_ci	}
288c2ecf20Sopenharmony_ci	if (bytes) {
298c2ecf20Sopenharmony_ci		chacha_block_generic(state, stream, nrounds);
308c2ecf20Sopenharmony_ci		crypto_xor_cpy(dst, src, stream, bytes);
318c2ecf20Sopenharmony_ci	}
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ciEXPORT_SYMBOL(chacha_crypt_generic);
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
36