blob: 6e949c86ba08cc8e81319a5d8c7d191b28a80ca3 [file] [log] [blame]
Paul Bakker50157ff2016-07-19 14:57:00 +01001/* BEGIN_HEADER */
Gilles Peskine8064bf32017-10-10 19:56:06 +02002
3/* This test module exercises the timing module. One of the expected failure
4 modes is for timers to never expire, which could lead to an infinite loop.
5 The function timing_timer_simple is protected against this failure mode and
6 checks that timers do expire. Other functions will terminate if their
7 timers do expire. Therefore it is recommended to run timing_timer_simple
8 first and run other test functions only if that timing_timer_simple
9 succeeded. */
10
11#include <limits.h>
12
Paul Bakker50157ff2016-07-19 14:57:00 +010013#include "mbedtls/timing.h"
Gilles Peskine8064bf32017-10-10 19:56:06 +020014
15/* Wait this many milliseconds for a short timing test. This duration
16 should be large enough that, in practice, if you read the timer
17 value twice in a row, it won't have jumped by that much. */
18#define TIMING_SHORT_TEST_MS 100
19
20/* A loop that waits TIMING_SHORT_TEST_MS must not take more than this many
21 iterations. This value needs to be large enough to accommodate fast
22 platforms (e.g. at 4GHz and 10 cycles/iteration a CPU can run through 20
23 million iterations in 50ms). The only motivation to keep this value low is
24 to avoid having an infinite loop if the timer functions are not implemented
25 correctly. Ideally this value should be based on the processor speed but we
26 don't have this information! */
27#define TIMING_SHORT_TEST_ITERATIONS_MAX 1e8
28
29/* alarm(0) must fire in no longer than this amount of time. */
30#define TIMING_ALARM_0_DELAY_MS TIMING_SHORT_TEST_MS
31
32static int expected_delay_status( uint32_t int_ms, uint32_t fin_ms,
33 unsigned long actual_ms )
34{
35 return( fin_ms == 0 ? -1 :
36 actual_ms >= fin_ms ? 2 :
37 actual_ms >= int_ms ? 1 :
38 0 );
39}
40
Gilles Peskine2a26d622017-10-18 20:00:32 +020041/* Some conditions in timing_timer_simple suggest that timers are unreliable.
42 Most other test cases rely on timers to terminate, and could loop
43 indefinitely if timers are too broken. So if timing_timer_simple detected a
44 timer that risks not terminating (going backwards, or not reaching the
45 desired count in the alloted clock cycles), set this flag to immediately
46 fail those other tests without running any timers. */
47static int timers_are_badly_broken = 0;
48
Paul Bakker50157ff2016-07-19 14:57:00 +010049/* END_HEADER */
50
51/* BEGIN_DEPENDENCIES
52 * depends_on:MBEDTLS_TIMING_C
53 * END_DEPENDENCIES
54 */
55
Azim Khanf1aaec92017-05-30 14:23:15 +010056<<<<<<< HEAD
Gilles Peskine8064bf32017-10-10 19:56:06 +020057/* BEGIN_CASE */
58void timing_timer_simple( )
Paul Bakker50157ff2016-07-19 14:57:00 +010059{
Gilles Peskine8064bf32017-10-10 19:56:06 +020060 struct mbedtls_timing_hr_time timer;
61 unsigned long millis = 0;
62 unsigned long new_millis = 0;
63 unsigned long iterations = 0;
64 /* Start the timer. */
65 (void) mbedtls_timing_get_timer( &timer, 1 );
66 /* Busy-wait loop for a few milliseconds. */
67 do
68 {
69 new_millis = mbedtls_timing_get_timer( &timer, 0 );
70 ++iterations;
71 /* Check that the timer didn't go backwards */
72 TEST_ASSERT( new_millis >= millis );
73 millis = new_millis;
74 }
75 while( millis < TIMING_SHORT_TEST_MS &&
76 iterations <= TIMING_SHORT_TEST_ITERATIONS_MAX );
77 /* The wait duration should have been large enough for at least a
78 few runs through the loop, even on the slowest realistic platform. */
79 TEST_ASSERT( iterations >= 2 );
80 /* The wait duration shouldn't have overflowed the iteration count. */
81 TEST_ASSERT( iterations < TIMING_SHORT_TEST_ITERATIONS_MAX );
82 return;
83
84exit:
Gilles Peskine2a26d622017-10-18 20:00:32 +020085 if( iterations >= TIMING_SHORT_TEST_ITERATIONS_MAX ||
86 new_millis < millis )
87 {
88 /* The timer was very unreliable: it didn't increment and the loop ran
89 out, or it went backwards. Other tests that use timers might go
90 into an infinite loop, so we'll skip them. */
91 timers_are_badly_broken = 1;
92 }
93
Gilles Peskine8064bf32017-10-10 19:56:06 +020094 /* No cleanup needed, but show some diagnostic iterations, because timing
95 problems can be hard to reproduce. */
96 mbedtls_fprintf( stdout, " Finished with millis=%lu new_millis=%lu get(timer)<=%lu iterations=%lu\n",
97 millis, new_millis, mbedtls_timing_get_timer( &timer, 0 ),
98 iterations );
Paul Bakker50157ff2016-07-19 14:57:00 +010099}
100/* END_CASE */
Gilles Peskine8064bf32017-10-10 19:56:06 +0200101
102/* BEGIN_CASE */
103void timing_timer_reset( )
104{
105 struct mbedtls_timing_hr_time timer;
106 unsigned long millis = 0;
107 unsigned long iterations = 0;
Gilles Peskine2a26d622017-10-18 20:00:32 +0200108
109 /* Skip this test if it looks like timers don't work at all, to avoid an
110 infinite loop below. */
111 TEST_ASSERT( !timers_are_badly_broken );
112
Gilles Peskine8064bf32017-10-10 19:56:06 +0200113 /* Start the timer. Timers are always reset to 0. */
114 TEST_ASSERT( mbedtls_timing_get_timer( &timer, 1 ) == 0 );
115 /* Busy-wait loop for a few milliseconds */
116 do
117 {
118 ++iterations;
119 millis = mbedtls_timing_get_timer( &timer, 0 );
120 }
121 while( millis < TIMING_SHORT_TEST_MS );
122
123 /* Reset the timer and check that it has restarted. */
124 TEST_ASSERT( mbedtls_timing_get_timer( &timer, 1 ) == 0 );
125 /* Read the timer immediately after reset. It should be 0 or close
126 to it. */
127 TEST_ASSERT( mbedtls_timing_get_timer( &timer, 0 ) < TIMING_SHORT_TEST_MS );
128 return;
129
130exit:
131 /* No cleanup needed, but show some diagnostic information, because timing
132 problems can be hard to reproduce. */
Gilles Peskine2a26d622017-10-18 20:00:32 +0200133 if( !timers_are_badly_broken )
134 mbedtls_fprintf( stdout, " Finished with millis=%lu get(timer)<=%lu iterations=%lu\n",
135 millis, mbedtls_timing_get_timer( &timer, 0 ),
136 iterations );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200137}
138/* END_CASE */
139
140/* BEGIN_CASE */
141void timing_two_timers( int delta )
142{
143 struct mbedtls_timing_hr_time timer1, timer2;
Gilles Peskine2a26d622017-10-18 20:00:32 +0200144 unsigned long millis1 = 0, millis2 = 0;
145
146 /* Skip this test if it looks like timers don't work at all, to avoid an
147 infinite loop below. */
148 TEST_ASSERT( !timers_are_badly_broken );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200149
150 /* Start the first timer and wait for a short time. */
151 (void) mbedtls_timing_get_timer( &timer1, 1 );
152 do
153 {
154 millis1 = mbedtls_timing_get_timer( &timer1, 0 );
155 }
156 while( millis1 < TIMING_SHORT_TEST_MS );
157
158 /* Do a short busy-wait, so that the difference between timer1 and timer2
159 doesn't practically always end up being very close to a whole number of
160 milliseconds. */
161 while( delta > 0 )
162 --delta;
163
164 /* Start the second timer and compare it with the first. */
165 mbedtls_timing_get_timer( &timer2, 1 );
166 do
167 {
168 millis1 = mbedtls_timing_get_timer( &timer1, 0 );
169 millis2 = mbedtls_timing_get_timer( &timer2, 0 );
170 /* The first timer should always be ahead of the first. */
171 TEST_ASSERT( millis1 > millis2 );
172 /* The timers shouldn't drift apart, i.e. millis2-millis1 should stay
173 roughly constant, but this is hard to test reliably, especially in
174 a busy environment such as an overloaded continuous integration
175 system, so we don't test it it. */
176 }
177 while( millis2 < TIMING_SHORT_TEST_MS );
178
179 return;
180
181exit:
182 /* No cleanup needed, but show some diagnostic iterations, because timing
183 problems can be hard to reproduce. */
Gilles Peskine2a26d622017-10-18 20:00:32 +0200184 if( !timers_are_badly_broken )
185 mbedtls_fprintf( stdout, " Finished with millis1=%lu get(timer1)<=%lu millis2=%lu get(timer2)<=%lu\n",
186 millis1, mbedtls_timing_get_timer( &timer1, 0 ),
187 millis2, mbedtls_timing_get_timer( &timer2, 0 ) );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200188}
189/* END_CASE */
190
191/* BEGIN_CASE */
192void timing_alarm( int seconds )
193{
194 struct mbedtls_timing_hr_time timer;
195 unsigned long millis = 0;
196 /* We check that about the desired number of seconds has elapsed. Be
197 slightly liberal with the lower bound, so as to allow platforms where
198 the alarm (with second resolution) and the timer (with millisecond
199 resolution) are based on different clocks. Be very liberal with the
200 upper bound, because the platform might be busy. */
201 unsigned long millis_min = ( seconds > 0 ?
202 seconds * 900 :
203 0 );
204 unsigned long millis_max = ( seconds > 0 ?
205 seconds * 1100 + 400 :
206 TIMING_ALARM_0_DELAY_MS );
207 unsigned long iterations = 0;
208
Gilles Peskine2a26d622017-10-18 20:00:32 +0200209 /* Skip this test if it looks like timers don't work at all, to avoid an
210 infinite loop below. */
211 TEST_ASSERT( !timers_are_badly_broken );
212
Gilles Peskine8064bf32017-10-10 19:56:06 +0200213 /* Set an alarm and count how long it takes with a timer. */
214 (void) mbedtls_timing_get_timer( &timer, 1 );
215 mbedtls_set_alarm( seconds );
216
217 if( seconds > 0 )
218 {
219 /* We set the alarm for at least 1 second. It should not have fired
220 immediately, even on a slow and busy platform. */
221 TEST_ASSERT( !mbedtls_timing_alarmed );
222 }
223 /* A 0-second alarm should fire quickly, but we don't guarantee that it
224 fires immediately, so mbedtls_timing_alarmed may or may not be set at
225 this point. */
226
227 /* Busy-wait until the alarm rings */
228 do
229 {
230 ++iterations;
231 millis = mbedtls_timing_get_timer( &timer, 0 );
232 }
233 while( !mbedtls_timing_alarmed && millis <= millis_max );
234
235 TEST_ASSERT( mbedtls_timing_alarmed );
236 TEST_ASSERT( millis >= millis_min );
237 TEST_ASSERT( millis <= millis_max );
238
239 mbedtls_timing_alarmed = 0;
240 return;
241
242exit:
243 /* Show some diagnostic iterations, because timing
244 problems can be hard to reproduce. */
Gilles Peskine2a26d622017-10-18 20:00:32 +0200245 if( !timers_are_badly_broken )
246 mbedtls_fprintf( stdout, " Finished with alarmed=%d millis=%lu get(timer)<=%lu iterations=%lu\n",
247 mbedtls_timing_alarmed,
248 millis, mbedtls_timing_get_timer( &timer, 0 ),
249 iterations );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200250 /* Cleanup */
251 mbedtls_timing_alarmed = 0;
252}
253/* END_CASE */
254
255/* BEGIN_CASE */
256void timing_delay( int int_ms, int fin_ms )
257{
258 /* This function assumes that if int_ms is nonzero then it is large
259 enough that we have time to read all timers at least once in an
260 interval of time lasting int_ms milliseconds, and likewise for (fin_ms
261 - int_ms). So don't call it with arguments that are too small. */
262
263 mbedtls_timing_delay_context delay;
264 struct mbedtls_timing_hr_time timer;
Gilles Peskine2a26d622017-10-18 20:00:32 +0200265 unsigned long delta = 0; /* delay started between timer=0 and timer=delta */
Gilles Peskine8064bf32017-10-10 19:56:06 +0200266 unsigned long before = 0, after = 0;
267 unsigned long iterations = 0;
268 int status = -2;
269 int saw_status_1 = 0;
270 int warn_inconclusive = 0;
271
272 assert( int_ms >= 0 );
273 assert( fin_ms >= 0 );
274
Gilles Peskine2a26d622017-10-18 20:00:32 +0200275 /* Skip this test if it looks like timers don't work at all, to avoid an
276 infinite loop below. */
277 TEST_ASSERT( !timers_are_badly_broken );
278
Gilles Peskine8064bf32017-10-10 19:56:06 +0200279 /* Start a reference timer. Program a delay, and verify that the status of
280 the delay is consistent with the time given by the reference timer. */
281 (void) mbedtls_timing_get_timer( &timer, 1 );
282 mbedtls_timing_set_delay( &delay, int_ms, fin_ms );
283 /* Set delta to an upper bound for the interval between the start of timer
284 and the start of delay. Reading timer after starting delay gives us an
285 upper bound for the interval, rounded to a 1ms precision. Since this
286 might have been rounded down, but we need an upper bound, we add 1. */
287 delta = mbedtls_timing_get_timer( &timer, 0 ) + 1;
288
289 status = mbedtls_timing_get_delay( &delay );
290 if( fin_ms == 0 )
291 {
292 /* Cancelled timer. Just check the correct status for this case. */
293 TEST_ASSERT( status == -1 );
294 return;
295 }
296
297 /* Initially, none of the delays must be passed yet if they're nonzero.
298 This could fail for very small values of int_ms and fin_ms, where "very
299 small" depends how fast and how busy the platform is. */
300 if( int_ms > 0 )
301 {
302 TEST_ASSERT( status == 0 );
303 }
304 else
305 {
306 TEST_ASSERT( status == 1 );
307 }
308
309 do
310 {
311 unsigned long delay_min, delay_max;
312 int status_min, status_max;
313 ++iterations;
314 before = mbedtls_timing_get_timer( &timer, 0 );
315 status = mbedtls_timing_get_delay( &delay );
316 after = mbedtls_timing_get_timer( &timer, 0 );
317 /* At a time between before and after, the delay's status was status.
318 Check that this is consistent given that the delay was started
319 between times 0 and delta. */
320 delay_min = ( before > delta ? before - delta : 0 );
321 status_min = expected_delay_status( int_ms, fin_ms, delay_min );
322 delay_max = after;
323 status_max = expected_delay_status( int_ms, fin_ms, delay_max );
324 TEST_ASSERT( status >= status_min );
325 TEST_ASSERT( status <= status_max );
326 if( status == 1 )
327 saw_status_1 = 1;
328 }
329 while ( before <= fin_ms + delta && status != 2 );
330
331 /* Since we've waited at least fin_ms, the delay must have fully
332 expired. */
333 TEST_ASSERT( status == 2 );
334
335 /* If the second delay is more than the first, then there must have been a
336 point in time when the first delay was passed but not the second delay.
337 This could fail for very small values of (fin_ms - int_ms), where "very
338 small" depends how fast and how busy the platform is. In practice, this
339 is the test that's most likely to fail on a heavily loaded machine. */
340 if( fin_ms > int_ms )
341 {
342 warn_inconclusive = 1;
343 TEST_ASSERT( saw_status_1 );
344 }
345
346 return;
347
348exit:
349 /* No cleanup needed, but show some diagnostic iterations, because timing
350 problems can be hard to reproduce. */
Gilles Peskine2a26d622017-10-18 20:00:32 +0200351 if( !timers_are_badly_broken )
352 mbedtls_fprintf( stdout, " Finished with delta=%lu before=%lu after=%lu status=%d iterations=%lu\n",
353 delta, before, after, status, iterations );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200354 if( warn_inconclusive )
355 mbedtls_fprintf( stdout, " Inconclusive test, try running it on a less heavily loaded machine.\n" );
356 }
357/* END_CASE */
Gilles Peskine078f1a12017-10-11 16:13:13 +0200358
359/* BEGIN_CASE */
360void timing_hardclock( )
361{
362 /* We make very few guarantees about mbedtls_timing_hardclock: its rate is
363 platform-dependent, it can wrap around. So there isn't much we can
364 test. But we do at least test that it doesn't crash, stall or return
365 completely nonsensical values. */
366
367 struct mbedtls_timing_hr_time timer;
Gilles Peskine2a26d622017-10-18 20:00:32 +0200368 unsigned long hardclock0 = -1, hardclock1 = -1, delta1 = -1;
369
370 /* Skip this test if it looks like timers don't work at all, to avoid an
371 infinite loop below. */
372 TEST_ASSERT( !timers_are_badly_broken );
Gilles Peskine078f1a12017-10-11 16:13:13 +0200373
374 hardclock0 = mbedtls_timing_hardclock( );
375 /* Wait 2ms to ensure a nonzero delay. Since the timer interface has 1ms
376 resolution and unspecified precision, waiting 1ms might be a very small
377 delay that's rounded up. */
378 (void) mbedtls_timing_get_timer( &timer, 1 );
379 while( mbedtls_timing_get_timer( &timer, 0 ) < 2 )
380 /*busy-wait loop*/;
381 hardclock1 = mbedtls_timing_hardclock( );
382
383 /* Although the hardclock counter can wrap around, the difference
384 (hardclock1 - hardclock0) is taken modulo the type size, so it is
385 correct as long as the counter only wrapped around at most once. We
386 further require the difference to be nonzero (after a wait of more than
387 1ms, the counter must have changed), and not to be overly large (after
388 a wait of less than 3ms, plus time lost because other processes were
389 scheduled on the CPU). If the hardclock counter runs at 4GHz, then
390 1000000000 (which is 1/4 of the counter wraparound on a 32-bit machine)
391 allows 250ms. */
392 delta1 = hardclock1 - hardclock0;
393 TEST_ASSERT( delta1 > 0 );
394 TEST_ASSERT( delta1 < 1000000000 );
395 return;
396
397exit:
398 /* No cleanup needed, but show some diagnostic iterations, because timing
399 problems can be hard to reproduce. */
Gilles Peskine2a26d622017-10-18 20:00:32 +0200400 if( !timers_are_badly_broken )
401 mbedtls_fprintf( stdout, " Finished with hardclock=%lu,%lu\n",
402 hardclock0, hardclock1 );
Gilles Peskine078f1a12017-10-11 16:13:13 +0200403}
404/* END_CASE */