mbedtls_timing_get_timer: don't use uninitialized memory

mbedtls_timing_get_timer with reset=1 is called both to initialize a
timer object and to reset an already-initialized object. In an
initial call, the content of the data structure is indeterminate, so
the code should not read from it. This could crash if signed overflows
trap, for example.

As a consequence, on reset, we can't return the previously elapsed
time as was previously done on Windows. Return 0 as was done on Unix.
This commit is contained in:
Gilles Peskine 2017-10-16 19:33:06 +02:00
parent a9edc4805b
commit d92f0aa3be
3 changed files with 35 additions and 24 deletions

View File

@ -10,6 +10,7 @@ Bugfix
Found by projectgus and jethrogb, #836.
* Fix usage help in ssl_server2 example. Found and fixed by Bei Lin.
* Fix mbedtls_timing_alarm(0) on Unix.
* Fix use of uninitialized memory in mbedtls_timing_get_timer when reset=1.
= mbed TLS 2.6.0 branch released 2017-08-10

View File

@ -75,9 +75,18 @@ unsigned long mbedtls_timing_hardclock( void );
* \brief Return the elapsed time in milliseconds
*
* \param val points to a timer structure
* \param reset if set to 1, the timer is restarted
* \param reset If 0, query the elapsed time. Otherwise (re)start the timer.
*
* \return Elapsed time in ms (before the reset, if there is a reset)
* \return Elapsed time since the previous reset in ms. When
* restarting, this is always 0.
*
* \note To initialize a timer, call this function with reset=1.
*
* Determining the elapsed time and resetting the timer is not
* atomic on all platforms, so after the sequence
* `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 =
* get_timer(0) }` the value time1+time2 is only approximately
* the delay since the first reset.
*/
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset );

View File

@ -244,21 +244,23 @@ volatile int mbedtls_timing_alarmed = 0;
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
{
unsigned long delta;
LARGE_INTEGER offset, hfreq;
struct _hr_time *t = (struct _hr_time *) val;
QueryPerformanceCounter( &offset );
QueryPerformanceFrequency( &hfreq );
delta = (unsigned long)( ( 1000 *
( offset.QuadPart - t->start.QuadPart ) ) /
hfreq.QuadPart );
if( reset )
{
QueryPerformanceCounter( &t->start );
return( delta );
return( 0 );
}
else
{
unsigned long delta;
LARGE_INTEGER now, hfreq;
QueryPerformanceCounter( &now );
QueryPerformanceFrequency( &hfreq );
delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul
/ hfreq.QuadPart );
return( delta );
}
}
/* It's OK to use a global because alarm() is supposed to be global anyway */
@ -285,23 +287,22 @@ void mbedtls_set_alarm( int seconds )
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
{
unsigned long delta;
struct timeval offset;
struct _hr_time *t = (struct _hr_time *) val;
gettimeofday( &offset, NULL );
if( reset )
{
t->start.tv_sec = offset.tv_sec;
t->start.tv_usec = offset.tv_usec;
gettimeofday( &t->start, NULL );
return( 0 );
}
delta = ( offset.tv_sec - t->start.tv_sec ) * 1000
+ ( offset.tv_usec - t->start.tv_usec ) / 1000;
return( delta );
else
{
unsigned long delta;
struct timeval now;
gettimeofday( &now, NULL );
delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul
+ ( now.tv_usec - t->start.tv_usec ) / 1000;
return( delta );
}
}
static void sighandler( int signum )