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