xref: /aosp_15_r20/external/ltp/testcases/kernel/crypto/af_alg02.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright 2019 Google LLC
4  */
5 
6 /*
7  * Regression test for commit ecaaab564978 ("crypto: salsa20 - fix
8  * blkcipher_walk API usage"), or CVE-2017-17805.  This test verifies that an
9  * empty message can be encrypted with Salsa20 without crashing the kernel.
10  *
11  * Fix for kernels < 4.14:
12  * With kernels missing commit 2d97591ef43d ("crypto: af_alg - consolidation
13  * of duplicate code") read() does not return in this situation. The call is
14  * now moved to a child thread in order to cancel it in case read() takes an
15  * unusual long amount of time.
16  */
17 
18 #include "tst_test.h"
19 #include "tst_af_alg.h"
20 #include "tst_safe_pthread.h"
21 #include <pthread.h>
22 #include <errno.h>
23 
24 #define SALSA20_IV_SIZE       8
25 #define SALSA20_MIN_KEY_SIZE  16
26 static int volatile completed;
27 
verify_encrypt(void * arg)28 static void *verify_encrypt(void *arg)
29 {
30 	const uint8_t iv[SALSA20_IV_SIZE] = { 0 };
31 	const struct tst_alg_sendmsg_params params = {
32 		.encrypt = true,
33 		.iv = iv,
34 		.ivlen = SALSA20_IV_SIZE,
35 	};
36 	char buf[16];
37 	int reqfd = tst_alg_setup_reqfd("skcipher", "salsa20", NULL,
38 					SALSA20_MIN_KEY_SIZE);
39 
40 	/* Send a zero-length message to encrypt */
41 	tst_alg_sendmsg(reqfd, NULL, 0, &params);
42 
43 	/*
44 	 * Read the zero-length encrypted data.
45 	 * With the bug, the kernel crashed here.
46 	 */
47 	TST_CHECKPOINT_WAKE(0);
48 	if (read(reqfd, buf, 16) == 0)
49 		tst_res(TPASS, "Successfully \"encrypted\" an empty message");
50 	else
51 		tst_res(TFAIL, "read() didn't return 0");
52 
53 	completed = 1;
54 	return arg;
55 }
56 
run(void)57 static void run(void)
58 {
59 	pthread_t thr;
60 
61 	completed = 0;
62 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
63 	SAFE_PTHREAD_CREATE(&thr, NULL, verify_encrypt, NULL);
64 
65 	TST_CHECKPOINT_WAIT(0);
66 
67 	while (!completed) {
68 		if (!tst_remaining_runtime()) {
69 			pthread_cancel(thr);
70 			tst_brk(TBROK,
71 				"Timed out while reading from request socket.");
72 		}
73 		usleep(1000);
74 	}
75 	pthread_join(thr, NULL);
76 }
77 
78 static struct tst_test test = {
79 	.test_all = run,
80 	.max_runtime = 20,
81 	.needs_checkpoints = 1,
82 	.tags = (const struct tst_tag[]) {
83 		{"linux-git", "ecaaab564978"},
84 		{"CVE", "2017-17805"},
85 		{}
86 	}
87 };
88