blob: 69e5c3a41dc1ca79085a407d82cbfd2d8f57cb13 [file] [log] [blame]
Paul Bakkerf3b86c12011-01-27 15:24:17 +00001/**
2 * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
Paul Bakker5121ce52009-01-03 21:22:43 +00003 *
Manuel Pégourié-Gonnard6fb81872015-07-27 11:11:48 +02004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakkerb96f1542010-07-18 20:36:00 +000018 *
Manuel Pégourié-Gonnardfe446432015-03-06 13:17:10 +000019 * This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker5121ce52009-01-03 21:22:43 +000020 */
21/*
22 * The HAVEGE RNG was designed by Andre Seznec in 2002.
23 *
24 * http://www.irisa.fr/caps/projects/hipsor/publi.php
25 *
26 * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
27 */
28
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if !defined(MBEDTLS_CONFIG_FILE)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/config.h"
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020031#else
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020032#include MBEDTLS_CONFIG_FILE
Manuel Pégourié-Gonnardcef4ad22014-04-29 12:39:06 +020033#endif
Paul Bakker5121ce52009-01-03 21:22:43 +000034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_HAVEGE_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000036
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000037#include "mbedtls/havege.h"
38#include "mbedtls/timing.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000039
Gilles Peskined1800a72019-06-17 15:12:51 +020040#include <limits.h>
Paul Bakker23986e52011-04-24 08:57:21 +000041#include <string.h>
Paul Bakker23986e52011-04-24 08:57:21 +000042
Gilles Peskined1800a72019-06-17 15:12:51 +020043/* If int isn't capable of storing 2^32 distinct values, the code of this
44 * module may cause a processor trap or a miscalculation. If int is more
45 * than 32 bits, the code may not calculate the intended values. */
46#if INT_MIN + 1 != -0x7fffffff
47#error "The HAVEGE module requires int to be exactly 32 bits, with INT_MIN = -2^31."
48#endif
49#if UINT_MAX != 0xffffffff
50#error "The HAVEGE module requires unsigned to be exactly 32 bits."
51#endif
52
Paul Bakkera317a982014-06-18 16:44:11 +020053/* Implementation that should never be optimized out by the compiler */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020054static void mbedtls_zeroize( void *v, size_t n ) {
Paul Bakkera317a982014-06-18 16:44:11 +020055 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
56}
57
Paul Bakker5121ce52009-01-03 21:22:43 +000058/* ------------------------------------------------------------------------
59 * On average, one iteration accesses two 8-word blocks in the havege WALK
60 * table, and generates 16 words in the RES array.
61 *
62 * The data read in the WALK table is updated and permuted after each use.
63 * The result of the hardware clock counter read is used for this update.
64 *
65 * 25 conditional tests are present. The conditional tests are grouped in
66 * two nested groups of 12 conditional tests and 1 test that controls the
67 * permutation; on average, there should be 6 tests executed and 3 of them
68 * should be mispredicted.
69 * ------------------------------------------------------------------------
70 */
71
Gilles Peskine8850e2e2019-06-17 15:01:08 +020072#define SWAP(X,Y) { unsigned *T = (X); (X) = (Y); (Y) = T; }
Paul Bakker5121ce52009-01-03 21:22:43 +000073
74#define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
75#define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
76
77#define TST1_LEAVE U1++; }
78#define TST2_LEAVE U2++; }
79
80#define ONE_ITERATION \
81 \
82 PTEST = PT1 >> 20; \
83 \
84 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
85 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
86 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
87 \
88 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
89 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
90 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
91 \
92 PTX = (PT1 >> 18) & 7; \
93 PT1 &= 0x1FFF; \
94 PT2 &= 0x1FFF; \
Gilles Peskine8850e2e2019-06-17 15:01:08 +020095 CLK = (unsigned) mbedtls_timing_hardclock(); \
Paul Bakker5121ce52009-01-03 21:22:43 +000096 \
97 i = 0; \
98 A = &WALK[PT1 ]; RES[i++] ^= *A; \
99 B = &WALK[PT2 ]; RES[i++] ^= *B; \
100 C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \
101 D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \
102 \
103 IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \
104 *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \
105 *B = IN ^ U1; \
106 *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \
107 *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \
108 \
109 A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \
110 B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \
111 C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \
112 D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \
113 \
114 if( PTEST & 1 ) SWAP( A, C ); \
115 \
116 IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
117 *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
Gilles Peskine8850e2e2019-06-17 15:01:08 +0200118 *B = IN; CLK = (unsigned) mbedtls_timing_hardclock(); \
Paul Bakker5121ce52009-01-03 21:22:43 +0000119 *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
120 *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
121 \
122 A = &WALK[PT1 ^ 4]; \
123 B = &WALK[PT2 ^ 1]; \
124 \
125 PTEST = PT2 >> 1; \
126 \
127 PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \
128 PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \
129 PTY = (PT2 >> 10) & 7; \
130 \
131 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
132 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
133 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
134 \
135 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
136 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
137 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
138 \
139 C = &WALK[PT1 ^ 5]; \
140 D = &WALK[PT2 ^ 5]; \
141 \
142 RES[i++] ^= *A; \
143 RES[i++] ^= *B; \
144 RES[i++] ^= *C; \
145 RES[i++] ^= *D; \
146 \
147 IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \
148 *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \
149 *B = IN ^ U2; \
150 *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \
151 *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \
152 \
153 A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \
154 B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \
155 C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \
156 D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \
157 \
158 IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \
159 *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \
160 *B = IN; \
161 *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \
162 *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \
163 \
Paul Bakker66d5d072014-06-17 16:39:18 +0200164 PT1 = ( RES[( i - 8 ) ^ PTX] ^ \
Paul Bakker5121ce52009-01-03 21:22:43 +0000165 WALK[PT1 ^ PTX ^ 7] ) & (~1); \
166 PT1 ^= (PT2 ^ 0x10) & 0x10; \
167 \
168 for( n++, i = 0; i < 16; i++ ) \
Gilles Peskine8850e2e2019-06-17 15:01:08 +0200169 POOL[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i];
Paul Bakker5121ce52009-01-03 21:22:43 +0000170
171/*
172 * Entropy gathering function
173 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174static void havege_fill( mbedtls_havege_state *hs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000175{
Gilles Peskine8850e2e2019-06-17 15:01:08 +0200176 unsigned i, n = 0;
177 unsigned U1, U2, *A, *B, *C, *D;
178 unsigned PT1, PT2, *WALK, *POOL, RES[16];
179 unsigned PTX, PTY, CLK, PTEST, IN;
Paul Bakker5121ce52009-01-03 21:22:43 +0000180
Gilles Peskine8850e2e2019-06-17 15:01:08 +0200181 WALK = (unsigned *) hs->WALK;
182 POOL = (unsigned *) hs->pool;
Paul Bakker5121ce52009-01-03 21:22:43 +0000183 PT1 = hs->PT1;
184 PT2 = hs->PT2;
185
186 PTX = U1 = 0;
187 PTY = U2 = 0;
188
Simon Butcher65b1fa62016-05-23 23:18:26 +0100189 (void)PTX;
190
Paul Bakker5121ce52009-01-03 21:22:43 +0000191 memset( RES, 0, sizeof( RES ) );
192
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200193 while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000194 {
195 ONE_ITERATION
196 ONE_ITERATION
197 ONE_ITERATION
198 ONE_ITERATION
199 }
200
201 hs->PT1 = PT1;
202 hs->PT2 = PT2;
203
204 hs->offset[0] = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2;
Paul Bakker5121ce52009-01-03 21:22:43 +0000206}
207
208/*
209 * HAVEGE initialization
210 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200211void mbedtls_havege_init( mbedtls_havege_state *hs )
Paul Bakker5121ce52009-01-03 21:22:43 +0000212{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200213 memset( hs, 0, sizeof( mbedtls_havege_state ) );
Paul Bakker5121ce52009-01-03 21:22:43 +0000214
215 havege_fill( hs );
216}
217
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218void mbedtls_havege_free( mbedtls_havege_state *hs )
Paul Bakkera317a982014-06-18 16:44:11 +0200219{
220 if( hs == NULL )
221 return;
222
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200223 mbedtls_zeroize( hs, sizeof( mbedtls_havege_state ) );
Paul Bakkera317a982014-06-18 16:44:11 +0200224}
225
Paul Bakker5121ce52009-01-03 21:22:43 +0000226/*
227 * HAVEGE rand function
228 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200229int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len )
Paul Bakker5121ce52009-01-03 21:22:43 +0000230{
Paul Bakkera3d195c2011-11-27 21:07:34 +0000231 int val;
232 size_t use_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200233 mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng;
Paul Bakkera3d195c2011-11-27 21:07:34 +0000234 unsigned char *p = buf;
Paul Bakker5121ce52009-01-03 21:22:43 +0000235
Paul Bakkera3d195c2011-11-27 21:07:34 +0000236 while( len > 0 )
237 {
238 use_len = len;
239 if( use_len > sizeof(int) )
240 use_len = sizeof(int);
Paul Bakker5121ce52009-01-03 21:22:43 +0000241
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200242 if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE )
Paul Bakkera3d195c2011-11-27 21:07:34 +0000243 havege_fill( hs );
Paul Bakker5121ce52009-01-03 21:22:43 +0000244
Paul Bakkera3d195c2011-11-27 21:07:34 +0000245 val = hs->pool[hs->offset[0]++];
246 val ^= hs->pool[hs->offset[1]++];
247
248 memcpy( p, &val, use_len );
Paul Bakker9af723c2014-05-01 13:03:14 +0200249
Paul Bakkera3d195c2011-11-27 21:07:34 +0000250 len -= use_len;
251 p += use_len;
252 }
253
254 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000255}
256
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200257#endif /* MBEDTLS_HAVEGE_C */