Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbedtls by
havege.c
00001 /** 00002 * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 /* 00022 * The HAVEGE RNG was designed by Andre Seznec in 2002. 00023 * 00024 * http://www.irisa.fr/caps/projects/hipsor/publi.php 00025 * 00026 * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr 00027 */ 00028 00029 #if !defined(MBEDTLS_CONFIG_FILE) 00030 #include "mbedtls/config.h" 00031 #else 00032 #include MBEDTLS_CONFIG_FILE 00033 #endif 00034 00035 #if defined(MBEDTLS_HAVEGE_C) 00036 00037 #include "mbedtls/havege.h" 00038 #include "mbedtls/timing.h" 00039 00040 #include <string.h> 00041 00042 /* Implementation that should never be optimized out by the compiler */ 00043 static void mbedtls_zeroize( void *v, size_t n ) { 00044 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 00045 } 00046 00047 /* ------------------------------------------------------------------------ 00048 * On average, one iteration accesses two 8-word blocks in the havege WALK 00049 * table, and generates 16 words in the RES array. 00050 * 00051 * The data read in the WALK table is updated and permuted after each use. 00052 * The result of the hardware clock counter read is used for this update. 00053 * 00054 * 25 conditional tests are present. The conditional tests are grouped in 00055 * two nested groups of 12 conditional tests and 1 test that controls the 00056 * permutation; on average, there should be 6 tests executed and 3 of them 00057 * should be mispredicted. 00058 * ------------------------------------------------------------------------ 00059 */ 00060 00061 #define SWAP(X,Y) { int *T = X; X = Y; Y = T; } 00062 00063 #define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; 00064 #define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; 00065 00066 #define TST1_LEAVE U1++; } 00067 #define TST2_LEAVE U2++; } 00068 00069 #define ONE_ITERATION \ 00070 \ 00071 PTEST = PT1 >> 20; \ 00072 \ 00073 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ 00074 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ 00075 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ 00076 \ 00077 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ 00078 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ 00079 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ 00080 \ 00081 PTX = (PT1 >> 18) & 7; \ 00082 PT1 &= 0x1FFF; \ 00083 PT2 &= 0x1FFF; \ 00084 CLK = (int) mbedtls_timing_hardclock(); \ 00085 \ 00086 i = 0; \ 00087 A = &WALK[PT1 ]; RES[i++] ^= *A; \ 00088 B = &WALK[PT2 ]; RES[i++] ^= *B; \ 00089 C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ 00090 D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ 00091 \ 00092 IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ 00093 *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ 00094 *B = IN ^ U1; \ 00095 *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ 00096 *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ 00097 \ 00098 A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ 00099 B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ 00100 C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ 00101 D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ 00102 \ 00103 if( PTEST & 1 ) SWAP( A, C ); \ 00104 \ 00105 IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ 00106 *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ 00107 *B = IN; CLK = (int) mbedtls_timing_hardclock(); \ 00108 *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ 00109 *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ 00110 \ 00111 A = &WALK[PT1 ^ 4]; \ 00112 B = &WALK[PT2 ^ 1]; \ 00113 \ 00114 PTEST = PT2 >> 1; \ 00115 \ 00116 PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ 00117 PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ 00118 PTY = (PT2 >> 10) & 7; \ 00119 \ 00120 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ 00121 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ 00122 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ 00123 \ 00124 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ 00125 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ 00126 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ 00127 \ 00128 C = &WALK[PT1 ^ 5]; \ 00129 D = &WALK[PT2 ^ 5]; \ 00130 \ 00131 RES[i++] ^= *A; \ 00132 RES[i++] ^= *B; \ 00133 RES[i++] ^= *C; \ 00134 RES[i++] ^= *D; \ 00135 \ 00136 IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ 00137 *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ 00138 *B = IN ^ U2; \ 00139 *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ 00140 *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ 00141 \ 00142 A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ 00143 B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ 00144 C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ 00145 D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ 00146 \ 00147 IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ 00148 *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ 00149 *B = IN; \ 00150 *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ 00151 *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ 00152 \ 00153 PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ 00154 WALK[PT1 ^ PTX ^ 7] ) & (~1); \ 00155 PT1 ^= (PT2 ^ 0x10) & 0x10; \ 00156 \ 00157 for( n++, i = 0; i < 16; i++ ) \ 00158 hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; 00159 00160 /* 00161 * Entropy gathering function 00162 */ 00163 static void havege_fill( mbedtls_havege_state *hs ) 00164 { 00165 int i, n = 0; 00166 int U1, U2, *A, *B, *C, *D; 00167 int PT1, PT2, *WALK, RES[16]; 00168 int PTX, PTY, CLK, PTEST, IN; 00169 00170 WALK = hs->WALK; 00171 PT1 = hs->PT1; 00172 PT2 = hs->PT2; 00173 00174 PTX = U1 = 0; 00175 PTY = U2 = 0; 00176 00177 memset( RES, 0, sizeof( RES ) ); 00178 00179 while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) 00180 { 00181 ONE_ITERATION 00182 ONE_ITERATION 00183 ONE_ITERATION 00184 ONE_ITERATION 00185 } 00186 00187 hs->PT1 = PT1; 00188 hs->PT2 = PT2; 00189 00190 hs->offset[0] = 0; 00191 hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; 00192 } 00193 00194 /* 00195 * HAVEGE initialization 00196 */ 00197 void mbedtls_havege_init( mbedtls_havege_state *hs ) 00198 { 00199 memset( hs, 0, sizeof( mbedtls_havege_state ) ); 00200 00201 havege_fill( hs ); 00202 } 00203 00204 void mbedtls_havege_free( mbedtls_havege_state *hs ) 00205 { 00206 if( hs == NULL ) 00207 return; 00208 00209 mbedtls_zeroize( hs, sizeof( mbedtls_havege_state ) ); 00210 } 00211 00212 /* 00213 * HAVEGE rand function 00214 */ 00215 int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) 00216 { 00217 int val; 00218 size_t use_len; 00219 mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; 00220 unsigned char *p = buf; 00221 00222 while( len > 0 ) 00223 { 00224 use_len = len; 00225 if( use_len > sizeof(int) ) 00226 use_len = sizeof(int); 00227 00228 if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) 00229 havege_fill( hs ); 00230 00231 val = hs->pool[hs->offset[0]++]; 00232 val ^= hs->pool[hs->offset[1]++]; 00233 00234 memcpy( p, &val, use_len ); 00235 00236 len -= use_len; 00237 p += use_len; 00238 } 00239 00240 return( 0 ); 00241 } 00242 00243 #endif /* MBEDTLS_HAVEGE_C */
Generated on Tue Jul 12 2022 12:52:43 by
