RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /*
kevman 0:38ceb79fef03 2 * Portable interface to the CPU cycle counter
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 #if !defined(MBEDTLS_CONFIG_FILE)
kevman 0:38ceb79fef03 23 #include "mbedtls/config.h"
kevman 0:38ceb79fef03 24 #else
kevman 0:38ceb79fef03 25 #include MBEDTLS_CONFIG_FILE
kevman 0:38ceb79fef03 26 #endif
kevman 0:38ceb79fef03 27
kevman 0:38ceb79fef03 28 #if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C)
kevman 0:38ceb79fef03 29 #include "mbedtls/platform.h"
kevman 0:38ceb79fef03 30 #else
kevman 0:38ceb79fef03 31 #include <stdio.h>
kevman 0:38ceb79fef03 32 #define mbedtls_printf printf
kevman 0:38ceb79fef03 33 #endif
kevman 0:38ceb79fef03 34
kevman 0:38ceb79fef03 35 #if defined(MBEDTLS_TIMING_C)
kevman 0:38ceb79fef03 36
kevman 0:38ceb79fef03 37 #include "mbedtls/timing.h"
kevman 0:38ceb79fef03 38
kevman 0:38ceb79fef03 39 #if !defined(MBEDTLS_TIMING_ALT)
kevman 0:38ceb79fef03 40
kevman 0:38ceb79fef03 41 #if !defined(unix) && !defined(__unix__) && !defined(__unix) && \
kevman 0:38ceb79fef03 42 !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \
kevman 0:38ceb79fef03 43 !defined(__HAIKU__)
kevman 0:38ceb79fef03 44 #error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h"
kevman 0:38ceb79fef03 45 #endif
kevman 0:38ceb79fef03 46
kevman 0:38ceb79fef03 47 #ifndef asm
kevman 0:38ceb79fef03 48 #define asm __asm
kevman 0:38ceb79fef03 49 #endif
kevman 0:38ceb79fef03 50
kevman 0:38ceb79fef03 51 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
kevman 0:38ceb79fef03 52
kevman 0:38ceb79fef03 53 #include <windows.h>
kevman 0:38ceb79fef03 54 #include <winbase.h>
kevman 0:38ceb79fef03 55
kevman 0:38ceb79fef03 56 struct _hr_time
kevman 0:38ceb79fef03 57 {
kevman 0:38ceb79fef03 58 LARGE_INTEGER start;
kevman 0:38ceb79fef03 59 };
kevman 0:38ceb79fef03 60
kevman 0:38ceb79fef03 61 #else
kevman 0:38ceb79fef03 62
kevman 0:38ceb79fef03 63 #include <unistd.h>
kevman 0:38ceb79fef03 64 #include <sys/types.h>
kevman 0:38ceb79fef03 65 #include <sys/time.h>
kevman 0:38ceb79fef03 66 #include <signal.h>
kevman 0:38ceb79fef03 67 #include <time.h>
kevman 0:38ceb79fef03 68
kevman 0:38ceb79fef03 69 struct _hr_time
kevman 0:38ceb79fef03 70 {
kevman 0:38ceb79fef03 71 struct timeval start;
kevman 0:38ceb79fef03 72 };
kevman 0:38ceb79fef03 73
kevman 0:38ceb79fef03 74 #endif /* _WIN32 && !EFIX64 && !EFI32 */
kevman 0:38ceb79fef03 75
kevman 0:38ceb79fef03 76 #if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \
kevman 0:38ceb79fef03 77 ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__)
kevman 0:38ceb79fef03 78
kevman 0:38ceb79fef03 79 #define HAVE_HARDCLOCK
kevman 0:38ceb79fef03 80
kevman 0:38ceb79fef03 81 unsigned long mbedtls_timing_hardclock( void )
kevman 0:38ceb79fef03 82 {
kevman 0:38ceb79fef03 83 unsigned long tsc;
kevman 0:38ceb79fef03 84 __asm rdtsc
kevman 0:38ceb79fef03 85 __asm mov [tsc], eax
kevman 0:38ceb79fef03 86 return( tsc );
kevman 0:38ceb79fef03 87 }
kevman 0:38ceb79fef03 88 #endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
kevman 0:38ceb79fef03 89 ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */
kevman 0:38ceb79fef03 90
kevman 0:38ceb79fef03 91 /* some versions of mingw-64 have 32-bit longs even on x84_64 */
kevman 0:38ceb79fef03 92 #if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \
kevman 0:38ceb79fef03 93 defined(__GNUC__) && ( defined(__i386__) || ( \
kevman 0:38ceb79fef03 94 ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) )
kevman 0:38ceb79fef03 95
kevman 0:38ceb79fef03 96 #define HAVE_HARDCLOCK
kevman 0:38ceb79fef03 97
kevman 0:38ceb79fef03 98 unsigned long mbedtls_timing_hardclock( void )
kevman 0:38ceb79fef03 99 {
kevman 0:38ceb79fef03 100 unsigned long lo, hi;
kevman 0:38ceb79fef03 101 asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
kevman 0:38ceb79fef03 102 return( lo );
kevman 0:38ceb79fef03 103 }
kevman 0:38ceb79fef03 104 #endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
kevman 0:38ceb79fef03 105 __GNUC__ && __i386__ */
kevman 0:38ceb79fef03 106
kevman 0:38ceb79fef03 107 #if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \
kevman 0:38ceb79fef03 108 defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) )
kevman 0:38ceb79fef03 109
kevman 0:38ceb79fef03 110 #define HAVE_HARDCLOCK
kevman 0:38ceb79fef03 111
kevman 0:38ceb79fef03 112 unsigned long mbedtls_timing_hardclock( void )
kevman 0:38ceb79fef03 113 {
kevman 0:38ceb79fef03 114 unsigned long lo, hi;
kevman 0:38ceb79fef03 115 asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
kevman 0:38ceb79fef03 116 return( lo | ( hi << 32 ) );
kevman 0:38ceb79fef03 117 }
kevman 0:38ceb79fef03 118 #endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
kevman 0:38ceb79fef03 119 __GNUC__ && ( __amd64__ || __x86_64__ ) */
kevman 0:38ceb79fef03 120
kevman 0:38ceb79fef03 121 #if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \
kevman 0:38ceb79fef03 122 defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) )
kevman 0:38ceb79fef03 123
kevman 0:38ceb79fef03 124 #define HAVE_HARDCLOCK
kevman 0:38ceb79fef03 125
kevman 0:38ceb79fef03 126 unsigned long mbedtls_timing_hardclock( void )
kevman 0:38ceb79fef03 127 {
kevman 0:38ceb79fef03 128 unsigned long tbl, tbu0, tbu1;
kevman 0:38ceb79fef03 129
kevman 0:38ceb79fef03 130 do
kevman 0:38ceb79fef03 131 {
kevman 0:38ceb79fef03 132 asm volatile( "mftbu %0" : "=r" (tbu0) );
kevman 0:38ceb79fef03 133 asm volatile( "mftb %0" : "=r" (tbl ) );
kevman 0:38ceb79fef03 134 asm volatile( "mftbu %0" : "=r" (tbu1) );
kevman 0:38ceb79fef03 135 }
kevman 0:38ceb79fef03 136 while( tbu0 != tbu1 );
kevman 0:38ceb79fef03 137
kevman 0:38ceb79fef03 138 return( tbl );
kevman 0:38ceb79fef03 139 }
kevman 0:38ceb79fef03 140 #endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
kevman 0:38ceb79fef03 141 __GNUC__ && ( __powerpc__ || __ppc__ ) */
kevman 0:38ceb79fef03 142
kevman 0:38ceb79fef03 143 #if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \
kevman 0:38ceb79fef03 144 defined(__GNUC__) && defined(__sparc64__)
kevman 0:38ceb79fef03 145
kevman 0:38ceb79fef03 146 #if defined(__OpenBSD__)
kevman 0:38ceb79fef03 147 #warning OpenBSD does not allow access to tick register using software version instead
kevman 0:38ceb79fef03 148 #else
kevman 0:38ceb79fef03 149 #define HAVE_HARDCLOCK
kevman 0:38ceb79fef03 150
kevman 0:38ceb79fef03 151 unsigned long mbedtls_timing_hardclock( void )
kevman 0:38ceb79fef03 152 {
kevman 0:38ceb79fef03 153 unsigned long tick;
kevman 0:38ceb79fef03 154 asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) );
kevman 0:38ceb79fef03 155 return( tick );
kevman 0:38ceb79fef03 156 }
kevman 0:38ceb79fef03 157 #endif /* __OpenBSD__ */
kevman 0:38ceb79fef03 158 #endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
kevman 0:38ceb79fef03 159 __GNUC__ && __sparc64__ */
kevman 0:38ceb79fef03 160
kevman 0:38ceb79fef03 161 #if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \
kevman 0:38ceb79fef03 162 defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__)
kevman 0:38ceb79fef03 163
kevman 0:38ceb79fef03 164 #define HAVE_HARDCLOCK
kevman 0:38ceb79fef03 165
kevman 0:38ceb79fef03 166 unsigned long mbedtls_timing_hardclock( void )
kevman 0:38ceb79fef03 167 {
kevman 0:38ceb79fef03 168 unsigned long tick;
kevman 0:38ceb79fef03 169 asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" );
kevman 0:38ceb79fef03 170 asm volatile( "mov %%g1, %0" : "=r" (tick) );
kevman 0:38ceb79fef03 171 return( tick );
kevman 0:38ceb79fef03 172 }
kevman 0:38ceb79fef03 173 #endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
kevman 0:38ceb79fef03 174 __GNUC__ && __sparc__ && !__sparc64__ */
kevman 0:38ceb79fef03 175
kevman 0:38ceb79fef03 176 #if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \
kevman 0:38ceb79fef03 177 defined(__GNUC__) && defined(__alpha__)
kevman 0:38ceb79fef03 178
kevman 0:38ceb79fef03 179 #define HAVE_HARDCLOCK
kevman 0:38ceb79fef03 180
kevman 0:38ceb79fef03 181 unsigned long mbedtls_timing_hardclock( void )
kevman 0:38ceb79fef03 182 {
kevman 0:38ceb79fef03 183 unsigned long cc;
kevman 0:38ceb79fef03 184 asm volatile( "rpcc %0" : "=r" (cc) );
kevman 0:38ceb79fef03 185 return( cc & 0xFFFFFFFF );
kevman 0:38ceb79fef03 186 }
kevman 0:38ceb79fef03 187 #endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
kevman 0:38ceb79fef03 188 __GNUC__ && __alpha__ */
kevman 0:38ceb79fef03 189
kevman 0:38ceb79fef03 190 #if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \
kevman 0:38ceb79fef03 191 defined(__GNUC__) && defined(__ia64__)
kevman 0:38ceb79fef03 192
kevman 0:38ceb79fef03 193 #define HAVE_HARDCLOCK
kevman 0:38ceb79fef03 194
kevman 0:38ceb79fef03 195 unsigned long mbedtls_timing_hardclock( void )
kevman 0:38ceb79fef03 196 {
kevman 0:38ceb79fef03 197 unsigned long itc;
kevman 0:38ceb79fef03 198 asm volatile( "mov %0 = ar.itc" : "=r" (itc) );
kevman 0:38ceb79fef03 199 return( itc );
kevman 0:38ceb79fef03 200 }
kevman 0:38ceb79fef03 201 #endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
kevman 0:38ceb79fef03 202 __GNUC__ && __ia64__ */
kevman 0:38ceb79fef03 203
kevman 0:38ceb79fef03 204 #if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \
kevman 0:38ceb79fef03 205 !defined(EFIX64) && !defined(EFI32)
kevman 0:38ceb79fef03 206
kevman 0:38ceb79fef03 207 #define HAVE_HARDCLOCK
kevman 0:38ceb79fef03 208
kevman 0:38ceb79fef03 209 unsigned long mbedtls_timing_hardclock( void )
kevman 0:38ceb79fef03 210 {
kevman 0:38ceb79fef03 211 LARGE_INTEGER offset;
kevman 0:38ceb79fef03 212
kevman 0:38ceb79fef03 213 QueryPerformanceCounter( &offset );
kevman 0:38ceb79fef03 214
kevman 0:38ceb79fef03 215 return( (unsigned long)( offset.QuadPart ) );
kevman 0:38ceb79fef03 216 }
kevman 0:38ceb79fef03 217 #endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */
kevman 0:38ceb79fef03 218
kevman 0:38ceb79fef03 219 #if !defined(HAVE_HARDCLOCK)
kevman 0:38ceb79fef03 220
kevman 0:38ceb79fef03 221 #define HAVE_HARDCLOCK
kevman 0:38ceb79fef03 222
kevman 0:38ceb79fef03 223 static int hardclock_init = 0;
kevman 0:38ceb79fef03 224 static struct timeval tv_init;
kevman 0:38ceb79fef03 225
kevman 0:38ceb79fef03 226 unsigned long mbedtls_timing_hardclock( void )
kevman 0:38ceb79fef03 227 {
kevman 0:38ceb79fef03 228 struct timeval tv_cur;
kevman 0:38ceb79fef03 229
kevman 0:38ceb79fef03 230 if( hardclock_init == 0 )
kevman 0:38ceb79fef03 231 {
kevman 0:38ceb79fef03 232 gettimeofday( &tv_init, NULL );
kevman 0:38ceb79fef03 233 hardclock_init = 1;
kevman 0:38ceb79fef03 234 }
kevman 0:38ceb79fef03 235
kevman 0:38ceb79fef03 236 gettimeofday( &tv_cur, NULL );
kevman 0:38ceb79fef03 237 return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000
kevman 0:38ceb79fef03 238 + ( tv_cur.tv_usec - tv_init.tv_usec ) );
kevman 0:38ceb79fef03 239 }
kevman 0:38ceb79fef03 240 #endif /* !HAVE_HARDCLOCK */
kevman 0:38ceb79fef03 241
kevman 0:38ceb79fef03 242 volatile int mbedtls_timing_alarmed = 0;
kevman 0:38ceb79fef03 243
kevman 0:38ceb79fef03 244 #if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
kevman 0:38ceb79fef03 245
kevman 0:38ceb79fef03 246 unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
kevman 0:38ceb79fef03 247 {
kevman 0:38ceb79fef03 248 struct _hr_time *t = (struct _hr_time *) val;
kevman 0:38ceb79fef03 249
kevman 0:38ceb79fef03 250 if( reset )
kevman 0:38ceb79fef03 251 {
kevman 0:38ceb79fef03 252 QueryPerformanceCounter( &t->start );
kevman 0:38ceb79fef03 253 return( 0 );
kevman 0:38ceb79fef03 254 }
kevman 0:38ceb79fef03 255 else
kevman 0:38ceb79fef03 256 {
kevman 0:38ceb79fef03 257 unsigned long delta;
kevman 0:38ceb79fef03 258 LARGE_INTEGER now, hfreq;
kevman 0:38ceb79fef03 259 QueryPerformanceCounter( &now );
kevman 0:38ceb79fef03 260 QueryPerformanceFrequency( &hfreq );
kevman 0:38ceb79fef03 261 delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul
kevman 0:38ceb79fef03 262 / hfreq.QuadPart );
kevman 0:38ceb79fef03 263 return( delta );
kevman 0:38ceb79fef03 264 }
kevman 0:38ceb79fef03 265 }
kevman 0:38ceb79fef03 266
kevman 0:38ceb79fef03 267 /* It's OK to use a global because alarm() is supposed to be global anyway */
kevman 0:38ceb79fef03 268 static DWORD alarmMs;
kevman 0:38ceb79fef03 269
kevman 0:38ceb79fef03 270 static DWORD WINAPI TimerProc( LPVOID TimerContext )
kevman 0:38ceb79fef03 271 {
kevman 0:38ceb79fef03 272 ((void) TimerContext);
kevman 0:38ceb79fef03 273 Sleep( alarmMs );
kevman 0:38ceb79fef03 274 mbedtls_timing_alarmed = 1;
kevman 0:38ceb79fef03 275 return( TRUE );
kevman 0:38ceb79fef03 276 }
kevman 0:38ceb79fef03 277
kevman 0:38ceb79fef03 278 void mbedtls_set_alarm( int seconds )
kevman 0:38ceb79fef03 279 {
kevman 0:38ceb79fef03 280 DWORD ThreadId;
kevman 0:38ceb79fef03 281
kevman 0:38ceb79fef03 282 if( seconds == 0 )
kevman 0:38ceb79fef03 283 {
kevman 0:38ceb79fef03 284 /* No need to create a thread for this simple case.
kevman 0:38ceb79fef03 285 * Also, this shorcut is more reliable at least on MinGW32 */
kevman 0:38ceb79fef03 286 mbedtls_timing_alarmed = 1;
kevman 0:38ceb79fef03 287 return;
kevman 0:38ceb79fef03 288 }
kevman 0:38ceb79fef03 289
kevman 0:38ceb79fef03 290 mbedtls_timing_alarmed = 0;
kevman 0:38ceb79fef03 291 alarmMs = seconds * 1000;
kevman 0:38ceb79fef03 292 CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) );
kevman 0:38ceb79fef03 293 }
kevman 0:38ceb79fef03 294
kevman 0:38ceb79fef03 295 #else /* _WIN32 && !EFIX64 && !EFI32 */
kevman 0:38ceb79fef03 296
kevman 0:38ceb79fef03 297 unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
kevman 0:38ceb79fef03 298 {
kevman 0:38ceb79fef03 299 struct _hr_time *t = (struct _hr_time *) val;
kevman 0:38ceb79fef03 300
kevman 0:38ceb79fef03 301 if( reset )
kevman 0:38ceb79fef03 302 {
kevman 0:38ceb79fef03 303 gettimeofday( &t->start, NULL );
kevman 0:38ceb79fef03 304 return( 0 );
kevman 0:38ceb79fef03 305 }
kevman 0:38ceb79fef03 306 else
kevman 0:38ceb79fef03 307 {
kevman 0:38ceb79fef03 308 unsigned long delta;
kevman 0:38ceb79fef03 309 struct timeval now;
kevman 0:38ceb79fef03 310 gettimeofday( &now, NULL );
kevman 0:38ceb79fef03 311 delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul
kevman 0:38ceb79fef03 312 + ( now.tv_usec - t->start.tv_usec ) / 1000;
kevman 0:38ceb79fef03 313 return( delta );
kevman 0:38ceb79fef03 314 }
kevman 0:38ceb79fef03 315 }
kevman 0:38ceb79fef03 316
kevman 0:38ceb79fef03 317 static void sighandler( int signum )
kevman 0:38ceb79fef03 318 {
kevman 0:38ceb79fef03 319 mbedtls_timing_alarmed = 1;
kevman 0:38ceb79fef03 320 signal( signum, sighandler );
kevman 0:38ceb79fef03 321 }
kevman 0:38ceb79fef03 322
kevman 0:38ceb79fef03 323 void mbedtls_set_alarm( int seconds )
kevman 0:38ceb79fef03 324 {
kevman 0:38ceb79fef03 325 mbedtls_timing_alarmed = 0;
kevman 0:38ceb79fef03 326 signal( SIGALRM, sighandler );
kevman 0:38ceb79fef03 327 alarm( seconds );
kevman 0:38ceb79fef03 328 if( seconds == 0 )
kevman 0:38ceb79fef03 329 {
kevman 0:38ceb79fef03 330 /* alarm(0) cancelled any previous pending alarm, but the
kevman 0:38ceb79fef03 331 handler won't fire, so raise the flag straight away. */
kevman 0:38ceb79fef03 332 mbedtls_timing_alarmed = 1;
kevman 0:38ceb79fef03 333 }
kevman 0:38ceb79fef03 334 }
kevman 0:38ceb79fef03 335
kevman 0:38ceb79fef03 336 #endif /* _WIN32 && !EFIX64 && !EFI32 */
kevman 0:38ceb79fef03 337
kevman 0:38ceb79fef03 338 /*
kevman 0:38ceb79fef03 339 * Set delays to watch
kevman 0:38ceb79fef03 340 */
kevman 0:38ceb79fef03 341 void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms )
kevman 0:38ceb79fef03 342 {
kevman 0:38ceb79fef03 343 mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
kevman 0:38ceb79fef03 344
kevman 0:38ceb79fef03 345 ctx->int_ms = int_ms;
kevman 0:38ceb79fef03 346 ctx->fin_ms = fin_ms;
kevman 0:38ceb79fef03 347
kevman 0:38ceb79fef03 348 if( fin_ms != 0 )
kevman 0:38ceb79fef03 349 (void) mbedtls_timing_get_timer( &ctx->timer, 1 );
kevman 0:38ceb79fef03 350 }
kevman 0:38ceb79fef03 351
kevman 0:38ceb79fef03 352 /*
kevman 0:38ceb79fef03 353 * Get number of delays expired
kevman 0:38ceb79fef03 354 */
kevman 0:38ceb79fef03 355 int mbedtls_timing_get_delay( void *data )
kevman 0:38ceb79fef03 356 {
kevman 0:38ceb79fef03 357 mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
kevman 0:38ceb79fef03 358 unsigned long elapsed_ms;
kevman 0:38ceb79fef03 359
kevman 0:38ceb79fef03 360 if( ctx->fin_ms == 0 )
kevman 0:38ceb79fef03 361 return( -1 );
kevman 0:38ceb79fef03 362
kevman 0:38ceb79fef03 363 elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 );
kevman 0:38ceb79fef03 364
kevman 0:38ceb79fef03 365 if( elapsed_ms >= ctx->fin_ms )
kevman 0:38ceb79fef03 366 return( 2 );
kevman 0:38ceb79fef03 367
kevman 0:38ceb79fef03 368 if( elapsed_ms >= ctx->int_ms )
kevman 0:38ceb79fef03 369 return( 1 );
kevman 0:38ceb79fef03 370
kevman 0:38ceb79fef03 371 return( 0 );
kevman 0:38ceb79fef03 372 }
kevman 0:38ceb79fef03 373
kevman 0:38ceb79fef03 374 #endif /* !MBEDTLS_TIMING_ALT */
kevman 0:38ceb79fef03 375
kevman 0:38ceb79fef03 376 #if defined(MBEDTLS_SELF_TEST)
kevman 0:38ceb79fef03 377
kevman 0:38ceb79fef03 378 /*
kevman 0:38ceb79fef03 379 * Busy-waits for the given number of milliseconds.
kevman 0:38ceb79fef03 380 * Used for testing mbedtls_timing_hardclock.
kevman 0:38ceb79fef03 381 */
kevman 0:38ceb79fef03 382 static void busy_msleep( unsigned long msec )
kevman 0:38ceb79fef03 383 {
kevman 0:38ceb79fef03 384 struct mbedtls_timing_hr_time hires;
kevman 0:38ceb79fef03 385 unsigned long i = 0; /* for busy-waiting */
kevman 0:38ceb79fef03 386 volatile unsigned long j; /* to prevent optimisation */
kevman 0:38ceb79fef03 387
kevman 0:38ceb79fef03 388 (void) mbedtls_timing_get_timer( &hires, 1 );
kevman 0:38ceb79fef03 389
kevman 0:38ceb79fef03 390 while( mbedtls_timing_get_timer( &hires, 0 ) < msec )
kevman 0:38ceb79fef03 391 i++;
kevman 0:38ceb79fef03 392
kevman 0:38ceb79fef03 393 j = i;
kevman 0:38ceb79fef03 394 (void) j;
kevman 0:38ceb79fef03 395 }
kevman 0:38ceb79fef03 396
kevman 0:38ceb79fef03 397 #define FAIL do \
kevman 0:38ceb79fef03 398 { \
kevman 0:38ceb79fef03 399 if( verbose != 0 ) \
kevman 0:38ceb79fef03 400 { \
kevman 0:38ceb79fef03 401 mbedtls_printf( "failed at line %d\n", __LINE__ ); \
kevman 0:38ceb79fef03 402 mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \
kevman 0:38ceb79fef03 403 cycles, ratio, millisecs, secs, hardfail, \
kevman 0:38ceb79fef03 404 (unsigned long) a, (unsigned long) b ); \
kevman 0:38ceb79fef03 405 mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \
kevman 0:38ceb79fef03 406 mbedtls_timing_get_timer( &hires, 0 ), \
kevman 0:38ceb79fef03 407 mbedtls_timing_get_timer( &ctx.timer, 0 ), \
kevman 0:38ceb79fef03 408 mbedtls_timing_get_delay( &ctx ) ); \
kevman 0:38ceb79fef03 409 } \
kevman 0:38ceb79fef03 410 return( 1 ); \
kevman 0:38ceb79fef03 411 } while( 0 )
kevman 0:38ceb79fef03 412
kevman 0:38ceb79fef03 413 /*
kevman 0:38ceb79fef03 414 * Checkup routine
kevman 0:38ceb79fef03 415 *
kevman 0:38ceb79fef03 416 * Warning: this is work in progress, some tests may not be reliable enough
kevman 0:38ceb79fef03 417 * yet! False positives may happen.
kevman 0:38ceb79fef03 418 */
kevman 0:38ceb79fef03 419 int mbedtls_timing_self_test( int verbose )
kevman 0:38ceb79fef03 420 {
kevman 0:38ceb79fef03 421 unsigned long cycles = 0, ratio = 0;
kevman 0:38ceb79fef03 422 unsigned long millisecs = 0, secs = 0;
kevman 0:38ceb79fef03 423 int hardfail = 0;
kevman 0:38ceb79fef03 424 struct mbedtls_timing_hr_time hires;
kevman 0:38ceb79fef03 425 uint32_t a = 0, b = 0;
kevman 0:38ceb79fef03 426 mbedtls_timing_delay_context ctx;
kevman 0:38ceb79fef03 427
kevman 0:38ceb79fef03 428 if( verbose != 0 )
kevman 0:38ceb79fef03 429 mbedtls_printf( " TIMING tests note: will take some time!\n" );
kevman 0:38ceb79fef03 430
kevman 0:38ceb79fef03 431 if( verbose != 0 )
kevman 0:38ceb79fef03 432 mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " );
kevman 0:38ceb79fef03 433
kevman 0:38ceb79fef03 434 {
kevman 0:38ceb79fef03 435 secs = 1;
kevman 0:38ceb79fef03 436
kevman 0:38ceb79fef03 437 (void) mbedtls_timing_get_timer( &hires, 1 );
kevman 0:38ceb79fef03 438
kevman 0:38ceb79fef03 439 mbedtls_set_alarm( (int) secs );
kevman 0:38ceb79fef03 440 while( !mbedtls_timing_alarmed )
kevman 0:38ceb79fef03 441 ;
kevman 0:38ceb79fef03 442
kevman 0:38ceb79fef03 443 millisecs = mbedtls_timing_get_timer( &hires, 0 );
kevman 0:38ceb79fef03 444
kevman 0:38ceb79fef03 445 /* For some reason on Windows it looks like alarm has an extra delay
kevman 0:38ceb79fef03 446 * (maybe related to creating a new thread). Allow some room here. */
kevman 0:38ceb79fef03 447 if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 )
kevman 0:38ceb79fef03 448 FAIL;
kevman 0:38ceb79fef03 449 }
kevman 0:38ceb79fef03 450
kevman 0:38ceb79fef03 451 if( verbose != 0 )
kevman 0:38ceb79fef03 452 mbedtls_printf( "passed\n" );
kevman 0:38ceb79fef03 453
kevman 0:38ceb79fef03 454 if( verbose != 0 )
kevman 0:38ceb79fef03 455 mbedtls_printf( " TIMING test #2 (set/get_delay ): " );
kevman 0:38ceb79fef03 456
kevman 0:38ceb79fef03 457 {
kevman 0:38ceb79fef03 458 a = 800;
kevman 0:38ceb79fef03 459 b = 400;
kevman 0:38ceb79fef03 460 mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */
kevman 0:38ceb79fef03 461
kevman 0:38ceb79fef03 462 busy_msleep( a - a / 4 ); /* T = a - a/4 */
kevman 0:38ceb79fef03 463 if( mbedtls_timing_get_delay( &ctx ) != 0 )
kevman 0:38ceb79fef03 464 FAIL;
kevman 0:38ceb79fef03 465
kevman 0:38ceb79fef03 466 busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */
kevman 0:38ceb79fef03 467 if( mbedtls_timing_get_delay( &ctx ) != 1 )
kevman 0:38ceb79fef03 468 FAIL;
kevman 0:38ceb79fef03 469
kevman 0:38ceb79fef03 470 busy_msleep( b ); /* T = a + b + b/4 */
kevman 0:38ceb79fef03 471 if( mbedtls_timing_get_delay( &ctx ) != 2 )
kevman 0:38ceb79fef03 472 FAIL;
kevman 0:38ceb79fef03 473 }
kevman 0:38ceb79fef03 474
kevman 0:38ceb79fef03 475 mbedtls_timing_set_delay( &ctx, 0, 0 );
kevman 0:38ceb79fef03 476 busy_msleep( 200 );
kevman 0:38ceb79fef03 477 if( mbedtls_timing_get_delay( &ctx ) != -1 )
kevman 0:38ceb79fef03 478 FAIL;
kevman 0:38ceb79fef03 479
kevman 0:38ceb79fef03 480 if( verbose != 0 )
kevman 0:38ceb79fef03 481 mbedtls_printf( "passed\n" );
kevman 0:38ceb79fef03 482
kevman 0:38ceb79fef03 483 if( verbose != 0 )
kevman 0:38ceb79fef03 484 mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " );
kevman 0:38ceb79fef03 485
kevman 0:38ceb79fef03 486 /*
kevman 0:38ceb79fef03 487 * Allow one failure for possible counter wrapping.
kevman 0:38ceb79fef03 488 * On a 4Ghz 32-bit machine the cycle counter wraps about once per second;
kevman 0:38ceb79fef03 489 * since the whole test is about 10ms, it shouldn't happen twice in a row.
kevman 0:38ceb79fef03 490 */
kevman 0:38ceb79fef03 491
kevman 0:38ceb79fef03 492 hard_test:
kevman 0:38ceb79fef03 493 if( hardfail > 1 )
kevman 0:38ceb79fef03 494 {
kevman 0:38ceb79fef03 495 if( verbose != 0 )
kevman 0:38ceb79fef03 496 mbedtls_printf( "failed (ignored)\n" );
kevman 0:38ceb79fef03 497
kevman 0:38ceb79fef03 498 goto hard_test_done;
kevman 0:38ceb79fef03 499 }
kevman 0:38ceb79fef03 500
kevman 0:38ceb79fef03 501 /* Get a reference ratio cycles/ms */
kevman 0:38ceb79fef03 502 millisecs = 1;
kevman 0:38ceb79fef03 503 cycles = mbedtls_timing_hardclock();
kevman 0:38ceb79fef03 504 busy_msleep( millisecs );
kevman 0:38ceb79fef03 505 cycles = mbedtls_timing_hardclock() - cycles;
kevman 0:38ceb79fef03 506 ratio = cycles / millisecs;
kevman 0:38ceb79fef03 507
kevman 0:38ceb79fef03 508 /* Check that the ratio is mostly constant */
kevman 0:38ceb79fef03 509 for( millisecs = 2; millisecs <= 4; millisecs++ )
kevman 0:38ceb79fef03 510 {
kevman 0:38ceb79fef03 511 cycles = mbedtls_timing_hardclock();
kevman 0:38ceb79fef03 512 busy_msleep( millisecs );
kevman 0:38ceb79fef03 513 cycles = mbedtls_timing_hardclock() - cycles;
kevman 0:38ceb79fef03 514
kevman 0:38ceb79fef03 515 /* Allow variation up to 20% */
kevman 0:38ceb79fef03 516 if( cycles / millisecs < ratio - ratio / 5 ||
kevman 0:38ceb79fef03 517 cycles / millisecs > ratio + ratio / 5 )
kevman 0:38ceb79fef03 518 {
kevman 0:38ceb79fef03 519 hardfail++;
kevman 0:38ceb79fef03 520 goto hard_test;
kevman 0:38ceb79fef03 521 }
kevman 0:38ceb79fef03 522 }
kevman 0:38ceb79fef03 523
kevman 0:38ceb79fef03 524 if( verbose != 0 )
kevman 0:38ceb79fef03 525 mbedtls_printf( "passed\n" );
kevman 0:38ceb79fef03 526
kevman 0:38ceb79fef03 527 hard_test_done:
kevman 0:38ceb79fef03 528
kevman 0:38ceb79fef03 529 if( verbose != 0 )
kevman 0:38ceb79fef03 530 mbedtls_printf( "\n" );
kevman 0:38ceb79fef03 531
kevman 0:38ceb79fef03 532 return( 0 );
kevman 0:38ceb79fef03 533 }
kevman 0:38ceb79fef03 534
kevman 0:38ceb79fef03 535 #endif /* MBEDTLS_SELF_TEST */
kevman 0:38ceb79fef03 536
kevman 0:38ceb79fef03 537 #endif /* MBEDTLS_TIMING_C */