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