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.
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 #include "mbedtls/platform_util.h" 00040 00041 #include <string.h> 00042 00043 /* ------------------------------------------------------------------------ 00044 * On average, one iteration accesses two 8-word blocks in the havege WALK 00045 * table, and generates 16 words in the RES array. 00046 * 00047 * The data read in the WALK table is updated and permuted after each use. 00048 * The result of the hardware clock counter read is used for this update. 00049 * 00050 * 25 conditional tests are present. The conditional tests are grouped in 00051 * two nested groups of 12 conditional tests and 1 test that controls the 00052 * permutation; on average, there should be 6 tests executed and 3 of them 00053 * should be mispredicted. 00054 * ------------------------------------------------------------------------ 00055 */ 00056 00057 #define SWAP(X,Y) { int *T = X; X = Y; Y = T; } 00058 00059 #define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; 00060 #define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; 00061 00062 #define TST1_LEAVE U1++; } 00063 #define TST2_LEAVE U2++; } 00064 00065 #define ONE_ITERATION \ 00066 \ 00067 PTEST = PT1 >> 20; \ 00068 \ 00069 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ 00070 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ 00071 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ 00072 \ 00073 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ 00074 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ 00075 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ 00076 \ 00077 PTX = (PT1 >> 18) & 7; \ 00078 PT1 &= 0x1FFF; \ 00079 PT2 &= 0x1FFF; \ 00080 CLK = (int) mbedtls_timing_hardclock(); \ 00081 \ 00082 i = 0; \ 00083 A = &WALK[PT1 ]; RES[i++] ^= *A; \ 00084 B = &WALK[PT2 ]; RES[i++] ^= *B; \ 00085 C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ 00086 D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ 00087 \ 00088 IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ 00089 *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ 00090 *B = IN ^ U1; \ 00091 *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ 00092 *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ 00093 \ 00094 A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ 00095 B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ 00096 C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ 00097 D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ 00098 \ 00099 if( PTEST & 1 ) SWAP( A, C ); \ 00100 \ 00101 IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ 00102 *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ 00103 *B = IN; CLK = (int) mbedtls_timing_hardclock(); \ 00104 *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ 00105 *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ 00106 \ 00107 A = &WALK[PT1 ^ 4]; \ 00108 B = &WALK[PT2 ^ 1]; \ 00109 \ 00110 PTEST = PT2 >> 1; \ 00111 \ 00112 PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ 00113 PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ 00114 PTY = (PT2 >> 10) & 7; \ 00115 \ 00116 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ 00117 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ 00118 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ 00119 \ 00120 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ 00121 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ 00122 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ 00123 \ 00124 C = &WALK[PT1 ^ 5]; \ 00125 D = &WALK[PT2 ^ 5]; \ 00126 \ 00127 RES[i++] ^= *A; \ 00128 RES[i++] ^= *B; \ 00129 RES[i++] ^= *C; \ 00130 RES[i++] ^= *D; \ 00131 \ 00132 IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ 00133 *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ 00134 *B = IN ^ U2; \ 00135 *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ 00136 *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ 00137 \ 00138 A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ 00139 B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ 00140 C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ 00141 D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ 00142 \ 00143 IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ 00144 *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ 00145 *B = IN; \ 00146 *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ 00147 *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ 00148 \ 00149 PT1 = ( RES[( i - 8 ) ^ PTX] ^ \ 00150 WALK[PT1 ^ PTX ^ 7] ) & (~1); \ 00151 PT1 ^= (PT2 ^ 0x10) & 0x10; \ 00152 \ 00153 for( n++, i = 0; i < 16; i++ ) \ 00154 hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i]; 00155 00156 /* 00157 * Entropy gathering function 00158 */ 00159 static void havege_fill( mbedtls_havege_state *hs ) 00160 { 00161 int i, n = 0; 00162 int U1, U2, *A, *B, *C, *D; 00163 int PT1, PT2, *WALK, RES[16]; 00164 int PTX, PTY, CLK, PTEST, IN; 00165 00166 WALK = hs->WALK; 00167 PT1 = hs->PT1; 00168 PT2 = hs->PT2; 00169 00170 PTX = U1 = 0; 00171 PTY = U2 = 0; 00172 00173 (void)PTX; 00174 00175 memset( RES, 0, sizeof( RES ) ); 00176 00177 while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 ) 00178 { 00179 ONE_ITERATION 00180 ONE_ITERATION 00181 ONE_ITERATION 00182 ONE_ITERATION 00183 } 00184 00185 hs->PT1 = PT1; 00186 hs->PT2 = PT2; 00187 00188 hs->offset[0] = 0; 00189 hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2; 00190 } 00191 00192 /* 00193 * HAVEGE initialization 00194 */ 00195 void mbedtls_havege_init( mbedtls_havege_state *hs ) 00196 { 00197 memset( hs, 0, sizeof( mbedtls_havege_state ) ); 00198 00199 havege_fill( hs ); 00200 } 00201 00202 void mbedtls_havege_free( mbedtls_havege_state *hs ) 00203 { 00204 if( hs == NULL ) 00205 return; 00206 00207 mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) ); 00208 } 00209 00210 /* 00211 * HAVEGE rand function 00212 */ 00213 int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len ) 00214 { 00215 int val; 00216 size_t use_len; 00217 mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng; 00218 unsigned char *p = buf; 00219 00220 while( len > 0 ) 00221 { 00222 use_len = len; 00223 if( use_len > sizeof(int) ) 00224 use_len = sizeof(int); 00225 00226 if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE ) 00227 havege_fill( hs ); 00228 00229 val = hs->pool[hs->offset[0]++]; 00230 val ^= hs->pool[hs->offset[1]++]; 00231 00232 memcpy( p, &val, use_len ); 00233 00234 len -= use_len; 00235 p += use_len; 00236 } 00237 00238 return( 0 ); 00239 } 00240 00241 #endif /* MBEDTLS_HAVEGE_C */
Generated on Tue Jul 12 2022 12:44:20 by
