aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/generic/backport-5.4/080-wireguard-0033-crypto-lib-chacha20poly1305-reimplement-crypt_from_s.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/generic/backport-5.4/080-wireguard-0033-crypto-lib-chacha20poly1305-reimplement-crypt_from_s.patch')
-rw-r--r--target/linux/generic/backport-5.4/080-wireguard-0033-crypto-lib-chacha20poly1305-reimplement-crypt_from_s.patch295
1 files changed, 0 insertions, 295 deletions
diff --git a/target/linux/generic/backport-5.4/080-wireguard-0033-crypto-lib-chacha20poly1305-reimplement-crypt_from_s.patch b/target/linux/generic/backport-5.4/080-wireguard-0033-crypto-lib-chacha20poly1305-reimplement-crypt_from_s.patch
deleted file mode 100644
index e4b2b58b82..0000000000
--- a/target/linux/generic/backport-5.4/080-wireguard-0033-crypto-lib-chacha20poly1305-reimplement-crypt_from_s.patch
+++ /dev/null
@@ -1,295 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Ard Biesheuvel <ardb@kernel.org>
-Date: Fri, 8 Nov 2019 13:22:40 +0100
-Subject: [PATCH] crypto: lib/chacha20poly1305 - reimplement crypt_from_sg()
- routine
-
-commit d95312a3ccc0cd544d374be2fc45aeaa803e5fd9 upstream.
-
-Reimplement the library routines to perform chacha20poly1305 en/decryption
-on scatterlists, without [ab]using the [deprecated] blkcipher interface,
-which is rather heavyweight and does things we don't really need.
-
-Instead, we use the sg_miter API in a novel and clever way, to iterate
-over the scatterlist in-place (i.e., source == destination, which is the
-only way this library is expected to be used). That way, we don't have to
-iterate over two scatterlists in parallel.
-
-Another optimization is that, instead of relying on the blkcipher walker
-to present the input in suitable chunks, we recognize that ChaCha is a
-streamcipher, and so we can simply deal with partial blocks by keeping a
-block of cipherstream on the stack and use crypto_xor() to mix it with
-the in/output.
-
-Finally, we omit the scatterwalk_and_copy() call if the last element of
-the scatterlist covers the MAC as well (which is the common case),
-avoiding the need to walk the scatterlist and kmap() the page twice.
-
-Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
-Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
----
- include/crypto/chacha20poly1305.h | 11 ++
- lib/crypto/chacha20poly1305-selftest.c | 45 ++++++++
- lib/crypto/chacha20poly1305.c | 150 +++++++++++++++++++++++++
- 3 files changed, 206 insertions(+)
-
---- a/include/crypto/chacha20poly1305.h
-+++ b/include/crypto/chacha20poly1305.h
-@@ -7,6 +7,7 @@
- #define __CHACHA20POLY1305_H
-
- #include <linux/types.h>
-+#include <linux/scatterlist.h>
-
- enum chacha20poly1305_lengths {
- XCHACHA20POLY1305_NONCE_SIZE = 24,
-@@ -34,4 +35,14 @@ bool __must_check xchacha20poly1305_decr
- const size_t ad_len, const u8 nonce[XCHACHA20POLY1305_NONCE_SIZE],
- const u8 key[CHACHA20POLY1305_KEY_SIZE]);
-
-+bool chacha20poly1305_encrypt_sg_inplace(struct scatterlist *src, size_t src_len,
-+ const u8 *ad, const size_t ad_len,
-+ const u64 nonce,
-+ const u8 key[CHACHA20POLY1305_KEY_SIZE]);
-+
-+bool chacha20poly1305_decrypt_sg_inplace(struct scatterlist *src, size_t src_len,
-+ const u8 *ad, const size_t ad_len,
-+ const u64 nonce,
-+ const u8 key[CHACHA20POLY1305_KEY_SIZE]);
-+
- #endif /* __CHACHA20POLY1305_H */
---- a/lib/crypto/chacha20poly1305-selftest.c
-+++ b/lib/crypto/chacha20poly1305-selftest.c
-@@ -7250,6 +7250,7 @@ bool __init chacha20poly1305_selftest(vo
- enum { MAXIMUM_TEST_BUFFER_LEN = 1UL << 12 };
- size_t i;
- u8 *computed_output = NULL, *heap_src = NULL;
-+ struct scatterlist sg_src;
- bool success = true, ret;
-
- heap_src = kmalloc(MAXIMUM_TEST_BUFFER_LEN, GFP_KERNEL);
-@@ -7280,6 +7281,29 @@ bool __init chacha20poly1305_selftest(vo
- }
- }
-
-+ for (i = 0; i < ARRAY_SIZE(chacha20poly1305_enc_vectors); ++i) {
-+ if (chacha20poly1305_enc_vectors[i].nlen != 8)
-+ continue;
-+ memcpy(heap_src, chacha20poly1305_enc_vectors[i].input,
-+ chacha20poly1305_enc_vectors[i].ilen);
-+ sg_init_one(&sg_src, heap_src,
-+ chacha20poly1305_enc_vectors[i].ilen + POLY1305_DIGEST_SIZE);
-+ chacha20poly1305_encrypt_sg_inplace(&sg_src,
-+ chacha20poly1305_enc_vectors[i].ilen,
-+ chacha20poly1305_enc_vectors[i].assoc,
-+ chacha20poly1305_enc_vectors[i].alen,
-+ get_unaligned_le64(chacha20poly1305_enc_vectors[i].nonce),
-+ chacha20poly1305_enc_vectors[i].key);
-+ if (memcmp(heap_src,
-+ chacha20poly1305_enc_vectors[i].output,
-+ chacha20poly1305_enc_vectors[i].ilen +
-+ POLY1305_DIGEST_SIZE)) {
-+ pr_err("chacha20poly1305 sg encryption self-test %zu: FAIL\n",
-+ i + 1);
-+ success = false;
-+ }
-+ }
-+
- for (i = 0; i < ARRAY_SIZE(chacha20poly1305_dec_vectors); ++i) {
- memset(computed_output, 0, MAXIMUM_TEST_BUFFER_LEN);
- ret = chacha20poly1305_decrypt(computed_output,
-@@ -7301,6 +7325,27 @@ bool __init chacha20poly1305_selftest(vo
- }
- }
-
-+ for (i = 0; i < ARRAY_SIZE(chacha20poly1305_dec_vectors); ++i) {
-+ memcpy(heap_src, chacha20poly1305_dec_vectors[i].input,
-+ chacha20poly1305_dec_vectors[i].ilen);
-+ sg_init_one(&sg_src, heap_src,
-+ chacha20poly1305_dec_vectors[i].ilen);
-+ ret = chacha20poly1305_decrypt_sg_inplace(&sg_src,
-+ chacha20poly1305_dec_vectors[i].ilen,
-+ chacha20poly1305_dec_vectors[i].assoc,
-+ chacha20poly1305_dec_vectors[i].alen,
-+ get_unaligned_le64(chacha20poly1305_dec_vectors[i].nonce),
-+ chacha20poly1305_dec_vectors[i].key);
-+ if (!decryption_success(ret,
-+ chacha20poly1305_dec_vectors[i].failure,
-+ memcmp(heap_src, chacha20poly1305_dec_vectors[i].output,
-+ chacha20poly1305_dec_vectors[i].ilen -
-+ POLY1305_DIGEST_SIZE))) {
-+ pr_err("chacha20poly1305 sg decryption self-test %zu: FAIL\n",
-+ i + 1);
-+ success = false;
-+ }
-+ }
-
- for (i = 0; i < ARRAY_SIZE(xchacha20poly1305_enc_vectors); ++i) {
- memset(computed_output, 0, MAXIMUM_TEST_BUFFER_LEN);
---- a/lib/crypto/chacha20poly1305.c
-+++ b/lib/crypto/chacha20poly1305.c
-@@ -11,6 +11,7 @@
- #include <crypto/chacha20poly1305.h>
- #include <crypto/chacha.h>
- #include <crypto/poly1305.h>
-+#include <crypto/scatterwalk.h>
-
- #include <asm/unaligned.h>
- #include <linux/kernel.h>
-@@ -205,6 +206,155 @@ bool xchacha20poly1305_decrypt(u8 *dst,
- }
- EXPORT_SYMBOL(xchacha20poly1305_decrypt);
-
-+static
-+bool chacha20poly1305_crypt_sg_inplace(struct scatterlist *src,
-+ const size_t src_len,
-+ const u8 *ad, const size_t ad_len,
-+ const u64 nonce,
-+ const u8 key[CHACHA20POLY1305_KEY_SIZE],
-+ int encrypt)
-+{
-+ const u8 *pad0 = page_address(ZERO_PAGE(0));
-+ struct poly1305_desc_ctx poly1305_state;
-+ u32 chacha_state[CHACHA_STATE_WORDS];
-+ struct sg_mapping_iter miter;
-+ size_t partial = 0;
-+ unsigned int flags;
-+ bool ret = true;
-+ int sl;
-+ union {
-+ struct {
-+ u32 k[CHACHA_KEY_WORDS];
-+ __le64 iv[2];
-+ };
-+ u8 block0[POLY1305_KEY_SIZE];
-+ u8 chacha_stream[CHACHA_BLOCK_SIZE];
-+ struct {
-+ u8 mac[2][POLY1305_DIGEST_SIZE];
-+ };
-+ __le64 lens[2];
-+ } b __aligned(16);
-+
-+ chacha_load_key(b.k, key);
-+
-+ b.iv[0] = 0;
-+ b.iv[1] = cpu_to_le64(nonce);
-+
-+ chacha_init(chacha_state, b.k, (u8 *)b.iv);
-+ chacha_crypt(chacha_state, b.block0, pad0, sizeof(b.block0), 20);
-+ poly1305_init(&poly1305_state, b.block0);
-+
-+ if (unlikely(ad_len)) {
-+ poly1305_update(&poly1305_state, ad, ad_len);
-+ if (ad_len & 0xf)
-+ poly1305_update(&poly1305_state, pad0, 0x10 - (ad_len & 0xf));
-+ }
-+
-+ flags = SG_MITER_TO_SG;
-+ if (!preemptible())
-+ flags |= SG_MITER_ATOMIC;
-+
-+ sg_miter_start(&miter, src, sg_nents(src), flags);
-+
-+ for (sl = src_len; sl > 0 && sg_miter_next(&miter); sl -= miter.length) {
-+ u8 *addr = miter.addr;
-+ size_t length = min_t(size_t, sl, miter.length);
-+
-+ if (!encrypt)
-+ poly1305_update(&poly1305_state, addr, length);
-+
-+ if (unlikely(partial)) {
-+ size_t l = min(length, CHACHA_BLOCK_SIZE - partial);
-+
-+ crypto_xor(addr, b.chacha_stream + partial, l);
-+ partial = (partial + l) & (CHACHA_BLOCK_SIZE - 1);
-+
-+ addr += l;
-+ length -= l;
-+ }
-+
-+ if (likely(length >= CHACHA_BLOCK_SIZE || length == sl)) {
-+ size_t l = length;
-+
-+ if (unlikely(length < sl))
-+ l &= ~(CHACHA_BLOCK_SIZE - 1);
-+ chacha_crypt(chacha_state, addr, addr, l, 20);
-+ addr += l;
-+ length -= l;
-+ }
-+
-+ if (unlikely(length > 0)) {
-+ chacha_crypt(chacha_state, b.chacha_stream, pad0,
-+ CHACHA_BLOCK_SIZE, 20);
-+ crypto_xor(addr, b.chacha_stream, length);
-+ partial = length;
-+ }
-+
-+ if (encrypt)
-+ poly1305_update(&poly1305_state, miter.addr,
-+ min_t(size_t, sl, miter.length));
-+ }
-+
-+ if (src_len & 0xf)
-+ poly1305_update(&poly1305_state, pad0, 0x10 - (src_len & 0xf));
-+
-+ b.lens[0] = cpu_to_le64(ad_len);
-+ b.lens[1] = cpu_to_le64(src_len);
-+ poly1305_update(&poly1305_state, (u8 *)b.lens, sizeof(b.lens));
-+
-+ if (likely(sl <= -POLY1305_DIGEST_SIZE)) {
-+ if (encrypt) {
-+ poly1305_final(&poly1305_state,
-+ miter.addr + miter.length + sl);
-+ ret = true;
-+ } else {
-+ poly1305_final(&poly1305_state, b.mac[0]);
-+ ret = !crypto_memneq(b.mac[0],
-+ miter.addr + miter.length + sl,
-+ POLY1305_DIGEST_SIZE);
-+ }
-+ }
-+
-+ sg_miter_stop(&miter);
-+
-+ if (unlikely(sl > -POLY1305_DIGEST_SIZE)) {
-+ poly1305_final(&poly1305_state, b.mac[1]);
-+ scatterwalk_map_and_copy(b.mac[encrypt], src, src_len,
-+ sizeof(b.mac[1]), encrypt);
-+ ret = encrypt ||
-+ !crypto_memneq(b.mac[0], b.mac[1], POLY1305_DIGEST_SIZE);
-+ }
-+
-+ memzero_explicit(chacha_state, sizeof(chacha_state));
-+ memzero_explicit(&b, sizeof(b));
-+
-+ return ret;
-+}
-+
-+bool chacha20poly1305_encrypt_sg_inplace(struct scatterlist *src, size_t src_len,
-+ const u8 *ad, const size_t ad_len,
-+ const u64 nonce,
-+ const u8 key[CHACHA20POLY1305_KEY_SIZE])
-+{
-+ return chacha20poly1305_crypt_sg_inplace(src, src_len, ad, ad_len,
-+ nonce, key, 1);
-+}
-+EXPORT_SYMBOL(chacha20poly1305_encrypt_sg_inplace);
-+
-+bool chacha20poly1305_decrypt_sg_inplace(struct scatterlist *src, size_t src_len,
-+ const u8 *ad, const size_t ad_len,
-+ const u64 nonce,
-+ const u8 key[CHACHA20POLY1305_KEY_SIZE])
-+{
-+ if (unlikely(src_len < POLY1305_DIGEST_SIZE))
-+ return false;
-+
-+ return chacha20poly1305_crypt_sg_inplace(src,
-+ src_len - POLY1305_DIGEST_SIZE,
-+ ad, ad_len, nonce, key, 0);
-+}
-+EXPORT_SYMBOL(chacha20poly1305_decrypt_sg_inplace);
-+
- static int __init mod_init(void)
- {
- if (!IS_ENABLED(CONFIG_CRYPTO_MANAGER_DISABLE_TESTS) &&