xref: /linux/tools/testing/selftests/vDSO/vdso_test_chacha.c (revision a3a02a52bcfcbcc4a637d4b68bf1bc391c9fad02)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2022-2024 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
4  */
5 
6 #include <sodium/crypto_stream_chacha20.h>
7 #include <sys/random.h>
8 #include <string.h>
9 #include <stdint.h>
10 #include "../kselftest.h"
11 
12 extern void __arch_chacha20_blocks_nostack(uint8_t *dst_bytes, const uint8_t *key, uint32_t *counter, size_t nblocks);
13 
14 int main(int argc, char *argv[])
15 {
16 	enum { TRIALS = 1000, BLOCKS = 128, BLOCK_SIZE = 64 };
17 	static const uint8_t nonce[8] = { 0 };
18 	uint32_t counter[2];
19 	uint8_t key[32];
20 	uint8_t output1[BLOCK_SIZE * BLOCKS], output2[BLOCK_SIZE * BLOCKS];
21 
22 	ksft_print_header();
23 	ksft_set_plan(1);
24 
25 	for (unsigned int trial = 0; trial < TRIALS; ++trial) {
26 		if (getrandom(key, sizeof(key), 0) != sizeof(key)) {
27 			printf("getrandom() failed!\n");
28 			return KSFT_SKIP;
29 		}
30 		crypto_stream_chacha20(output1, sizeof(output1), nonce, key);
31 		for (unsigned int split = 0; split < BLOCKS; ++split) {
32 			memset(output2, 'X', sizeof(output2));
33 			memset(counter, 0, sizeof(counter));
34 			if (split)
35 				__arch_chacha20_blocks_nostack(output2, key, counter, split);
36 			__arch_chacha20_blocks_nostack(output2 + split * BLOCK_SIZE, key, counter, BLOCKS - split);
37 			if (memcmp(output1, output2, sizeof(output1)))
38 				return KSFT_FAIL;
39 		}
40 	}
41 	ksft_test_result_pass("chacha: PASS\n");
42 	return KSFT_PASS;
43 }
44