1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright (C) 2018-2022, Linaro Limited
4 */
5
6 /*
7 * Developerbox doesn't provide a hardware based true random number
8 * generator. So this pseudo TA provides a good source of entropy using
9 * noise from 7 thermal sensors. Its suitable for entropy required
10 * during boot, seeding kernel entropy pool, cryptographic use etc.
11 *
12 * Assumption
13 * ==========
14 *
15 * We have assumed the entropy of the sensor is better than 8 bits per
16 * 14 sensor readings. This entropy estimate is based on our simple
17 * minimal entropy estimates done on 2.1G bytes of raw samples collected
18 * from thermal sensors.
19 *
20 * We believe our estimate to be conservative and have designed to
21 * health tests to trigger if a sensor does not achieve at least
22 * 8 bits in 16 sensor reading (we use 16 rather than 14 to prevent
23 * spurious failures on edge cases).
24 *
25 * Theory of operation
26 * ===================
27 *
28 * This routine uses secure timer interrupt to sample raw thermal sensor
29 * readings. As thermal sensor refresh rate is every 2ms, so interrupt
30 * fires every 2ms. It implements continuous health test counting rising
31 * and falling edges to report if sensors fail to provide entropy.
32 *
33 * It uses vetted conditioner as SHA512/256 (approved hash algorithm)
34 * to condense entropy. As per NIST.SP.800-90B spec, to get full entropy
35 * from vetted conditioner, we need to supply double of input entropy.
36 * According to assumption above and requirement for vetted conditioner,
37 * we need to supply 28 raw sensor readings to get 1 byte of full
38 * entropy as output. So for 32 bytes of conditioner output, we need to
39 * supply 896 bytes of raw sensor readings.
40 *
41 * Interfaces -> Input
42 * -------------------
43 *
44 * void rng_collect_entropy(void);
45 *
46 * Called as part of secure timer interrupt handler to sample raw
47 * thermal sensor readings and add entropy to the pool.
48 *
49 * Interfaces -> Output
50 * --------------------
51 *
52 * TEE_Result rng_get_entropy(uint32_t types,
53 * TEE_Param params[TEE_NUM_PARAMS]);
54 *
55 * Invoke command to expose an entropy interface to normal world.
56 *
57 * Testing
58 * =======
59 *
60 * Passes FIPS 140-2 rngtest.
61 *
62 * Limitations
63 * ===========
64 *
65 * Output rate is limited to approx. 125 bytes per second.
66 *
67 * Our entropy estimation was not reached using any approved or
68 * published estimation framework such as NIST.SP.800-90B and was tested
69 * on a very small set of physical samples. Instead we have adopted what
70 * we believe to be a conservative estimate and partnered it with a
71 * fairly agressive health check.
72 *
73 * Generating the SHA512/256 hash takes 24uS and will be run by an
74 * interrupt handler that pre-empts the normal world.
75 */
76
77 #include <crypto/crypto.h>
78 #include <kernel/delay.h>
79 #include <kernel/pseudo_ta.h>
80 #include <kernel/spinlock.h>
81 #include <kernel/timer.h>
82 #include <mm/core_memprot.h>
83 #include <io.h>
84 #include <pta_rng.h>
85 #include <string.h>
86
87 #include "synquacer_rng_pta.h"
88
89 #define PTA_NAME "rng.pta"
90
91 #define THERMAL_SENSOR_BASE0 0x54190800
92 #define THERMAL_SENSOR_OFFSET 0x80
93 #define NUM_SENSORS 7
94 #define NUM_SLOTS ((NUM_SENSORS * 2) - 1)
95
96 #define TEMP_DATA_REG_OFFSET 0x34
97
98 #define ENTROPY_POOL_SIZE 4096
99
100 #define SENSOR_DATA_SIZE 128
101 #define CONDITIONER_PAYLOAD (SENSOR_DATA_SIZE * NUM_SENSORS)
102
103 /*
104 * The health test monitors each sensor's least significant bit and counts
105 * the number of rising and falling edges. It verifies that both counts
106 * lie within interval of between 12.5% and 37.5% of the samples.
107 * For true random data with 8 bits of entropy per byte, both counts would
108 * be close to 25%.
109 */
110 #define MAX_BIT_FLIP_EDGE_COUNT ((3 * SENSOR_DATA_SIZE) / 8)
111 #define MIN_BIT_FLIP_EDGE_COUNT (SENSOR_DATA_SIZE / 8)
112
113 static uint8_t entropy_pool[ENTROPY_POOL_SIZE] = {0};
114 static uint32_t entropy_size;
115
116 static uint8_t sensors_data[NUM_SLOTS][SENSOR_DATA_SIZE] = {0};
117 static uint8_t sensors_data_slot_idx;
118 static uint8_t sensors_data_idx;
119
120 static uint32_t health_test_fail_cnt;
121 static uint32_t health_test_cnt;
122
123 static unsigned int entropy_lock = SPINLOCK_UNLOCK;
124
pool_add_entropy(uint8_t * entropy,uint32_t size)125 static void pool_add_entropy(uint8_t *entropy, uint32_t size)
126 {
127 uint32_t copy_size = 0;
128
129 if (entropy_size >= ENTROPY_POOL_SIZE)
130 return;
131
132 if ((ENTROPY_POOL_SIZE - entropy_size) >= size)
133 copy_size = size;
134 else
135 copy_size = ENTROPY_POOL_SIZE - entropy_size;
136
137 memcpy((entropy_pool + entropy_size), entropy, copy_size);
138
139 entropy_size += copy_size;
140 }
141
pool_get_entropy(uint8_t * buf,uint32_t size)142 static void pool_get_entropy(uint8_t *buf, uint32_t size)
143 {
144 uint32_t off = 0;
145
146 if (size > entropy_size)
147 return;
148
149 off = entropy_size - size;
150
151 memcpy(buf, &entropy_pool[off], size);
152 entropy_size -= size;
153 }
154
health_test(uint8_t sensor_id)155 static bool health_test(uint8_t sensor_id)
156 {
157 uint32_t falling_edge_count = 0;
158 uint32_t rising_edge_count = 0;
159 uint32_t lo_edge_count = 0;
160 uint32_t hi_edge_count = 0;
161 uint32_t i = 0;
162
163 for (i = 0; i < (SENSOR_DATA_SIZE - 1); i++) {
164 if ((sensors_data[sensor_id][i] ^
165 sensors_data[sensor_id][i + 1]) & 0x1) {
166 falling_edge_count += (sensors_data[sensor_id][i] &
167 0x1);
168 rising_edge_count += (sensors_data[sensor_id][i + 1] &
169 0x1);
170 }
171 }
172
173 lo_edge_count = rising_edge_count < falling_edge_count ?
174 rising_edge_count : falling_edge_count;
175 hi_edge_count = rising_edge_count < falling_edge_count ?
176 falling_edge_count : rising_edge_count;
177
178 return (lo_edge_count >= MIN_BIT_FLIP_EDGE_COUNT) &&
179 (hi_edge_count <= MAX_BIT_FLIP_EDGE_COUNT);
180 }
181
pool_check_add_entropy(void)182 static uint8_t pool_check_add_entropy(void)
183 {
184 uint32_t i = 0;
185 uint8_t entropy_sha512_256[TEE_SHA256_HASH_SIZE];
186 uint8_t pool_status = 0;
187 TEE_Result res = TEE_ERROR_GENERIC;
188
189 for (i = 0; i < NUM_SENSORS; i++) {
190 /* Check if particular sensor data passes health test */
191 if (health_test(sensors_data_slot_idx) == true) {
192 sensors_data_slot_idx++;
193 } else {
194 health_test_fail_cnt++;
195 memmove(sensors_data[sensors_data_slot_idx],
196 sensors_data[sensors_data_slot_idx + 1],
197 (SENSOR_DATA_SIZE * (NUM_SENSORS - i - 1)));
198 }
199 }
200
201 health_test_cnt += NUM_SENSORS;
202
203 /* Check if sensors_data have enough pass data for conditioning */
204 if (sensors_data_slot_idx >= NUM_SENSORS) {
205 /*
206 * Use vetted conditioner SHA512/256 as per
207 * NIST.SP.800-90B to condition raw data from entropy
208 * source.
209 */
210 sensors_data_slot_idx -= NUM_SENSORS;
211 res = hash_sha512_256_compute(entropy_sha512_256,
212 sensors_data[sensors_data_slot_idx],
213 CONDITIONER_PAYLOAD);
214 if (res == TEE_SUCCESS)
215 pool_add_entropy(entropy_sha512_256,
216 TEE_SHA256_HASH_SIZE);
217 }
218
219 if (entropy_size >= ENTROPY_POOL_SIZE)
220 pool_status = 1;
221
222 return pool_status;
223 }
224
rng_collect_entropy(void)225 void rng_collect_entropy(void)
226 {
227 uint8_t i = 0;
228 void *vaddr = 0;
229 uint8_t pool_full = 0;
230 uint32_t exceptions = 0;
231
232 exceptions = cpu_spin_lock_xsave(&entropy_lock);
233
234 for (i = 0; i < NUM_SENSORS; i++) {
235 vaddr = phys_to_virt_io(THERMAL_SENSOR_BASE0 +
236 (THERMAL_SENSOR_OFFSET * i) +
237 TEMP_DATA_REG_OFFSET,
238 sizeof(uint32_t));
239 sensors_data[sensors_data_slot_idx + i][sensors_data_idx] =
240 (uint8_t)io_read32((vaddr_t)vaddr);
241 }
242
243 sensors_data_idx++;
244
245 if (sensors_data_idx >= SENSOR_DATA_SIZE) {
246 pool_full = pool_check_add_entropy();
247 sensors_data_idx = 0;
248 }
249
250 if (pool_full)
251 generic_timer_stop();
252
253 cpu_spin_unlock_xrestore(&entropy_lock, exceptions);
254 }
255
rng_get_entropy(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])256 static TEE_Result rng_get_entropy(uint32_t types,
257 TEE_Param params[TEE_NUM_PARAMS])
258 {
259 uint8_t *e = NULL;
260 uint32_t rq_size = 0;
261 uint32_t pool_size = 0;
262 uint32_t exceptions = 0;
263 TEE_Result res = TEE_SUCCESS;
264
265 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
266 TEE_PARAM_TYPE_NONE,
267 TEE_PARAM_TYPE_NONE,
268 TEE_PARAM_TYPE_NONE)) {
269 EMSG("bad parameters types: 0x%" PRIx32, types);
270 return TEE_ERROR_BAD_PARAMETERS;
271 }
272
273 rq_size = params[0].memref.size;
274
275 if ((rq_size == 0) || (rq_size > ENTROPY_POOL_SIZE))
276 return TEE_ERROR_NOT_SUPPORTED;
277
278 e = (uint8_t *)params[0].memref.buffer;
279 if (!e)
280 return TEE_ERROR_BAD_PARAMETERS;
281
282 exceptions = cpu_spin_lock_xsave(&entropy_lock);
283
284 /*
285 * Report health test failure to normal world in case fail count
286 * exceeds 1% of pass count.
287 */
288 if (health_test_fail_cnt > ((health_test_cnt + 100) / 100)) {
289 res = TEE_ERROR_HEALTH_TEST_FAIL;
290 params[0].memref.size = 0;
291 health_test_cnt = 0;
292 health_test_fail_cnt = 0;
293 goto exit;
294 }
295
296 pool_size = entropy_size;
297
298 if (pool_size < rq_size) {
299 params[0].memref.size = pool_size;
300 pool_get_entropy(e, pool_size);
301 } else {
302 params[0].memref.size = rq_size;
303 pool_get_entropy(e, rq_size);
304 }
305
306 exit:
307 /* Enable timer FIQ to fetch entropy */
308 generic_timer_start(TIMER_PERIOD_MS);
309
310 cpu_spin_unlock_xrestore(&entropy_lock, exceptions);
311
312 return res;
313 }
314
rng_get_info(uint32_t types,TEE_Param params[TEE_NUM_PARAMS])315 static TEE_Result rng_get_info(uint32_t types,
316 TEE_Param params[TEE_NUM_PARAMS])
317 {
318 if (types != TEE_PARAM_TYPES(TEE_PARAM_TYPE_VALUE_OUTPUT,
319 TEE_PARAM_TYPE_NONE,
320 TEE_PARAM_TYPE_NONE,
321 TEE_PARAM_TYPE_NONE)) {
322 EMSG("bad parameters types: 0x%" PRIx32, types);
323 return TEE_ERROR_BAD_PARAMETERS;
324 }
325
326 /* Output RNG rate (per second) */
327 params[0].value.a = 125;
328
329 /*
330 * Quality/entropy per 1024 bit of output data. As we have used
331 * a vetted conditioner as per NIST.SP.800-90B to provide full
332 * entropy given our assumption of entropy estimate for raw sensor
333 * data.
334 */
335 params[0].value.b = 1024;
336
337 return TEE_SUCCESS;
338 }
339
invoke_command(void * pSessionContext __unused,uint32_t nCommandID,uint32_t nParamTypes,TEE_Param pParams[TEE_NUM_PARAMS])340 static TEE_Result invoke_command(void *pSessionContext __unused,
341 uint32_t nCommandID, uint32_t nParamTypes,
342 TEE_Param pParams[TEE_NUM_PARAMS])
343 {
344 FMSG("command entry point for pseudo-TA \"%s\"", PTA_NAME);
345
346 switch (nCommandID) {
347 case PTA_CMD_GET_ENTROPY:
348 return rng_get_entropy(nParamTypes, pParams);
349 case PTA_CMD_GET_RNG_INFO:
350 return rng_get_info(nParamTypes, pParams);
351 default:
352 break;
353 }
354
355 return TEE_ERROR_NOT_IMPLEMENTED;
356 }
357
358 pseudo_ta_register(.uuid = PTA_RNG_UUID, .name = PTA_NAME,
359 .flags = PTA_DEFAULT_FLAGS | TA_FLAG_DEVICE_ENUM,
360 .invoke_command_entry_point = invoke_command);
361