diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2024-08-28 15:49:32 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2024-09-13 17:28:35 +0200 |
commit | 7fe5b3e4e7a61f3640d7645c434ac8c982f1388e (patch) | |
tree | 10dc19ffe6bd21bd25dc432d4654a0598e484237 /tools | |
parent | 6fd13b282f62bd840f2410692deaa23a42fd91fa (diff) | |
download | linux-stable-7fe5b3e4e7a61f3640d7645c434ac8c982f1388e.tar.gz linux-stable-7fe5b3e4e7a61f3640d7645c434ac8c982f1388e.tar.bz2 linux-stable-7fe5b3e4e7a61f3640d7645c434ac8c982f1388e.zip |
selftests: vDSO: open code basic chacha instead of linking to libsodium
Linking to libsodium makes building this test annoying in cross
compilation environments and is just way too much. Since this is just a
basic correctness test, simply open code a simple, unoptimized, dumb
chacha, rather than linking to libsodium.
This also fixes a correctness issue on big endian systems. The kernel's
random.c doesn't bother doing a le32_to_cpu operation on the random
bytes that are passed as the key, and consequently neither does
vgetrandom-chacha.S. However, libsodium's chacha _does_ do this, since
it takes the key as an array of bytes. This meant that the test was
broken on big endian systems, which this commit rectifies.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/selftests/vDSO/Makefile | 7 | ||||
-rw-r--r-- | tools/testing/selftests/vDSO/vdso_test_chacha.c | 47 |
2 files changed, 45 insertions, 9 deletions
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile index 32ea4c2a9a23..e21e78aae24d 100644 --- a/tools/testing/selftests/vDSO/Makefile +++ b/tools/testing/selftests/vDSO/Makefile @@ -1,8 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 uname_M := $(shell uname -m 2>/dev/null || echo not) ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/) -SODIUM_LIBS := $(shell pkg-config --libs libsodium 2>/dev/null) -SODIUM_CFLAGS := $(shell pkg-config --cflags libsodium 2>/dev/null) TEST_GEN_PROGS := vdso_test_gettimeofday TEST_GEN_PROGS += vdso_test_getcpu @@ -14,10 +12,8 @@ endif TEST_GEN_PROGS += vdso_test_correctness ifeq ($(uname_M),x86_64) TEST_GEN_PROGS += vdso_test_getrandom -ifneq ($(SODIUM_LIBS),) TEST_GEN_PROGS += vdso_test_chacha endif -endif CFLAGS := -std=gnu99 @@ -43,8 +39,7 @@ $(OUTPUT)/vdso_test_getrandom: CFLAGS += -isystem $(top_srcdir)/tools/include \ -isystem $(top_srcdir)/include/uapi $(OUTPUT)/vdso_test_chacha: $(top_srcdir)/tools/arch/$(ARCH)/vdso/vgetrandom-chacha.S -$(OUTPUT)/vdso_test_chacha: LDLIBS += $(SODIUM_LIBS) $(OUTPUT)/vdso_test_chacha: CFLAGS += -idirafter $(top_srcdir)/tools/include \ -idirafter $(top_srcdir)/arch/$(ARCH)/include \ -idirafter $(top_srcdir)/include \ - -D__ASSEMBLY__ -Wa,--noexecstack $(SODIUM_CFLAGS) + -D__ASSEMBLY__ -Wa,--noexecstack diff --git a/tools/testing/selftests/vDSO/vdso_test_chacha.c b/tools/testing/selftests/vDSO/vdso_test_chacha.c index ca5639d02969..f8603650d26b 100644 --- a/tools/testing/selftests/vDSO/vdso_test_chacha.c +++ b/tools/testing/selftests/vDSO/vdso_test_chacha.c @@ -3,13 +3,55 @@ * Copyright (C) 2022-2024 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. */ -#include <sodium/crypto_stream_chacha20.h> +#include <tools/le_byteshift.h> #include <sys/random.h> #include <string.h> #include <stdint.h> #include <stdbool.h> #include "../kselftest.h" +static uint32_t rol32(uint32_t word, unsigned int shift) +{ + return (word << (shift & 31)) | (word >> ((-shift) & 31)); +} + +static void reference_chacha20_blocks(uint8_t *dst_bytes, const uint32_t *key, size_t nblocks) +{ + uint32_t s[16] = { + 0x61707865U, 0x3320646eU, 0x79622d32U, 0x6b206574U, + key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7] + }; + + while (nblocks--) { + uint32_t x[16]; + memcpy(x, s, sizeof(x)); + for (unsigned int r = 0; r < 20; r += 2) { + #define QR(a, b, c, d) ( \ + x[a] += x[b], \ + x[d] = rol32(x[d] ^ x[a], 16), \ + x[c] += x[d], \ + x[b] = rol32(x[b] ^ x[c], 12), \ + x[a] += x[b], \ + x[d] = rol32(x[d] ^ x[a], 8), \ + x[c] += x[d], \ + x[b] = rol32(x[b] ^ x[c], 7)) + + QR(0, 4, 8, 12); + QR(1, 5, 9, 13); + QR(2, 6, 10, 14); + QR(3, 7, 11, 15); + QR(0, 5, 10, 15); + QR(1, 6, 11, 12); + QR(2, 7, 8, 13); + QR(3, 4, 9, 14); + } + for (unsigned int i = 0; i < 16; ++i, dst_bytes += sizeof(uint32_t)) + put_unaligned_le32(x[i] + s[i], dst_bytes); + if (!++s[12]) + ++s[13]; + } +} + typedef uint8_t u8; typedef uint32_t u32; typedef uint64_t u64; @@ -18,7 +60,6 @@ typedef uint64_t u64; int main(int argc, char *argv[]) { enum { TRIALS = 1000, BLOCKS = 128, BLOCK_SIZE = 64 }; - static const uint8_t nonce[8] = { 0 }; uint32_t counter[2]; uint32_t key[8]; uint8_t output1[BLOCK_SIZE * BLOCKS], output2[BLOCK_SIZE * BLOCKS]; @@ -31,7 +72,7 @@ int main(int argc, char *argv[]) printf("getrandom() failed!\n"); return KSFT_SKIP; } - crypto_stream_chacha20(output1, sizeof(output1), nonce, (uint8_t *)key); + reference_chacha20_blocks(output1, key, BLOCKS); for (unsigned int split = 0; split < BLOCKS; ++split) { memset(output2, 'X', sizeof(output2)); memset(counter, 0, sizeof(counter)); |