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