Add timing_self_test() with consistency tests
diff --git a/include/polarssl/timing.h b/include/polarssl/timing.h
index cb6abe3..09624fc 100644
--- a/include/polarssl/timing.h
+++ b/include/polarssl/timing.h
@@ -74,6 +74,15 @@
*/
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 8322411..c8fa653 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 <stdio.h>
+#define polarssl_printf printf
+#endif
+
#if defined(POLARSSL_TIMING_C) && !defined(POLARSSL_TIMING_ALT)
#include "polarssl/timing.h"
@@ -254,7 +261,7 @@
Sleep( milliseconds );
}
-#else
+#else /* _WIN32 && !EFIX64 && !EFI32 */
unsigned long get_timer( struct hr_time *val, int reset )
{
@@ -282,7 +289,7 @@
usleep( milliseconds * 1000 );
}
-#else
+#else /* INTEGRITY */
static void sighandler( int signum )
{
@@ -308,6 +315,120 @@
}
#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 c029e9b..6f73608 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 @@
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