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-2014, Brainspark B.V. 00005 * 00006 * This file is part of PolarSSL (http://www.polarssl.org) 00007 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org> 00008 * 00009 * All rights reserved. 00010 * 00011 * This program is free software; you can redistribute it and/or modify 00012 * it under the terms of the GNU General Public License as published by 00013 * the Free Software Foundation; either version 2 of the License, or 00014 * (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License along 00022 * with this program; if not, write to the Free Software Foundation, Inc., 00023 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00024 */ 00025 /* 00026 * The HAVEGE RNG was designed by Andre Seznec in 2002. 00027 * 00028 * http://www.irisa.fr/caps/projects/hipsor/publi.php 00029 * 00030 * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr 00031 */ 00032 00033 #if !defined(POLARSSL_CONFIG_FILE) 00034 #include "polarssl/config.h" 00035 #else 00036 #include POLARSSL_CONFIG_FILE 00037 #endif 00038 00039 #if defined(POLARSSL_HAVEGE_C) 00040 00041 #include "polarssl/havege.h" 00042 #include "polarssl/timing.h" 00043 00044 #include <string.h> 00045 00046 /* ------------------------------------------------------------------------ 00047 * On average, one iteration accesses two 8-word blocks in the havege WALK 00048 * table, and generates 16 words in the RES array. 00049 * 00050 * The data read in the WALK table is updated and permuted after each use. 00051 * The result of the hardware clock counter read is used for this update. 00052 * 00053 * 25 conditional tests are present. The conditional tests are grouped in 00054 * two nested groups of 12 conditional tests and 1 test that controls the 00055 * permutation; on average, there should be 6 tests executed and 3 of them 00056 * should be mispredicted. 00057 * ------------------------------------------------------------------------ 00058 */ 00059 00060 #define SWAP(X,Y) { int *T = X; X = Y; Y = T; } 00061 00062 #define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; 00063 #define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1; 00064 00065 #define TST1_LEAVE U1++; } 00066 #define TST2_LEAVE U2++; } 00067 00068 #define ONE_ITERATION \ 00069 \ 00070 PTEST = PT1 >> 20; \ 00071 \ 00072 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ 00073 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ 00074 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \ 00075 \ 00076 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ 00077 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ 00078 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \ 00079 \ 00080 PTX = (PT1 >> 18) & 7; \ 00081 PT1 &= 0x1FFF; \ 00082 PT2 &= 0x1FFF; \ 00083 CLK = (int) hardclock(); \ 00084 \ 00085 i = 0; \ 00086 A = &WALK[PT1 ]; RES[i++] ^= *A; \ 00087 B = &WALK[PT2 ]; RES[i++] ^= *B; \ 00088 C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \ 00089 D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \ 00090 \ 00091 IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \ 00092 *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \ 00093 *B = IN ^ U1; \ 00094 *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \ 00095 *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \ 00096 \ 00097 A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \ 00098 B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \ 00099 C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \ 00100 D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \ 00101 \ 00102 if( PTEST & 1 ) SWAP( A, C ); \ 00103 \ 00104 IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \ 00105 *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \ 00106 *B = IN; CLK = (int) hardclock(); \ 00107 *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \ 00108 *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \ 00109 \ 00110 A = &WALK[PT1 ^ 4]; \ 00111 B = &WALK[PT2 ^ 1]; \ 00112 \ 00113 PTEST = PT2 >> 1; \ 00114 \ 00115 PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \ 00116 PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \ 00117 PTY = (PT2 >> 10) & 7; \ 00118 \ 00119 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ 00120 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ 00121 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \ 00122 \ 00123 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ 00124 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ 00125 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \ 00126 \ 00127 C = &WALK[PT1 ^ 5]; \ 00128 D = &WALK[PT2 ^ 5]; \ 00129 \ 00130 RES[i++] ^= *A; \ 00131 RES[i++] ^= *B; \ 00132 RES[i++] ^= *C; \ 00133 RES[i++] ^= *D; \ 00134 \ 00135 IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \ 00136 *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \ 00137 *B = IN ^ U2; \ 00138 *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \ 00139 *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \ 00140 \ 00141 A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \ 00142 B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \ 00143 C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \ 00144 D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \ 00145 \ 00146 IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \ 00147 *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \ 00148 *B = IN; \ 00149 *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \ 00150 *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \ 00151 \ 00152 PT1 = ( RES[(i - 8) ^ PTX] ^ \ 00153 WALK[PT1 ^ PTX ^ 7] ) & (~1); \ 00154 PT1 ^= (PT2 ^ 0x10) & 0x10; \ 00155 \ 00156 for( n++, i = 0; i < 16; i++ ) \ 00157 hs->pool[n % COLLECT_SIZE] ^= RES[i]; 00158 00159 /* 00160 * Entropy gathering function 00161 */ 00162 static void havege_fill( havege_state *hs ) 00163 { 00164 int i, n = 0; 00165 int U1, U2, *A, *B, *C, *D; 00166 int PT1, PT2, *WALK, RES[16]; 00167 int PTX, PTY, CLK, PTEST, IN; 00168 00169 WALK = hs->WALK; 00170 PT1 = hs->PT1; 00171 PT2 = hs->PT2; 00172 00173 PTX = U1 = 0; 00174 PTY = U2 = 0; 00175 00176 memset( RES, 0, sizeof( RES ) ); 00177 00178 while( n < COLLECT_SIZE * 4 ) 00179 { 00180 ONE_ITERATION 00181 ONE_ITERATION 00182 ONE_ITERATION 00183 ONE_ITERATION 00184 } 00185 00186 hs->PT1 = PT1; 00187 hs->PT2 = PT2; 00188 00189 hs->offset[0] = 0; 00190 hs->offset[1] = COLLECT_SIZE / 2; 00191 } 00192 00193 /* 00194 * HAVEGE initialization 00195 */ 00196 void havege_init( havege_state *hs ) 00197 { 00198 memset( hs, 0, sizeof( havege_state ) ); 00199 00200 havege_fill( hs ); 00201 } 00202 00203 /* 00204 * HAVEGE rand function 00205 */ 00206 int havege_random( void *p_rng, unsigned char *buf, size_t len ) 00207 { 00208 int val; 00209 size_t use_len; 00210 havege_state *hs = (havege_state *) p_rng; 00211 unsigned char *p = buf; 00212 00213 while( len > 0 ) 00214 { 00215 use_len = len; 00216 if( use_len > sizeof(int) ) 00217 use_len = sizeof(int); 00218 00219 if( hs->offset[1] >= COLLECT_SIZE ) 00220 havege_fill( hs ); 00221 00222 val = hs->pool[hs->offset[0]++]; 00223 val ^= hs->pool[hs->offset[1]++]; 00224 00225 memcpy( p, &val, use_len ); 00226 00227 len -= use_len; 00228 p += use_len; 00229 } 00230 00231 return( 0 ); 00232 } 00233 00234 #endif /* POLARSSL_HAVEGE_C */ 00235 00236
Generated on Tue Jul 12 2022 19:40:15 by
1.7.2