RTC auf true

Committer:
kevman
Date:
Wed Mar 13 11:03:24 2019 +0000
Revision:
2:7aab896b1a3b
Parent:
0:38ceb79fef03
2019-03-13

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /**
kevman 0:38ceb79fef03 2 * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
kevman 0:38ceb79fef03 3 *
kevman 0:38ceb79fef03 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
kevman 0:38ceb79fef03 5 * SPDX-License-Identifier: Apache-2.0
kevman 0:38ceb79fef03 6 *
kevman 0:38ceb79fef03 7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
kevman 0:38ceb79fef03 8 * not use this file except in compliance with the License.
kevman 0:38ceb79fef03 9 * You may obtain a copy of the License at
kevman 0:38ceb79fef03 10 *
kevman 0:38ceb79fef03 11 * http://www.apache.org/licenses/LICENSE-2.0
kevman 0:38ceb79fef03 12 *
kevman 0:38ceb79fef03 13 * Unless required by applicable law or agreed to in writing, software
kevman 0:38ceb79fef03 14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
kevman 0:38ceb79fef03 15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 0:38ceb79fef03 16 * See the License for the specific language governing permissions and
kevman 0:38ceb79fef03 17 * limitations under the License.
kevman 0:38ceb79fef03 18 *
kevman 0:38ceb79fef03 19 * This file is part of mbed TLS (https://tls.mbed.org)
kevman 0:38ceb79fef03 20 */
kevman 0:38ceb79fef03 21 /*
kevman 0:38ceb79fef03 22 * The HAVEGE RNG was designed by Andre Seznec in 2002.
kevman 0:38ceb79fef03 23 *
kevman 0:38ceb79fef03 24 * http://www.irisa.fr/caps/projects/hipsor/publi.php
kevman 0:38ceb79fef03 25 *
kevman 0:38ceb79fef03 26 * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
kevman 0:38ceb79fef03 27 */
kevman 0:38ceb79fef03 28
kevman 0:38ceb79fef03 29 #if !defined(MBEDTLS_CONFIG_FILE)
kevman 0:38ceb79fef03 30 #include "mbedtls/config.h"
kevman 0:38ceb79fef03 31 #else
kevman 0:38ceb79fef03 32 #include MBEDTLS_CONFIG_FILE
kevman 0:38ceb79fef03 33 #endif
kevman 0:38ceb79fef03 34
kevman 0:38ceb79fef03 35 #if defined(MBEDTLS_HAVEGE_C)
kevman 0:38ceb79fef03 36
kevman 0:38ceb79fef03 37 #include "mbedtls/havege.h"
kevman 0:38ceb79fef03 38 #include "mbedtls/timing.h"
kevman 0:38ceb79fef03 39 #include "mbedtls/platform_util.h"
kevman 0:38ceb79fef03 40
kevman 0:38ceb79fef03 41 #include <string.h>
kevman 0:38ceb79fef03 42
kevman 0:38ceb79fef03 43 /* ------------------------------------------------------------------------
kevman 0:38ceb79fef03 44 * On average, one iteration accesses two 8-word blocks in the havege WALK
kevman 0:38ceb79fef03 45 * table, and generates 16 words in the RES array.
kevman 0:38ceb79fef03 46 *
kevman 0:38ceb79fef03 47 * The data read in the WALK table is updated and permuted after each use.
kevman 0:38ceb79fef03 48 * The result of the hardware clock counter read is used for this update.
kevman 0:38ceb79fef03 49 *
kevman 0:38ceb79fef03 50 * 25 conditional tests are present. The conditional tests are grouped in
kevman 0:38ceb79fef03 51 * two nested groups of 12 conditional tests and 1 test that controls the
kevman 0:38ceb79fef03 52 * permutation; on average, there should be 6 tests executed and 3 of them
kevman 0:38ceb79fef03 53 * should be mispredicted.
kevman 0:38ceb79fef03 54 * ------------------------------------------------------------------------
kevman 0:38ceb79fef03 55 */
kevman 0:38ceb79fef03 56
kevman 0:38ceb79fef03 57 #define SWAP(X,Y) { int *T = X; X = Y; Y = T; }
kevman 0:38ceb79fef03 58
kevman 0:38ceb79fef03 59 #define TST1_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
kevman 0:38ceb79fef03 60 #define TST2_ENTER if( PTEST & 1 ) { PTEST ^= 3; PTEST >>= 1;
kevman 0:38ceb79fef03 61
kevman 0:38ceb79fef03 62 #define TST1_LEAVE U1++; }
kevman 0:38ceb79fef03 63 #define TST2_LEAVE U2++; }
kevman 0:38ceb79fef03 64
kevman 0:38ceb79fef03 65 #define ONE_ITERATION \
kevman 0:38ceb79fef03 66 \
kevman 0:38ceb79fef03 67 PTEST = PT1 >> 20; \
kevman 0:38ceb79fef03 68 \
kevman 0:38ceb79fef03 69 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
kevman 0:38ceb79fef03 70 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
kevman 0:38ceb79fef03 71 TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
kevman 0:38ceb79fef03 72 \
kevman 0:38ceb79fef03 73 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
kevman 0:38ceb79fef03 74 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
kevman 0:38ceb79fef03 75 TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
kevman 0:38ceb79fef03 76 \
kevman 0:38ceb79fef03 77 PTX = (PT1 >> 18) & 7; \
kevman 0:38ceb79fef03 78 PT1 &= 0x1FFF; \
kevman 0:38ceb79fef03 79 PT2 &= 0x1FFF; \
kevman 0:38ceb79fef03 80 CLK = (int) mbedtls_timing_hardclock(); \
kevman 0:38ceb79fef03 81 \
kevman 0:38ceb79fef03 82 i = 0; \
kevman 0:38ceb79fef03 83 A = &WALK[PT1 ]; RES[i++] ^= *A; \
kevman 0:38ceb79fef03 84 B = &WALK[PT2 ]; RES[i++] ^= *B; \
kevman 0:38ceb79fef03 85 C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \
kevman 0:38ceb79fef03 86 D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \
kevman 0:38ceb79fef03 87 \
kevman 0:38ceb79fef03 88 IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \
kevman 0:38ceb79fef03 89 *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \
kevman 0:38ceb79fef03 90 *B = IN ^ U1; \
kevman 0:38ceb79fef03 91 *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \
kevman 0:38ceb79fef03 92 *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \
kevman 0:38ceb79fef03 93 \
kevman 0:38ceb79fef03 94 A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \
kevman 0:38ceb79fef03 95 B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \
kevman 0:38ceb79fef03 96 C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \
kevman 0:38ceb79fef03 97 D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \
kevman 0:38ceb79fef03 98 \
kevman 0:38ceb79fef03 99 if( PTEST & 1 ) SWAP( A, C ); \
kevman 0:38ceb79fef03 100 \
kevman 0:38ceb79fef03 101 IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
kevman 0:38ceb79fef03 102 *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
kevman 0:38ceb79fef03 103 *B = IN; CLK = (int) mbedtls_timing_hardclock(); \
kevman 0:38ceb79fef03 104 *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
kevman 0:38ceb79fef03 105 *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
kevman 0:38ceb79fef03 106 \
kevman 0:38ceb79fef03 107 A = &WALK[PT1 ^ 4]; \
kevman 0:38ceb79fef03 108 B = &WALK[PT2 ^ 1]; \
kevman 0:38ceb79fef03 109 \
kevman 0:38ceb79fef03 110 PTEST = PT2 >> 1; \
kevman 0:38ceb79fef03 111 \
kevman 0:38ceb79fef03 112 PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \
kevman 0:38ceb79fef03 113 PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \
kevman 0:38ceb79fef03 114 PTY = (PT2 >> 10) & 7; \
kevman 0:38ceb79fef03 115 \
kevman 0:38ceb79fef03 116 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
kevman 0:38ceb79fef03 117 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
kevman 0:38ceb79fef03 118 TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
kevman 0:38ceb79fef03 119 \
kevman 0:38ceb79fef03 120 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
kevman 0:38ceb79fef03 121 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
kevman 0:38ceb79fef03 122 TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
kevman 0:38ceb79fef03 123 \
kevman 0:38ceb79fef03 124 C = &WALK[PT1 ^ 5]; \
kevman 0:38ceb79fef03 125 D = &WALK[PT2 ^ 5]; \
kevman 0:38ceb79fef03 126 \
kevman 0:38ceb79fef03 127 RES[i++] ^= *A; \
kevman 0:38ceb79fef03 128 RES[i++] ^= *B; \
kevman 0:38ceb79fef03 129 RES[i++] ^= *C; \
kevman 0:38ceb79fef03 130 RES[i++] ^= *D; \
kevman 0:38ceb79fef03 131 \
kevman 0:38ceb79fef03 132 IN = (*A >> ( 9)) ^ (*A << (23)) ^ CLK; \
kevman 0:38ceb79fef03 133 *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \
kevman 0:38ceb79fef03 134 *B = IN ^ U2; \
kevman 0:38ceb79fef03 135 *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \
kevman 0:38ceb79fef03 136 *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \
kevman 0:38ceb79fef03 137 \
kevman 0:38ceb79fef03 138 A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \
kevman 0:38ceb79fef03 139 B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \
kevman 0:38ceb79fef03 140 C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \
kevman 0:38ceb79fef03 141 D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \
kevman 0:38ceb79fef03 142 \
kevman 0:38ceb79fef03 143 IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \
kevman 0:38ceb79fef03 144 *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \
kevman 0:38ceb79fef03 145 *B = IN; \
kevman 0:38ceb79fef03 146 *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \
kevman 0:38ceb79fef03 147 *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \
kevman 0:38ceb79fef03 148 \
kevman 0:38ceb79fef03 149 PT1 = ( RES[( i - 8 ) ^ PTX] ^ \
kevman 0:38ceb79fef03 150 WALK[PT1 ^ PTX ^ 7] ) & (~1); \
kevman 0:38ceb79fef03 151 PT1 ^= (PT2 ^ 0x10) & 0x10; \
kevman 0:38ceb79fef03 152 \
kevman 0:38ceb79fef03 153 for( n++, i = 0; i < 16; i++ ) \
kevman 0:38ceb79fef03 154 hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i];
kevman 0:38ceb79fef03 155
kevman 0:38ceb79fef03 156 /*
kevman 0:38ceb79fef03 157 * Entropy gathering function
kevman 0:38ceb79fef03 158 */
kevman 0:38ceb79fef03 159 static void havege_fill( mbedtls_havege_state *hs )
kevman 0:38ceb79fef03 160 {
kevman 0:38ceb79fef03 161 int i, n = 0;
kevman 0:38ceb79fef03 162 int U1, U2, *A, *B, *C, *D;
kevman 0:38ceb79fef03 163 int PT1, PT2, *WALK, RES[16];
kevman 0:38ceb79fef03 164 int PTX, PTY, CLK, PTEST, IN;
kevman 0:38ceb79fef03 165
kevman 0:38ceb79fef03 166 WALK = hs->WALK;
kevman 0:38ceb79fef03 167 PT1 = hs->PT1;
kevman 0:38ceb79fef03 168 PT2 = hs->PT2;
kevman 0:38ceb79fef03 169
kevman 0:38ceb79fef03 170 PTX = U1 = 0;
kevman 0:38ceb79fef03 171 PTY = U2 = 0;
kevman 0:38ceb79fef03 172
kevman 0:38ceb79fef03 173 (void)PTX;
kevman 0:38ceb79fef03 174
kevman 0:38ceb79fef03 175 memset( RES, 0, sizeof( RES ) );
kevman 0:38ceb79fef03 176
kevman 0:38ceb79fef03 177 while( n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4 )
kevman 0:38ceb79fef03 178 {
kevman 0:38ceb79fef03 179 ONE_ITERATION
kevman 0:38ceb79fef03 180 ONE_ITERATION
kevman 0:38ceb79fef03 181 ONE_ITERATION
kevman 0:38ceb79fef03 182 ONE_ITERATION
kevman 0:38ceb79fef03 183 }
kevman 0:38ceb79fef03 184
kevman 0:38ceb79fef03 185 hs->PT1 = PT1;
kevman 0:38ceb79fef03 186 hs->PT2 = PT2;
kevman 0:38ceb79fef03 187
kevman 0:38ceb79fef03 188 hs->offset[0] = 0;
kevman 0:38ceb79fef03 189 hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2;
kevman 0:38ceb79fef03 190 }
kevman 0:38ceb79fef03 191
kevman 0:38ceb79fef03 192 /*
kevman 0:38ceb79fef03 193 * HAVEGE initialization
kevman 0:38ceb79fef03 194 */
kevman 0:38ceb79fef03 195 void mbedtls_havege_init( mbedtls_havege_state *hs )
kevman 0:38ceb79fef03 196 {
kevman 0:38ceb79fef03 197 memset( hs, 0, sizeof( mbedtls_havege_state ) );
kevman 0:38ceb79fef03 198
kevman 0:38ceb79fef03 199 havege_fill( hs );
kevman 0:38ceb79fef03 200 }
kevman 0:38ceb79fef03 201
kevman 0:38ceb79fef03 202 void mbedtls_havege_free( mbedtls_havege_state *hs )
kevman 0:38ceb79fef03 203 {
kevman 0:38ceb79fef03 204 if( hs == NULL )
kevman 0:38ceb79fef03 205 return;
kevman 0:38ceb79fef03 206
kevman 0:38ceb79fef03 207 mbedtls_platform_zeroize( hs, sizeof( mbedtls_havege_state ) );
kevman 0:38ceb79fef03 208 }
kevman 0:38ceb79fef03 209
kevman 0:38ceb79fef03 210 /*
kevman 0:38ceb79fef03 211 * HAVEGE rand function
kevman 0:38ceb79fef03 212 */
kevman 0:38ceb79fef03 213 int mbedtls_havege_random( void *p_rng, unsigned char *buf, size_t len )
kevman 0:38ceb79fef03 214 {
kevman 0:38ceb79fef03 215 int val;
kevman 0:38ceb79fef03 216 size_t use_len;
kevman 0:38ceb79fef03 217 mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng;
kevman 0:38ceb79fef03 218 unsigned char *p = buf;
kevman 0:38ceb79fef03 219
kevman 0:38ceb79fef03 220 while( len > 0 )
kevman 0:38ceb79fef03 221 {
kevman 0:38ceb79fef03 222 use_len = len;
kevman 0:38ceb79fef03 223 if( use_len > sizeof(int) )
kevman 0:38ceb79fef03 224 use_len = sizeof(int);
kevman 0:38ceb79fef03 225
kevman 0:38ceb79fef03 226 if( hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE )
kevman 0:38ceb79fef03 227 havege_fill( hs );
kevman 0:38ceb79fef03 228
kevman 0:38ceb79fef03 229 val = hs->pool[hs->offset[0]++];
kevman 0:38ceb79fef03 230 val ^= hs->pool[hs->offset[1]++];
kevman 0:38ceb79fef03 231
kevman 0:38ceb79fef03 232 memcpy( p, &val, use_len );
kevman 0:38ceb79fef03 233
kevman 0:38ceb79fef03 234 len -= use_len;
kevman 0:38ceb79fef03 235 p += use_len;
kevman 0:38ceb79fef03 236 }
kevman 0:38ceb79fef03 237
kevman 0:38ceb79fef03 238 return( 0 );
kevman 0:38ceb79fef03 239 }
kevman 0:38ceb79fef03 240
kevman 0:38ceb79fef03 241 #endif /* MBEDTLS_HAVEGE_C */