mbed TLS library

Dependents:   HTTPClient-SSL WS_SERVER

Committer:
ansond
Date:
Thu Jun 11 03:27:03 2015 +0000
Revision:
0:137634ff4186
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ansond 0:137634ff4186 1 /**
ansond 0:137634ff4186 2 * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
ansond 0:137634ff4186 3 *
ansond 0:137634ff4186 4 * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
ansond 0:137634ff4186 5 *
ansond 0:137634ff4186 6 * This file is part of mbed TLS (https://tls.mbed.org)
ansond 0:137634ff4186 7 *
ansond 0:137634ff4186 8 * This program is free software; you can redistribute it and/or modify
ansond 0:137634ff4186 9 * it under the terms of the GNU General Public License as published by
ansond 0:137634ff4186 10 * the Free Software Foundation; either version 2 of the License, or
ansond 0:137634ff4186 11 * (at your option) any later version.
ansond 0:137634ff4186 12 *
ansond 0:137634ff4186 13 * This program is distributed in the hope that it will be useful,
ansond 0:137634ff4186 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ansond 0:137634ff4186 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ansond 0:137634ff4186 16 * GNU General Public License for more details.
ansond 0:137634ff4186 17 *
ansond 0:137634ff4186 18 * You should have received a copy of the GNU General Public License along
ansond 0:137634ff4186 19 * with this program; if not, write to the Free Software Foundation, Inc.,
ansond 0:137634ff4186 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ansond 0:137634ff4186 21 */
ansond 0:137634ff4186 22 /*
ansond 0:137634ff4186 23 * The HAVEGE RNG was designed by Andre Seznec in 2002.
ansond 0:137634ff4186 24 *
ansond 0:137634ff4186 25 * http://www.irisa.fr/caps/projects/hipsor/publi.php
ansond 0:137634ff4186 26 *
ansond 0:137634ff4186 27 * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
ansond 0:137634ff4186 28 */
ansond 0:137634ff4186 29
ansond 0:137634ff4186 30 #if !defined(POLARSSL_CONFIG_FILE)
ansond 0:137634ff4186 31 #include "polarssl/config.h"
ansond 0:137634ff4186 32 #else
ansond 0:137634ff4186 33 #include POLARSSL_CONFIG_FILE
ansond 0:137634ff4186 34 #endif
ansond 0:137634ff4186 35
ansond 0:137634ff4186 36 #if defined(POLARSSL_HAVEGE_C)
ansond 0:137634ff4186 37
ansond 0:137634ff4186 38 #include "polarssl/havege.h"
ansond 0:137634ff4186 39 #include "polarssl/timing.h"
ansond 0:137634ff4186 40
ansond 0:137634ff4186 41 #include <string.h>
ansond 0:137634ff4186 42
ansond 0:137634ff4186 43 /* Implementation that should never be optimized out by the compiler */
ansond 0:137634ff4186 44 static void polarssl_zeroize( void *v, size_t n ) {
ansond 0:137634ff4186 45 volatile unsigned char *p = v; while( n-- ) *p++ = 0;
ansond 0:137634ff4186 46 }
ansond 0:137634ff4186 47
ansond 0:137634ff4186 48 /* ------------------------------------------------------------------------
ansond 0:137634ff4186 49 * On average, one iteration accesses two 8-word blocks in the havege WALK
ansond 0:137634ff4186 50 * table, and generates 16 words in the RES array.
ansond 0:137634ff4186 51 *
ansond 0:137634ff4186 52 * The data read in the WALK table is updated and permuted after each use.
ansond 0:137634ff4186 53 * The result of the hardware clock counter read is used for this update.
ansond 0:137634ff4186 54 *
ansond 0:137634ff4186 55 * 25 conditional tests are present. The conditional tests are grouped in
ansond 0:137634ff4186 56 * two nested groups of 12 conditional tests and 1 test that controls the
ansond 0:137634ff4186 57 * permutation; on average, there should be 6 tests executed and 3 of them
ansond 0:137634ff4186 58 * should be mispredicted.
ansond 0:137634ff4186 59 * ------------------------------------------------------------------------
ansond 0:137634ff4186 60 */
ansond 0:137634ff4186 61
ansond 0:137634ff4186 62 #define SWAP(X,Y) { int *T = X; X = Y; Y = T; }
ansond 0:137634ff4186 63
ansond 0:137634ff4186 64 #define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
ansond 0:137634ff4186 65 #define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
ansond 0:137634ff4186 66
ansond 0:137634ff4186 67 #define TST1_LEAVE U1++; }
ansond 0:137634ff4186 68 #define TST2_LEAVE U2++; }
ansond 0:137634ff4186 69
ansond 0:137634ff4186 70 #define ONE_ITERATION \
ansond 0:137634ff4186 71 \
ansond 0:137634ff4186 72 PTEST = PT1 >> 20; \
ansond 0:137634ff4186 73 \
ansond 0:137634ff4186 74 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
ansond 0:137634ff4186 75 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
ansond 0:137634ff4186 76 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
ansond 0:137634ff4186 77 \
ansond 0:137634ff4186 78 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
ansond 0:137634ff4186 79 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
ansond 0:137634ff4186 80 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
ansond 0:137634ff4186 81 \
ansond 0:137634ff4186 82 PTX = (PT1 >> 18) & 7; \
ansond 0:137634ff4186 83 PT1 &= 0x1FFF; \
ansond 0:137634ff4186 84 PT2 &= 0x1FFF; \
ansond 0:137634ff4186 85 CLK = (int) hardclock(); \
ansond 0:137634ff4186 86 \
ansond 0:137634ff4186 87 i = 0; \
ansond 0:137634ff4186 88 A = &WALK[PT1 ]; RES[i++] ^= *A; \
ansond 0:137634ff4186 89 B = &WALK[PT2 ]; RES[i++] ^= *B; \
ansond 0:137634ff4186 90 C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \
ansond 0:137634ff4186 91 D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \
ansond 0:137634ff4186 92 \
ansond 0:137634ff4186 93 IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \
ansond 0:137634ff4186 94 *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \
ansond 0:137634ff4186 95 *B = IN ^ U1; \
ansond 0:137634ff4186 96 *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \
ansond 0:137634ff4186 97 *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \
ansond 0:137634ff4186 98 \
ansond 0:137634ff4186 99 A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \
ansond 0:137634ff4186 100 B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \
ansond 0:137634ff4186 101 C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \
ansond 0:137634ff4186 102 D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \
ansond 0:137634ff4186 103 \
ansond 0:137634ff4186 104 if( PTEST & 1 ) SWAP( A, C ); \
ansond 0:137634ff4186 105 \
ansond 0:137634ff4186 106 IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
ansond 0:137634ff4186 107 *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
ansond 0:137634ff4186 108 *B = IN; CLK = (int) hardclock(); \
ansond 0:137634ff4186 109 *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
ansond 0:137634ff4186 110 *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
ansond 0:137634ff4186 111 \
ansond 0:137634ff4186 112 A = &WALK[PT1 ^ 4]; \
ansond 0:137634ff4186 113 B = &WALK[PT2 ^ 1]; \
ansond 0:137634ff4186 114 \
ansond 0:137634ff4186 115 PTEST = PT2 >> 1; \
ansond 0:137634ff4186 116 \
ansond 0:137634ff4186 117 PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \
ansond 0:137634ff4186 118 PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \
ansond 0:137634ff4186 119 PTY = (PT2 >> 10) & 7; \
ansond 0:137634ff4186 120 \
ansond 0:137634ff4186 121 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
ansond 0:137634ff4186 122 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
ansond 0:137634ff4186 123 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
ansond 0:137634ff4186 124 \
ansond 0:137634ff4186 125 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
ansond 0:137634ff4186 126 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
ansond 0:137634ff4186 127 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
ansond 0:137634ff4186 128 \
ansond 0:137634ff4186 129 C = &WALK[PT1 ^ 5]; \
ansond 0:137634ff4186 130 D = &WALK[PT2 ^ 5]; \
ansond 0:137634ff4186 131 \
ansond 0:137634ff4186 132 RES[i++] ^= *A; \
ansond 0:137634ff4186 133 RES[i++] ^= *B; \
ansond 0:137634ff4186 134 RES[i++] ^= *C; \
ansond 0:137634ff4186 135 RES[i++] ^= *D; \
ansond 0:137634ff4186 136 \
ansond 0:137634ff4186 137 IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \
ansond 0:137634ff4186 138 *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \
ansond 0:137634ff4186 139 *B = IN ^ U2; \
ansond 0:137634ff4186 140 *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \
ansond 0:137634ff4186 141 *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \
ansond 0:137634ff4186 142 \
ansond 0:137634ff4186 143 A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \
ansond 0:137634ff4186 144 B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \
ansond 0:137634ff4186 145 C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \
ansond 0:137634ff4186 146 D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \
ansond 0:137634ff4186 147 \
ansond 0:137634ff4186 148 IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \
ansond 0:137634ff4186 149 *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \
ansond 0:137634ff4186 150 *B = IN; \
ansond 0:137634ff4186 151 *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \
ansond 0:137634ff4186 152 *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \
ansond 0:137634ff4186 153 \
ansond 0:137634ff4186 154 PT1 = ( RES[( i - 8 ) ^ PTX] ^ \
ansond 0:137634ff4186 155 WALK[PT1 ^ PTX ^ 7] ) & (~1); \
ansond 0:137634ff4186 156 PT1 ^= (PT2 ^ 0x10) & 0x10; \
ansond 0:137634ff4186 157 \
ansond 0:137634ff4186 158 for( n++, i = 0; i < 16; i++ ) \
ansond 0:137634ff4186 159 hs->pool[n % COLLECT_SIZE] ^= RES[i];
ansond 0:137634ff4186 160
ansond 0:137634ff4186 161 /*
ansond 0:137634ff4186 162 * Entropy gathering function
ansond 0:137634ff4186 163 */
ansond 0:137634ff4186 164 static void havege_fill( havege_state *hs )
ansond 0:137634ff4186 165 {
ansond 0:137634ff4186 166 int i, n = 0;
ansond 0:137634ff4186 167 int U1, U2, *A, *B, *C, *D;
ansond 0:137634ff4186 168 int PT1, PT2, *WALK, RES[16];
ansond 0:137634ff4186 169 int PTX, PTY, CLK, PTEST, IN;
ansond 0:137634ff4186 170
ansond 0:137634ff4186 171 WALK = hs->WALK;
ansond 0:137634ff4186 172 PT1 = hs->PT1;
ansond 0:137634ff4186 173 PT2 = hs->PT2;
ansond 0:137634ff4186 174
ansond 0:137634ff4186 175 PTX = U1 = 0;
ansond 0:137634ff4186 176 PTY = U2 = 0;
ansond 0:137634ff4186 177
ansond 0:137634ff4186 178 memset( RES, 0, sizeof( RES ) );
ansond 0:137634ff4186 179
ansond 0:137634ff4186 180 while( n < COLLECT_SIZE * 4 )
ansond 0:137634ff4186 181 {
ansond 0:137634ff4186 182 ONE_ITERATION
ansond 0:137634ff4186 183 ONE_ITERATION
ansond 0:137634ff4186 184 ONE_ITERATION
ansond 0:137634ff4186 185 ONE_ITERATION
ansond 0:137634ff4186 186 }
ansond 0:137634ff4186 187
ansond 0:137634ff4186 188 hs->PT1 = PT1;
ansond 0:137634ff4186 189 hs->PT2 = PT2;
ansond 0:137634ff4186 190
ansond 0:137634ff4186 191 hs->offset[0] = 0;
ansond 0:137634ff4186 192 hs->offset[1] = COLLECT_SIZE / 2;
ansond 0:137634ff4186 193 }
ansond 0:137634ff4186 194
ansond 0:137634ff4186 195 /*
ansond 0:137634ff4186 196 * HAVEGE initialization
ansond 0:137634ff4186 197 */
ansond 0:137634ff4186 198 void havege_init( havege_state *hs )
ansond 0:137634ff4186 199 {
ansond 0:137634ff4186 200 memset( hs, 0, sizeof( havege_state ) );
ansond 0:137634ff4186 201
ansond 0:137634ff4186 202 havege_fill( hs );
ansond 0:137634ff4186 203 }
ansond 0:137634ff4186 204
ansond 0:137634ff4186 205 void havege_free( havege_state *hs )
ansond 0:137634ff4186 206 {
ansond 0:137634ff4186 207 if( hs == NULL )
ansond 0:137634ff4186 208 return;
ansond 0:137634ff4186 209
ansond 0:137634ff4186 210 polarssl_zeroize( hs, sizeof( havege_state ) );
ansond 0:137634ff4186 211 }
ansond 0:137634ff4186 212
ansond 0:137634ff4186 213 /*
ansond 0:137634ff4186 214 * HAVEGE rand function
ansond 0:137634ff4186 215 */
ansond 0:137634ff4186 216 int havege_random( void *p_rng, unsigned char *buf, size_t len )
ansond 0:137634ff4186 217 {
ansond 0:137634ff4186 218 int val;
ansond 0:137634ff4186 219 size_t use_len;
ansond 0:137634ff4186 220 havege_state *hs = (havege_state *) p_rng;
ansond 0:137634ff4186 221 unsigned char *p = buf;
ansond 0:137634ff4186 222
ansond 0:137634ff4186 223 while( len > 0 )
ansond 0:137634ff4186 224 {
ansond 0:137634ff4186 225 use_len = len;
ansond 0:137634ff4186 226 if( use_len > sizeof(int) )
ansond 0:137634ff4186 227 use_len = sizeof(int);
ansond 0:137634ff4186 228
ansond 0:137634ff4186 229 if( hs->offset[1] >= COLLECT_SIZE )
ansond 0:137634ff4186 230 havege_fill( hs );
ansond 0:137634ff4186 231
ansond 0:137634ff4186 232 val = hs->pool[hs->offset[0]++];
ansond 0:137634ff4186 233 val ^= hs->pool[hs->offset[1]++];
ansond 0:137634ff4186 234
ansond 0:137634ff4186 235 memcpy( p, &val, use_len );
ansond 0:137634ff4186 236
ansond 0:137634ff4186 237 len -= use_len;
ansond 0:137634ff4186 238 p += use_len;
ansond 0:137634ff4186 239 }
ansond 0:137634ff4186 240
ansond 0:137634ff4186 241 return( 0 );
ansond 0:137634ff4186 242 }
ansond 0:137634ff4186 243
ansond 0:137634ff4186 244 #endif /* POLARSSL_HAVEGE_C */
ansond 0:137634ff4186 245