1*69f1c387SStephan Müller /* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
2*69f1c387SStephan Müller /*
3*69f1c387SStephan Müller * Test interface for Jitter RNG.
4*69f1c387SStephan Müller *
5*69f1c387SStephan Müller * Copyright (C) 2023, Stephan Mueller <smueller@chronox.de>
6*69f1c387SStephan Müller */
7*69f1c387SStephan Müller
8*69f1c387SStephan Müller #include <linux/debugfs.h>
9*69f1c387SStephan Müller #include <linux/module.h>
10*69f1c387SStephan Müller #include <linux/uaccess.h>
11*69f1c387SStephan Müller
12*69f1c387SStephan Müller #include "jitterentropy.h"
13*69f1c387SStephan Müller
14*69f1c387SStephan Müller #define JENT_TEST_RINGBUFFER_SIZE (1<<10)
15*69f1c387SStephan Müller #define JENT_TEST_RINGBUFFER_MASK (JENT_TEST_RINGBUFFER_SIZE - 1)
16*69f1c387SStephan Müller
17*69f1c387SStephan Müller struct jent_testing {
18*69f1c387SStephan Müller u32 jent_testing_rb[JENT_TEST_RINGBUFFER_SIZE];
19*69f1c387SStephan Müller u32 rb_reader;
20*69f1c387SStephan Müller atomic_t rb_writer;
21*69f1c387SStephan Müller atomic_t jent_testing_enabled;
22*69f1c387SStephan Müller spinlock_t lock;
23*69f1c387SStephan Müller wait_queue_head_t read_wait;
24*69f1c387SStephan Müller };
25*69f1c387SStephan Müller
26*69f1c387SStephan Müller static struct dentry *jent_raw_debugfs_root = NULL;
27*69f1c387SStephan Müller
28*69f1c387SStephan Müller /*************************** Generic Data Handling ****************************/
29*69f1c387SStephan Müller
30*69f1c387SStephan Müller /*
31*69f1c387SStephan Müller * boot variable:
32*69f1c387SStephan Müller * 0 ==> No boot test, gathering of runtime data allowed
33*69f1c387SStephan Müller * 1 ==> Boot test enabled and ready for collecting data, gathering runtime
34*69f1c387SStephan Müller * data is disabled
35*69f1c387SStephan Müller * 2 ==> Boot test completed and disabled, gathering of runtime data is
36*69f1c387SStephan Müller * disabled
37*69f1c387SStephan Müller */
38*69f1c387SStephan Müller
jent_testing_reset(struct jent_testing * data)39*69f1c387SStephan Müller static void jent_testing_reset(struct jent_testing *data)
40*69f1c387SStephan Müller {
41*69f1c387SStephan Müller unsigned long flags;
42*69f1c387SStephan Müller
43*69f1c387SStephan Müller spin_lock_irqsave(&data->lock, flags);
44*69f1c387SStephan Müller data->rb_reader = 0;
45*69f1c387SStephan Müller atomic_set(&data->rb_writer, 0);
46*69f1c387SStephan Müller spin_unlock_irqrestore(&data->lock, flags);
47*69f1c387SStephan Müller }
48*69f1c387SStephan Müller
jent_testing_data_init(struct jent_testing * data,u32 boot)49*69f1c387SStephan Müller static void jent_testing_data_init(struct jent_testing *data, u32 boot)
50*69f1c387SStephan Müller {
51*69f1c387SStephan Müller /*
52*69f1c387SStephan Müller * The boot time testing implies we have a running test. If the
53*69f1c387SStephan Müller * caller wants to clear it, he has to unset the boot_test flag
54*69f1c387SStephan Müller * at runtime via sysfs to enable regular runtime testing
55*69f1c387SStephan Müller */
56*69f1c387SStephan Müller if (boot)
57*69f1c387SStephan Müller return;
58*69f1c387SStephan Müller
59*69f1c387SStephan Müller jent_testing_reset(data);
60*69f1c387SStephan Müller atomic_set(&data->jent_testing_enabled, 1);
61*69f1c387SStephan Müller pr_warn("Enabling data collection\n");
62*69f1c387SStephan Müller }
63*69f1c387SStephan Müller
jent_testing_fini(struct jent_testing * data,u32 boot)64*69f1c387SStephan Müller static void jent_testing_fini(struct jent_testing *data, u32 boot)
65*69f1c387SStephan Müller {
66*69f1c387SStephan Müller /* If we have boot data, we do not reset yet to allow data to be read */
67*69f1c387SStephan Müller if (boot)
68*69f1c387SStephan Müller return;
69*69f1c387SStephan Müller
70*69f1c387SStephan Müller atomic_set(&data->jent_testing_enabled, 0);
71*69f1c387SStephan Müller jent_testing_reset(data);
72*69f1c387SStephan Müller pr_warn("Disabling data collection\n");
73*69f1c387SStephan Müller }
74*69f1c387SStephan Müller
jent_testing_store(struct jent_testing * data,u32 value,u32 * boot)75*69f1c387SStephan Müller static bool jent_testing_store(struct jent_testing *data, u32 value,
76*69f1c387SStephan Müller u32 *boot)
77*69f1c387SStephan Müller {
78*69f1c387SStephan Müller unsigned long flags;
79*69f1c387SStephan Müller
80*69f1c387SStephan Müller if (!atomic_read(&data->jent_testing_enabled) && (*boot != 1))
81*69f1c387SStephan Müller return false;
82*69f1c387SStephan Müller
83*69f1c387SStephan Müller spin_lock_irqsave(&data->lock, flags);
84*69f1c387SStephan Müller
85*69f1c387SStephan Müller /*
86*69f1c387SStephan Müller * Disable entropy testing for boot time testing after ring buffer
87*69f1c387SStephan Müller * is filled.
88*69f1c387SStephan Müller */
89*69f1c387SStephan Müller if (*boot) {
90*69f1c387SStephan Müller if (((u32)atomic_read(&data->rb_writer)) >
91*69f1c387SStephan Müller JENT_TEST_RINGBUFFER_SIZE) {
92*69f1c387SStephan Müller *boot = 2;
93*69f1c387SStephan Müller pr_warn_once("One time data collection test disabled\n");
94*69f1c387SStephan Müller spin_unlock_irqrestore(&data->lock, flags);
95*69f1c387SStephan Müller return false;
96*69f1c387SStephan Müller }
97*69f1c387SStephan Müller
98*69f1c387SStephan Müller if (atomic_read(&data->rb_writer) == 1)
99*69f1c387SStephan Müller pr_warn("One time data collection test enabled\n");
100*69f1c387SStephan Müller }
101*69f1c387SStephan Müller
102*69f1c387SStephan Müller data->jent_testing_rb[((u32)atomic_read(&data->rb_writer)) &
103*69f1c387SStephan Müller JENT_TEST_RINGBUFFER_MASK] = value;
104*69f1c387SStephan Müller atomic_inc(&data->rb_writer);
105*69f1c387SStephan Müller
106*69f1c387SStephan Müller spin_unlock_irqrestore(&data->lock, flags);
107*69f1c387SStephan Müller
108*69f1c387SStephan Müller if (wq_has_sleeper(&data->read_wait))
109*69f1c387SStephan Müller wake_up_interruptible(&data->read_wait);
110*69f1c387SStephan Müller
111*69f1c387SStephan Müller return true;
112*69f1c387SStephan Müller }
113*69f1c387SStephan Müller
jent_testing_have_data(struct jent_testing * data)114*69f1c387SStephan Müller static bool jent_testing_have_data(struct jent_testing *data)
115*69f1c387SStephan Müller {
116*69f1c387SStephan Müller return ((((u32)atomic_read(&data->rb_writer)) &
117*69f1c387SStephan Müller JENT_TEST_RINGBUFFER_MASK) !=
118*69f1c387SStephan Müller (data->rb_reader & JENT_TEST_RINGBUFFER_MASK));
119*69f1c387SStephan Müller }
120*69f1c387SStephan Müller
jent_testing_reader(struct jent_testing * data,u32 * boot,u8 * outbuf,u32 outbuflen)121*69f1c387SStephan Müller static int jent_testing_reader(struct jent_testing *data, u32 *boot,
122*69f1c387SStephan Müller u8 *outbuf, u32 outbuflen)
123*69f1c387SStephan Müller {
124*69f1c387SStephan Müller unsigned long flags;
125*69f1c387SStephan Müller int collected_data = 0;
126*69f1c387SStephan Müller
127*69f1c387SStephan Müller jent_testing_data_init(data, *boot);
128*69f1c387SStephan Müller
129*69f1c387SStephan Müller while (outbuflen) {
130*69f1c387SStephan Müller u32 writer = (u32)atomic_read(&data->rb_writer);
131*69f1c387SStephan Müller
132*69f1c387SStephan Müller spin_lock_irqsave(&data->lock, flags);
133*69f1c387SStephan Müller
134*69f1c387SStephan Müller /* We have no data or reached the writer. */
135*69f1c387SStephan Müller if (!writer || (writer == data->rb_reader)) {
136*69f1c387SStephan Müller
137*69f1c387SStephan Müller spin_unlock_irqrestore(&data->lock, flags);
138*69f1c387SStephan Müller
139*69f1c387SStephan Müller /*
140*69f1c387SStephan Müller * Now we gathered all boot data, enable regular data
141*69f1c387SStephan Müller * collection.
142*69f1c387SStephan Müller */
143*69f1c387SStephan Müller if (*boot) {
144*69f1c387SStephan Müller *boot = 0;
145*69f1c387SStephan Müller goto out;
146*69f1c387SStephan Müller }
147*69f1c387SStephan Müller
148*69f1c387SStephan Müller wait_event_interruptible(data->read_wait,
149*69f1c387SStephan Müller jent_testing_have_data(data));
150*69f1c387SStephan Müller if (signal_pending(current)) {
151*69f1c387SStephan Müller collected_data = -ERESTARTSYS;
152*69f1c387SStephan Müller goto out;
153*69f1c387SStephan Müller }
154*69f1c387SStephan Müller
155*69f1c387SStephan Müller continue;
156*69f1c387SStephan Müller }
157*69f1c387SStephan Müller
158*69f1c387SStephan Müller /* We copy out word-wise */
159*69f1c387SStephan Müller if (outbuflen < sizeof(u32)) {
160*69f1c387SStephan Müller spin_unlock_irqrestore(&data->lock, flags);
161*69f1c387SStephan Müller goto out;
162*69f1c387SStephan Müller }
163*69f1c387SStephan Müller
164*69f1c387SStephan Müller memcpy(outbuf, &data->jent_testing_rb[data->rb_reader],
165*69f1c387SStephan Müller sizeof(u32));
166*69f1c387SStephan Müller data->rb_reader++;
167*69f1c387SStephan Müller
168*69f1c387SStephan Müller spin_unlock_irqrestore(&data->lock, flags);
169*69f1c387SStephan Müller
170*69f1c387SStephan Müller outbuf += sizeof(u32);
171*69f1c387SStephan Müller outbuflen -= sizeof(u32);
172*69f1c387SStephan Müller collected_data += sizeof(u32);
173*69f1c387SStephan Müller }
174*69f1c387SStephan Müller
175*69f1c387SStephan Müller out:
176*69f1c387SStephan Müller jent_testing_fini(data, *boot);
177*69f1c387SStephan Müller return collected_data;
178*69f1c387SStephan Müller }
179*69f1c387SStephan Müller
jent_testing_extract_user(struct file * file,char __user * buf,size_t nbytes,loff_t * ppos,int (* reader)(u8 * outbuf,u32 outbuflen))180*69f1c387SStephan Müller static int jent_testing_extract_user(struct file *file, char __user *buf,
181*69f1c387SStephan Müller size_t nbytes, loff_t *ppos,
182*69f1c387SStephan Müller int (*reader)(u8 *outbuf, u32 outbuflen))
183*69f1c387SStephan Müller {
184*69f1c387SStephan Müller u8 *tmp, *tmp_aligned;
185*69f1c387SStephan Müller int ret = 0, large_request = (nbytes > 256);
186*69f1c387SStephan Müller
187*69f1c387SStephan Müller if (!nbytes)
188*69f1c387SStephan Müller return 0;
189*69f1c387SStephan Müller
190*69f1c387SStephan Müller /*
191*69f1c387SStephan Müller * The intention of this interface is for collecting at least
192*69f1c387SStephan Müller * 1000 samples due to the SP800-90B requirements. So, we make no
193*69f1c387SStephan Müller * effort in avoiding allocating more memory that actually needed
194*69f1c387SStephan Müller * by the user. Hence, we allocate sufficient memory to always hold
195*69f1c387SStephan Müller * that amount of data.
196*69f1c387SStephan Müller */
197*69f1c387SStephan Müller tmp = kmalloc(JENT_TEST_RINGBUFFER_SIZE + sizeof(u32), GFP_KERNEL);
198*69f1c387SStephan Müller if (!tmp)
199*69f1c387SStephan Müller return -ENOMEM;
200*69f1c387SStephan Müller
201*69f1c387SStephan Müller tmp_aligned = PTR_ALIGN(tmp, sizeof(u32));
202*69f1c387SStephan Müller
203*69f1c387SStephan Müller while (nbytes) {
204*69f1c387SStephan Müller int i;
205*69f1c387SStephan Müller
206*69f1c387SStephan Müller if (large_request && need_resched()) {
207*69f1c387SStephan Müller if (signal_pending(current)) {
208*69f1c387SStephan Müller if (ret == 0)
209*69f1c387SStephan Müller ret = -ERESTARTSYS;
210*69f1c387SStephan Müller break;
211*69f1c387SStephan Müller }
212*69f1c387SStephan Müller schedule();
213*69f1c387SStephan Müller }
214*69f1c387SStephan Müller
215*69f1c387SStephan Müller i = min_t(int, nbytes, JENT_TEST_RINGBUFFER_SIZE);
216*69f1c387SStephan Müller i = reader(tmp_aligned, i);
217*69f1c387SStephan Müller if (i <= 0) {
218*69f1c387SStephan Müller if (i < 0)
219*69f1c387SStephan Müller ret = i;
220*69f1c387SStephan Müller break;
221*69f1c387SStephan Müller }
222*69f1c387SStephan Müller if (copy_to_user(buf, tmp_aligned, i)) {
223*69f1c387SStephan Müller ret = -EFAULT;
224*69f1c387SStephan Müller break;
225*69f1c387SStephan Müller }
226*69f1c387SStephan Müller
227*69f1c387SStephan Müller nbytes -= i;
228*69f1c387SStephan Müller buf += i;
229*69f1c387SStephan Müller ret += i;
230*69f1c387SStephan Müller }
231*69f1c387SStephan Müller
232*69f1c387SStephan Müller kfree_sensitive(tmp);
233*69f1c387SStephan Müller
234*69f1c387SStephan Müller if (ret > 0)
235*69f1c387SStephan Müller *ppos += ret;
236*69f1c387SStephan Müller
237*69f1c387SStephan Müller return ret;
238*69f1c387SStephan Müller }
239*69f1c387SStephan Müller
240*69f1c387SStephan Müller /************** Raw High-Resolution Timer Entropy Data Handling **************/
241*69f1c387SStephan Müller
242*69f1c387SStephan Müller static u32 boot_raw_hires_test = 0;
243*69f1c387SStephan Müller module_param(boot_raw_hires_test, uint, 0644);
244*69f1c387SStephan Müller MODULE_PARM_DESC(boot_raw_hires_test,
245*69f1c387SStephan Müller "Enable gathering boot time high resolution timer entropy of the first Jitter RNG entropy events");
246*69f1c387SStephan Müller
247*69f1c387SStephan Müller static struct jent_testing jent_raw_hires = {
248*69f1c387SStephan Müller .rb_reader = 0,
249*69f1c387SStephan Müller .rb_writer = ATOMIC_INIT(0),
250*69f1c387SStephan Müller .lock = __SPIN_LOCK_UNLOCKED(jent_raw_hires.lock),
251*69f1c387SStephan Müller .read_wait = __WAIT_QUEUE_HEAD_INITIALIZER(jent_raw_hires.read_wait)
252*69f1c387SStephan Müller };
253*69f1c387SStephan Müller
jent_raw_hires_entropy_store(__u32 value)254*69f1c387SStephan Müller int jent_raw_hires_entropy_store(__u32 value)
255*69f1c387SStephan Müller {
256*69f1c387SStephan Müller return jent_testing_store(&jent_raw_hires, value, &boot_raw_hires_test);
257*69f1c387SStephan Müller }
258*69f1c387SStephan Müller EXPORT_SYMBOL(jent_raw_hires_entropy_store);
259*69f1c387SStephan Müller
jent_raw_hires_entropy_reader(u8 * outbuf,u32 outbuflen)260*69f1c387SStephan Müller static int jent_raw_hires_entropy_reader(u8 *outbuf, u32 outbuflen)
261*69f1c387SStephan Müller {
262*69f1c387SStephan Müller return jent_testing_reader(&jent_raw_hires, &boot_raw_hires_test,
263*69f1c387SStephan Müller outbuf, outbuflen);
264*69f1c387SStephan Müller }
265*69f1c387SStephan Müller
jent_raw_hires_read(struct file * file,char __user * to,size_t count,loff_t * ppos)266*69f1c387SStephan Müller static ssize_t jent_raw_hires_read(struct file *file, char __user *to,
267*69f1c387SStephan Müller size_t count, loff_t *ppos)
268*69f1c387SStephan Müller {
269*69f1c387SStephan Müller return jent_testing_extract_user(file, to, count, ppos,
270*69f1c387SStephan Müller jent_raw_hires_entropy_reader);
271*69f1c387SStephan Müller }
272*69f1c387SStephan Müller
273*69f1c387SStephan Müller static const struct file_operations jent_raw_hires_fops = {
274*69f1c387SStephan Müller .owner = THIS_MODULE,
275*69f1c387SStephan Müller .read = jent_raw_hires_read,
276*69f1c387SStephan Müller };
277*69f1c387SStephan Müller
278*69f1c387SStephan Müller /******************************* Initialization *******************************/
279*69f1c387SStephan Müller
jent_testing_init(void)280*69f1c387SStephan Müller void jent_testing_init(void)
281*69f1c387SStephan Müller {
282*69f1c387SStephan Müller jent_raw_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
283*69f1c387SStephan Müller
284*69f1c387SStephan Müller debugfs_create_file_unsafe("jent_raw_hires", 0400,
285*69f1c387SStephan Müller jent_raw_debugfs_root, NULL,
286*69f1c387SStephan Müller &jent_raw_hires_fops);
287*69f1c387SStephan Müller }
288*69f1c387SStephan Müller EXPORT_SYMBOL(jent_testing_init);
289*69f1c387SStephan Müller
jent_testing_exit(void)290*69f1c387SStephan Müller void jent_testing_exit(void)
291*69f1c387SStephan Müller {
292*69f1c387SStephan Müller debugfs_remove_recursive(jent_raw_debugfs_root);
293*69f1c387SStephan Müller }
294*69f1c387SStephan Müller EXPORT_SYMBOL(jent_testing_exit);
295