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 (void)PTX; 00178 00179 memset( RES, 0, sizeof( RES ) ); 00180 00181 while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) 00182 { 00183 ONE_ITERATION 00184 ONE_ITERATION 00185 ONE_ITERATION 00186 ONE_ITERATION 00187 } 00188 00189 hs->PT1 = PT1; 00190 hs->PT2 = PT2; 00191 00192 hs->offset[0] = 0; 00193 hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; 00194 } 00195 00196 /* 00197 * HAVEGE initialization 00198 */ 00199 void mbedtls_havege_init( mbedtls_havege_state *hs ) 00200 { 00201 memset( hs, 0, sizeof( mbedtls_havege_state ) ); 00202 00203 havege_fill( hs ); 00204 } 00205 00206 void mbedtls_havege_free( mbedtls_havege_state *hs ) 00207 { 00208 if( hs == NULL ) 00209 return; 00210 00211 mbedtls_zeroize( hs, sizeof( mbedtls_havege_state ) ); 00212 } 00213 00214 /* 00215 * HAVEGE rand function 00216 */ 00217 int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) 00218 { 00219 int val; 00220 size_t use_len; 00221 mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; 00222 unsigned char *p = buf; 00223 00224 while( len > 0 ) 00225 { 00226 use_len = len; 00227 if( use_len > sizeof(int) ) 00228 use_len = sizeof(int); 00229 00230 if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) 00231 havege_fill( hs ); 00232 00233 val = hs->pool[hs->offset[0]++]; 00234 val ^= hs->pool[hs->offset[1]++]; 00235 00236 memcpy( p, &val, use_len ); 00237 00238 len -= use_len; 00239 p += use_len; 00240 } 00241 00242 return( 0 ); 00243 } 00244 00245 #endif /* MBEDTLS_HAVEGE_C */
Generated on Tue Jul 12 2022 17:25:42 by
