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 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 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 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 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 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 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 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 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