1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (C) 2022 Linaro Limited 4 */ 5 6 #include <assert.h> 7 #include <config.h> 8 #include <crypto/crypto.h> 9 #include <kernel/panic.h> 10 #include <kernel/thread_arch.h> 11 #include <rng_support.h> 12 #include <sm/std_smc.h> 13 #include <stdbool.h> 14 #include <string.h> 15 #include <util.h> 16 #include <tee_api_types.h> 17 #include <tee/tee_cryp_utl.h> 18 #include <trace.h> 19 20 /* 21 * Arm SMCCC TRNG firmware interface specification: 22 * https://developer.arm.com/documentation/den0098/ 23 */ 24 #define ARM_SMCCC_TRNG_VERSION 0x84000050 25 #define ARM_SMCCC_TRNG_FEATURES 0x84000051 26 #define ARM_SMCCC_TRNG_GET_UUID 0x84000052 27 #define ARM_SMCCC_TRNG_RND_32 0x84000053 28 #define ARM_SMCCC_TRNG_RND_64 0xc4000053 29 30 #define ARM_SMCCC_RET_TRNG_SUCCESS U(0) 31 #define ARM_SMCCC_RET_TRNG_NOT_SUPPORTED ((unsigned long)-1) 32 #define ARM_SMCCC_RET_TRNG_INVALID_PARAMETER ((unsigned long)-2) 33 #define ARM_SMCCC_RET_TRNG_NO_ENTROPY ((unsigned long)-3) 34 35 #define TRNG_MAJOR_MASK GENMASK_32(30, 16) 36 #define TRNG_MAJOR_SHIFT 16 37 #define TRNG_MINOR_MASK GENMASK_32(15, 0) 38 #define TRNG_MINOR_SHIFT 0 39 #define TRNG_MAKE_VERSION(major, minor) \ 40 ((SHIFT_U32(major, TRNG_MAJOR_SHIFT) & TRNG_MAJOR_MASK) | \ 41 (SHIFT_U32(minor, TRNG_MINOR_SHIFT) & TRNG_MINOR_MASK)) 42 43 #define TRNG_VERSION_1_0 TRNG_MAKE_VERSION(1, 0) 44 45 #define TRNG_MAX_RND_64 (192 / 8) 46 #define TRNG_MAX_RND_32 (96 / 8) 47 48 /* Function ID discovered for getting random bytes or 0 if not supported */ 49 static uint32_t trng_rnd_fid; 50 51 static bool smccc_trng_is_supported(void) 52 { 53 struct thread_smc_args args = { }; 54 static bool inited; 55 56 if (inited) 57 return trng_rnd_fid != 0; 58 59 inited = true; 60 61 /* 62 * TRNG ABI requires caller to check that Arm SMCCC version is 63 * larger or equal to v1.1 64 */ 65 args.a0 = ARM_SMCCC_VERSION; 66 thread_smccc(&args); 67 if (args.a0 & BIT32(31) || args.a0 < SMCCC_V_1_1) 68 return false; 69 70 /* 71 * Check TRNG version, if successful we're guaranteed to have at least 72 * the ARM_SMCCC_TRNG_FEATURES fid. 73 */ 74 args.a0 = ARM_SMCCC_TRNG_VERSION; 75 thread_smccc(&args); 76 if (args.a0 & BIT32(31) || args.a0 < TRNG_VERSION_1_0) 77 return false; 78 79 #ifdef ARM64 80 args.a0 = ARM_SMCCC_TRNG_FEATURES; 81 args.a1 = ARM_SMCCC_TRNG_RND_64; 82 thread_smccc(&args); 83 if (args.a0 == ARM_SMCCC_RET_SUCCESS) { 84 trng_rnd_fid = ARM_SMCCC_TRNG_RND_64; 85 return true; 86 } 87 #endif 88 89 args.a0 = ARM_SMCCC_TRNG_FEATURES; 90 args.a1 = ARM_SMCCC_TRNG_RND_32; 91 thread_smccc(&args); 92 if (args.a0 == ARM_SMCCC_RET_TRNG_SUCCESS) { 93 trng_rnd_fid = ARM_SMCCC_TRNG_RND_32; 94 return true; 95 } 96 97 return false; 98 } 99 100 static void read_bytes(unsigned long val, size_t byte_count, uint8_t **buf, 101 size_t *rem) 102 { 103 size_t count = MIN(byte_count, *rem); 104 size_t n = 0; 105 106 for (n = 0; n < count; n++) 107 (*buf)[n] = val >> (n * 8); 108 109 *buf += count; 110 *rem -= count; 111 } 112 113 static void read_samples(struct thread_smc_args *args, uint8_t *buf, size_t len) 114 { 115 uint8_t *ptr = buf; 116 size_t rem = len; 117 size_t byte_count = 4; 118 119 #ifdef ARM64 120 if (trng_rnd_fid == ARM_SMCCC_TRNG_RND_64) 121 byte_count = 8; 122 #endif 123 124 read_bytes(args->a3, byte_count, &ptr, &rem); 125 read_bytes(args->a2, byte_count, &ptr, &rem); 126 read_bytes(args->a1, byte_count, &ptr, &rem); 127 } 128 129 static TEE_Result __maybe_unused smccc_trng_read(void *buf, size_t len) 130 { 131 struct thread_smc_args args = { }; 132 uint8_t *ptr = buf; 133 size_t rem = len; 134 size_t max_burst = 0; 135 136 if (!smccc_trng_is_supported()) 137 return TEE_ERROR_NOT_SUPPORTED; 138 139 if (trng_rnd_fid == ARM_SMCCC_TRNG_RND_64) 140 max_burst = TRNG_MAX_RND_64; 141 else 142 max_burst = TRNG_MAX_RND_32; 143 144 while (rem) { 145 size_t burst = MIN(rem, max_burst); 146 147 args.a0 = trng_rnd_fid; 148 args.a1 = burst * 8; 149 150 thread_smccc(&args); 151 152 switch (args.a0) { 153 case ARM_SMCCC_RET_TRNG_SUCCESS: 154 read_samples(&args, ptr, burst); 155 rem -= burst; 156 ptr += burst; 157 break; 158 case ARM_SMCCC_RET_TRNG_NO_ENTROPY: 159 break; 160 default: 161 return TEE_ERROR_GENERIC; 162 } 163 } 164 165 return TEE_SUCCESS; 166 } 167 168 static void __maybe_unused smccc_trng_print_info(void) 169 { 170 struct thread_smc_args args = { }; 171 unsigned int __maybe_unused major = 0; 172 unsigned int __maybe_unused minor = 0; 173 174 if (!IS_ENABLED(CFG_TEE_CORE_DEBUG)) 175 return; 176 177 args.a0 = ARM_SMCCC_TRNG_VERSION; 178 thread_smccc(&args); 179 assert((args.a0 & BIT32(31)) == 0); 180 major = (args.a0 & TRNG_MAJOR_MASK) >> TRNG_MAJOR_SHIFT; 181 minor = (args.a0 & TRNG_MINOR_MASK) >> TRNG_MINOR_SHIFT; 182 183 args.a0 = ARM_SMCCC_TRNG_GET_UUID; 184 thread_smccc(&args); 185 assert(args.a0 != ARM_SMCCC_RET_TRNG_NOT_SUPPORTED); 186 187 DMSG("SMCCC TRNG v%u.%u, UUID %08lx-%04lx-%04lx-%04lx-%04lx%08lx", 188 major, minor, (unsigned long)args.a0, (unsigned long)args.a1 >> 16, 189 (unsigned long)args.a1 & GENMASK_32(16, 0), 190 (unsigned long)args.a2 >> 16, 191 (unsigned long)args.a2 & GENMASK_32(16, 0), 192 (unsigned long)args.a3); 193 } 194 195 void plat_rng_init(void) 196 { 197 if (!smccc_trng_is_supported()) 198 panic("SMCCC TRNG not supported"); 199 200 smccc_trng_print_info(); 201 202 if (IS_ENABLED(CFG_WITH_SOFTWARE_PRNG)) { 203 /* If CFG_WITH_SOFTWARE_PRNG is enabled, seed PRNG with TRNG */ 204 uint8_t seed[32] = { 0 }; 205 206 if (smccc_trng_read(seed, sizeof(seed))) 207 panic("SMCCC TRNG not supported"); 208 209 if (crypto_rng_init(seed, sizeof(seed))) 210 panic(); 211 } 212 } 213 214 /* If CFG_WITH_SOFTWARE_PRNG is disabled, TRNG is our HW RNG */ 215 #ifndef CFG_WITH_SOFTWARE_PRNG 216 TEE_Result hw_get_random_bytes(void *buf, size_t len) 217 { 218 return smccc_trng_read(buf, len); 219 } 220 #endif 221