timing.c 14.4 KB
Newer Older
1 2 3
/*
 *  Portable interface to the CPU cycle counter
 *
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
4
 *  Copyright (C) 2006-2014, ARM Limited, All Rights Reserved
Paul Bakker's avatar
Paul Bakker committed
5
 *
6
 *  This file is part of mbed TLS (https://tls.mbed.org)
Paul Bakker's avatar
Paul Bakker committed
7
 *
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
23
#if !defined(MBEDTLS_CONFIG_FILE)
24
#include "mbedtls/config.h"
25
#else
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
26
#include MBEDTLS_CONFIG_FILE
27
#endif
28

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
29
#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C)
30
#include "mbedtls/platform.h"
31 32
#else
#include <stdio.h>
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
33
#define mbedtls_printf     printf
34 35
#endif

36
#if defined(MBEDTLS_TIMING_C)
37

38
#include "mbedtls/timing.h"
39

40 41
#if !defined(MBEDTLS_TIMING_ALT)

42
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64

#include <windows.h>
#include <winbase.h>

struct _hr_time
{
    LARGE_INTEGER start;
};

#else

#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <time.h>

struct _hr_time
{
    struct timeval start;
};

65
#endif /* _WIN32 && !EFIX64 && !EFI32 */
66

67
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
68
    ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__)
69

70
#define HAVE_HARDCLOCK
71

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
72
unsigned long mbedtls_timing_hardclock( void )
73 74 75 76 77 78
{
    unsigned long tsc;
    __asm   rdtsc
    __asm   mov  [tsc], eax
    return( tsc );
}
79
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
80
          ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */
81

82
/* some versions of mingw-64 have 32-bit longs even on x84_64 */
83
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
84 85
    defined(__GNUC__) && ( defined(__i386__) || (                       \
    ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) )
86

87
#define HAVE_HARDCLOCK
88

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
89
unsigned long mbedtls_timing_hardclock( void )
90
{
91
    unsigned long lo, hi;
92
    asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
93
    return( lo );
94
}
95
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
96
          __GNUC__ && __i386__ */
97

98
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
99
    defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) )
100

101
#define HAVE_HARDCLOCK
102

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
103
unsigned long mbedtls_timing_hardclock( void )
104 105
{
    unsigned long lo, hi;
106
    asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) );
107
    return( lo | ( hi << 32 ) );
108
}
109
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
110
          __GNUC__ && ( __amd64__ || __x86_64__ ) */
111

112
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
113
    defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) )
114

115
#define HAVE_HARDCLOCK
116

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
117
unsigned long mbedtls_timing_hardclock( void )
118 119 120 121 122
{
    unsigned long tbl, tbu0, tbu1;

    do
    {
123 124 125
        asm volatile( "mftbu %0" : "=r" (tbu0) );
        asm volatile( "mftb  %0" : "=r" (tbl ) );
        asm volatile( "mftbu %0" : "=r" (tbu1) );
126 127 128 129 130
    }
    while( tbu0 != tbu1 );

    return( tbl );
}
131
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
132
          __GNUC__ && ( __powerpc__ || __ppc__ ) */
133

134
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
135
    defined(__GNUC__) && defined(__sparc64__)
136

137 138
#if defined(__OpenBSD__)
#warning OpenBSD does not allow access to tick register using software version instead
139
#else
140
#define HAVE_HARDCLOCK
141

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
142
unsigned long mbedtls_timing_hardclock( void )
143 144
{
    unsigned long tick;
145
    asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) );
146 147
    return( tick );
}
148
#endif /* __OpenBSD__ */
149
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
150
          __GNUC__ && __sparc64__ */
151

152
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&  \
153 154
    defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__)

155
#define HAVE_HARDCLOCK
156

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
157
unsigned long mbedtls_timing_hardclock( void )
158 159
{
    unsigned long tick;
160 161
    asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" );
    asm volatile( "mov   %%g1, %0" : "=r" (tick) );
162 163
    return( tick );
}
164
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
165
          __GNUC__ && __sparc__ && !__sparc64__ */
166

167
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&      \
168 169
    defined(__GNUC__) && defined(__alpha__)

170
#define HAVE_HARDCLOCK
171

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
172
unsigned long mbedtls_timing_hardclock( void )
173 174
{
    unsigned long cc;
175
    asm volatile( "rpcc %0" : "=r" (cc) );
176 177
    return( cc & 0xFFFFFFFF );
}
178
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
179
          __GNUC__ && __alpha__ */
180

181
#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) &&      \
182 183
    defined(__GNUC__) && defined(__ia64__)

184
#define HAVE_HARDCLOCK
185

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
186
unsigned long mbedtls_timing_hardclock( void )
187 188
{
    unsigned long itc;
189
    asm volatile( "mov %0 = ar.itc" : "=r" (itc) );
190 191
    return( itc );
}
192
#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM &&
193
          __GNUC__ && __ia64__ */
194

195
#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \
196
    !defined(EFIX64) && !defined(EFI32)
197

198
#define HAVE_HARDCLOCK
199

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
200
unsigned long mbedtls_timing_hardclock( void )
201 202
{
    LARGE_INTEGER offset;
203

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
204
    QueryPerformanceCounter( &offset );
205

206
    return( (unsigned long)( offset.QuadPart ) );
207
}
208
#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */
209

210
#if !defined(HAVE_HARDCLOCK)
211

212
#define HAVE_HARDCLOCK
213 214 215 216

static int hardclock_init = 0;
static struct timeval tv_init;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
217
unsigned long mbedtls_timing_hardclock( void )
218 219 220 221 222 223 224 225 226 227 228 229 230
{
    struct timeval tv_cur;

    if( hardclock_init == 0 )
    {
        gettimeofday( &tv_init, NULL );
        hardclock_init = 1;
    }

    gettimeofday( &tv_cur, NULL );
    return( ( tv_cur.tv_sec  - tv_init.tv_sec  ) * 1000000
          + ( tv_cur.tv_usec - tv_init.tv_usec ) );
}
231
#endif /* !HAVE_HARDCLOCK */
232

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
233
volatile int mbedtls_timing_alarmed = 0;
234

235
#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)
236

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
237
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
{
    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 );
}

256 257 258
/* It's OK to use a global because alarm() is supposed to be global anyway */
static DWORD alarmMs;

259
static DWORD WINAPI TimerProc( LPVOID TimerContext )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
260
{
261 262
    ((void) TimerContext);
    Sleep( alarmMs );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
263
    mbedtls_timing_alarmed = 1;
264 265 266
    return( TRUE );
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
267
void mbedtls_set_alarm( int seconds )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
268
{
269 270
    DWORD ThreadId;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
271
    mbedtls_timing_alarmed = 0;
272 273
    alarmMs = seconds * 1000;
    CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) );
274 275
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
276
void mbedtls_timing_m_sleep( int milliseconds )
277 278 279 280
{
    Sleep( milliseconds );
}

281
#else /* _WIN32 && !EFIX64 && !EFI32 */
282

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
283
unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset )
284 285 286 287 288 289 290 291 292 293 294
{
    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;
295
        return( 0 );
296 297
    }

298 299 300
    delta = ( offset.tv_sec  - t->start.tv_sec  ) * 1000
          + ( offset.tv_usec - t->start.tv_usec ) / 1000;

301 302 303
    return( delta );
}

Paul Bakker's avatar
Paul Bakker committed
304
#if defined(INTEGRITY)
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
305
void mbedtls_timing_m_sleep( int milliseconds )
Paul Bakker's avatar
Paul Bakker committed
306 307 308 309
{
    usleep( milliseconds * 1000 );
}

310
#else /* INTEGRITY */
Paul Bakker's avatar
Paul Bakker committed
311

312
static void sighandler( int signum )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
313
{
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
314
    mbedtls_timing_alarmed = 1;
315 316 317
    signal( signum, sighandler );
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
318
void mbedtls_set_alarm( int seconds )
319
{
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
320
    mbedtls_timing_alarmed = 0;
321 322 323 324
    signal( SIGALRM, sighandler );
    alarm( seconds );
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
325
void mbedtls_timing_m_sleep( int milliseconds )
326 327 328 329
{
    struct timeval tv;

    tv.tv_sec  = milliseconds / 1000;
330
    tv.tv_usec = ( milliseconds % 1000 ) * 1000;
331 332 333

    select( 0, NULL, NULL, NULL, &tv );
}
Paul Bakker's avatar
Paul Bakker committed
334
#endif /* INTEGRITY */
335

336
#endif /* _WIN32 && !EFIX64 && !EFI32 */
337

338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
/*
 * 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 );
}

374 375
#endif /* !MBEDTLS_TIMING_ALT */

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
376
#if defined(MBEDTLS_SELF_TEST)
377

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
378 379
/* To test mbedtls_net_usleep against our functions */
#if defined(MBEDTLS_NET_C) && defined(MBEDTLS_HAVE_TIME)
380
#include "mbedtls/net.h"
381 382
#endif

383 384
/*
 * Busy-waits for the given number of milliseconds.
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
385
 * Used for testing mbedtls_timing_hardclock.
386 387 388
 */
static void busy_msleep( unsigned long msec )
{
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
389
    struct mbedtls_timing_hr_time hires;
390 391 392
    unsigned long i = 0; /* for busy-waiting */
    volatile unsigned long j; /* to prevent optimisation */

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
393
    (void) mbedtls_timing_get_timer( &hires, 1 );
394

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
395
    while( mbedtls_timing_get_timer( &hires, 0 ) < msec )
396 397 398 399 400 401
        i++;

    j = i;
    (void) j;
}

402 403 404 405 406 407 408 409
#define FAIL    do                      \
{                                       \
    if( verbose != 0 )                  \
        mbedtls_printf( "failed\n" );   \
                                        \
    return( 1 );                        \
} while( 0 )

410 411
/*
 * Checkup routine
412 413 414
 *
 * Warning: this is work in progress, some tests may not be reliable enough
 * yet! False positives may happen.
415
 */
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
416
int mbedtls_timing_self_test( int verbose )
417 418 419 420
{
    unsigned long cycles, ratio;
    unsigned long millisecs, secs;
    int hardfail;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
421
    struct mbedtls_timing_hr_time hires;
422 423
    uint32_t a, b;
    mbedtls_timing_delay_context ctx;
424

425
    if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
426
        mbedtls_printf( "  TIMING tests note: will take some time!\n" );
427 428

    if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
429
        mbedtls_printf( "  TIMING test #1 (m_sleep   / get_timer): " );
430 431 432

    for( secs = 1; secs <= 3; secs++ )
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
433
        (void) mbedtls_timing_get_timer( &hires, 1 );
434

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
435
        mbedtls_timing_m_sleep( (int)( 500 * secs ) );
436

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
437
        millisecs = mbedtls_timing_get_timer( &hires, 0 );
438

439
        if( millisecs < 450 * secs || millisecs > 550 * secs )
440 441
        {
            if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
442
                mbedtls_printf( "failed\n" );
443 444 445 446 447 448

            return( 1 );
        }
    }

    if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
449
        mbedtls_printf( "passed\n" );
450 451

    if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
452
        mbedtls_printf( "  TIMING test #2 (set_alarm / get_timer): " );
453 454 455

    for( secs = 1; secs <= 3; secs++ )
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
456
        (void) mbedtls_timing_get_timer( &hires, 1 );
457

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
458 459
        mbedtls_set_alarm( (int) secs );
        while( !mbedtls_timing_alarmed )
460 461
            ;

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
462
        millisecs = mbedtls_timing_get_timer( &hires, 0 );
463 464 465 466

        if( millisecs < 900 * secs || millisecs > 1100 * secs )
        {
            if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
467
                mbedtls_printf( "failed\n" );
468 469 470 471 472 473

            return( 1 );
        }
    }

    if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
474
        mbedtls_printf( "passed\n" );
475 476

    if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
477
        mbedtls_printf( "  TIMING test #3 (hardclock / get_timer): " );
478 479 480 481 482 483 484 485 486 487 488 489

    /*
     * 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 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
490
            mbedtls_printf( "failed\n" );
491 492 493 494 495

        return( 1 );
    }

    /* Get a reference ratio cycles/ms */
496
    millisecs = 1;
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
497
    cycles = mbedtls_timing_hardclock();
498
    busy_msleep( millisecs );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
499
    cycles = mbedtls_timing_hardclock() - cycles;
500
    ratio = cycles / millisecs;
501

502
    /* Check that the ratio is mostly constant */
503 504
    for( millisecs = 2; millisecs <= 4; millisecs++ )
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
505
        cycles = mbedtls_timing_hardclock();
506
        busy_msleep( millisecs );
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
507
        cycles = mbedtls_timing_hardclock() - cycles;
508 509 510 511 512 513 514 515 516 517 518

        /* Allow variation up to 20% */
        if( cycles / millisecs < ratio - ratio / 5 ||
            cycles / millisecs > ratio + ratio / 5 )
        {
            hardfail++;
            goto hard_test;
        }
    }

    if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
519
        mbedtls_printf( "passed\n" );
520

521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
    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" );

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
556
#if defined(MBEDTLS_NET_C) && defined(MBEDTLS_HAVE_TIME)
557
    if( verbose != 0 )
558
        mbedtls_printf( "  TIMING test #5 (net_usleep/ get_timer): " );
559 560 561

    for( secs = 1; secs <= 3; secs++ )
    {
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
562
        (void) mbedtls_timing_get_timer( &hires, 1 );
563

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
564
        mbedtls_net_usleep( 500000 * secs );
565

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
566
        millisecs = mbedtls_timing_get_timer( &hires, 0 );
567 568 569 570

        if( millisecs < 450 * secs || millisecs > 550 * secs )
        {
            if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
571
                mbedtls_printf( "failed\n" );
572 573 574 575 576 577

            return( 1 );
        }
    }

    if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
578 579
        mbedtls_printf( "passed\n" );
#endif /* MBEDTLS_NET_C */
580

581
    if( verbose != 0 )
Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
582
        mbedtls_printf( "\n" );
583

584 585 586
    return( 0 );
}

Manuel Pégourié-Gonnard's avatar
Manuel Pégourié-Gonnard committed
587
#endif /* MBEDTLS_SELF_TEST */
588

589
#endif /* MBEDTLS_TIMING_C */