xref: /arm-trusted-firmware/services/std_svc/trng/trng_main.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
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