Allow compile-time configuration of timer callbacks

Introduces
- MBEDTLS_SSL_CONF_SET_TIMER
- MBEDTLS_SSL_CONF_GET_TIMER
which allows to configure timer callbacks at compile-time.

Impact on code-size:

|  | GCC 8.2.1 | ARMC5 5.06 | ARMC6 6.12 |
| --- | --- | --- | --- |
| `libmbedtls.a` before | 23379 | 23981 | 26941 |
| `libmbedtls.a` after | 23351 | 23953 | 26869 |
| gain in Bytes | 28 | 28 | 72 |
diff --git a/configs/baremetal.h b/configs/baremetal.h
index d6ce9a3..ee514b4 100644
--- a/configs/baremetal.h
+++ b/configs/baremetal.h
@@ -93,6 +93,8 @@
 #define MBEDTLS_SSL_CONF_AUTHMODE MBEDTLS_SSL_VERIFY_REQUIRED
 #define MBEDTLS_SSL_CONF_BADMAC_LIMIT 0
 #define MBEDTLS_SSL_CONF_ANTI_REPLAY MBEDTLS_SSL_ANTI_REPLAY_ENABLED
+#define MBEDTLS_SSL_CONF_GET_TIMER mbedtls_timing_get_delay
+#define MBEDTLS_SSL_CONF_SET_TIMER mbedtls_timing_set_delay
 #define MBEDTLS_SSL_CONF_RECV mbedtls_net_recv
 #define MBEDTLS_SSL_CONF_SEND mbedtls_net_send
 #define MBEDTLS_SSL_CONF_RECV_TIMEOUT mbedtls_net_recv_timeout
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 29d9906..496f7e1 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -683,6 +683,13 @@
 #define "MBEDTLS_SSL_CONF_SEND/RECV/RECV_TIMEOUT must be defined simultaneously"
 #endif
 
+#if ( defined(MBEDTLS_SSL_CONF_GET_TIMER) &&            \
+      !defined(MBEDTLS_SSL_CONF_SET_TIMER) ) || \
+    ( !defined(MBEDTLS_SSL_CONF_GET_TIMER) &&           \
+      defined(MBEDTLS_SSL_CONF_SET_TIMER) )
+#define "MBEDTLS_SSL_CONF_GET_TIMER and MBEDTLS_SSL_CONF_SET_TIMER must be defined together."
+#endif
+
 #if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C)
 #error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites"
 #endif
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index a767cb2..da1ae42 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -3601,6 +3601,18 @@
 //#define MBEDTLS_SSL_CONF_CID_LEN 0
 //#define MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID MBEDTLS_SSL_UNEXPECTED_CID_IGNORE
 
+/* The timer callbacks to use by the SSL module.
+ * If defined,
+ * - MBEDTLS_SSL_CONF_SET_TIMER must evaluate to the name of an externally
+ *   defined function with signature
+ *      void (*f_set_timer)( void* , uint32_t, uint32_t ),
+ * * MBEDTLS_SSL_CONF_SEND must evaluate to the name of an externally
+ *   defined function with signature
+ *      int (*f_get_timer)( void* ).
+ */
+//#define MBEDTLS_SSL_CONF_GET_TIMER mbedtls_timing_get_delay
+//#define MBEDTLS_SSL_CONF_SET_TIMER mbedtls_timing_set_delay
+
 /* The send and receive callbacks to use by the SSL module.
  * If defined,
  * - MBEDTLS_SSL_CONF_RECV must evaluate to the name of an externally
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 671d107..f422d44 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1183,8 +1183,12 @@
      */
     void *p_timer;              /*!< context for the timer callbacks */
 
+#if !defined(MBEDTLS_SSL_CONF_SET_TIMER)
     mbedtls_ssl_set_timer_t *f_set_timer;       /*!< set timer callback */
+#endif /* !MBEDTLS_SSL_CONF_SET_TIMER */
+#if !defined(MBEDTLS_SSL_CONF_GET_TIMER)
     mbedtls_ssl_get_timer_t *f_get_timer;       /*!< get timer callback */
+#endif /* !MBEDTLS_SSL_CONF_GET_TIMER */
 
     /*
      * Record layer (incoming data)
@@ -1779,6 +1783,8 @@
 void mbedtls_ssl_conf_read_timeout( mbedtls_ssl_config *conf, uint32_t timeout );
 #endif /* !MBEDTLS_SSL_CONF_READ_TIMEOUT */
 
+#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && \
+    !defined(MBEDTLS_SSL_CONF_GET_TIMER)
 /**
  * \brief          Set the timer callbacks (Mandatory for DTLS.)
  *
@@ -1796,6 +1802,12 @@
  *                 \c mbedtls_timing_get_delay() that are suitable for using
  *                 here, except if using an event-driven style.
  *
+ * \note           On constrained systems, the timer callbacks \p f_set_timer
+ *                 and \p f_get_timer may also be configured at compile-time
+ *                 via MBEDTLS_SSL_CONF_GET_TIMER and MBEDTLS_SSL_CONF_SET_TIMER.
+ *                 In this case, the corresponding arguments to this function
+ *                 are ignored.
+ *
  * \note           See also the "DTLS tutorial" article in our knowledge base.
  *                 https://tls.mbed.org/kb/how-to/dtls-tutorial
  */
@@ -1803,6 +1815,18 @@
                                void *p_timer,
                                mbedtls_ssl_set_timer_t *f_set_timer,
                                mbedtls_ssl_get_timer_t *f_get_timer );
+#else
+/**
+ * \brief          Set the context to be passed to the timer callbacks
+ *                 (Mandatory for DTLS.)
+ *
+ * \param ssl      The SSL context to configure.
+ * \param p_timer  The context to be passed to the timer callbacks.
+ *
+ */
+void mbedtls_ssl_set_timer_cb_ctx( mbedtls_ssl_context *ssl,
+                                   void *p_timer );
+#endif
 
 /**
  * \brief           Callback type: generate and write session ticket
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 8d5170c..4b85781 100644
--- a/include/mbedtls/ssl_internal.h
+++ b/include/mbedtls/ssl_internal.h
@@ -1291,6 +1291,44 @@
 
 typedef int (*mbedtls_frng_t)( void*, unsigned char*, size_t );
 
+#if !defined(MBEDTLS_SSL_CONF_SET_TIMER)
+static inline mbedtls_ssl_set_timer_t* mbedtls_ssl_get_set_timer(
+    mbedtls_ssl_context const *ssl )
+{
+    return( ssl->f_set_timer );
+}
+#else /* !MBEDTLS_SSL_CONF_SET_TIMER */
+
+#define mbedtls_ssl_conf_set_timer_func MBEDTLS_SSL_CONF_SET_TIMER
+extern void mbedtls_ssl_conf_set_timer_func( void*, uint32_t, uint32_t );
+
+static inline mbedtls_ssl_set_timer_t* mbedtls_ssl_get_set_timer(
+    mbedtls_ssl_context const *ssl )
+{
+    ((void) ssl);
+    return ((mbedtls_ssl_set_timer_t*) mbedtls_ssl_conf_set_timer_func);
+}
+#endif /* MBEDTLS_SSL_CONF_SET_TIMER */
+
+#if !defined(MBEDTLS_SSL_CONF_GET_TIMER)
+static inline mbedtls_ssl_get_timer_t* mbedtls_ssl_get_get_timer(
+    mbedtls_ssl_context const *ssl )
+{
+    return( ssl->f_get_timer );
+}
+#else /* !MBEDTLS_SSL_CONF_GET_TIMER */
+
+#define mbedtls_ssl_conf_get_timer_func MBEDTLS_SSL_CONF_GET_TIMER
+extern int mbedtls_ssl_conf_get_timer_func( void* );
+
+static inline mbedtls_ssl_get_timer_t* mbedtls_ssl_get_get_timer(
+    mbedtls_ssl_context const *ssl )
+{
+    ((void) ssl);
+    return ((mbedtls_ssl_get_timer_t*) mbedtls_ssl_conf_get_timer_func);
+}
+#endif /* MBEDTLS_SSL_CONF_GET_TIMER */
+
 #if !defined(MBEDTLS_SSL_CONF_RECV)
 static inline mbedtls_ssl_recv_t* mbedtls_ssl_get_recv(
     mbedtls_ssl_context const *ssl )
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 847ac71..016c5d8 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -81,11 +81,13 @@
  */
 static void ssl_set_timer( mbedtls_ssl_context *ssl, uint32_t millisecs )
 {
-    if( ssl->f_set_timer == NULL )
+    if( mbedtls_ssl_get_set_timer( ssl ) == NULL )
         return;
 
     MBEDTLS_SSL_DEBUG_MSG( 3, ( "set_timer to %d ms", (int) millisecs ) );
-    ssl->f_set_timer( ssl->p_timer, millisecs / 4, millisecs );
+    mbedtls_ssl_get_set_timer( ssl )( ssl->p_timer,
+                                           millisecs / 4,
+                                           millisecs );
 }
 
 /*
@@ -93,10 +95,10 @@
  */
 static int ssl_check_timer( mbedtls_ssl_context *ssl )
 {
-    if( ssl->f_get_timer == NULL )
+    if( mbedtls_ssl_get_get_timer( ssl ) == NULL )
         return( 0 );
 
-    if( ssl->f_get_timer( ssl->p_timer ) == 2 )
+    if( mbedtls_ssl_get_get_timer( ssl )( ssl->p_timer ) == 2 )
     {
         MBEDTLS_SSL_DEBUG_MSG( 3, ( "timer expired" ) );
         return( -1 );
@@ -3084,7 +3086,8 @@
         uint32_t timeout;
 
         /* Just to be sure */
-        if( ssl->f_set_timer == NULL || ssl->f_get_timer == NULL )
+        if( mbedtls_ssl_get_set_timer( ssl ) == NULL ||
+            mbedtls_ssl_get_get_timer( ssl ) == NULL )
         {
             MBEDTLS_SSL_DEBUG_MSG( 1, ( "You must use "
                         "mbedtls_ssl_set_timer_cb() for DTLS" ) );
@@ -8254,6 +8257,8 @@
 }
 #endif /* MBEDTLS_SSL_CONF_READ_TIMEOUT */
 
+#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && \
+    !defined(MBEDTLS_SSL_CONF_GET_TIMER)
 void mbedtls_ssl_set_timer_cb( mbedtls_ssl_context *ssl,
                                void *p_timer,
                                mbedtls_ssl_set_timer_t *f_set_timer,
@@ -8262,10 +8267,18 @@
     ssl->p_timer        = p_timer;
     ssl->f_set_timer    = f_set_timer;
     ssl->f_get_timer    = f_get_timer;
-
     /* Make sure we start with no timer running */
     ssl_set_timer( ssl, 0 );
 }
+#else
+void mbedtls_ssl_set_timer_cb_ctx( mbedtls_ssl_context *ssl,
+                               void *p_timer )
+{
+    ssl->p_timer        = p_timer;
+    /* Make sure we start with no timer running */
+    ssl_set_timer( ssl, 0 );
+}
+#endif
 
 #if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_NO_SESSION_CACHE)
 void mbedtls_ssl_conf_session_cache( mbedtls_ssl_config *conf,
@@ -10017,8 +10030,8 @@
     while( ssl->in_offt == NULL )
     {
         /* Start timer if not already running */
-        if( ssl->f_get_timer != NULL &&
-            ssl->f_get_timer( ssl->p_timer ) == -1 )
+        if( mbedtls_ssl_get_get_timer( ssl ) != NULL &&
+            mbedtls_ssl_get_get_timer( ssl )( ssl->p_timer ) == -1 )
         {
             ssl_set_timer( ssl,
                            mbedtls_ssl_conf_get_read_timeout( ssl->conf ) );
diff --git a/programs/ssl/dtls_client.c b/programs/ssl/dtls_client.c
index 6f508ae..700e197 100644
--- a/programs/ssl/dtls_client.c
+++ b/programs/ssl/dtls_client.c
@@ -213,8 +213,15 @@
      mbedtls_ssl_set_bio_ctx( &ssl, &server_fd );
 #endif
 
+#if defined(MBEDTLS_TIMING_C)
+#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && \
+    !defined(MBEDTLS_SSL_CONF_GET_TIMER)
     mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay,
                                             mbedtls_timing_get_delay );
+#else
+    mbedtls_ssl_set_timer_cb_ctx( &ssl, &timer );
+#endif
+#endif
 
     mbedtls_printf( " ok\n" );
 
diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c
index 7d19d69..e238a95 100644
--- a/programs/ssl/dtls_server.c
+++ b/programs/ssl/dtls_server.c
@@ -254,8 +254,14 @@
         goto exit;
     }
 
-    mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay,
-                                            mbedtls_timing_get_delay );
+#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && \
+    !defined(MBEDTLS_SSL_CONF_GET_TIMER)
+    mbedtls_ssl_set_timer_cb( &ssl, &timer,
+                              mbedtls_timing_set_delay,
+                              mbedtls_timing_get_delay );
+#else
+    mbedtls_ssl_set_timer_cb_ctx( &ssl, &timer );
+#endif
 
     printf( " ok\n" );
 
diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c
index a4881df..cda71fd 100644
--- a/programs/ssl/query_config.c
+++ b/programs/ssl/query_config.c
@@ -2706,6 +2706,22 @@
     }
 #endif /* MBEDTLS_SSL_CONF_IGNORE_UNEXPECTED_CID */
 
+#if defined(MBEDTLS_SSL_CONF_GET_TIMER)
+    if( strcmp( "MBEDTLS_SSL_CONF_GET_TIMER", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_GET_TIMER );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_GET_TIMER */
+
+#if defined(MBEDTLS_SSL_CONF_SET_TIMER)
+    if( strcmp( "MBEDTLS_SSL_CONF_SET_TIMER", config ) == 0 )
+    {
+        MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_CONF_SET_TIMER );
+        return( 0 );
+    }
+#endif /* MBEDTLS_SSL_CONF_SET_TIMER */
+
 #if defined(MBEDTLS_SSL_CONF_RECV)
     if( strcmp( "MBEDTLS_SSL_CONF_RECV", config ) == 0 )
     {
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index 695cc6a..c63b445 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -1915,8 +1915,13 @@
 #endif
 
 #if defined(MBEDTLS_TIMING_C)
+#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && \
+    !defined(MBEDTLS_SSL_CONF_GET_TIMER)
     mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay,
                                             mbedtls_timing_get_delay );
+#else
+    mbedtls_ssl_set_timer_cb_ctx( &ssl, &timer );
+#endif
 #endif
 
 #if defined(MBEDTLS_ECP_RESTARTABLE)
@@ -2507,9 +2512,16 @@
 
 #if defined(MBEDTLS_TIMING_C)
             if( opt.nbio != 0 && opt.read_timeout != 0 )
+            {
+#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && \
+    !defined(MBEDTLS_SSL_CONF_GET_TIMER)
                 mbedtls_ssl_set_timer_cb( &ssl, &timer,
                                           mbedtls_timing_set_delay,
                                           mbedtls_timing_get_delay );
+#else
+                mbedtls_ssl_set_timer_cb_ctx( &ssl, &timer );
+#endif
+            }
 #endif /* MBEDTLS_TIMING_C */
         }
 
diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 916a642..876a7a0 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -2898,8 +2898,13 @@
 #endif
 
 #if defined(MBEDTLS_TIMING_C)
+#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && \
+    !defined(MBEDTLS_SSL_CONF_GET_TIMER)
     mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay,
                                             mbedtls_timing_get_delay );
+#else
+    mbedtls_ssl_set_timer_cb_ctx( &ssl, &timer );
+#endif
 #endif
 
     mbedtls_printf( " ok\n" );
@@ -3515,9 +3520,16 @@
 
 #if defined(MBEDTLS_TIMING_C)
             if( opt.nbio != 0 && opt.read_timeout != 0 )
+            {
+#if !defined(MBEDTLS_SSL_CONF_SET_TIMER) && \
+    !defined(MBEDTLS_SSL_CONF_GET_TIMER)
                 mbedtls_ssl_set_timer_cb( &ssl, &timer,
                                           mbedtls_timing_set_delay,
                                           mbedtls_timing_get_delay );
+#else
+                mbedtls_ssl_set_timer_cb_ctx( &ssl, &timer );
+#endif
+            }
 #endif /* MBEDTLS_TIMING_C */
         }