1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright (C) 2022 Xilinx, Inc. All rights reserved.
4 * Copyright (C) 2022 Foundries Ltd.
5 *
6 * Driver port from Xilinx's FSBL implementation, jorge@foundries.io
7 *
8 * The Xilinx True Random Number Generator(TRNG) module in Versal - PMC TRNG
9 * consists of an entropy source, a deterministic random bit generator (DRBG)
10 * and health test logic, which tests the randomness of the generated data.
11 * The entropy source for the unit is an array of Ring Oscillators.
12 *
13 * The Versal PMC TRNG is envisaged to operate in three basic modes: DRNG, PTRNG
14 * and HRNG . Each of these can be operated with or without Derivative Function
15 * (DF), resulting in a total of 6 different modes of operation.
16 *
17 * NIST SP-800-90A practically requires the true random generators based on
18 * CTR_DRBG to include a derivation function (DF). This is expected to be
19 * implemented inside the Silicon (TRNG IP). However, the version of the IP used
20 * in Versal PMC does not have this capability. Hence, a software
21 * implementation of the DF is done in this driver.
22 *
23 * DRNG mode: Deterministic Random Number Generator mode.
24 * In this mode, the DRBG portion of the TRNG is used. User provides
25 * the (external) seed.
26 * PTRNG mode: Physical True Random Number Generator mode (aka Entropy mode).
27 * In this mode digitized Entropy source is output as random number.
28 * HRNG mode: Hybrid Random Number Generator mode.
29 * This is combination of above two modes in which the Entropy source
30 * is used to provide the seed, which is fed to the DRBG, which in
31 * turn generates the random number.
32 *
33 * DRNG mode with DF: It may not be common usecase to use the DF with DRNG as
34 * the general expectation would be that the seed would have sufficient entropy.
35 * However, the below guideline from section 10.2.1 of NIST SP-800-90A implies
36 * that need for DF for DRNG mode too: "..the DRBG mechanism is specified to
37 * allow an implementation tradeoff with respect to the use of this derivation
38 * function. The use of the derivation function is optional if either an
39 * approved RBG or an entropy source provides full entropy output when entropy
40 * input is requested by the DRBG mechanism. Otherwise, the derivation function
41 * shall be used". Sufficient large entropy data from user is fed to DF to
42 * generate the seed which will be loaded into the external seed registers.
43 * From here, it is similar to regular DRNG mode.
44 *
45 * PTRNG mode with DF: This mode is similar to PTRNG mode, however, the entropy
46 * data from the core output registers are accumulated and fed to the DF
47 * (instead of directly consuming it). The output of the DF would be final
48 * random data. In this mode, the output of DF is not seed but the random data.
49 *
50 * HRNG mode with DF: This mode is the combination of the above two modes.
51 * The entropy data is fed to the DF to produce seed. This seed is loaded to the
52 * external seed registers which provide seed to the DRBG.
53 */
54
55 #include <config.h>
56 #include <drivers/versal_pmc.h>
57 #include <drivers/versal_trng.h>
58 #include <initcall.h>
59 #include <io.h>
60 #include <kernel/delay.h>
61 #include <kernel/panic.h>
62 #include <mm/core_mmu.h>
63 #include <mm/core_memprot.h>
64 #include <rng_support.h>
65 #include <stdint.h>
66 #include <string.h>
67 #include <tee/tee_cryp_utl.h>
68 #include <util.h>
69
70 #ifdef CFG_VERSAL_RNG_IO
71 #define TRNG_STATUS 0x04
72 #define TRNG_STATUS_QCNT_SHIFT 9
73 #define TRNG_STATUS_QCNT_MASK (BIT(9) | BIT(10) | BIT(11))
74 #define TRNG_STATUS_CERTF_MASK BIT(3)
75 #define TRNG_STATUS_DTF_MASK BIT(1)
76 #define TRNG_STATUS_DONE_MASK BIT(0)
77 #define TRNG_CTRL 0x08
78 #define TRNG_CTRL_EUMODE_MASK BIT(8)
79 #define TRNG_CTRL_PRNGMODE_MASK BIT(7)
80 #define TRNG_CTRL_TSTMODE_MASK BIT(6)
81 #define TRNG_CTRL_PRNGSTART_MASK BIT(5)
82 #define TRNG_CTRL_PRNGXS_MASK BIT(3)
83 #define TRNG_CTRL_TRSSEN_MASK BIT(2)
84 #define TRNG_CTRL_PRNGSRST_MASK BIT(0)
85
86 #define TRNG_CTRL_PERSODISABLE_MASK BIT(10)
87 #define TRNG_CTRL_SINGLEGENMODE_MASK BIT(9)
88
89 #ifdef CFG_VERSAL_RNG_V2
90 /* register CTRL_2 is also called CONF_0 */
91 #define TRNG_CTRL_2 0x0C
92 #define TRNG_CTRL_2_RCTCUTOFF_SHIFT 8
93 #define TRNG_CTRL_2_RCTCUTOFF_MASK GENMASK_32(16, 8)
94 #define TRNG_CTRL_2_RCTCUTOFF_DEFVAL 0x21
95 #define TRNG_CTRL_2_DIT_SHIFT 0
96 #define TRNG_CTRL_2_DIT_MASK GENMASK_32(4, 0)
97 #define TRNG_CTRL_2_DIT_DEFVAL 0xC
98 /* register CTRL_3 is also called CONF_1 */
99 #define TRNG_CTRL_3 0x10
100 #define TRNG_CTRL_3_APTCUTOFF_SHIFT 8
101 #define TRNG_CTRL_3_APTCUTOFF_MASK GENMASK_32(17, 8)
102 #define TRNG_CTRL_3_APTCUTOFF_DEFVAL 0x264
103 #define TRNG_CTRL_3_DLEN_SHIFT 0
104 #define TRNG_CTRL_3_DLEN_MASK GENMASK_32(7, 0)
105 #define TRNG_CTRL_3_DLEN_DEFVAL 0x9
106 /* register CTRL_4 is also called TEST */
107 #define TRNG_CTRL_4 0x14
108 #define TRNG_CTRL_4_SINGLEBITRAW_MASK BIT(0)
109 #endif
110
111 #define TRNG_EXT_SEED_0 0x40
112 /*
113 * Below registers are not directly referenced in driver but are accessed
114 * with offset from TRNG_EXT_SEED_0
115 * Register: TRNG_EXT_SEED_1 0x00000044
116 * Register: TRNG_EXT_SEED_2 0x00000048
117 * Register: TRNG_EXT_SEED_3 0x0000004C
118 * Register: TRNG_EXT_SEED_4 0x00000050
119 * Register: TRNG_EXT_SEED_5 0x00000054
120 * Register: TRNG_EXT_SEED_6 0x00000058
121 * Register: TRNG_EXT_SEED_7 0x0000005C
122 * Register: TRNG_EXT_SEED_8 0x00000060
123 * Register: TRNG_EXT_SEED_9 0x00000064
124 * Register: TRNG_EXT_SEED_10 0x00000068
125 * Register: TRNG_EXT_SEED_11 0x0000006C
126 */
127 #define TRNG_PER_STRING_0 0x80
128 /*
129 * Below registers are not directly referenced in driver but are accessed
130 * with offset from TRNG_PER_STRING_0
131 * Register: TRNG_PER_STRING_1 0x00000084
132 * Register: TRNG_PER_STRING_2 0x00000088
133 * Register: TRNG_PER_STRING_3 0x0000008C
134 * Register: TRNG_PER_STRING_4 0x00000090
135 * Register: TRNG_PER_STRING_5 0x00000094
136 * Register: TRNG_PER_STRING_6 0x00000098
137 * Register: TRNG_PER_STRING_7 0x0000009C
138 * Register: TRNG_PER_STRING_8 0x000000A0
139 * Register: TRNG_PER_STRING_9 0x000000A4
140 * Register: TRNG_PER_STRING_10 0x000000A8
141 * Register: TRNG_PER_STRING_11 0x000000AC
142 */
143 #define TRNG_CORE_OUTPUT 0xC0
144 #define TRNG_RESET 0xD0
145 #define TRNG_RESET_VAL_MASK BIT(0)
146 #define TRNG_OSC_EN 0xD4
147 #define TRNG_OSC_EN_VAL_MASK BIT(0)
148
149 /* TRNG configuration */
150 #define TRNG_BURST_SIZE 16
151 #define TRNG_BURST_SIZE_BITS 128
152 #define TRNG_NUM_INIT_REGS 12
153 #define TRNG_REG_SIZE 32
154 #define TRNG_BYTES_PER_REG 4
155 #define TRNG_MAX_QCNT 4
156 #define TRNG_RESEED_TIMEOUT 15000
157 #define TRNG_GENERATE_TIMEOUT 8000
158 #define TRNG_V2_RESEED_TIMEOUT 1500000
159 #define TRNG_V2_GENERATE_TIMEOUT 1500000
160 #define TRNG_V2_MIN_SEEDLIFE 1
161 #define TRNG_V2_MAX_SEEDLIFE 0x80000
162 #define TRNG_MIN_DFLENMULT 2
163 #define TRNG_MAX_DFLENMULT 9
164 #define TRNG_V2_MIN_DFLENMULT TRNG_MIN_DFLENMULT
165 #define TRNG_V2_MAX_DFLENMULT 31
166 #define PRNGMODE_RESEED 0
167 #define PRNGMODE_GEN TRNG_CTRL_PRNGMODE_MASK
168 #define RESET_DELAY 10
169 #define TRNG_ENTROPY_SEED_LEN 64
170 #define TRNG_SEC_STRENGTH_LEN 32
171 #define TRNG_SEED_REGS 12
172 #define TRNG_GEN_LEN 32
173 #define BYTES_PER_BLOCK 16
174 #define ALL_A_PATTERN_32 0xAAAAAAAA
175 #define ALL_5_PATTERN_32 0x55555555
176
177 #ifdef CFG_VERSAL_RNG_V2
178 #define TRNG_DF_2CLKS_WAIT 2
179 #define TRNG_DF_700CLKS_WAIT 10
180 #define TRNG_DF_NUM_OF_BYTES_BEFORE_MIN_700CLKS_WAIT 8
181 #endif
182
183 /* Derivative function helper macros */
184 #define DF_SEED 0
185 #define DF_RAND 1
186
187 #ifdef CFG_VERSAL_RNG_V1
188 #define DF_PAD_VAL 0x80
189 #define DF_KEY_LEN 32
190 #define BLK_SIZE 16
191 #define MAX_ROUNDS 14
192
193 /* Derivative function variables */
194 static unsigned char sbx1[256];
195 static unsigned char sbx2[256];
196 static unsigned char sbx3[256];
197 static unsigned char schedule[BLK_SIZE * (MAX_ROUNDS + 1)];
198 static unsigned int rounds;
199
rota4(uint8_t * a,uint8_t * b,uint8_t * c,uint8_t * d)200 static void rota4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d)
201 {
202 uint8_t t = *a;
203
204 *a = sbx1[*b];
205 *b = sbx1[*c];
206 *c = sbx1[*d];
207 *d = sbx1[t];
208 }
209
rota2(uint8_t * a,uint8_t * b)210 static void rota2(uint8_t *a, uint8_t *b)
211 {
212 uint8_t t = *a;
213
214 *a = sbx1[*b];
215 *b = sbx1[t];
216 }
217
sbox4(uint8_t * a,uint8_t * b,uint8_t * c,uint8_t * d)218 static void sbox4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d)
219 {
220 *a = sbx1[*a];
221 *b = sbx1[*b];
222 *c = sbx1[*c];
223 *d = sbx1[*d];
224 }
225
xorb(uint8_t * res,const uint8_t * in)226 static void xorb(uint8_t *res, const uint8_t *in)
227 {
228 size_t i = 0;
229
230 for (i = 0; i < BLK_SIZE; ++i)
231 res[i] ^= in[i];
232 }
233
set_key(uint8_t * res,const uint8_t * src,unsigned int roundval)234 static void set_key(uint8_t *res, const uint8_t *src, unsigned int roundval)
235 {
236 memcpy(res, src, BLK_SIZE);
237 xorb(res, schedule + roundval * BLK_SIZE);
238 }
239
mix_column_sbox(uint8_t * dst,const uint8_t * f)240 static void mix_column_sbox(uint8_t *dst, const uint8_t *f)
241 {
242 size_t i = 0;
243 size_t a = 0;
244 size_t b = 0;
245 size_t c = 0;
246 size_t d = 0;
247
248 for (i = 0; i < 4; i++) {
249 a = 4 * i;
250 b = (0x5 + a) % 16;
251 c = (0xa + a) % 16;
252 d = (0xf + a) % 16;
253 dst[0 + a] = sbx2[f[a]] ^ sbx3[f[b]] ^ sbx1[f[c]] ^ sbx1[f[d]];
254 dst[1 + a] = sbx1[f[a]] ^ sbx2[f[b]] ^ sbx3[f[c]] ^ sbx1[f[d]];
255 dst[2 + a] = sbx1[f[a]] ^ sbx1[f[b]] ^ sbx2[f[c]] ^ sbx3[f[d]];
256 dst[3 + a] = sbx3[f[a]] ^ sbx1[f[b]] ^ sbx1[f[c]] ^ sbx2[f[d]];
257 }
258 }
259
shift_row_sbox(uint8_t * f)260 static void shift_row_sbox(uint8_t *f)
261 {
262 sbox4(&f[0], &f[4], &f[8], &f[12]);
263 rota4(&f[1], &f[5], &f[9], &f[13]);
264 rota2(&f[2], &f[10]);
265 rota2(&f[6], &f[14]);
266 rota4(&f[15], &f[11], &f[7], &f[3]);
267 }
268
encrypt(uint8_t * in,uint8_t * out)269 static void encrypt(uint8_t *in, uint8_t *out)
270 {
271 uint8_t fa[BLK_SIZE] = { 0 };
272 uint8_t fb[BLK_SIZE] = { 0 };
273 size_t roundval = 0;
274
275 set_key(fa, in, 0);
276 for (roundval = 1; roundval < rounds; ++roundval) {
277 mix_column_sbox(fb, fa);
278 set_key(fa, fb, roundval);
279 }
280
281 shift_row_sbox(fa);
282 set_key(out, fa, roundval);
283 }
284
checksum(unsigned char * in,uint8_t * iv,int max_blk)285 static void checksum(unsigned char *in, uint8_t *iv, int max_blk)
286 {
287 while (max_blk > 0) {
288 xorb(iv, in);
289 encrypt(iv, iv);
290 in += BLK_SIZE;
291 max_blk -= 1;
292 }
293 }
294
setup_key(const unsigned char * k,size_t klen)295 static void setup_key(const unsigned char *k, size_t klen)
296 {
297 unsigned char rcon = 1;
298 size_t sch_size = 240;
299 size_t i = 0;
300
301 rounds = MAX_ROUNDS;
302 memcpy(schedule, k, klen);
303 for (i = klen; i < sch_size; i += 4) {
304 unsigned char t0 = 0;
305 unsigned char t1 = 0;
306 unsigned char t2 = 0;
307 unsigned char t3 = 0;
308 int ik = 0;
309
310 t0 = schedule[i - 4];
311 t1 = schedule[i - 3];
312 t2 = schedule[i - 2];
313 t3 = schedule[i - 1];
314 if (i % klen == 0) {
315 rota4(&t0, &t1, &t2, &t3);
316 t0 ^= rcon;
317 rcon = (rcon << 1) ^ (((rcon >> 7) & 1) * 0x1B);
318 } else if (i % klen == 16) {
319 sbox4(&t0, &t1, &t2, &t3);
320 }
321 ik = i - klen;
322 schedule[i + 0] = schedule[ik + 0] ^ t0;
323 schedule[i + 1] = schedule[ik + 1] ^ t1;
324 schedule[i + 2] = schedule[ik + 2] ^ t2;
325 schedule[i + 3] = schedule[ik + 3] ^ t3;
326 }
327 }
328
trng_df_init(void)329 static void trng_df_init(void)
330 {
331 const uint8_t sb[] = {
332 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01,
333 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d,
334 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4,
335 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
336 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7,
337 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
338 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e,
339 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
340 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb,
341 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb,
342 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
343 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
344 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c,
345 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d,
346 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a,
347 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
348 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3,
349 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
350 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a,
351 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
352 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e,
353 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
354 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9,
355 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
356 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99,
357 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
358 };
359 size_t i = 0;
360
361 memcpy(sbx1, sb, sizeof(sb));
362 for (i = 0; i < sizeof(sb); i++) {
363 sbx2[i] = (sb[i] << 1) ^ (((sb[i] >> 7) & 1) * 0x1B);
364 sbx3[i] = sbx2[i] ^ sb[i];
365 }
366 }
367
368 /*
369 * This function implements the Derivative Function by distilling the entropy
370 * available in its input into a smaller number of bits on the output.
371 * - per NIST SP80090A.
372 *
373 * The Block Cipher algorithm follows sections 10.3.2 and 10.3.3 of the
374 * NIST.SP.800-90Ar1 document
375 */
trng_df_algorithm(struct versal_trng * trng,uint8_t * dfout,uint32_t flag,const uint8_t * pstr)376 static void trng_df_algorithm(struct versal_trng *trng, uint8_t *dfout,
377 uint32_t flag, const uint8_t *pstr)
378 {
379 static bool df_init;
380 const uint8_t df_key[DF_KEY_LEN] = {
381 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
382 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
383 };
384 size_t dfin_len = sizeof(struct trng_dfin) + trng->len;
385 uint8_t *inp_blk = NULL;
386 uint8_t *out_blk = NULL;
387 uintptr_t reminder = 0;
388 size_t xfer_len = 0;
389 uint32_t index = 0;
390 uintptr_t src = 0;
391 uintptr_t dst = 0;
392 size_t offset = 0;
393
394 if (!df_init) {
395 trng_df_init();
396 df_init = true;
397 }
398
399 if (flag == DF_SEED)
400 trng->dfin.val2 = TEE_U32_TO_BIG_ENDIAN(TRNG_PERS_STR_LEN);
401 else
402 trng->dfin.val2 = TEE_U32_TO_BIG_ENDIAN(TRNG_GEN_LEN);
403
404 trng->dfin.pad_data[0] = DF_PAD_VAL;
405
406 if (!pstr) {
407 if (trng->len > (MAX_PRE_DF_LEN + TRNG_PERS_STR_LEN))
408 panic();
409
410 dfin_len = dfin_len - TRNG_PERS_STR_LEN - MAX_PRE_DF_LEN;
411 trng->dfin.val1 = TEE_U32_TO_BIG_ENDIAN(trng->len);
412
413 xfer_len = DF_PAD_DATA_LEN;
414 src = (uintptr_t)trng->dfin.pad_data;
415 offset = MAX_PRE_DF_LEN + TRNG_PERS_STR_LEN - trng->len;
416 } else {
417 if (trng->len > MAX_PRE_DF_LEN)
418 panic();
419
420 memcpy(trng->dfin.pstr, pstr, TRNG_PERS_STR_LEN);
421 dfin_len = dfin_len - MAX_PRE_DF_LEN;
422 trng->dfin.val1 = TEE_U32_TO_BIG_ENDIAN(trng->len +
423 TRNG_PERS_STR_LEN);
424 xfer_len = DF_PAD_DATA_LEN + TRNG_PERS_STR_LEN;
425 src = (uintptr_t)trng->dfin.pstr;
426 offset = MAX_PRE_DF_LEN - trng->len;
427 }
428
429 /* Move back into the dfin structure */
430 dst = src - offset;
431 reminder = (uintptr_t)&trng->dfin + sizeof(trng->dfin) - offset;
432 if (offset) {
433 if (xfer_len > offset)
434 panic("Overlapping data");
435
436 memcpy((void *)dst, (void *)src, xfer_len);
437 memset((void *)reminder, 0, offset);
438 }
439
440 /* DF algorithm - step 1 */
441 setup_key(df_key, DF_KEY_LEN);
442 for (index = 0; index < TRNG_SEED_LEN; index += BLK_SIZE) {
443 memset((void *)(trng->dfout + index), 0, BLK_SIZE);
444 trng->dfin.ivc[0] = TEE_U32_TO_BIG_ENDIAN(index / BLK_SIZE);
445 checksum((unsigned char *)&trng->dfin,
446 trng->dfout + index, dfin_len / BLK_SIZE);
447 }
448
449 /* DF algorithm - step 2 */
450 setup_key(trng->dfout, DF_KEY_LEN);
451 for (index = 0; index < TRNG_SEED_LEN; index += BLK_SIZE) {
452 if (!index)
453 inp_blk = &dfout[TRNG_SEC_STRENGTH_LEN];
454 else
455 inp_blk = &dfout[index - BLK_SIZE];
456
457 out_blk = &dfout[index];
458 encrypt(inp_blk, out_blk);
459 }
460 }
461 #endif
462
trng_read32(vaddr_t addr,size_t off)463 static uint32_t trng_read32(vaddr_t addr, size_t off)
464 {
465 return io_read32(addr + off);
466 }
467
trng_write32(vaddr_t addr,size_t off,uint32_t val)468 static void trng_write32(vaddr_t addr, size_t off, uint32_t val)
469 {
470 io_write32(addr + off, val);
471 }
472
trng_clrset32(vaddr_t addr,size_t off,uint32_t mask,uint32_t val)473 static void trng_clrset32(vaddr_t addr, size_t off, uint32_t mask, uint32_t val)
474 {
475 io_clrsetbits32(addr + off, mask, mask & val);
476 }
477
trng_write32_range(const struct versal_trng * trng,uint32_t start,uint32_t num_regs,const uint8_t * buf)478 static void trng_write32_range(const struct versal_trng *trng, uint32_t start,
479 uint32_t num_regs, const uint8_t *buf)
480 {
481 size_t off = 0;
482 uint32_t val = 0;
483 size_t cnt = 0;
484 size_t i = 0;
485
486 for (i = 0; i < num_regs; ++i) {
487 if (!buf) {
488 off = start + i * TRNG_BYTES_PER_REG;
489 trng_write32(trng->cfg.addr, off, 0);
490 continue;
491 }
492
493 val = 0;
494 for (cnt = 0; cnt < TRNG_BYTES_PER_REG; ++cnt)
495 val = (val << 8) | buf[i * TRNG_BYTES_PER_REG + cnt];
496
497 off = start + (TRNG_NUM_INIT_REGS - 1 - i) * TRNG_BYTES_PER_REG;
498 trng_write32(trng->cfg.addr, off, val);
499 }
500 }
501
trng_wait_for_event(vaddr_t addr,size_t off,uint32_t mask,uint32_t event,uint32_t time_out)502 static TEE_Result trng_wait_for_event(vaddr_t addr, size_t off, uint32_t mask,
503 uint32_t event, uint32_t time_out)
504 {
505 uint64_t tref = timeout_init_us(time_out);
506
507 do {
508 if (timeout_elapsed(tref))
509 break;
510 } while ((io_read32(addr + off) & mask) != event);
511
512 /* Normal world might have suspended the OP-TEE thread, check again */
513 if ((io_read32(addr + off) & mask) != event)
514 return TEE_ERROR_GENERIC;
515
516 return TEE_SUCCESS;
517 }
518
trng_soft_reset(const struct versal_trng * trng)519 static void trng_soft_reset(const struct versal_trng *trng)
520 {
521 trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSRST_MASK,
522 TRNG_CTRL_PRNGSRST_MASK);
523 udelay(RESET_DELAY);
524 trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSRST_MASK, 0);
525 }
526
trng_reset(const struct versal_trng * trng)527 static void trng_reset(const struct versal_trng *trng)
528 {
529 trng_write32(trng->cfg.addr, TRNG_RESET, TRNG_RESET_VAL_MASK);
530 udelay(RESET_DELAY);
531 trng_write32(trng->cfg.addr, TRNG_RESET, 0);
532 trng_soft_reset(trng);
533 }
534
trng_hold_reset(const struct versal_trng * trng)535 static void trng_hold_reset(const struct versal_trng *trng)
536 {
537 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
538 TRNG_CTRL_PRNGSRST_MASK, TRNG_CTRL_PRNGSRST_MASK);
539 trng_write32(trng->cfg.addr, TRNG_RESET, TRNG_RESET_VAL_MASK);
540 udelay(RESET_DELAY);
541 }
542
543 #ifdef CFG_VERSAL_RNG_V2
trng_v2_write_seed(const struct versal_trng * trng,const uint8_t * seed,uint8_t dlen)544 static int trng_v2_write_seed(const struct versal_trng *trng,
545 const uint8_t *seed, uint8_t dlen)
546 {
547 int status = TEE_ERROR_GENERIC;
548 uint32_t seed_len = (dlen + 1) * BYTES_PER_BLOCK;
549 uint32_t idx = 0;
550 uint8_t cnt = 0;
551
552 while (idx < seed_len) {
553 uint8_t seed_construct = 0;
554
555 for (cnt = 0; cnt < 8; cnt++) {
556 uint32_t bit = (seed[idx] >> (8 - 1 - cnt)) & 0x01;
557
558 trng_write32(trng->cfg.addr, TRNG_CTRL_4, bit);
559 seed_construct = (seed_construct << 1) | bit;
560 }
561
562 if (seed_construct != seed[idx])
563 goto END;
564
565 udelay(TRNG_DF_2CLKS_WAIT);
566 if (!(idx % TRNG_DF_NUM_OF_BYTES_BEFORE_MIN_700CLKS_WAIT))
567 udelay(TRNG_DF_700CLKS_WAIT);
568
569 idx++;
570 }
571 if (idx == seed_len)
572 status = TEE_SUCCESS;
573
574 END:
575 return status;
576 }
577 #endif
578
579 #ifdef CFG_VERSAL_RNG_V1
trng_check_seed(uint8_t * entropy,uint32_t len)580 static TEE_Result trng_check_seed(uint8_t *entropy, uint32_t len)
581 {
582 uint32_t *p = (void *)entropy;
583 size_t i = 0;
584
585 for (i = 0; i < len / sizeof(*p); i++) {
586 if (p[i] == ALL_A_PATTERN_32)
587 return TEE_ERROR_GENERIC;
588
589 if (p[i] == ALL_5_PATTERN_32)
590 return TEE_ERROR_GENERIC;
591 }
592
593 return TEE_SUCCESS;
594 }
595 #endif
596
trng_collect_random(struct versal_trng * trng,uint8_t * dst,size_t len)597 static TEE_Result trng_collect_random(struct versal_trng *trng, uint8_t *dst,
598 size_t len)
599 {
600 const size_t bursts = len / TRNG_BURST_SIZE;
601 const size_t words = TRNG_BURST_SIZE_BITS / TRNG_REG_SIZE;
602 uint32_t *p = (void *)dst;
603 size_t bcnt = 0;
604 size_t wcnt = 0;
605 size_t index = 0;
606 uint32_t val = 0;
607 bool match = false;
608 uint32_t timeout = TRNG_GENERATE_TIMEOUT;
609 bool do_start = true;
610
611 if (IS_ENABLED(CFG_VERSAL_RNG_V2) && trng->cfg.version == TRNG_V2) {
612 if (trng->usr_cfg.predict_en ||
613 !trng->stats.elapsed_seed_life) {
614 uint32_t singlegen = 0;
615
616 if (trng->usr_cfg.predict_en)
617 singlegen = TRNG_CTRL_SINGLEGENMODE_MASK;
618
619 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
620 TRNG_CTRL_PRNGMODE_MASK |
621 TRNG_CTRL_SINGLEGENMODE_MASK |
622 TRNG_CTRL_PRNGSTART_MASK,
623 PRNGMODE_GEN | singlegen);
624 } else {
625 do_start = false;
626 }
627
628 timeout = TRNG_V2_GENERATE_TIMEOUT;
629 }
630
631 if (do_start)
632 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
633 TRNG_CTRL_PRNGSTART_MASK,
634 TRNG_CTRL_PRNGSTART_MASK);
635
636 /*
637 * Loop as many times based on len requested. In each burst 128 bits
638 * are generated, which is reflected in QCNT value of 4 by hardware.
639 */
640 for (bcnt = 0; bcnt < bursts; bcnt++) {
641 if (trng_wait_for_event(trng->cfg.addr,
642 TRNG_STATUS, TRNG_STATUS_QCNT_MASK,
643 TRNG_MAX_QCNT << TRNG_STATUS_QCNT_SHIFT,
644 timeout)) {
645 EMSG("Timeout waiting for randomness");
646 return TEE_ERROR_GENERIC;
647 }
648
649 /*
650 * DTF flag set during generate indicates catastrophic
651 * condition, which needs to be checked for every time unless we
652 * are in PTRNG mode
653 */
654 if (trng->usr_cfg.mode != TRNG_PTRNG) {
655 val = trng_read32(trng->cfg.addr, TRNG_STATUS);
656 if (val & TRNG_STATUS_DTF_MASK) {
657 EMSG("Catastrophic DFT error");
658 trng->status = TRNG_CATASTROPHIC;
659
660 return TEE_ERROR_GENERIC;
661 }
662 }
663 /*
664 * Read the core output register 4 times to consume the random
665 * data generated for every burst.
666 */
667 match = true;
668 for (wcnt = 0; wcnt < words; wcnt++) {
669 val = trng_read32(trng->cfg.addr, TRNG_CORE_OUTPUT);
670
671 if (bcnt > 0 && trng->buf[wcnt] != val)
672 match = false;
673
674 trng->buf[wcnt] = val;
675
676 if (dst) {
677 p[index] = TEE_U32_TO_BIG_ENDIAN(val);
678 index++;
679 }
680 }
681
682 if (bursts > 1 && bcnt > 0 && match) {
683 EMSG("Catastrophic software error");
684 trng->status = TRNG_CATASTROPHIC;
685 return TEE_ERROR_GENERIC;
686 }
687 }
688
689 return TEE_SUCCESS;
690 }
691
692 #ifdef CFG_VERSAL_RNG_V2
trng_v2_reseed_internal(struct versal_trng * trng,uint8_t * eseed,uint8_t * str,uint32_t mul)693 static TEE_Result trng_v2_reseed_internal(struct versal_trng *trng,
694 uint8_t *eseed, uint8_t *str,
695 uint32_t mul)
696 {
697 uint32_t ret = TEE_ERROR_GENERIC;
698 uint32_t persmask = TRNG_CTRL_PERSODISABLE_MASK;
699 uint32_t val = 0;
700
701 trng->stats.bytes_reseed = 0;
702 trng->stats.elapsed_seed_life = 0;
703
704 /* Configure DF Len */
705 trng_clrset32(trng->cfg.addr, TRNG_CTRL_3, TRNG_CTRL_3_DLEN_MASK,
706 (mul << TRNG_CTRL_3_DLEN_SHIFT));
707
708 if (str) {
709 trng_write32_range(trng, TRNG_PER_STRING_0, TRNG_PERS_STR_REGS,
710 str);
711 persmask = 0;
712 }
713
714 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
715 TRNG_CTRL_PERSODISABLE_MASK | TRNG_CTRL_PRNGSTART_MASK,
716 persmask);
717
718 switch (trng->usr_cfg.mode) {
719 case TRNG_HRNG:
720 /* Enable ring oscillators for random seed source */
721 trng_clrset32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK,
722 TRNG_OSC_EN_VAL_MASK);
723
724 /* Enable TRSSEN and set PRNG mode for reseed operation */
725 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
726 TRNG_CTRL_PRNGMODE_MASK |
727 TRNG_CTRL_TRSSEN_MASK | TRNG_CTRL_PRNGXS_MASK,
728 PRNGMODE_RESEED |
729 TRNG_CTRL_TRSSEN_MASK);
730
731 /* Start reseed operation */
732 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
733 TRNG_CTRL_PRNGSTART_MASK,
734 TRNG_CTRL_PRNGSTART_MASK);
735 break;
736 case TRNG_DRNG:
737 /* Enable TST mode and set PRNG mode for reseed operation */
738 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
739 TRNG_CTRL_PRNGMODE_MASK |
740 TRNG_CTRL_TSTMODE_MASK | TRNG_CTRL_TRSSEN_MASK,
741 PRNGMODE_RESEED |
742 TRNG_CTRL_TSTMODE_MASK | TRNG_CTRL_TRSSEN_MASK);
743
744 /* Start reseed operation */
745 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
746 TRNG_CTRL_PRNGSTART_MASK,
747 TRNG_CTRL_PRNGSTART_MASK);
748
749 ret = trng_v2_write_seed(trng, eseed, mul);
750 if (ret)
751 return ret;
752 break;
753 default:
754 /* shall not be reached */
755 panic();
756 }
757
758 /* Wait for reseed operation */
759 if (trng_wait_for_event(trng->cfg.addr, TRNG_STATUS,
760 TRNG_STATUS_DONE_MASK,
761 TRNG_STATUS_DONE_MASK,
762 TRNG_V2_RESEED_TIMEOUT))
763 goto error;
764
765 /* Check SP800 - 90B (entropy health test error) */
766 val = trng_read32(trng->cfg.addr, TRNG_STATUS) & TRNG_STATUS_CERTF_MASK;
767 if (val == TRNG_STATUS_CERTF_MASK)
768 goto error;
769
770 /* Stop reseed operation */
771 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
772 TRNG_CTRL_PRNGSTART_MASK | TRNG_CTRL_TRSSEN_MASK, 0);
773 return TEE_SUCCESS;
774
775 error:
776 trng->status = TRNG_ERROR;
777 return TEE_ERROR_GENERIC;
778 }
779 #else
trng_v2_reseed_internal(struct versal_trng * trng __unused,uint8_t * eseed __unused,uint8_t * str __unused,uint32_t mul __unused)780 static TEE_Result trng_v2_reseed_internal(struct versal_trng *trng __unused,
781 uint8_t *eseed __unused,
782 uint8_t *str __unused,
783 uint32_t mul __unused)
784 {
785 return TEE_ERROR_NOT_SUPPORTED;
786 }
787 #endif
788
789 #ifdef CFG_VERSAL_RNG_V1
trng_reseed_internal_nodf(struct versal_trng * trng,uint8_t * eseed,uint8_t * str)790 static TEE_Result trng_reseed_internal_nodf(struct versal_trng *trng,
791 uint8_t *eseed, uint8_t *str)
792 {
793 uint8_t entropy[TRNG_ENTROPY_SEED_LEN] = { 0 };
794 uint8_t *seed = NULL;
795
796 switch (trng->usr_cfg.mode) {
797 case TRNG_HRNG:
798 /*
799 * Versal TRNG IP doesn't recognize alternate 1 and 0 pattern,
800 * hence the entropy output need to be monitored before using it
801 * as seed. This means, TRNG couldn't be configured for entropy
802 * source as seed source. Instead, entropy data is collected as
803 * random data, and after inspecting for pattern, is fed again
804 * to the external seed registers. This is essentially similar
805 * to HRNG + DF case except that there is no DF involved. This
806 * actually is configuration for PTRNG mode (not for reseed) to
807 * collect random output data from entropy source.
808 */
809 trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK);
810 trng_soft_reset(trng);
811 trng_write32(trng->cfg.addr, TRNG_CTRL,
812 TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK);
813
814 if (trng_collect_random(trng, entropy, TRNG_ENTROPY_SEED_LEN))
815 return TEE_ERROR_GENERIC;
816
817 if (trng_check_seed(entropy, TRNG_ENTROPY_SEED_LEN))
818 return TEE_ERROR_GENERIC;
819
820 seed = entropy;
821 break;
822 case TRNG_DRNG:
823 seed = eseed;
824 break;
825 default:
826 seed = NULL;
827 break;
828 }
829
830 trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, seed);
831 if (str)
832 trng_write32_range(trng, TRNG_PER_STRING_0, TRNG_PERS_STR_REGS,
833 str);
834
835 return TEE_SUCCESS;
836 }
837
trng_reseed_internal_df(struct versal_trng * trng,uint8_t * eseed,uint8_t * str)838 static TEE_Result trng_reseed_internal_df(struct versal_trng *trng,
839 uint8_t *eseed, uint8_t *str)
840 {
841 memset(&trng->dfin, 0, sizeof(trng->dfin));
842
843 switch (trng->usr_cfg.mode) {
844 case TRNG_HRNG:
845 /* see comment in _nodf() */
846 trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK);
847 trng_soft_reset(trng);
848 trng_write32(trng->cfg.addr, TRNG_CTRL,
849 TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK);
850
851 if (trng_collect_random(trng, trng->dfin.entropy, trng->len))
852 return TEE_ERROR_GENERIC;
853
854 if (trng_check_seed(trng->dfin.entropy, trng->len))
855 return TEE_ERROR_GENERIC;
856 break;
857 case TRNG_DRNG:
858 memcpy(trng->dfin.entropy, eseed, trng->len);
859 break;
860 default:
861 break;
862 }
863
864 trng_df_algorithm(trng, trng->dfout, DF_SEED, str);
865 trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, trng->dfout);
866
867 return TEE_SUCCESS;
868 }
869
trng_v1_reseed_internal(struct versal_trng * trng,uint8_t * eseed,uint8_t * str,uint32_t mul)870 static TEE_Result trng_v1_reseed_internal(struct versal_trng *trng,
871 uint8_t *eseed, uint8_t *str,
872 uint32_t mul)
873 {
874 uint32_t val = 0;
875
876 trng->stats.bytes_reseed = 0;
877 trng->stats.elapsed_seed_life = 0;
878
879 if (trng->usr_cfg.df_disable)
880 trng->len = TRNG_SEED_LEN;
881 else
882 trng->len = (mul + 1) * BYTES_PER_BLOCK;
883
884 if (trng->usr_cfg.df_disable) {
885 if (trng_reseed_internal_nodf(trng, eseed, str))
886 goto error;
887 } else {
888 if (trng_reseed_internal_df(trng, eseed, str))
889 goto error;
890 }
891
892 /*
893 * Set PRNGMODE to reseed and seed source (PRNGXS) to
894 * TRNG_EXT_SEED_*; the latter especially also for HRNG due to
895 * not being able to selected entropy source as seed source.
896 */
897 trng_write32(trng->cfg.addr, TRNG_CTRL,
898 PRNGMODE_RESEED | TRNG_CTRL_PRNGXS_MASK);
899
900 /* Start the reseed operation */
901 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
902 TRNG_CTRL_PRNGSTART_MASK,
903 TRNG_CTRL_PRNGSTART_MASK);
904
905 /* Wait for reseed operation */
906 if (trng_wait_for_event(trng->cfg.addr, TRNG_STATUS,
907 TRNG_STATUS_DONE_MASK,
908 TRNG_STATUS_DONE_MASK,
909 TRNG_RESEED_TIMEOUT))
910 goto error;
911
912 /* Check SP800 - 90B (entropy health test error) */
913 val = trng_read32(trng->cfg.addr, TRNG_STATUS) & TRNG_STATUS_CERTF_MASK;
914 if (val == TRNG_STATUS_CERTF_MASK)
915 goto error;
916
917 /* Stop reseed operation */
918 trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSTART_MASK, 0);
919 return TEE_SUCCESS;
920 error:
921 trng->status = TRNG_ERROR;
922 return TEE_ERROR_GENERIC;
923 }
924 #else
trng_df_algorithm(struct versal_trng * trng __unused,uint8_t * dfout __unused,uint32_t flag __unused,const uint8_t * pstr __unused)925 static void trng_df_algorithm(struct versal_trng *trng __unused,
926 uint8_t *dfout __unused,
927 uint32_t flag __unused,
928 const uint8_t *pstr __unused)
929
930 {
931 panic();
932 }
933
trng_v1_reseed_internal(struct versal_trng * trng __unused,uint8_t * eseed __unused,uint8_t * str __unused,uint32_t mul __unused)934 static TEE_Result trng_v1_reseed_internal(struct versal_trng *trng __unused,
935 uint8_t *eseed __unused,
936 uint8_t *str __unused,
937 uint32_t mul __unused)
938 {
939 return TEE_ERROR_NOT_SUPPORTED;
940 }
941 #endif
942
trng_reseed_internal(struct versal_trng * trng,uint8_t * eseed,uint8_t * str,uint32_t mul)943 static TEE_Result trng_reseed_internal(struct versal_trng *trng,
944 uint8_t *eseed, uint8_t *str,
945 uint32_t mul)
946 {
947 if (IS_ENABLED(CFG_VERSAL_RNG_V1) && trng->cfg.version == TRNG_V1)
948 return trng_v1_reseed_internal(trng, eseed, str, mul);
949 if (IS_ENABLED(CFG_VERSAL_RNG_V2) && trng->cfg.version == TRNG_V2)
950 return trng_v2_reseed_internal(trng, eseed, str, mul);
951
952 return TEE_ERROR_GENERIC;
953 }
954
trng_instantiate(struct versal_trng * trng,const struct trng_usr_cfg * usr_cfg)955 static TEE_Result trng_instantiate(struct versal_trng *trng,
956 const struct trng_usr_cfg *usr_cfg)
957 {
958 uint8_t *seed = NULL;
959 uint8_t *pers = NULL;
960
961 if (!trng)
962 return TEE_ERROR_GENERIC;
963
964 if (!usr_cfg)
965 goto error;
966
967 if (trng->status != TRNG_UNINITIALIZED)
968 goto error;
969
970 if (usr_cfg->mode != TRNG_HRNG && usr_cfg->mode != TRNG_DRNG &&
971 usr_cfg->mode != TRNG_PTRNG)
972 goto error;
973
974 if (usr_cfg->mode != TRNG_PTRNG && !usr_cfg->seed_life)
975 goto error;
976
977 if (IS_ENABLED(CFG_VERSAL_RNG_V2) && trng->cfg.version == TRNG_V2 &&
978 usr_cfg->mode != TRNG_PTRNG)
979 if (usr_cfg->seed_life < TRNG_V2_MIN_SEEDLIFE ||
980 usr_cfg->seed_life > TRNG_V2_MAX_SEEDLIFE)
981 goto error;
982
983 if (!usr_cfg->iseed_en && usr_cfg->mode == TRNG_DRNG)
984 goto error;
985
986 if (usr_cfg->iseed_en && usr_cfg->mode == TRNG_HRNG)
987 goto error;
988
989 if (IS_ENABLED(CFG_VERSAL_RNG_V1) && trng->cfg.version == TRNG_V1 &&
990 !usr_cfg->df_disable &&
991 (usr_cfg->dfmul < TRNG_MIN_DFLENMULT ||
992 usr_cfg->dfmul > TRNG_MAX_DFLENMULT))
993 goto error;
994 if (IS_ENABLED(CFG_VERSAL_RNG_V2) && trng->cfg.version == TRNG_V2 &&
995 (usr_cfg->df_disable ||
996 (usr_cfg->dfmul < TRNG_V2_MIN_DFLENMULT ||
997 usr_cfg->dfmul > TRNG_V2_MAX_DFLENMULT)))
998 goto error;
999
1000 if (usr_cfg->df_disable && usr_cfg->dfmul)
1001 goto error;
1002
1003 if (usr_cfg->mode == TRNG_PTRNG &&
1004 (usr_cfg->iseed_en || usr_cfg->pstr_en ||
1005 usr_cfg->predict_en || usr_cfg->seed_life))
1006 goto error;
1007
1008 memcpy(&trng->usr_cfg, usr_cfg, sizeof(struct trng_usr_cfg));
1009 trng_reset(trng);
1010
1011 if (trng->usr_cfg.iseed_en)
1012 seed = (void *)trng->usr_cfg.init_seed;
1013
1014 if (trng->usr_cfg.pstr_en)
1015 pers = (void *)trng->usr_cfg.pstr;
1016
1017 if (trng->usr_cfg.mode != TRNG_PTRNG) {
1018 if (trng_reseed_internal(trng, seed, pers, trng->usr_cfg.dfmul))
1019 goto error;
1020 }
1021
1022 trng->status = TRNG_HEALTHY;
1023 return TEE_SUCCESS;
1024 error:
1025 trng->status = TRNG_ERROR;
1026 return TEE_ERROR_GENERIC;
1027 }
1028
trng_reseed(struct versal_trng * trng,uint8_t * eseed,uint32_t mul)1029 static TEE_Result trng_reseed(struct versal_trng *trng, uint8_t *eseed,
1030 uint32_t mul)
1031 {
1032 if (!trng)
1033 return TEE_ERROR_GENERIC;
1034
1035 if (trng->status != TRNG_HEALTHY)
1036 goto error;
1037
1038 if (trng->usr_cfg.mode != TRNG_DRNG && trng->usr_cfg.mode != TRNG_HRNG)
1039 goto error;
1040
1041 if (trng->usr_cfg.mode == TRNG_DRNG && !eseed)
1042 goto error;
1043
1044 if (trng->usr_cfg.mode != TRNG_DRNG && eseed)
1045 goto error;
1046
1047 if (IS_ENABLED(CFG_VERSAL_RNG_V1) && trng->cfg.version == TRNG_V1 &&
1048 !trng->usr_cfg.df_disable) {
1049 if (mul < TRNG_MIN_DFLENMULT || mul > TRNG_MAX_DFLENMULT)
1050 goto error;
1051 }
1052 if (IS_ENABLED(CFG_VERSAL_RNG_V2) && trng->cfg.version == TRNG_V2 &&
1053 (trng->usr_cfg.df_disable ||
1054 (mul < TRNG_V2_MIN_DFLENMULT || mul > TRNG_V2_MAX_DFLENMULT)))
1055 goto error;
1056
1057 if (trng->usr_cfg.df_disable && mul)
1058 goto error;
1059
1060 if (IS_ENABLED(CFG_VERSAL_RNG_V1) && trng->cfg.version == TRNG_V1 &&
1061 eseed && (trng->len > TRNG_SEED_LEN ||
1062 !memcmp(eseed, trng->usr_cfg.init_seed, trng->len)))
1063 goto error;
1064
1065 if (trng_reseed_internal(trng, eseed, NULL, mul))
1066 goto error;
1067
1068 return TEE_SUCCESS;
1069 error:
1070 trng->status = TRNG_ERROR;
1071 return TEE_ERROR_GENERIC;
1072 }
1073
trng_generate(struct versal_trng * trng,uint8_t * buf,size_t blen,bool predict)1074 static TEE_Result trng_generate(struct versal_trng *trng, uint8_t *buf,
1075 size_t blen, bool predict)
1076 {
1077 uint32_t len = TRNG_SEC_STRENGTH_LEN;
1078 uint8_t *p = buf;
1079 uint32_t mul = 0;
1080
1081 if (!trng)
1082 return TEE_ERROR_GENERIC;
1083
1084 if (!p)
1085 goto error;
1086
1087 if (blen < TRNG_SEC_STRENGTH_LEN)
1088 goto error;
1089
1090 if (trng->status != TRNG_HEALTHY)
1091 goto error;
1092
1093 if (trng->usr_cfg.mode == TRNG_PTRNG && predict)
1094 goto error;
1095
1096 if (!trng->usr_cfg.predict_en && predict)
1097 goto error;
1098
1099 switch (trng->usr_cfg.mode) {
1100 case TRNG_HRNG:
1101 if (IS_ENABLED(CFG_VERSAL_RNG_V2) &&
1102 trng->cfg.version == TRNG_V2)
1103 mul = trng->usr_cfg.dfmul;
1104
1105 if (trng->stats.elapsed_seed_life >= trng->usr_cfg.seed_life) {
1106 if (trng_reseed_internal(trng, NULL, NULL, mul))
1107 goto error;
1108 }
1109
1110 if (predict && trng->stats.elapsed_seed_life > 0) {
1111 if (trng_reseed_internal(trng, NULL, NULL, mul))
1112 goto error;
1113 }
1114
1115 if (IS_ENABLED(CFG_VERSAL_RNG_V1) &&
1116 trng->cfg.version == TRNG_V1)
1117 trng_write32(trng->cfg.addr, TRNG_CTRL,
1118 PRNGMODE_GEN | TRNG_CTRL_PRNGXS_MASK);
1119 break;
1120 case TRNG_DRNG:
1121 if (trng->stats.elapsed_seed_life >= trng->usr_cfg.seed_life) {
1122 EMSG("Reseeding required");
1123 goto error;
1124 }
1125
1126 if (predict && trng->stats.elapsed_seed_life > 0) {
1127 EMSG("Reseeding required");
1128 goto error;
1129 }
1130
1131 if (IS_ENABLED(CFG_VERSAL_RNG_V1) &&
1132 trng->cfg.version == TRNG_V1)
1133 trng_write32(trng->cfg.addr, TRNG_CTRL,
1134 PRNGMODE_GEN | TRNG_CTRL_PRNGXS_MASK);
1135 break;
1136 default:
1137 if (IS_ENABLED(CFG_VERSAL_RNG_V1) &&
1138 trng->cfg.version == TRNG_V1 &&
1139 !trng->usr_cfg.df_disable) {
1140 memset(&trng->dfin, 0, sizeof(trng->dfin));
1141 len = (trng->usr_cfg.dfmul + 1) * BYTES_PER_BLOCK;
1142 trng->len = len;
1143 p = trng->dfin.entropy;
1144 }
1145 /* Enable the 8 ring oscillators used for entropy source */
1146 trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK);
1147 if (IS_ENABLED(CFG_VERSAL_RNG_V1) &&
1148 trng->cfg.version == TRNG_V1) {
1149 trng_soft_reset(trng);
1150 trng_write32(trng->cfg.addr, TRNG_CTRL,
1151 TRNG_CTRL_EUMODE_MASK |
1152 TRNG_CTRL_TRSSEN_MASK);
1153 }
1154
1155 if (IS_ENABLED(CFG_VERSAL_RNG_V2) &&
1156 trng->cfg.version == TRNG_V2)
1157 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
1158 TRNG_CTRL_TRSSEN_MASK |
1159 TRNG_CTRL_EUMODE_MASK |
1160 TRNG_CTRL_PRNGXS_MASK,
1161 TRNG_CTRL_TRSSEN_MASK |
1162 TRNG_CTRL_EUMODE_MASK);
1163 break;
1164 }
1165
1166 if (trng_collect_random(trng, p, len))
1167 goto error;
1168
1169 trng->stats.bytes_reseed += len;
1170 trng->stats.bytes += len;
1171 trng->stats.elapsed_seed_life++;
1172
1173 if (IS_ENABLED(CFG_VERSAL_RNG_V1) && trng->cfg.version == TRNG_V1 &&
1174 !trng->usr_cfg.df_disable && trng->usr_cfg.mode == TRNG_PTRNG)
1175 trng_df_algorithm(trng, buf, DF_RAND, NULL);
1176
1177 return TEE_SUCCESS;
1178 error:
1179 if (trng->status != TRNG_CATASTROPHIC)
1180 trng->status = TRNG_ERROR;
1181
1182 return TEE_ERROR_GENERIC;
1183 }
1184
trng_release(struct versal_trng * trng)1185 static TEE_Result trng_release(struct versal_trng *trng)
1186 {
1187 if (!trng)
1188 return TEE_ERROR_GENERIC;
1189
1190 if (trng->status == TRNG_UNINITIALIZED)
1191 goto error;
1192
1193 trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, NULL);
1194 trng_write32_range(trng, TRNG_PER_STRING_0, TRNG_PERS_STR_REGS, NULL);
1195 trng_hold_reset(trng);
1196
1197 /* Clear the instance */
1198 memset(&trng->usr_cfg, 0, sizeof(trng->usr_cfg));
1199 memset(trng->buf, 0, sizeof(trng->buf));
1200 memset(trng->dfout, 0, sizeof(trng->dfout));
1201 trng->status = TRNG_UNINITIALIZED;
1202
1203 return TEE_SUCCESS;
1204 error:
1205 trng->status = TRNG_ERROR;
1206
1207 return TEE_ERROR_GENERIC;
1208 }
1209
1210 /* Health tests should be run when the configured mode is of PTRNG or HRNG */
trng_health_test(struct versal_trng * trng)1211 static TEE_Result trng_health_test(struct versal_trng *trng)
1212 {
1213 struct trng_usr_cfg tests = {
1214 .mode = TRNG_HRNG,
1215 .seed_life = 10,
1216 .dfmul = 7,
1217 .predict_en = false,
1218 .iseed_en = false,
1219 .pstr_en = false,
1220 .df_disable = false,
1221 };
1222
1223 if (trng_instantiate(trng, &tests))
1224 goto error;
1225
1226 if (trng_release(trng))
1227 goto error;
1228
1229 return TEE_SUCCESS;
1230 error:
1231 trng->status = TRNG_ERROR;
1232
1233 return TEE_ERROR_GENERIC;
1234 }
1235
1236 const uint8_t trng_pers_str[TRNG_PERS_STR_LEN] = {
1237 0xB2U, 0x80U, 0x7EU, 0x4CU, 0xD0U, 0xE4U, 0xE2U, 0xA9U,
1238 0x2FU, 0x1FU, 0x5DU, 0xC1U, 0xA2U, 0x1FU, 0x40U, 0xFCU,
1239 0x1FU, 0x24U, 0x5DU, 0x42U, 0x61U, 0x80U, 0xE6U, 0xE9U,
1240 0x71U, 0x05U, 0x17U, 0x5BU, 0xAFU, 0x70U, 0x30U, 0x18U,
1241 0xBCU, 0x23U, 0x18U, 0x15U, 0xCBU, 0xB8U, 0xA6U, 0x3EU,
1242 0x83U, 0xB8U, 0x4AU, 0xFEU, 0x38U, 0xFCU, 0x25U, 0x87U,
1243 };
1244
1245 #ifdef CFG_VERSAL_RNG_V1
1246 static const uint8_t trng_ext_seed[TRNG_SEED_LEN] = {
1247 0x3BU, 0xC3U, 0xEDU, 0x64U, 0xF4U, 0x80U, 0x1CU, 0xC7U,
1248 0x14U, 0xCCU, 0x35U, 0xEDU, 0x57U, 0x01U, 0x2AU, 0xE4U,
1249 0xBCU, 0xEFU, 0xDEU, 0xF6U, 0x7CU, 0x46U, 0xA6U, 0x34U,
1250 0xC6U, 0x79U, 0xE8U, 0x91U, 0x5DU, 0xB1U, 0xDBU, 0xA7U,
1251 0x49U, 0xA5U, 0xBBU, 0x4FU, 0xEDU, 0x30U, 0xB3U, 0x7BU,
1252 0xA9U, 0x8BU, 0xF5U, 0x56U, 0x4DU, 0x40U, 0x18U, 0x9FU,
1253 };
1254
1255 static const uint8_t trng_ext_reseed[TRNG_SEED_LEN] = {
1256 0xFDU, 0x85U, 0xA8U, 0x36U, 0xBBU, 0xA8U, 0x50U, 0x19U,
1257 0x88U, 0x1EU, 0x8CU, 0x6BU, 0xADU, 0x23U, 0xC9U, 0x06U,
1258 0x1AU, 0xDCU, 0x75U, 0x47U, 0x76U, 0x59U, 0xACU, 0xAEU,
1259 0xA8U, 0xE4U, 0xA0U, 0x1DU, 0xFEU, 0x07U, 0xA1U, 0x83U,
1260 0x2DU, 0xADU, 0x1CU, 0x13U, 0x6FU, 0x59U, 0xD7U, 0x0FU,
1261 0x86U, 0x53U, 0xA5U, 0xDCU, 0x11U, 0x86U, 0x63U, 0xD6U,
1262 };
1263
1264 static const uint8_t trng_expected_out[TRNG_GEN_LEN] = {
1265 0xEBU, 0xF6U, 0x97U, 0x6EU, 0x7EU, 0xF0U, 0x4AU, 0x34U,
1266 0xEEU, 0xF6U, 0xA8U, 0x1AU, 0x67U, 0x33U, 0xF2U, 0x3CU,
1267 0x27U, 0x24U, 0x7AU, 0x6DU, 0x0EU, 0x12U, 0xD7U, 0x42U,
1268 0x73U, 0xEDU, 0xDDU, 0x3FU, 0x07U, 0x23U, 0xD8U, 0x52U,
1269 };
1270 #endif
1271
1272 #ifdef CFG_VERSAL_RNG_V2
1273 #define TRNG_V2_KAT_SEED_LIFE 2
1274 #define TRNG_V2_KAT_DF_LEN 7
1275 #define TRNG_V2_KAT_SEED_LEN ((TRNG_V2_KAT_DF_LEN + 1) * BYTES_PER_BLOCK)
1276
1277 static const uint8_t trng_v2_ext_seed[TRNG_V2_KAT_SEED_LEN] = {
1278 0x3BU, 0xC3U, 0xEDU, 0x64U, 0xF4U, 0x80U, 0x1CU, 0xC7U,
1279 0x14U, 0xCCU, 0x35U, 0xEDU, 0x57U, 0x01U, 0x2AU, 0xE4U,
1280 0xBCU, 0xEFU, 0xDEU, 0xF6U, 0x7CU, 0x46U, 0xA6U, 0x34U,
1281 0xC6U, 0x79U, 0xE8U, 0x91U, 0x5DU, 0xB1U, 0xDBU, 0xA7U,
1282 0x49U, 0xA5U, 0xBBU, 0x4FU, 0xEDU, 0x30U, 0xB3U, 0x7BU,
1283 0xA9U, 0x8BU, 0xF5U, 0x56U, 0x4DU, 0x40U, 0x18U, 0x9FU,
1284 0x66U, 0x4EU, 0x39U, 0xC0U, 0x60U, 0xC8U, 0x8EU, 0xF4U,
1285 0x1CU, 0xB9U, 0x9DU, 0x7BU, 0x97U, 0x8BU, 0x69U, 0x62U,
1286 0x45U, 0x0CU, 0xD4U, 0x85U, 0xFCU, 0xDCU, 0x5AU, 0x2BU,
1287 0xFDU, 0xABU, 0x92U, 0x4AU, 0x12U, 0x52U, 0x7DU, 0x45U,
1288 0xD2U, 0x61U, 0x0AU, 0x06U, 0x74U, 0xA7U, 0x88U, 0x36U,
1289 0x4BU, 0xA2U, 0x65U, 0xEEU, 0x71U, 0x0BU, 0x5AU, 0x4EU,
1290 0x33U, 0xB2U, 0x7AU, 0x2EU, 0xC0U, 0xA6U, 0xF2U, 0x7DU,
1291 0xBDU, 0x7DU, 0xDFU, 0x07U, 0xBBU, 0xE2U, 0x86U, 0xFFU,
1292 0xF0U, 0x8EU, 0xA4U, 0xB1U, 0x46U, 0xDBU, 0xF7U, 0x8CU,
1293 0x3CU, 0x62U, 0x4DU, 0xF0U, 0x51U, 0x50U, 0xE7U, 0x85U
1294 };
1295
1296 static const uint8_t trng_v2_ext_reseed[TRNG_V2_KAT_SEED_LEN] = {
1297 0xDFU, 0x5EU, 0x4DU, 0x4FU, 0x38U, 0x9EU, 0x2AU, 0x3EU,
1298 0xF2U, 0xABU, 0x46U, 0xE3U, 0xA0U, 0x26U, 0x77U, 0x84U,
1299 0x0BU, 0x9DU, 0x29U, 0xB0U, 0x5DU, 0xCEU, 0xC8U, 0xC3U,
1300 0xF9U, 0x4DU, 0x32U, 0xF7U, 0xBAU, 0x6FU, 0xA3U, 0xB5U,
1301 0x35U, 0xCBU, 0xC7U, 0x5CU, 0x62U, 0x48U, 0x01U, 0x65U,
1302 0x3AU, 0xAAU, 0x34U, 0x2DU, 0x89U, 0x6EU, 0xEFU, 0x6FU,
1303 0x69U, 0x96U, 0xE7U, 0x84U, 0xDAU, 0xEFU, 0x4EU, 0xBEU,
1304 0x27U, 0x4EU, 0x9FU, 0x88U, 0xB1U, 0xA0U, 0x7FU, 0x83U,
1305 0xDBU, 0x4AU, 0xA9U, 0x42U, 0x01U, 0xF1U, 0x84U, 0x71U,
1306 0xA9U, 0xEFU, 0xB9U, 0xE8U, 0x7FU, 0x81U, 0xC7U, 0xC1U,
1307 0x6CU, 0x5EU, 0xACU, 0x00U, 0x47U, 0x34U, 0xA1U, 0x75U,
1308 0xC0U, 0xE8U, 0x7FU, 0x48U, 0x00U, 0x45U, 0xC9U, 0xE9U,
1309 0x41U, 0xE3U, 0x8DU, 0xD8U, 0x4AU, 0x63U, 0xC4U, 0x94U,
1310 0x77U, 0x59U, 0xD9U, 0x50U, 0x2AU, 0x1DU, 0x4CU, 0x47U,
1311 0x64U, 0xA6U, 0x66U, 0x60U, 0x16U, 0xE7U, 0x29U, 0xC0U,
1312 0xB1U, 0xCFU, 0x3BU, 0x3FU, 0x54U, 0x49U, 0x31U, 0xD4U
1313 };
1314
1315 static const uint8_t trng_v2_expected_out[TRNG_SEC_STRENGTH_LEN] = {
1316 0xEEU, 0xA7U, 0x5BU, 0xB6U, 0x2BU, 0x97U, 0xF0U, 0xC0U,
1317 0x0FU, 0xD6U, 0xABU, 0x13U, 0x00U, 0x87U, 0x7EU, 0xF4U,
1318 0x00U, 0x7FU, 0xD7U, 0x56U, 0xFEU, 0xE5U, 0xDFU, 0xA6U,
1319 0x55U, 0x5BU, 0xB2U, 0x86U, 0xDDU, 0x81U, 0x73U, 0xB2U
1320 };
1321 #endif
1322
trng_kat_test(struct versal_trng * trng)1323 static TEE_Result trng_kat_test(struct versal_trng *trng)
1324 {
1325 struct trng_usr_cfg tests = {
1326 .mode = TRNG_DRNG,
1327 .seed_life = 5,
1328 .dfmul = 2,
1329 .predict_en = false,
1330 .iseed_en = true,
1331 .pstr_en = true,
1332 .df_disable = false,
1333 };
1334 uint32_t seed_len = TRNG_SEED_LEN;
1335 const uint8_t *ext_seed = NULL;
1336 const uint8_t *ext_reseed = NULL;
1337 const uint8_t *expected_out = NULL;
1338 uint8_t out[TRNG_GEN_LEN] = { 0 };
1339
1340 if (!trng)
1341 return TEE_ERROR_GENERIC;
1342
1343 #ifdef CFG_VERSAL_RNG_V1
1344 if (trng->cfg.version == TRNG_V1) {
1345 ext_seed = trng_ext_seed;
1346 ext_reseed = trng_ext_reseed;
1347 expected_out = trng_expected_out;
1348 }
1349 #endif
1350
1351 #ifdef CFG_VERSAL_RNG_V2
1352 if (trng->cfg.version == TRNG_V2) {
1353 tests.seed_life = TRNG_V2_KAT_SEED_LIFE;
1354 tests.dfmul = TRNG_V2_KAT_DF_LEN;
1355
1356 seed_len = TRNG_V2_KAT_SEED_LEN;
1357 ext_seed = trng_v2_ext_seed;
1358 ext_reseed = trng_v2_ext_reseed;
1359 expected_out = trng_v2_expected_out;
1360 }
1361 #endif
1362
1363 memcpy(&tests.init_seed, ext_seed, seed_len);
1364 memcpy(tests.pstr, trng_pers_str, sizeof(trng_pers_str));
1365
1366 if (trng_instantiate(trng, &tests))
1367 goto error;
1368
1369 if (trng_reseed(trng, (uint8_t *)ext_reseed, tests.dfmul))
1370 goto error;
1371
1372 if (trng_generate(trng, out, sizeof(out), false))
1373 goto error;
1374
1375 if (memcmp(out, expected_out, TRNG_GEN_LEN)) {
1376 EMSG("K.A.T mismatch");
1377 goto error;
1378 }
1379
1380 if (trng_release(trng))
1381 goto error;
1382
1383 return TEE_SUCCESS;
1384 error:
1385 trng->status = TRNG_ERROR;
1386 return TEE_ERROR_GENERIC;
1387 }
1388
versal_trng_get_random_bytes(struct versal_trng * trng,void * buf,size_t len)1389 TEE_Result versal_trng_get_random_bytes(struct versal_trng *trng,
1390 void *buf, size_t len)
1391 {
1392 uint8_t random[TRNG_SEC_STRENGTH_LEN] = { 0 };
1393 uint8_t *p = buf;
1394 size_t i = 0;
1395
1396 for (i = 0; i < len / TRNG_SEC_STRENGTH_LEN; i++) {
1397 if (trng_generate(trng, p + i * TRNG_SEC_STRENGTH_LEN,
1398 TRNG_SEC_STRENGTH_LEN, false))
1399 panic();
1400 }
1401
1402 if (len % TRNG_SEC_STRENGTH_LEN) {
1403 if (trng_generate(trng, random, TRNG_SEC_STRENGTH_LEN,
1404 false))
1405 panic();
1406 memcpy(p + i * TRNG_SEC_STRENGTH_LEN, random,
1407 len % TRNG_SEC_STRENGTH_LEN);
1408 }
1409
1410 return TEE_SUCCESS;
1411 }
1412
versal_trng_hw_init(struct versal_trng * trng,struct trng_usr_cfg * usr_cfg)1413 TEE_Result versal_trng_hw_init(struct versal_trng *trng,
1414 struct trng_usr_cfg *usr_cfg)
1415 {
1416 trng->cfg.addr = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC,
1417 trng->cfg.base,
1418 trng->cfg.len);
1419 if (!trng->cfg.addr) {
1420 EMSG("Failed to map TRNG");
1421 panic();
1422 }
1423
1424 if (trng_kat_test(trng)) {
1425 EMSG("KAT Failed");
1426 panic();
1427 }
1428
1429 if (trng_health_test(trng)) {
1430 EMSG("RunHealthTest Failed");
1431 panic();
1432 }
1433
1434 if (trng_instantiate(trng, usr_cfg)) {
1435 EMSG("Driver instantiation Failed");
1436 panic();
1437 }
1438
1439 if (trng->usr_cfg.mode == TRNG_HRNG &&
1440 trng_reseed(trng, NULL, trng->usr_cfg.dfmul)) {
1441 EMSG("Reseed Failed");
1442 panic();
1443 }
1444
1445 return TEE_SUCCESS;
1446 }
1447 #endif
1448
1449 #ifdef CFG_VERSAL_RNG_PLM
1450 #define SEC_MODULE_SHIFT 8
1451 #define SEC_MODULE_ID 5
1452
1453 #define CRYPTO_API_ID(__x) ((SEC_MODULE_ID << SEC_MODULE_SHIFT) | (__x))
1454
1455 #define VERSAL_TRNG_GENERATE 22
1456
1457 #define TRNG_SEC_STRENGTH_LEN 32
1458
versal_plm_get_random_bytes(void * buf,size_t len)1459 static TEE_Result versal_plm_get_random_bytes(void *buf, size_t len)
1460 {
1461 uint32_t low = 0;
1462 uint32_t hi = 0;
1463 struct versal_ipi_cmd cmd = { };
1464 struct versal_mbox_mem p = { };
1465 TEE_Result ret = TEE_SUCCESS;
1466 uint32_t status = 0;
1467 uint32_t offset = 0;
1468
1469 ret = versal_mbox_alloc(TRNG_SEC_STRENGTH_LEN, NULL, &p);
1470 if (ret)
1471 return ret;
1472
1473 cmd.data[0] = CRYPTO_API_ID(VERSAL_TRNG_GENERATE);
1474 cmd.ibuf[0].mem = p;
1475
1476 reg_pair_from_64(virt_to_phys(p.buf), &hi, &low);
1477 cmd.data[1] = low;
1478 cmd.data[2] = hi;
1479
1480 while (len) {
1481 uint32_t _len = (uint32_t)TRNG_SEC_STRENGTH_LEN;
1482
1483 if (len < TRNG_SEC_STRENGTH_LEN)
1484 _len = (uint32_t)len;
1485
1486 cmd.data[3] = _len;
1487
1488 ret = versal_pmc_notify(&cmd, NULL, &status);
1489 if (ret)
1490 panic();
1491
1492 memcpy((uint8_t *)buf + offset, p.buf, _len);
1493
1494 offset += TRNG_SEC_STRENGTH_LEN;
1495 len -= _len;
1496 }
1497
1498 versal_mbox_free(&p);
1499 return ret;
1500 }
1501 #endif
1502
1503 #if !defined(PLATFORM_FLAVOR_net)
1504
1505 #define TRNG_BASE 0xF1230000
1506 #define TRNG_SIZE 0x10000
1507
1508 static struct versal_trng versal_trng = {
1509 .cfg.base = TRNG_BASE,
1510 .cfg.len = TRNG_SIZE,
1511 .cfg.version = TRNG_V1,
1512 };
1513
hw_get_random_bytes(void * buf,size_t len)1514 TEE_Result hw_get_random_bytes(void *buf, size_t len)
1515 {
1516 return versal_trng_get_random_bytes(&versal_trng, buf, len);
1517 }
1518
trng_hrng_mode_init(void)1519 static TEE_Result trng_hrng_mode_init(void)
1520 {
1521 /* configure in hybrid mode with derivative function enabled */
1522 struct trng_usr_cfg usr_cfg = {
1523 .mode = TRNG_HRNG,
1524 .seed_life = CFG_VERSAL_TRNG_SEED_LIFE,
1525 .predict_en = false,
1526 .df_disable = false,
1527 .dfmul = CFG_VERSAL_TRNG_DF_MUL,
1528 .iseed_en = false,
1529 .pstr_en = true,
1530 };
1531
1532 memcpy(usr_cfg.pstr, trng_pers_str, sizeof(trng_pers_str));
1533 return versal_trng_hw_init(&versal_trng, &usr_cfg);
1534 }
1535
1536 early_init(trng_hrng_mode_init);
1537
1538 #else
1539
hw_get_random_bytes(void * buf,size_t len)1540 TEE_Result hw_get_random_bytes(void *buf, size_t len)
1541 {
1542 return versal_plm_get_random_bytes(buf, len);
1543 }
1544
1545 #endif
1546