diff --git a/include/polarssl/timing.h b/include/polarssl/timing.h index cb6abe35e..09624fcf1 100644 --- a/include/polarssl/timing.h +++ b/include/polarssl/timing.h @@ -74,6 +74,15 @@ void set_alarm( int seconds ); */ void m_sleep( int milliseconds ); +#if defined(POLARSSL_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int timing_self_test( int verbose ); +#endif + #ifdef __cplusplus } #endif diff --git a/library/timing.c b/library/timing.c index 8322411b4..c8fa653ce 100644 --- a/library/timing.c +++ b/library/timing.c @@ -25,6 +25,13 @@ #include "polarssl/config.h" +#if defined(POLARSSL_SELF_TEST) && defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#include +#define polarssl_printf printf +#endif + #if defined(POLARSSL_TIMING_C) && !defined(POLARSSL_TIMING_ALT) #include "polarssl/timing.h" @@ -254,7 +261,7 @@ void m_sleep( int milliseconds ) Sleep( milliseconds ); } -#else +#else /* _WIN32 && !EFIX64 && !EFI32 */ unsigned long get_timer( struct hr_time *val, int reset ) { @@ -282,7 +289,7 @@ void m_sleep( int milliseconds ) usleep( milliseconds * 1000 ); } -#else +#else /* INTEGRITY */ static void sighandler( int signum ) { @@ -308,6 +315,120 @@ void m_sleep( int milliseconds ) } #endif /* INTEGRITY */ -#endif +#endif /* _WIN32 && !EFIX64 && !EFI32 */ -#endif +#if defined(POLARSSL_SELF_TEST) + +/* + * Checkup routine + */ +int timing_self_test( int verbose ) +{ + unsigned long cycles, ratio; + unsigned long millisecs, secs; + int hardfail; + struct hr_time hires; + + if( verbose != 0) + polarssl_printf( " TIMING tests warning: will take some time!\n" ); + + if( verbose != 0 ) + polarssl_printf( " TIMING test #1 (m_sleep / get_timer): " ); + + for( secs = 1; secs <= 3; secs++ ) + { + (void) get_timer( &hires, 1 ); + + m_sleep( 1000 * secs ); + + millisecs = get_timer( &hires, 0 ); + + if( millisecs < 900 * secs || millisecs > 1100 * secs ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " TIMING test #2 (set_alarm / get_timer): " ); + + for( secs = 1; secs <= 3; secs++ ) + { + (void) get_timer( &hires, 1 ); + + set_alarm( secs ); + while( !alarmed ) + ; + + millisecs = get_timer( &hires, 0 ); + + if( millisecs < 900 * secs || millisecs > 1100 * secs ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( " TIMING test #3 (hardclock / m_sleep ): " ); + + /* + * Allow one failure for possible counter wrapping. + * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; + * since the whole test is about 10ms, it shouldn't happen twice in a row. + */ + hardfail = 0; + +hard_test: + if( hardfail > 1 ) + { + if( verbose != 0 ) + polarssl_printf( "failed\n" ); + + return( 1 ); + } + + /* Get a reference ratio cycles/ms */ + cycles = hardclock(); + m_sleep( 1 ); + cycles = hardclock() - cycles; + ratio = cycles / 1; + + for( millisecs = 2; millisecs <= 4; millisecs++ ) + { + cycles = hardclock(); + m_sleep( millisecs ); + cycles = hardclock() - cycles; + + /* Allow variation up to 20% */ + if( cycles / millisecs < ratio - ratio / 5 || + cycles / millisecs > ratio + ratio / 5 ) + { + hardfail++; + goto hard_test; + } + } + + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + return( 0 ); +} + +#endif /* POLARSSL_SELF_TEST */ + +#endif /* POLARSSL_TIMING_C && !POLARSSL_TIMING_ALT */ diff --git a/programs/test/selftest.c b/programs/test/selftest.c index c029e9b33..6f7360850 100644 --- a/programs/test/selftest.c +++ b/programs/test/selftest.c @@ -51,6 +51,7 @@ #include "polarssl/pkcs5.h" #include "polarssl/pbkdf2.h" #include "polarssl/ecp.h" +#include "polarssl/timing.h" #if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C) #include "polarssl/memory.h" @@ -192,6 +193,11 @@ int main( int argc, char *argv[] ) return( ret ); #endif +#if defined(POLARSSL_TIMING_C) + if( ( ret = timing_self_test( v ) ) != 0 ) + return( ret ); +#endif + #else printf( " POLARSSL_SELF_TEST not defined.\n" ); #endif