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, ¶ms);
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