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 #include <arm.h>
55 #include <crypto/crypto.h>
56 #include <initcall.h>
57 #include <io.h>
58 #include <kernel/delay.h>
59 #include <kernel/panic.h>
60 #include <mm/core_mmu.h>
61 #include <platform_config.h>
62 #include <rng_support.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <tee/tee_cryp_utl.h>
66 #include <trace.h>
67
68 #define TRNG_BASE 0xF1230000
69 #define TRNG_SIZE 0x10000
70
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_PRNGSTART_MASK BIT(5)
81 #define TRNG_CTRL_PRNGXS_MASK BIT(3)
82 #define TRNG_CTRL_TRSSEN_MASK BIT(2)
83 #define TRNG_CTRL_PRNGSRST_MASK BIT(0)
84 #define TRNG_EXT_SEED_0 0x40
85 /*
86 * Below registers are not directly referenced in driver but are accessed
87 * with offset from TRNG_EXT_SEED_0
88 * Register: TRNG_EXT_SEED_1 0x00000044
89 * Register: TRNG_EXT_SEED_2 0x00000048
90 * Register: TRNG_EXT_SEED_3 0x0000004C
91 * Register: TRNG_EXT_SEED_4 0x00000050
92 * Register: TRNG_EXT_SEED_5 0x00000054
93 * Register: TRNG_EXT_SEED_6 0x00000058
94 * Register: TRNG_EXT_SEED_7 0x0000005C
95 * Register: TRNG_EXT_SEED_8 0x00000060
96 * Register: TRNG_EXT_SEED_9 0x00000064
97 * Register: TRNG_EXT_SEED_10 0x00000068
98 * Register: TRNG_EXT_SEED_11 0x0000006C
99 */
100 #define TRNG_PER_STRING_0 0x80
101 /*
102 * Below registers are not directly referenced in driver but are accessed
103 * with offset from TRNG_PER_STRING_0
104 * Register: TRNG_PER_STRING_1 0x00000084
105 * Register: TRNG_PER_STRING_2 0x00000088
106 * Register: TRNG_PER_STRING_3 0x0000008C
107 * Register: TRNG_PER_STRING_4 0x00000090
108 * Register: TRNG_PER_STRING_5 0x00000094
109 * Register: TRNG_PER_STRING_6 0x00000098
110 * Register: TRNG_PER_STRING_7 0x0000009C
111 * Register: TRNG_PER_STRING_8 0x000000A0
112 * Register: TRNG_PER_STRING_9 0x000000A4
113 * Register: TRNG_PER_STRING_10 0x000000A8
114 * Register: TRNG_PER_STRING_11 0x000000AC
115 */
116 #define TRNG_CORE_OUTPUT 0xC0
117 #define TRNG_RESET 0xD0
118 #define TRNG_RESET_VAL_MASK BIT(0)
119 #define TRNG_OSC_EN 0xD4
120 #define TRNG_OSC_EN_VAL_MASK BIT(0)
121
122 /* TRNG configuration */
123 #define TRNG_BURST_SIZE 16
124 #define TRNG_BURST_SIZE_BITS 128
125 #define TRNG_NUM_INIT_REGS 12
126 #define TRNG_REG_SIZE 32
127 #define TRNG_BYTES_PER_REG 4
128 #define TRNG_MAX_QCNT 4
129 #define TRNG_RESEED_TIMEOUT 15000
130 #define TRNG_GENERATE_TIMEOUT 8000
131 #define TRNG_MIN_DFLENMULT 2
132 #define TRNG_MAX_DFLENMULT 9
133 #define PRNGMODE_RESEED 0
134 #define PRNGMODE_GEN TRNG_CTRL_PRNGMODE_MASK
135 #define RESET_DELAY 10
136 #define TRNG_SEC_STRENGTH_LEN 32
137 #define TRNG_PERS_STR_REGS 12
138 #define TRNG_PERS_STR_LEN 48
139 #define TRNG_SEED_REGS 12
140 #define TRNG_SEED_LEN 48
141 #define TRNG_GEN_LEN 32
142 #define RAND_BUF_LEN 4
143 #define BYTES_PER_BLOCK 16
144 #define ALL_A_PATTERN_32 0xAAAAAAAA
145 #define ALL_5_PATTERN_32 0x55555555
146
147 /* Derivative function helper macros */
148 #define DF_SEED 0
149 #define DF_RAND 1
150 #define DF_IP_IV_LEN 4
151 #define DF_PAD_DATA_LEN 8
152 #define MAX_PRE_DF_LEN 160
153 #define MAX_PRE_DF_LEN_WORDS 40
154 #define DF_PERS_STR_LEN TRNG_PERS_STR_LEN
155 #define DF_PAD_VAL 0x80
156 #define DF_KEY_LEN 32
157 #define BLK_SIZE 16
158 #define MAX_ROUNDS 14
159
160 enum trng_status {
161 TRNG_UNINITIALIZED = 0,
162 TRNG_HEALTHY,
163 TRNG_ERROR,
164 TRNG_CATASTROPHIC
165 };
166
167 enum trng_mode {
168 TRNG_HRNG = 0,
169 TRNG_DRNG,
170 TRNG_PTRNG
171 };
172
173 struct trng_cfg {
174 paddr_t base;
175 vaddr_t addr;
176 size_t len;
177 };
178
179 struct trng_usr_cfg {
180 enum trng_mode mode;
181 uint64_t seed_life; /* number of TRNG requests per seed */
182 bool predict_en; /* enable prediction resistance */
183 bool pstr_en; /* enable personalization string */
184 uint32_t pstr[TRNG_PERS_STR_REGS];
185 bool iseed_en; /* enable an initial seed */
186 uint32_t init_seed[MAX_PRE_DF_LEN_WORDS];
187 uint32_t df_disable; /* disable the derivative function */
188 uint32_t dfmul; /* derivative function multiplier */
189 };
190
191 struct trng_stats {
192 uint64_t bytes;
193 uint64_t bytes_reseed;
194 uint64_t elapsed_seed_life;
195 };
196
197 /* block cipher derivative function algorithm */
198 struct trng_dfin {
199 uint32_t ivc[DF_IP_IV_LEN];
200 uint32_t val1;
201 uint32_t val2;
202 uint8_t entropy[MAX_PRE_DF_LEN]; /* input entropy */
203 uint8_t pstr[DF_PERS_STR_LEN]; /* personalization string */
204 uint8_t pad_data[DF_PAD_DATA_LEN]; /* pad to multiples of 16 bytes*/
205 };
206
207 struct versal_trng {
208 struct trng_cfg cfg;
209 struct trng_usr_cfg usr_cfg;
210 struct trng_stats stats;
211 enum trng_status status;
212 uint32_t buf[RAND_BUF_LEN]; /* buffer of random bits */
213 size_t len;
214 struct trng_dfin dfin;
215 uint8_t dfout[TRNG_SEED_LEN]; /* output of the DF operation */
216 };
217
218 /* Derivative function variables */
219 static unsigned char sbx1[256];
220 static unsigned char sbx2[256];
221 static unsigned char sbx3[256];
222 static unsigned char schedule[BLK_SIZE * (MAX_ROUNDS + 1)];
223 static unsigned int rounds;
224
rota4(uint8_t * a,uint8_t * b,uint8_t * c,uint8_t * d)225 static void rota4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d)
226 {
227 uint8_t t = *a;
228
229 *a = sbx1[*b];
230 *b = sbx1[*c];
231 *c = sbx1[*d];
232 *d = sbx1[t];
233 }
234
rota2(uint8_t * a,uint8_t * b)235 static void rota2(uint8_t *a, uint8_t *b)
236 {
237 uint8_t t = *a;
238
239 *a = sbx1[*b];
240 *b = sbx1[t];
241 }
242
sbox4(uint8_t * a,uint8_t * b,uint8_t * c,uint8_t * d)243 static void sbox4(uint8_t *a, uint8_t *b, uint8_t *c, uint8_t *d)
244 {
245 *a = sbx1[*a];
246 *b = sbx1[*b];
247 *c = sbx1[*c];
248 *d = sbx1[*d];
249 }
250
xorb(uint8_t * res,const uint8_t * in)251 static void xorb(uint8_t *res, const uint8_t *in)
252 {
253 size_t i = 0;
254
255 for (i = 0; i < BLK_SIZE; ++i)
256 res[i] ^= in[i];
257 }
258
set_key(uint8_t * res,const uint8_t * src,unsigned int roundval)259 static void set_key(uint8_t *res, const uint8_t *src, unsigned int roundval)
260 {
261 memcpy(res, src, BLK_SIZE);
262 xorb(res, schedule + roundval * BLK_SIZE);
263 }
264
mix_column_sbox(uint8_t * dst,const uint8_t * f)265 static void mix_column_sbox(uint8_t *dst, const uint8_t *f)
266 {
267 size_t i = 0;
268 size_t a = 0;
269 size_t b = 0;
270 size_t c = 0;
271 size_t d = 0;
272
273 for (i = 0; i < 4; i++) {
274 a = 4 * i;
275 b = (0x5 + a) % 16;
276 c = (0xa + a) % 16;
277 d = (0xf + a) % 16;
278 dst[0 + a] = sbx2[f[a]] ^ sbx3[f[b]] ^ sbx1[f[c]] ^ sbx1[f[d]];
279 dst[1 + a] = sbx1[f[a]] ^ sbx2[f[b]] ^ sbx3[f[c]] ^ sbx1[f[d]];
280 dst[2 + a] = sbx1[f[a]] ^ sbx1[f[b]] ^ sbx2[f[c]] ^ sbx3[f[d]];
281 dst[3 + a] = sbx3[f[a]] ^ sbx1[f[b]] ^ sbx1[f[c]] ^ sbx2[f[d]];
282 }
283 }
284
shift_row_sbox(uint8_t * f)285 static void shift_row_sbox(uint8_t *f)
286 {
287 sbox4(&f[0], &f[4], &f[8], &f[12]);
288 rota4(&f[1], &f[5], &f[9], &f[13]);
289 rota2(&f[2], &f[10]);
290 rota2(&f[6], &f[14]);
291 rota4(&f[15], &f[11], &f[7], &f[3]);
292 }
293
encrypt(uint8_t * in,uint8_t * out)294 static void encrypt(uint8_t *in, uint8_t *out)
295 {
296 uint8_t fa[BLK_SIZE] = { 0 };
297 uint8_t fb[BLK_SIZE] = { 0 };
298 size_t roundval = 0;
299
300 set_key(fa, in, 0);
301 for (roundval = 1; roundval < rounds; ++roundval) {
302 mix_column_sbox(fb, fa);
303 set_key(fa, fb, roundval);
304 }
305
306 shift_row_sbox(fa);
307 set_key(out, fa, roundval);
308 }
309
checksum(unsigned char * in,uint8_t * iv,int max_blk)310 static void checksum(unsigned char *in, uint8_t *iv, int max_blk)
311 {
312 while (max_blk > 0) {
313 xorb(iv, in);
314 encrypt(iv, iv);
315 in += BLK_SIZE;
316 max_blk -= 1;
317 }
318 }
319
setup_key(const unsigned char * k,size_t klen)320 static void setup_key(const unsigned char *k, size_t klen)
321 {
322 unsigned char rcon = 1;
323 size_t sch_size = 240;
324 size_t i = 0;
325
326 rounds = MAX_ROUNDS;
327 memcpy(schedule, k, klen);
328 for (i = klen; i < sch_size; i += 4) {
329 unsigned char t0 = 0;
330 unsigned char t1 = 0;
331 unsigned char t2 = 0;
332 unsigned char t3 = 0;
333 int ik = 0;
334
335 t0 = schedule[i - 4];
336 t1 = schedule[i - 3];
337 t2 = schedule[i - 2];
338 t3 = schedule[i - 1];
339 if (i % klen == 0) {
340 rota4(&t0, &t1, &t2, &t3);
341 t0 ^= rcon;
342 rcon = (rcon << 1) ^ (((rcon >> 7) & 1) * 0x1B);
343 } else if (i % klen == 16) {
344 sbox4(&t0, &t1, &t2, &t3);
345 }
346 ik = i - klen;
347 schedule[i + 0] = schedule[ik + 0] ^ t0;
348 schedule[i + 1] = schedule[ik + 1] ^ t1;
349 schedule[i + 2] = schedule[ik + 2] ^ t2;
350 schedule[i + 3] = schedule[ik + 3] ^ t3;
351 }
352 }
353
trng_df_init(void)354 static void trng_df_init(void)
355 {
356 const uint8_t sb[] = {
357 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01,
358 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d,
359 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4,
360 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
361 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7,
362 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
363 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e,
364 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
365 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb,
366 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb,
367 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
368 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
369 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c,
370 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d,
371 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a,
372 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
373 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3,
374 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
375 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a,
376 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
377 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e,
378 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
379 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9,
380 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
381 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99,
382 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
383 };
384 size_t i = 0;
385
386 memcpy(sbx1, sb, sizeof(sb));
387 for (i = 0; i < sizeof(sb); i++) {
388 sbx2[i] = (sb[i] << 1) ^ (((sb[i] >> 7) & 1) * 0x1B);
389 sbx3[i] = sbx2[i] ^ sb[i];
390 }
391 }
392
393 /*
394 * This function implements the Derivative Function by distilling the entropy
395 * available in its input into a smaller number of bits on the output.
396 * - per NIST SP80090A.
397 *
398 * The Block Cipher algorithm follows sections 10.3.2 and 10.3.3 of the
399 * NIST.SP.800-90Ar1 document
400 */
trng_df_algorithm(struct versal_trng * trng,uint8_t * dfout,uint32_t flag,const uint8_t * pstr)401 static void trng_df_algorithm(struct versal_trng *trng, uint8_t *dfout,
402 uint32_t flag, const uint8_t *pstr)
403 {
404 static bool df_init;
405 const uint8_t df_key[DF_KEY_LEN] = {
406 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
407 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
408 };
409 size_t dfin_len = sizeof(struct trng_dfin) + trng->len;
410 uint8_t *inp_blk = NULL;
411 uint8_t *out_blk = NULL;
412 uintptr_t reminder = 0;
413 size_t xfer_len = 0;
414 uint32_t index = 0;
415 uintptr_t src = 0;
416 uintptr_t dst = 0;
417 size_t offset = 0;
418
419 if (!df_init) {
420 trng_df_init();
421 df_init = true;
422 }
423
424 if (flag == DF_SEED)
425 trng->dfin.val2 = TEE_U32_TO_BIG_ENDIAN(TRNG_PERS_STR_LEN);
426 else
427 trng->dfin.val2 = TEE_U32_TO_BIG_ENDIAN(TRNG_GEN_LEN);
428
429 trng->dfin.pad_data[0] = DF_PAD_VAL;
430
431 if (!pstr) {
432 if (trng->len > (MAX_PRE_DF_LEN + TRNG_PERS_STR_LEN))
433 panic();
434
435 dfin_len = dfin_len - TRNG_PERS_STR_LEN - MAX_PRE_DF_LEN;
436 trng->dfin.val1 = TEE_U32_TO_BIG_ENDIAN(trng->len);
437
438 xfer_len = DF_PAD_DATA_LEN;
439 src = (uintptr_t)trng->dfin.pad_data;
440 offset = MAX_PRE_DF_LEN + TRNG_PERS_STR_LEN - trng->len;
441 } else {
442 if (trng->len > MAX_PRE_DF_LEN)
443 panic();
444
445 memcpy(trng->dfin.pstr, pstr, TRNG_PERS_STR_LEN);
446 dfin_len = dfin_len - MAX_PRE_DF_LEN;
447 trng->dfin.val1 = TEE_U32_TO_BIG_ENDIAN(trng->len +
448 TRNG_PERS_STR_LEN);
449 xfer_len = DF_PAD_DATA_LEN + TRNG_PERS_STR_LEN;
450 src = (uintptr_t)trng->dfin.pstr;
451 offset = MAX_PRE_DF_LEN - trng->len;
452 }
453
454 /* Move back into the dfin structure */
455 dst = src - offset;
456 reminder = (uintptr_t)&trng->dfin + sizeof(trng->dfin) - offset;
457 if (offset) {
458 if (xfer_len > offset)
459 panic("Overlapping data");
460
461 memcpy((void *)dst, (void *)src, xfer_len);
462 memset((void *)reminder, 0, offset);
463 }
464
465 /* DF algorithm - step 1 */
466 setup_key(df_key, DF_KEY_LEN);
467 for (index = 0; index < TRNG_SEED_LEN; index += BLK_SIZE) {
468 memset((void *)(trng->dfout + index), 0, BLK_SIZE);
469 trng->dfin.ivc[0] = TEE_U32_TO_BIG_ENDIAN(index / BLK_SIZE);
470 checksum((unsigned char *)&trng->dfin,
471 trng->dfout + index, dfin_len / BLK_SIZE);
472 }
473
474 /* DF algorithm - step 2 */
475 setup_key(trng->dfout, DF_KEY_LEN);
476 for (index = 0; index < TRNG_SEED_LEN; index += BLK_SIZE) {
477 if (!index)
478 inp_blk = &dfout[TRNG_SEC_STRENGTH_LEN];
479 else
480 inp_blk = &dfout[index - BLK_SIZE];
481
482 out_blk = &dfout[index];
483 encrypt(inp_blk, out_blk);
484 }
485 }
486
trng_read32(vaddr_t addr,size_t off)487 static uint32_t trng_read32(vaddr_t addr, size_t off)
488 {
489 return io_read32(addr + off);
490 }
491
trng_write32(vaddr_t addr,size_t off,uint32_t val)492 static void trng_write32(vaddr_t addr, size_t off, uint32_t val)
493 {
494 io_write32(addr + off, val);
495 }
496
trng_clrset32(vaddr_t addr,size_t off,uint32_t mask,uint32_t val)497 static void trng_clrset32(vaddr_t addr, size_t off, uint32_t mask, uint32_t val)
498 {
499 io_clrsetbits32(addr + off, mask, mask & val);
500 }
501
trng_write32_range(const struct versal_trng * trng,uint32_t start,uint32_t num_regs,const uint8_t * buf)502 static void trng_write32_range(const struct versal_trng *trng, uint32_t start,
503 uint32_t num_regs, const uint8_t *buf)
504 {
505 size_t off = 0;
506 uint32_t val = 0;
507 size_t cnt = 0;
508 size_t i = 0;
509
510 for (i = 0; i < num_regs; ++i) {
511 if (!buf) {
512 off = start + i * TRNG_BYTES_PER_REG;
513 trng_write32(trng->cfg.addr, off, 0);
514 continue;
515 }
516
517 val = 0;
518 for (cnt = 0; cnt < TRNG_BYTES_PER_REG; ++cnt)
519 val = (val << 8) | buf[i * TRNG_BYTES_PER_REG + cnt];
520
521 off = start + (TRNG_NUM_INIT_REGS - 1 - i) * TRNG_BYTES_PER_REG;
522 trng_write32(trng->cfg.addr, off, val);
523 }
524 }
525
trng_wait_for_event(vaddr_t addr,size_t off,uint32_t mask,uint32_t event,uint32_t time_out)526 static TEE_Result trng_wait_for_event(vaddr_t addr, size_t off, uint32_t mask,
527 uint32_t event, uint32_t time_out)
528 {
529 uint64_t tref = timeout_init_us(time_out);
530
531 do {
532 if (timeout_elapsed(tref))
533 break;
534 } while ((io_read32(addr + off) & mask) != event);
535
536 /* Normal world might have suspended the OP-TEE thread, check again */
537 if ((io_read32(addr + off) & mask) != event)
538 return TEE_ERROR_GENERIC;
539
540 return TEE_SUCCESS;
541 }
542
trng_soft_reset(const struct versal_trng * trng)543 static void trng_soft_reset(const struct versal_trng *trng)
544 {
545 trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSRST_MASK,
546 TRNG_CTRL_PRNGSRST_MASK);
547 udelay(RESET_DELAY);
548 trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSRST_MASK, 0);
549 }
550
trng_reset(const struct versal_trng * trng)551 static void trng_reset(const struct versal_trng *trng)
552 {
553 trng_write32(trng->cfg.addr, TRNG_RESET, TRNG_RESET_VAL_MASK);
554 udelay(RESET_DELAY);
555 trng_write32(trng->cfg.addr, TRNG_RESET, 0);
556 trng_soft_reset(trng);
557 }
558
trng_hold_reset(const struct versal_trng * trng)559 static void trng_hold_reset(const struct versal_trng *trng)
560 {
561 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
562 TRNG_CTRL_PRNGSRST_MASK, TRNG_CTRL_PRNGSRST_MASK);
563 trng_write32(trng->cfg.addr, TRNG_RESET, TRNG_RESET_VAL_MASK);
564 udelay(RESET_DELAY);
565 }
566
trng_check_seed(uint8_t * entropy,uint32_t len)567 static TEE_Result trng_check_seed(uint8_t *entropy, uint32_t len)
568 {
569 uint32_t *p = (void *)entropy;
570 size_t i = 0;
571
572 for (i = 0; i < len / sizeof(*p); i++) {
573 if (p[i] == ALL_A_PATTERN_32)
574 return TEE_ERROR_GENERIC;
575
576 if (p[i] == ALL_5_PATTERN_32)
577 return TEE_ERROR_GENERIC;
578 }
579
580 return TEE_SUCCESS;
581 }
582
trng_collect_random(struct versal_trng * trng,uint8_t * dst,size_t len)583 static TEE_Result trng_collect_random(struct versal_trng *trng, uint8_t *dst,
584 size_t len)
585 {
586 const size_t bursts = len / TRNG_BURST_SIZE;
587 const size_t words = TRNG_BURST_SIZE_BITS / TRNG_REG_SIZE;
588 uint32_t *p = (void *)dst;
589 size_t bcnt = 0;
590 size_t wcnt = 0;
591 size_t index = 0;
592 uint32_t val = 0;
593 bool match = false;
594
595 trng_clrset32(trng->cfg.addr, TRNG_CTRL,
596 TRNG_CTRL_PRNGSTART_MASK, TRNG_CTRL_PRNGSTART_MASK);
597
598 /*
599 * Loop as many times based on len requested. In each burst 128 bits
600 * are generated, which is reflected in QCNT value of 4 by hardware.
601 */
602 for (bcnt = 0; bcnt < bursts; bcnt++) {
603 if (trng_wait_for_event(trng->cfg.addr,
604 TRNG_STATUS, TRNG_STATUS_QCNT_MASK,
605 TRNG_MAX_QCNT << TRNG_STATUS_QCNT_SHIFT,
606 TRNG_GENERATE_TIMEOUT)) {
607 EMSG("Timeout waiting for randomness");
608 return TEE_ERROR_GENERIC;
609 }
610
611 /*
612 * DTF flag set during generate indicates catastrophic
613 * condition, which needs to be checked for every time unless we
614 * are in PTRNG mode
615 */
616 if (trng->usr_cfg.mode != TRNG_PTRNG) {
617 val = trng_read32(trng->cfg.addr, TRNG_STATUS);
618 if (val & TRNG_STATUS_DTF_MASK) {
619 EMSG("Catastrophic DFT error");
620 trng->status = TRNG_CATASTROPHIC;
621
622 return TEE_ERROR_GENERIC;
623 }
624 }
625 /*
626 * Read the core output register 4 times to consume the random
627 * data generated for every burst.
628 */
629 match = true;
630 for (wcnt = 0; wcnt < words; wcnt++) {
631 val = trng_read32(trng->cfg.addr, TRNG_CORE_OUTPUT);
632
633 if (bcnt > 0 && trng->buf[wcnt] != val)
634 match = false;
635
636 trng->buf[wcnt] = val;
637
638 if (dst) {
639 p[index] = TEE_U32_TO_BIG_ENDIAN(val);
640 index++;
641 }
642 }
643
644 if (bursts > 1 && bcnt > 0 && match) {
645 EMSG("Catastrophic software error");
646 trng->status = TRNG_CATASTROPHIC;
647 return TEE_ERROR_GENERIC;
648 }
649 }
650
651 return TEE_SUCCESS;
652 }
653
trng_reseed_internal_nodf(struct versal_trng * trng,uint8_t * eseed,uint8_t * str)654 static TEE_Result trng_reseed_internal_nodf(struct versal_trng *trng,
655 uint8_t *eseed, uint8_t *str)
656 {
657 uint8_t entropy[TRNG_SEED_LEN] = { 0 };
658 uint8_t *seed = NULL;
659
660 switch (trng->usr_cfg.mode) {
661 case TRNG_HRNG:
662 trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK);
663 trng_soft_reset(trng);
664 trng_write32(trng->cfg.addr, TRNG_CTRL,
665 TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK);
666
667 if (trng_collect_random(trng, entropy, TRNG_SEED_LEN))
668 return TEE_ERROR_GENERIC;
669
670 if (trng_check_seed(entropy, TRNG_SEED_LEN))
671 return TEE_ERROR_GENERIC;
672
673 seed = entropy;
674 break;
675 case TRNG_DRNG:
676 seed = eseed;
677 break;
678 default:
679 seed = NULL;
680 break;
681 }
682
683 trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, seed);
684 if (str)
685 trng_write32_range(trng, TRNG_PER_STRING_0, TRNG_PERS_STR_REGS,
686 str);
687
688 return TEE_SUCCESS;
689 }
690
trng_reseed_internal_df(struct versal_trng * trng,uint8_t * eseed,uint8_t * str)691 static TEE_Result trng_reseed_internal_df(struct versal_trng *trng,
692 uint8_t *eseed, uint8_t *str)
693 {
694 memset(&trng->dfin, 0, sizeof(trng->dfin));
695
696 switch (trng->usr_cfg.mode) {
697 case TRNG_HRNG:
698 trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK);
699 trng_soft_reset(trng);
700 trng_write32(trng->cfg.addr, TRNG_CTRL,
701 TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK);
702
703 if (trng_collect_random(trng, trng->dfin.entropy, trng->len))
704 return TEE_ERROR_GENERIC;
705
706 if (trng_check_seed(trng->dfin.entropy, trng->len))
707 return TEE_ERROR_GENERIC;
708 break;
709 case TRNG_DRNG:
710 memcpy(trng->dfin.entropy, eseed, trng->len);
711 break;
712 default:
713 break;
714 }
715
716 trng_df_algorithm(trng, trng->dfout, DF_SEED, str);
717 trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, trng->dfout);
718
719 return TEE_SUCCESS;
720 }
721
trng_reseed_internal(struct versal_trng * trng,uint8_t * eseed,uint8_t * str,uint32_t mul)722 static TEE_Result trng_reseed_internal(struct versal_trng *trng,
723 uint8_t *eseed, uint8_t *str,
724 uint32_t mul)
725 {
726 uint32_t val = 0;
727
728 trng->stats.bytes_reseed = 0;
729 trng->stats.elapsed_seed_life = 0;
730
731 if (trng->usr_cfg.df_disable)
732 trng->len = TRNG_SEED_LEN;
733 else
734 trng->len = (mul + 1) * BYTES_PER_BLOCK;
735
736 if (trng->usr_cfg.df_disable) {
737 if (trng_reseed_internal_nodf(trng, eseed, str))
738 goto error;
739 } else {
740 if (trng_reseed_internal_df(trng, eseed, str))
741 goto error;
742 }
743
744 trng_write32(trng->cfg.addr, TRNG_CTRL,
745 PRNGMODE_RESEED | TRNG_CTRL_PRNGXS_MASK);
746
747 /* Start the reseed operation */
748 trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSTART_MASK,
749 TRNG_CTRL_PRNGSTART_MASK);
750
751 if (trng_wait_for_event(trng->cfg.addr, TRNG_STATUS,
752 TRNG_STATUS_DONE_MASK, TRNG_STATUS_DONE_MASK,
753 TRNG_RESEED_TIMEOUT))
754 goto error;
755
756 /* Check SP800 - 90B (entropy health test error) */
757 val = trng_read32(trng->cfg.addr, TRNG_STATUS) & TRNG_STATUS_CERTF_MASK;
758 if (val == TRNG_STATUS_CERTF_MASK)
759 goto error;
760
761 trng_clrset32(trng->cfg.addr, TRNG_CTRL, TRNG_CTRL_PRNGSTART_MASK, 0);
762 return TEE_SUCCESS;
763 error:
764 trng->status = TRNG_ERROR;
765 return TEE_ERROR_GENERIC;
766 }
767
trng_instantiate(struct versal_trng * trng,const struct trng_usr_cfg * usr_cfg)768 static TEE_Result trng_instantiate(struct versal_trng *trng,
769 const struct trng_usr_cfg *usr_cfg)
770 {
771 uint8_t *seed = NULL;
772 uint8_t *pers = NULL;
773
774 if (!trng)
775 return TEE_ERROR_GENERIC;
776
777 if (!usr_cfg)
778 goto error;
779
780 if (trng->status != TRNG_UNINITIALIZED)
781 goto error;
782
783 if (usr_cfg->mode != TRNG_HRNG && usr_cfg->mode != TRNG_DRNG &&
784 usr_cfg->mode != TRNG_PTRNG)
785 goto error;
786
787 if (usr_cfg->mode != TRNG_PTRNG && !usr_cfg->seed_life)
788 goto error;
789
790 if (!usr_cfg->iseed_en && usr_cfg->mode == TRNG_DRNG)
791 goto error;
792
793 if (usr_cfg->iseed_en && usr_cfg->mode == TRNG_HRNG)
794 goto error;
795
796 if (!usr_cfg->df_disable &&
797 (usr_cfg->dfmul < TRNG_MIN_DFLENMULT ||
798 usr_cfg->dfmul > TRNG_MAX_DFLENMULT))
799 goto error;
800
801 if (usr_cfg->df_disable && usr_cfg->dfmul)
802 goto error;
803
804 if (usr_cfg->mode == TRNG_PTRNG &&
805 (usr_cfg->iseed_en || usr_cfg->pstr_en ||
806 usr_cfg->predict_en || usr_cfg->seed_life))
807 goto error;
808
809 memcpy(&trng->usr_cfg, usr_cfg, sizeof(struct trng_usr_cfg));
810 trng_reset(trng);
811
812 if (trng->usr_cfg.iseed_en)
813 seed = (void *)trng->usr_cfg.init_seed;
814
815 if (trng->usr_cfg.pstr_en)
816 pers = (void *)trng->usr_cfg.pstr;
817
818 if (trng->usr_cfg.mode != TRNG_PTRNG) {
819 if (trng_reseed_internal(trng, seed, pers, trng->usr_cfg.dfmul))
820 goto error;
821 }
822
823 trng->status = TRNG_HEALTHY;
824 return TEE_SUCCESS;
825 error:
826 trng->status = TRNG_ERROR;
827 return TEE_ERROR_GENERIC;
828 }
829
trng_reseed(struct versal_trng * trng,uint8_t * eseed,uint32_t mul)830 static TEE_Result trng_reseed(struct versal_trng *trng, uint8_t *eseed,
831 uint32_t mul)
832 {
833 if (!trng)
834 return TEE_ERROR_GENERIC;
835
836 if (trng->status != TRNG_HEALTHY)
837 goto error;
838
839 if (trng->usr_cfg.mode != TRNG_DRNG && trng->usr_cfg.mode != TRNG_HRNG)
840 goto error;
841
842 if (trng->usr_cfg.mode == TRNG_DRNG && !eseed)
843 goto error;
844
845 if (trng->usr_cfg.mode != TRNG_DRNG && eseed)
846 goto error;
847
848 if (!trng->usr_cfg.df_disable) {
849 if (mul < TRNG_MIN_DFLENMULT || mul > TRNG_MAX_DFLENMULT)
850 goto error;
851 }
852
853 if (trng->usr_cfg.df_disable && mul)
854 goto error;
855
856 if (eseed && !memcmp(eseed, trng->usr_cfg.init_seed, trng->len))
857 goto error;
858
859 if (trng_reseed_internal(trng, eseed, NULL, mul))
860 goto error;
861
862 return TEE_SUCCESS;
863 error:
864 trng->status = TRNG_ERROR;
865 return TEE_ERROR_GENERIC;
866 }
867
trng_generate(struct versal_trng * trng,uint8_t * buf,size_t blen,bool predict)868 static TEE_Result trng_generate(struct versal_trng *trng, uint8_t *buf,
869 size_t blen, bool predict)
870 {
871 uint32_t len = TRNG_SEC_STRENGTH_LEN;
872 uint8_t *p = buf;
873
874 if (!trng)
875 return TEE_ERROR_GENERIC;
876
877 if (!p)
878 goto error;
879
880 if (blen < TRNG_SEC_STRENGTH_LEN)
881 goto error;
882
883 if (trng->status != TRNG_HEALTHY)
884 goto error;
885
886 if (trng->usr_cfg.mode == TRNG_PTRNG && predict)
887 goto error;
888
889 if (!trng->usr_cfg.predict_en && predict)
890 goto error;
891
892 switch (trng->usr_cfg.mode) {
893 case TRNG_HRNG:
894 if (trng->stats.elapsed_seed_life >= trng->usr_cfg.seed_life) {
895 if (trng_reseed_internal(trng, NULL, NULL, 0))
896 goto error;
897 }
898
899 if (predict && trng->stats.elapsed_seed_life > 0) {
900 if (trng_reseed_internal(trng, NULL, NULL, 0))
901 goto error;
902 }
903
904 trng_write32(trng->cfg.addr, TRNG_CTRL, PRNGMODE_GEN);
905 break;
906 case TRNG_DRNG:
907 if (trng->stats.elapsed_seed_life > trng->usr_cfg.seed_life)
908 goto error;
909
910 if (predict && trng->stats.elapsed_seed_life > 0)
911 goto error;
912
913 trng_write32(trng->cfg.addr, TRNG_CTRL, PRNGMODE_GEN);
914 break;
915 default:
916 if (!trng->usr_cfg.df_disable) {
917 memset(&trng->dfin, 0, sizeof(trng->dfin));
918 len = (trng->usr_cfg.dfmul + 1) * BYTES_PER_BLOCK;
919 trng->len = len;
920 p = trng->dfin.entropy;
921 }
922 /* Enable the 8 ring oscillators used for entropy source */
923 trng_write32(trng->cfg.addr, TRNG_OSC_EN, TRNG_OSC_EN_VAL_MASK);
924 trng_soft_reset(trng);
925 trng_write32(trng->cfg.addr, TRNG_CTRL,
926 TRNG_CTRL_EUMODE_MASK | TRNG_CTRL_TRSSEN_MASK);
927 break;
928 }
929
930 if (trng_collect_random(trng, p, len))
931 goto error;
932
933 trng->stats.bytes_reseed += len;
934 trng->stats.bytes += len;
935 trng->stats.elapsed_seed_life++;
936
937 if (!trng->usr_cfg.df_disable && trng->usr_cfg.mode == TRNG_PTRNG)
938 trng_df_algorithm(trng, buf, DF_RAND, NULL);
939
940 return TEE_SUCCESS;
941 error:
942 if (trng->status != TRNG_CATASTROPHIC)
943 trng->status = TRNG_ERROR;
944
945 return TEE_ERROR_GENERIC;
946 }
947
trng_release(struct versal_trng * trng)948 static TEE_Result trng_release(struct versal_trng *trng)
949 {
950 if (!trng)
951 return TEE_ERROR_GENERIC;
952
953 if (trng->status == TRNG_UNINITIALIZED)
954 goto error;
955
956 trng_write32_range(trng, TRNG_EXT_SEED_0, TRNG_SEED_REGS, NULL);
957 trng_write32_range(trng, TRNG_PER_STRING_0, TRNG_PERS_STR_REGS, NULL);
958 trng_hold_reset(trng);
959
960 /* Clear the instance */
961 memset(&trng->usr_cfg, 0, sizeof(trng->usr_cfg));
962 memset(trng->buf, 0, sizeof(trng->buf));
963 memset(trng->dfout, 0, sizeof(trng->dfout));
964 trng->status = TRNG_UNINITIALIZED;
965
966 return TEE_SUCCESS;
967 error:
968 trng->status = TRNG_ERROR;
969
970 return TEE_ERROR_GENERIC;
971 }
972
973 /* Health tests should be run when the configured mode is of PTRNG or HRNG */
trng_health_test(struct versal_trng * trng)974 static TEE_Result trng_health_test(struct versal_trng *trng)
975 {
976 struct trng_usr_cfg tests = {
977 .mode = TRNG_HRNG,
978 .seed_life = 10,
979 .dfmul = 7,
980 .predict_en = false,
981 .iseed_en = false,
982 .pstr_en = false,
983 .df_disable = false,
984 };
985
986 if (trng_instantiate(trng, &tests))
987 goto error;
988
989 if (trng_release(trng))
990 goto error;
991
992 return TEE_SUCCESS;
993 error:
994 trng->status = TRNG_ERROR;
995
996 return TEE_ERROR_GENERIC;
997 }
998
999 /*
1000 * The KAT test should be run when the TRNG is configured in DRNG or HRNG mode.
1001 * If KAT fails, the driver has to be put in error state.
1002 */
trng_kat_test(struct versal_trng * trng)1003 static TEE_Result trng_kat_test(struct versal_trng *trng)
1004 {
1005 struct trng_usr_cfg tests = {
1006 .mode = TRNG_DRNG,
1007 .seed_life = 5,
1008 .dfmul = 2,
1009 .predict_en = false,
1010 .iseed_en = true,
1011 .pstr_en = true,
1012 .df_disable = false,
1013 };
1014 const uint8_t ext_seed[TRNG_SEED_LEN] = {
1015 0x3BU, 0xC3U, 0xEDU, 0x64U, 0xF4U, 0x80U, 0x1CU, 0xC7U,
1016 0x14U, 0xCCU, 0x35U, 0xEDU, 0x57U, 0x01U, 0x2AU, 0xE4U,
1017 0xBCU, 0xEFU, 0xDEU, 0xF6U, 0x7CU, 0x46U, 0xA6U, 0x34U,
1018 0xC6U, 0x79U, 0xE8U, 0x91U, 0x5DU, 0xB1U, 0xDBU, 0xA7U,
1019 0x49U, 0xA5U, 0xBBU, 0x4FU, 0xEDU, 0x30U, 0xB3U, 0x7BU,
1020 0xA9U, 0x8BU, 0xF5U, 0x56U, 0x4DU, 0x40U, 0x18U, 0x9FU,
1021 };
1022 const uint8_t pers_str[TRNG_PERS_STR_LEN] = {
1023 0xB2U, 0x80U, 0x7EU, 0x4CU, 0xD0U, 0xE4U, 0xE2U, 0xA9U,
1024 0x2FU, 0x1FU, 0x5DU, 0xC1U, 0xA2U, 0x1FU, 0x40U, 0xFCU,
1025 0x1FU, 0x24U, 0x5DU, 0x42U, 0x61U, 0x80U, 0xE6U, 0xE9U,
1026 0x71U, 0x05U, 0x17U, 0x5BU, 0xAFU, 0x70U, 0x30U, 0x18U,
1027 0xBCU, 0x23U, 0x18U, 0x15U, 0xCBU, 0xB8U, 0xA6U, 0x3EU,
1028 0x83U, 0xB8U, 0x4AU, 0xFEU, 0x38U, 0xFCU, 0x25U, 0x87U,
1029 };
1030 const uint8_t expected_out[TRNG_GEN_LEN] = {
1031 0x91U, 0x9AU, 0x6BU, 0x99U, 0xD5U, 0xBCU, 0x2CU, 0x11U,
1032 0x5FU, 0x3AU, 0xFCU, 0x0BU, 0x0EU, 0x7BU, 0xC7U, 0x69U,
1033 0x4DU, 0xE1U, 0xE5U, 0xFEU, 0x59U, 0x9EU, 0xAAU, 0x41U,
1034 0xD3U, 0x48U, 0xFDU, 0x3DU, 0xD2U, 0xC4U, 0x50U, 0x1EU,
1035 };
1036 uint8_t out[TRNG_GEN_LEN] = { 0 };
1037
1038 if (!trng)
1039 return TEE_ERROR_GENERIC;
1040
1041 memcpy(&tests.init_seed, ext_seed, sizeof(ext_seed));
1042 memcpy(tests.pstr, pers_str, sizeof(pers_str));
1043
1044 if (trng_instantiate(trng, &tests))
1045 goto error;
1046
1047 if (trng_generate(trng, out, sizeof(out), false))
1048 goto error;
1049
1050 if (memcmp(out, expected_out, TRNG_GEN_LEN)) {
1051 EMSG("K.A.T mismatch");
1052 goto error;
1053 }
1054
1055 if (trng_release(trng))
1056 goto error;
1057
1058 return TEE_SUCCESS;
1059 error:
1060 trng->status = TRNG_ERROR;
1061 return TEE_ERROR_GENERIC;
1062 }
1063
1064 static struct versal_trng versal_trng = {
1065 .cfg.base = TRNG_BASE,
1066 .cfg.len = TRNG_SIZE,
1067 };
1068
hw_get_random_bytes(void * buf,size_t len)1069 TEE_Result hw_get_random_bytes(void *buf, size_t len)
1070 {
1071 uint8_t random[TRNG_SEC_STRENGTH_LEN] = { 0 };
1072 uint8_t *p = buf;
1073 size_t i = 0;
1074
1075 for (i = 0; i < len / TRNG_SEC_STRENGTH_LEN; i++) {
1076 if (trng_generate(&versal_trng, p + i * TRNG_SEC_STRENGTH_LEN,
1077 TRNG_SEC_STRENGTH_LEN, false))
1078 panic();
1079 }
1080
1081 if (len % TRNG_SEC_STRENGTH_LEN) {
1082 if (trng_generate(&versal_trng, random, TRNG_SEC_STRENGTH_LEN,
1083 false))
1084 panic();
1085 memcpy(p + i * TRNG_SEC_STRENGTH_LEN, random,
1086 len % TRNG_SEC_STRENGTH_LEN);
1087 }
1088
1089 return TEE_SUCCESS;
1090 }
1091
plat_rng_init(void)1092 void plat_rng_init(void)
1093 {
1094 }
1095
trng_hrng_mode_init(void)1096 static TEE_Result trng_hrng_mode_init(void)
1097 {
1098 const uint8_t pers_str[TRNG_PERS_STR_LEN] = {
1099 0xB2, 0x80, 0x7E, 0x4C, 0xD0, 0xE4, 0xE2, 0xA9,
1100 0x2F, 0x1F, 0x5D, 0xC1, 0xA2, 0x1F, 0x40, 0xFC,
1101 0x1F, 0x24, 0x5D, 0x42, 0x61, 0x80, 0xE6, 0xE9,
1102 0x71, 0x05, 0x17, 0x5B, 0xAF, 0x70, 0x30, 0x18,
1103 0xBC, 0x23, 0x18, 0x15, 0xCB, 0xB8, 0xA6, 0x3E,
1104 0x83, 0xB8, 0x4A, 0xFE, 0x38, 0xFC, 0x25, 0x87,
1105 };
1106 /* configure in hybrid mode with derivative function enabled */
1107 struct trng_usr_cfg usr_cfg = {
1108 .mode = TRNG_HRNG,
1109 .seed_life = CFG_VERSAL_TRNG_SEED_LIFE,
1110 .predict_en = false,
1111 .df_disable = false,
1112 .dfmul = CFG_VERSAL_TRNG_DF_MUL,
1113 .iseed_en = false,
1114 .pstr_en = true,
1115 };
1116
1117 memcpy(usr_cfg.pstr, pers_str, TRNG_PERS_STR_LEN);
1118 versal_trng.cfg.addr = (vaddr_t)core_mmu_add_mapping(MEM_AREA_IO_SEC,
1119 versal_trng.cfg.base,
1120 versal_trng.cfg.len);
1121 if (!versal_trng.cfg.addr) {
1122 EMSG("Failed to map TRNG");
1123 panic();
1124 }
1125
1126 if (trng_kat_test(&versal_trng)) {
1127 EMSG("KAT Failed");
1128 panic();
1129 }
1130
1131 if (trng_health_test(&versal_trng)) {
1132 EMSG("RunHealthTest Failed");
1133 panic();
1134 }
1135
1136 if (trng_instantiate(&versal_trng, &usr_cfg)) {
1137 EMSG("Driver instantiation Failed");
1138 panic();
1139 }
1140
1141 if (trng_reseed(&versal_trng, NULL, usr_cfg.dfmul)) {
1142 EMSG("Reseed Failed");
1143 panic();
1144 }
1145
1146 return TEE_SUCCESS;
1147 }
1148
1149 driver_init(trng_hrng_mode_init);
1150