1 /*
2  * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include "util.h"
9 
10 #include "trng.h"
11 #include "fih.h"
12 
13 /* The average roll should be 4 by the CLT, and our secrets are usually 32
14  * bytes. Do 8 + 3 so there's a bit of extra. Should always be odd so the reseed
15  * oscillates between before and after the forward step.
16  */
17 #define RNG_CHUNK_BYTES  (11)
18 /* Reverse every between 0 and 7 bytes */
19 #define SHUFFLE_MASK     (0x7)
20 
bl_secure_memeql(const void * ptr1,const void * ptr2,size_t num)21 fih_int bl_secure_memeql(const void *ptr1, const void *ptr2, size_t num)
22 {
23     fih_int is_equal = FIH_SUCCESS;
24     size_t block_start;
25     size_t block_end;
26     size_t curr = 0;
27     uint8_t rnd[RNG_CHUNK_BYTES];
28     size_t rnd_curr_idx = sizeof(rnd);
29 
30     /* Do comparison. Every n bytes (where n is random between 1 and 9),
31      * reverse the direction.
32      */
33     while (curr < num) {
34         /* Only generate more entropy if we've run out */
35         if (rnd_curr_idx == sizeof(rnd)) {
36             bl1_trng_generate_random(rnd, sizeof(rnd));
37             rnd_curr_idx = 0;
38         }
39 
40         /* Forward case. Always at least one byte */
41         block_start = curr;
42         block_end = curr + (rnd[rnd_curr_idx++] & SHUFFLE_MASK) + 1;
43 
44         if (block_end > num) {
45             block_end = num;
46         }
47 
48         for (; curr < block_end; curr++) {
49             if (((uint8_t *)ptr1)[curr] != ((uint8_t *)ptr2)[curr]) {
50                 is_equal = FIH_FAILURE;
51             }
52         }
53 
54 
55         /* Only generate more entropy if we've run out */
56         if (rnd_curr_idx == sizeof(rnd)) {
57             bl1_trng_generate_random(rnd, sizeof(rnd));
58             rnd_curr_idx = 0;
59         }
60 
61         /* Reverse case. Always at least one byte */
62         block_start = curr;
63         block_end = curr + (rnd[rnd_curr_idx++] & SHUFFLE_MASK) + 1;
64 
65         if (block_end > num) {
66             block_end = num;
67         }
68 
69         for (curr = block_end - 1; curr >= block_start; curr--) {
70             if (((uint8_t *)ptr1)[curr] != ((uint8_t *)ptr2)[curr]) {
71                 is_equal = FIH_FAILURE;
72             }
73         }
74         curr = block_end;
75     }
76     if (curr != num) {
77         FIH_PANIC;
78     }
79 
80     FIH_RET(is_equal);
81 }
82 
bl_secure_memcpy(void * destination,const void * source,size_t num)83 fih_int bl_secure_memcpy(void *destination, const void *source, size_t num)
84 {
85     size_t block_start;
86     size_t block_end;
87     int64_t curr = 0;
88     uint8_t rnd[RNG_CHUNK_BYTES];
89     size_t rnd_curr_idx = sizeof(rnd);
90 
91     /* Do copy. Every n bytes (where n is random between 1 and 17), reverse the
92      * direction.
93      */
94     while (curr < num) {
95         /* Only generate more entropy if we've run out */
96         if (rnd_curr_idx == sizeof(rnd)) {
97             bl1_trng_generate_random(rnd, sizeof(rnd));
98             rnd_curr_idx = 0;
99         }
100 
101         /* Forward case */
102         bl1_trng_generate_random(rnd, sizeof(rnd));
103         block_start = curr;
104         block_end = curr + (rnd[rnd_curr_idx++] & SHUFFLE_MASK) + 1;
105 
106         if (block_end > num) {
107             block_end = num;
108         }
109 
110         for (; curr < block_end; curr++) {
111             ((uint8_t *)destination)[curr] = ((uint8_t *)source)[curr];
112         }
113 
114 
115         /* Only generate more entropy if we've run out */
116         if (rnd_curr_idx == sizeof(rnd)) {
117             bl1_trng_generate_random(rnd, sizeof(rnd));
118             rnd_curr_idx = 0;
119         }
120 
121         /* Reverse case */
122         block_start = curr;
123         block_end = curr + (rnd[rnd_curr_idx++] & SHUFFLE_MASK) + 1;
124 
125         if (block_end > num) {
126             block_end = num;
127         }
128 
129         for (curr = block_end - 1; block_start <= curr; curr--) {
130             ((uint8_t *)destination)[curr] = ((uint8_t *)source)[curr];
131         }
132         curr = block_end;
133     }
134     if (curr != num) {
135         FIH_PANIC;
136     }
137 
138     FIH_RET(FIH_SUCCESS);
139 }
140