]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/mbedtls/library/havege.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / mbedtls / library / havege.c
1 /**\r
2  *  \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion\r
3  *\r
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\r
5  *  SPDX-License-Identifier: Apache-2.0\r
6  *\r
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may\r
8  *  not use this file except in compliance with the License.\r
9  *  You may obtain a copy of the License at\r
10  *\r
11  *  http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  *  Unless required by applicable law or agreed to in writing, software\r
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  *  See the License for the specific language governing permissions and\r
17  *  limitations under the License.\r
18  *\r
19  *  This file is part of mbed TLS (https://tls.mbed.org)\r
20  */\r
21 /*\r
22  *  The HAVEGE RNG was designed by Andre Seznec in 2002.\r
23  *\r
24  *  http://www.irisa.fr/caps/projects/hipsor/publi.php\r
25  *\r
26  *  Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr\r
27  */\r
28 \r
29 #if !defined(MBEDTLS_CONFIG_FILE)\r
30 #include "mbedtls/config.h"\r
31 #else\r
32 #include MBEDTLS_CONFIG_FILE\r
33 #endif\r
34 \r
35 #if defined(MBEDTLS_HAVEGE_C)\r
36 \r
37 #include "mbedtls/havege.h"\r
38 #include "mbedtls/timing.h"\r
39 #include "mbedtls/platform_util.h"\r
40 \r
41 #include <string.h>\r
42 \r
43 /* ------------------------------------------------------------------------\r
44  * On average, one iteration accesses two 8-word blocks in the havege WALK\r
45  * table, and generates 16 words in the RES array.\r
46  *\r
47  * The data read in the WALK table is updated and permuted after each use.\r
48  * The result of the hardware clock counter read is used  for this update.\r
49  *\r
50  * 25 conditional tests are present.  The conditional tests are grouped in\r
51  * two nested  groups of 12 conditional tests and 1 test that controls the\r
52  * permutation; on average, there should be 6 tests executed and 3 of them\r
53  * should be mispredicted.\r
54  * ------------------------------------------------------------------------\r
55  */\r
56 \r
57 #define SWAP(X,Y) { int *T = (X); (X) = (Y); (Y) = T; }\r
58 \r
59 #define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;\r
60 #define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;\r
61 \r
62 #define TST1_LEAVE U1++; }\r
63 #define TST2_LEAVE U2++; }\r
64 \r
65 #define ONE_ITERATION                                   \\r
66                                                         \\r
67     PTEST = PT1 >> 20;                                  \\r
68                                                         \\r
69     TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \\r
70     TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \\r
71     TST1_ENTER  TST1_ENTER  TST1_ENTER  TST1_ENTER      \\r
72                                                         \\r
73     TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \\r
74     TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \\r
75     TST1_LEAVE  TST1_LEAVE  TST1_LEAVE  TST1_LEAVE      \\r
76                                                         \\r
77     PTX = (PT1 >> 18) & 7;                              \\r
78     PT1 &= 0x1FFF;                                      \\r
79     PT2 &= 0x1FFF;                                      \\r
80     CLK = (int) mbedtls_timing_hardclock();                            \\r
81                                                         \\r
82     i = 0;                                              \\r
83     A = &WALK[PT1    ]; RES[i++] ^= *A;                 \\r
84     B = &WALK[PT2    ]; RES[i++] ^= *B;                 \\r
85     C = &WALK[PT1 ^ 1]; RES[i++] ^= *C;                 \\r
86     D = &WALK[PT2 ^ 4]; RES[i++] ^= *D;                 \\r
87                                                         \\r
88     IN = (*A >> (1)) ^ (*A << (31)) ^ CLK;              \\r
89     *A = (*B >> (2)) ^ (*B << (30)) ^ CLK;              \\r
90     *B = IN ^ U1;                                       \\r
91     *C = (*C >> (3)) ^ (*C << (29)) ^ CLK;              \\r
92     *D = (*D >> (4)) ^ (*D << (28)) ^ CLK;              \\r
93                                                         \\r
94     A = &WALK[PT1 ^ 2]; RES[i++] ^= *A;                 \\r
95     B = &WALK[PT2 ^ 2]; RES[i++] ^= *B;                 \\r
96     C = &WALK[PT1 ^ 3]; RES[i++] ^= *C;                 \\r
97     D = &WALK[PT2 ^ 6]; RES[i++] ^= *D;                 \\r
98                                                         \\r
99     if( PTEST & 1 ) SWAP( A, C );                       \\r
100                                                         \\r
101     IN = (*A >> (5)) ^ (*A << (27)) ^ CLK;              \\r
102     *A = (*B >> (6)) ^ (*B << (26)) ^ CLK;              \\r
103     *B = IN; CLK = (int) mbedtls_timing_hardclock();                   \\r
104     *C = (*C >> (7)) ^ (*C << (25)) ^ CLK;              \\r
105     *D = (*D >> (8)) ^ (*D << (24)) ^ CLK;              \\r
106                                                         \\r
107     A = &WALK[PT1 ^ 4];                                 \\r
108     B = &WALK[PT2 ^ 1];                                 \\r
109                                                         \\r
110     PTEST = PT2 >> 1;                                   \\r
111                                                         \\r
112     PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]);   \\r
113     PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8);  \\r
114     PTY = (PT2 >> 10) & 7;                              \\r
115                                                         \\r
116     TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \\r
117     TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \\r
118     TST2_ENTER  TST2_ENTER  TST2_ENTER  TST2_ENTER      \\r
119                                                         \\r
120     TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \\r
121     TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \\r
122     TST2_LEAVE  TST2_LEAVE  TST2_LEAVE  TST2_LEAVE      \\r
123                                                         \\r
124     C = &WALK[PT1 ^ 5];                                 \\r
125     D = &WALK[PT2 ^ 5];                                 \\r
126                                                         \\r
127     RES[i++] ^= *A;                                     \\r
128     RES[i++] ^= *B;                                     \\r
129     RES[i++] ^= *C;                                     \\r
130     RES[i++] ^= *D;                                     \\r
131                                                         \\r
132     IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK;             \\r
133     *A = (*B >> (10)) ^ (*B << (22)) ^ CLK;             \\r
134     *B = IN ^ U2;                                       \\r
135     *C = (*C >> (11)) ^ (*C << (21)) ^ CLK;             \\r
136     *D = (*D >> (12)) ^ (*D << (20)) ^ CLK;             \\r
137                                                         \\r
138     A = &WALK[PT1 ^ 6]; RES[i++] ^= *A;                 \\r
139     B = &WALK[PT2 ^ 3]; RES[i++] ^= *B;                 \\r
140     C = &WALK[PT1 ^ 7]; RES[i++] ^= *C;                 \\r
141     D = &WALK[PT2 ^ 7]; RES[i++] ^= *D;                 \\r
142                                                         \\r
143     IN = (*A >> (13)) ^ (*A << (19)) ^ CLK;             \\r
144     *A = (*B >> (14)) ^ (*B << (18)) ^ CLK;             \\r
145     *B = IN;                                            \\r
146     *C = (*C >> (15)) ^ (*C << (17)) ^ CLK;             \\r
147     *D = (*D >> (16)) ^ (*D << (16)) ^ CLK;             \\r
148                                                         \\r
149     PT1 = ( RES[( i - 8 ) ^ PTX] ^                      \\r
150             WALK[PT1 ^ PTX ^ 7] ) & (~1);               \\r
151     PT1 ^= (PT2 ^ 0x10) & 0x10;                         \\r
152                                                         \\r
153     for( n++, i = 0; i < 16; i++ )                      \\r
154         hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i];\r
155 \r
156 /*\r
157  * Entropy gathering function\r
158  */\r
159 static void havege_fill( mbedtls_havege_state *hs )\r
160 {\r
161     int i, n = 0;\r
162     int  U1,  U2, *A, *B, *C, *D;\r
163     int PT1, PT2, *WALK, RES[16];\r
164     int PTX, PTY, CLK, PTEST, IN;\r
165 \r
166     WALK = hs->WALK;\r
167     PT1  = hs->PT1;\r
168     PT2  = hs->PT2;\r
169 \r
170     PTX  = U1 = 0;\r
171     PTY  = U2 = 0;\r
172 \r
173     (void)PTX;\r
174 \r
175     memset( RES, 0, sizeof( RES ) );\r
176 \r
177     while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 )\r
178     {\r
179         ONE_ITERATION\r
180         ONE_ITERATION\r
181         ONE_ITERATION\r
182         ONE_ITERATION\r
183     }\r
184 \r
185     hs->PT1 = PT1;\r
186     hs->PT2 = PT2;\r
187 \r
188     hs->offset[0] = 0;\r
189     hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2;\r
190 }\r
191 \r
192 /*\r
193  * HAVEGE initialization\r
194  */\r
195 void mbedtls_havege_init( mbedtls_havege_state *hs )\r
196 {\r
197     memset( hs, 0, sizeof( mbedtls_havege_state ) );\r
198 \r
199     havege_fill( hs );\r
200 }\r
201 \r
202 void mbedtls_havege_free( mbedtls_havege_state *hs )\r
203 {\r
204     if( hs == NULL )\r
205         return;\r
206 \r
207     mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) );\r
208 }\r
209 \r
210 /*\r
211  * HAVEGE rand function\r
212  */\r
213 int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len )\r
214 {\r
215     int val;\r
216     size_t use_len;\r
217     mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng;\r
218     unsigned char *p = buf;\r
219 \r
220     while( len > 0 )\r
221     {\r
222         use_len = len;\r
223         if( use_len > sizeof(int) )\r
224             use_len = sizeof(int);\r
225 \r
226         if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE )\r
227             havege_fill( hs );\r
228 \r
229         val  = hs->pool[hs->offset[0]++];\r
230         val ^= hs->pool[hs->offset[1]++];\r
231 \r
232         memcpy( p, &val, use_len );\r
233 \r
234         len -= use_len;\r
235         p += use_len;\r
236     }\r
237 \r
238     return( 0 );\r
239 }\r
240 \r
241 #endif /* MBEDTLS_HAVEGE_C */\r