1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <stdbool.h> 9*91f16700Schasinglulu #include <stdint.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include <arch_features.h> 12*91f16700Schasinglulu #include <lib/smccc.h> 13*91f16700Schasinglulu #include <services/trng_svc.h> 14*91f16700Schasinglulu #include <smccc_helpers.h> 15*91f16700Schasinglulu 16*91f16700Schasinglulu #include <plat/common/plat_trng.h> 17*91f16700Schasinglulu 18*91f16700Schasinglulu #include "trng_entropy_pool.h" 19*91f16700Schasinglulu 20*91f16700Schasinglulu static const uuid_t uuid_null; 21*91f16700Schasinglulu 22*91f16700Schasinglulu /* handle the RND call in SMC 32 bit mode */ 23*91f16700Schasinglulu static uintptr_t trng_rnd32(uint32_t nbits, void *handle) 24*91f16700Schasinglulu { 25*91f16700Schasinglulu uint32_t mask = ~0U; 26*91f16700Schasinglulu uint64_t ent[2] = {0}; 27*91f16700Schasinglulu 28*91f16700Schasinglulu if (nbits == 0U || nbits > TRNG_RND32_ENTROPY_MAXBITS) { 29*91f16700Schasinglulu SMC_RET1(handle, TRNG_E_INVALID_PARAMS); 30*91f16700Schasinglulu } 31*91f16700Schasinglulu 32*91f16700Schasinglulu if (!trng_pack_entropy(nbits, &ent[0])) { 33*91f16700Schasinglulu SMC_RET1(handle, TRNG_E_NO_ENTROPY); 34*91f16700Schasinglulu } 35*91f16700Schasinglulu 36*91f16700Schasinglulu if ((nbits % 32U) != 0U) { 37*91f16700Schasinglulu mask >>= 32U - (nbits % 32U); 38*91f16700Schasinglulu } 39*91f16700Schasinglulu 40*91f16700Schasinglulu switch ((nbits - 1U) / 32U) { 41*91f16700Schasinglulu case 0: 42*91f16700Schasinglulu SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask); 43*91f16700Schasinglulu break; /* unreachable */ 44*91f16700Schasinglulu case 1: 45*91f16700Schasinglulu SMC_RET4(handle, TRNG_E_SUCCESS, 0, (ent[0] >> 32) & mask, 46*91f16700Schasinglulu ent[0] & 0xFFFFFFFF); 47*91f16700Schasinglulu break; /* unreachable */ 48*91f16700Schasinglulu case 2: 49*91f16700Schasinglulu SMC_RET4(handle, TRNG_E_SUCCESS, ent[1] & mask, 50*91f16700Schasinglulu (ent[0] >> 32) & 0xFFFFFFFF, ent[0] & 0xFFFFFFFF); 51*91f16700Schasinglulu break; /* unreachable */ 52*91f16700Schasinglulu default: 53*91f16700Schasinglulu SMC_RET1(handle, TRNG_E_INVALID_PARAMS); 54*91f16700Schasinglulu break; /* unreachable */ 55*91f16700Schasinglulu } 56*91f16700Schasinglulu } 57*91f16700Schasinglulu 58*91f16700Schasinglulu /* handle the RND call in SMC 64 bit mode */ 59*91f16700Schasinglulu static uintptr_t trng_rnd64(uint32_t nbits, void *handle) 60*91f16700Schasinglulu { 61*91f16700Schasinglulu uint64_t mask = ~0ULL; 62*91f16700Schasinglulu uint64_t ent[3] = {0}; 63*91f16700Schasinglulu 64*91f16700Schasinglulu if (nbits == 0U || nbits > TRNG_RND64_ENTROPY_MAXBITS) { 65*91f16700Schasinglulu SMC_RET1(handle, TRNG_E_INVALID_PARAMS); 66*91f16700Schasinglulu } 67*91f16700Schasinglulu 68*91f16700Schasinglulu if (!trng_pack_entropy(nbits, &ent[0])) { 69*91f16700Schasinglulu SMC_RET1(handle, TRNG_E_NO_ENTROPY); 70*91f16700Schasinglulu } 71*91f16700Schasinglulu 72*91f16700Schasinglulu /* Mask off higher bits if only part of register requested */ 73*91f16700Schasinglulu if ((nbits % 64U) != 0U) { 74*91f16700Schasinglulu mask >>= 64U - (nbits % 64U); 75*91f16700Schasinglulu } 76*91f16700Schasinglulu 77*91f16700Schasinglulu switch ((nbits - 1U) / 64U) { 78*91f16700Schasinglulu case 0: 79*91f16700Schasinglulu SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask); 80*91f16700Schasinglulu break; /* unreachable */ 81*91f16700Schasinglulu case 1: 82*91f16700Schasinglulu SMC_RET4(handle, TRNG_E_SUCCESS, 0, ent[1] & mask, ent[0]); 83*91f16700Schasinglulu break; /* unreachable */ 84*91f16700Schasinglulu case 2: 85*91f16700Schasinglulu SMC_RET4(handle, TRNG_E_SUCCESS, ent[2] & mask, ent[1], ent[0]); 86*91f16700Schasinglulu break; /* unreachable */ 87*91f16700Schasinglulu default: 88*91f16700Schasinglulu SMC_RET1(handle, TRNG_E_INVALID_PARAMS); 89*91f16700Schasinglulu break; /* unreachable */ 90*91f16700Schasinglulu } 91*91f16700Schasinglulu } 92*91f16700Schasinglulu 93*91f16700Schasinglulu void trng_setup(void) 94*91f16700Schasinglulu { 95*91f16700Schasinglulu trng_entropy_pool_setup(); 96*91f16700Schasinglulu plat_entropy_setup(); 97*91f16700Schasinglulu } 98*91f16700Schasinglulu 99*91f16700Schasinglulu /* Predicate indicating that a function id is part of TRNG */ 100*91f16700Schasinglulu bool is_trng_fid(uint32_t smc_fid) 101*91f16700Schasinglulu { 102*91f16700Schasinglulu return ((smc_fid == ARM_TRNG_VERSION) || 103*91f16700Schasinglulu (smc_fid == ARM_TRNG_FEATURES) || 104*91f16700Schasinglulu (smc_fid == ARM_TRNG_GET_UUID) || 105*91f16700Schasinglulu (smc_fid == ARM_TRNG_RND32) || 106*91f16700Schasinglulu (smc_fid == ARM_TRNG_RND64)); 107*91f16700Schasinglulu } 108*91f16700Schasinglulu 109*91f16700Schasinglulu uintptr_t trng_smc_handler(uint32_t smc_fid, u_register_t x1, u_register_t x2, 110*91f16700Schasinglulu u_register_t x3, u_register_t x4, void *cookie, 111*91f16700Schasinglulu void *handle, u_register_t flags) 112*91f16700Schasinglulu { 113*91f16700Schasinglulu if (!memcmp(&plat_trng_uuid, &uuid_null, sizeof(uuid_t))) { 114*91f16700Schasinglulu SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED); 115*91f16700Schasinglulu } 116*91f16700Schasinglulu 117*91f16700Schasinglulu switch (smc_fid) { 118*91f16700Schasinglulu case ARM_TRNG_VERSION: 119*91f16700Schasinglulu SMC_RET1(handle, MAKE_SMCCC_VERSION( 120*91f16700Schasinglulu TRNG_VERSION_MAJOR, TRNG_VERSION_MINOR)); 121*91f16700Schasinglulu break; /* unreachable */ 122*91f16700Schasinglulu 123*91f16700Schasinglulu case ARM_TRNG_FEATURES: 124*91f16700Schasinglulu if (is_trng_fid((uint32_t)x1)) { 125*91f16700Schasinglulu SMC_RET1(handle, TRNG_E_SUCCESS); 126*91f16700Schasinglulu } else { 127*91f16700Schasinglulu SMC_RET1(handle, TRNG_E_NOT_SUPPORTED); 128*91f16700Schasinglulu } 129*91f16700Schasinglulu break; /* unreachable */ 130*91f16700Schasinglulu 131*91f16700Schasinglulu case ARM_TRNG_GET_UUID: 132*91f16700Schasinglulu SMC_UUID_RET(handle, plat_trng_uuid); 133*91f16700Schasinglulu break; /* unreachable */ 134*91f16700Schasinglulu 135*91f16700Schasinglulu case ARM_TRNG_RND32: 136*91f16700Schasinglulu return trng_rnd32((uint32_t)x1, handle); 137*91f16700Schasinglulu 138*91f16700Schasinglulu case ARM_TRNG_RND64: 139*91f16700Schasinglulu return trng_rnd64((uint32_t)x1, handle); 140*91f16700Schasinglulu 141*91f16700Schasinglulu default: 142*91f16700Schasinglulu WARN("Unimplemented TRNG Service Call: 0x%x\n", smc_fid); 143*91f16700Schasinglulu SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED); 144*91f16700Schasinglulu break; /* unreachable */ 145*91f16700Schasinglulu } 146*91f16700Schasinglulu } 147