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