Add mbedtls_timing_set/get_delay()
diff --git a/include/mbedtls/timing.h b/include/mbedtls/timing.h
index 0ef1827..efcc5dc 100644
--- a/include/mbedtls/timing.h
+++ b/include/mbedtls/timing.h
@@ -34,6 +34,8 @@
 // Regular implementation
 //
 
+#include <stdint.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -46,6 +48,16 @@
     unsigned char opaque[32];
 };
 
+/**
+ * \brief          Context for mbedtls_timing_set/get_delay()
+ */
+typedef struct
+{
+    struct mbedtls_timing_hr_time   timer;
+    uint32_t                        int_ms;
+    uint32_t                        fin_ms;
+} mbedtls_timing_delay_context;
+
 extern volatile int mbedtls_timing_alarmed;
 
 /**
@@ -79,6 +91,32 @@
  */
 void mbedtls_timing_m_sleep( int milliseconds );
 
+/**
+ * \brief          Set a pair of delays to watch
+ *                 (See \c mbedtls_timing_get_delay().)
+ *
+ * \param data     Pointer to timing data
+ *                 Must point to a valid \c mbetls_timing_delay_context struct.
+ * \param int_ms   First (intermediate) delay in milliseconds.
+ * \param fin_ms   Second (final) delay in milliseconds.
+ *                 Pass 0 to cancel the current delay.
+ */
+void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms );
+
+/**
+ * \brief          Get the status of delays
+ *                 (Memory helper: number of delays passed.)
+ *
+ * \param data     Pointer to timing data
+ *                 Must point to a valid \c mbetls_timing_delay_context struct.
+ *
+ * \return         -1 if cancelled (fin_ms = 0)
+ *                  0 if none of the delays are passed,
+ *                  1 if only the intermediate delay is passed,
+ *                  2 if the final delay is passed.
+ */
+int mbedtls_timing_get_delay( void *data );
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/library/timing.c b/library/timing.c
index 13a529a..8ce9753 100644
--- a/library/timing.c
+++ b/library/timing.c
@@ -335,6 +335,42 @@
 
 #endif /* _WIN32 && !EFIX64 && !EFI32 */
 
+/*
+ * Set delays to watch
+ */
+void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms )
+{
+    mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
+
+    ctx->int_ms = int_ms;
+    ctx->fin_ms = fin_ms;
+
+    if( fin_ms != 0 )
+        (void) mbedtls_timing_get_timer( &ctx->timer, 1 );
+}
+
+/*
+ * Get number of delays expired
+ */
+int mbedtls_timing_get_delay( void *data )
+{
+    mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data;
+    unsigned long elapsed_ms;
+
+    if( ctx->fin_ms == 0 )
+        return( -1 );
+
+    elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 );
+
+    if( elapsed_ms >= ctx->fin_ms )
+        return( 2 );
+
+    if( elapsed_ms >= ctx->int_ms )
+        return( 1 );
+
+    return( 0 );
+}
+
 #endif /* !MBEDTLS_TIMING_ALT */
 
 #if defined(MBEDTLS_SELF_TEST)
@@ -363,6 +399,14 @@
     (void) j;
 }
 
+#define FAIL    do                      \
+{                                       \
+    if( verbose != 0 )                  \
+        mbedtls_printf( "failed\n" );   \
+                                        \
+    return( 1 );                        \
+} while( 0 )
+
 /*
  * Checkup routine
  *
@@ -375,6 +419,8 @@
     unsigned long millisecs, secs;
     int hardfail;
     struct mbedtls_timing_hr_time hires;
+    uint32_t a, b;
+    mbedtls_timing_delay_context ctx;
 
     if( verbose != 0 )
         mbedtls_printf( "  TIMING tests note: will take some time!\n" );
@@ -472,9 +518,44 @@
     if( verbose != 0 )
         mbedtls_printf( "passed\n" );
 
+    if( verbose != 0 )
+        mbedtls_printf( "  TIMING test #4 (m_sleep   / delay    ): " );
+
+    for( a = 100; a <= 200; a += 100 )
+    {
+        for( b = 100; b <= 200; b += 100 )
+        {
+            mbedtls_timing_set_delay( &ctx, a, a + b );
+
+            mbedtls_timing_m_sleep( (int)( a - a / 10 ) );
+            if( mbedtls_timing_get_delay( &ctx ) != 0 )
+                FAIL;
+
+            mbedtls_timing_m_sleep( (int)( a / 5 ) );
+            if( mbedtls_timing_get_delay( &ctx ) != 1 )
+                FAIL;
+
+            mbedtls_timing_m_sleep( (int)( b - a / 5 ) );
+            if( mbedtls_timing_get_delay( &ctx ) != 1 )
+                FAIL;
+
+            mbedtls_timing_m_sleep( (int)( b / 5 ) );
+            if( mbedtls_timing_get_delay( &ctx ) != 2 )
+                FAIL;
+        }
+    }
+
+    mbedtls_timing_set_delay( &ctx, 0, 0 );
+    mbedtls_timing_m_sleep( 200 );
+    if( mbedtls_timing_get_delay( &ctx ) != -1 )
+        FAIL;
+
+    if( verbose != 0 )
+        mbedtls_printf( "passed\n" );
+
 #if defined(MBEDTLS_NET_C) && defined(MBEDTLS_HAVE_TIME)
     if( verbose != 0 )
-        mbedtls_printf( "  TIMING test #4 (net_usleep/ get_timer): " );
+        mbedtls_printf( "  TIMING test #5 (net_usleep/ get_timer): " );
 
     for( secs = 1; secs <= 3; secs++ )
     {