blob: 1610155fbf4f1a31274a7e30ce3e1b9e52d7150e [file] [log] [blame] [raw]
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
Gilles Peskine8064bf32017-10-10 19:56:06 +020056/* BEGIN_CASE */
57void timing_timer_simple( )
Paul Bakker50157ff2016-07-19 14:57:00 +010058{
Gilles Peskine8064bf32017-10-10 19:56:06 +020059 struct mbedtls_timing_hr_time timer;
60 unsigned long millis = 0;
61 unsigned long new_millis = 0;
62 unsigned long iterations = 0;
63 /* Start the timer. */
64 (void) mbedtls_timing_get_timer( &timer, 1 );
65 /* Busy-wait loop for a few milliseconds. */
66 do
67 {
68 new_millis = mbedtls_timing_get_timer( &timer, 0 );
69 ++iterations;
70 /* Check that the timer didn't go backwards */
71 TEST_ASSERT( new_millis >= millis );
72 millis = new_millis;
73 }
74 while( millis < TIMING_SHORT_TEST_MS &&
75 iterations <= TIMING_SHORT_TEST_ITERATIONS_MAX );
76 /* The wait duration should have been large enough for at least a
77 few runs through the loop, even on the slowest realistic platform. */
78 TEST_ASSERT( iterations >= 2 );
79 /* The wait duration shouldn't have overflowed the iteration count. */
80 TEST_ASSERT( iterations < TIMING_SHORT_TEST_ITERATIONS_MAX );
81 return;
82
83exit:
Gilles Peskine2a26d622017-10-18 20:00:32 +020084 if( iterations >= TIMING_SHORT_TEST_ITERATIONS_MAX ||
85 new_millis < millis )
86 {
87 /* The timer was very unreliable: it didn't increment and the loop ran
88 out, or it went backwards. Other tests that use timers might go
89 into an infinite loop, so we'll skip them. */
90 timers_are_badly_broken = 1;
91 }
92
Gilles Peskine8064bf32017-10-10 19:56:06 +020093 /* No cleanup needed, but show some diagnostic iterations, because timing
94 problems can be hard to reproduce. */
95 mbedtls_fprintf( stdout, " Finished with millis=%lu new_millis=%lu get(timer)<=%lu iterations=%lu\n",
96 millis, new_millis, mbedtls_timing_get_timer( &timer, 0 ),
97 iterations );
Paul Bakker50157ff2016-07-19 14:57:00 +010098}
99/* END_CASE */
Gilles Peskine8064bf32017-10-10 19:56:06 +0200100
101/* BEGIN_CASE */
102void timing_timer_reset( )
103{
104 struct mbedtls_timing_hr_time timer;
105 unsigned long millis = 0;
106 unsigned long iterations = 0;
Gilles Peskine2a26d622017-10-18 20:00:32 +0200107
108 /* Skip this test if it looks like timers don't work at all, to avoid an
109 infinite loop below. */
110 TEST_ASSERT( !timers_are_badly_broken );
111
Gilles Peskine8064bf32017-10-10 19:56:06 +0200112 /* Start the timer. Timers are always reset to 0. */
113 TEST_ASSERT( mbedtls_timing_get_timer( &timer, 1 ) == 0 );
114 /* Busy-wait loop for a few milliseconds */
115 do
116 {
117 ++iterations;
118 millis = mbedtls_timing_get_timer( &timer, 0 );
119 }
120 while( millis < TIMING_SHORT_TEST_MS );
121
122 /* Reset the timer and check that it has restarted. */
123 TEST_ASSERT( mbedtls_timing_get_timer( &timer, 1 ) == 0 );
124 /* Read the timer immediately after reset. It should be 0 or close
125 to it. */
126 TEST_ASSERT( mbedtls_timing_get_timer( &timer, 0 ) < TIMING_SHORT_TEST_MS );
127 return;
128
129exit:
130 /* No cleanup needed, but show some diagnostic information, because timing
131 problems can be hard to reproduce. */
Gilles Peskine2a26d622017-10-18 20:00:32 +0200132 if( !timers_are_badly_broken )
133 mbedtls_fprintf( stdout, " Finished with millis=%lu get(timer)<=%lu iterations=%lu\n",
134 millis, mbedtls_timing_get_timer( &timer, 0 ),
135 iterations );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200136}
137/* END_CASE */
138
139/* BEGIN_CASE */
140void timing_two_timers( int delta )
141{
142 struct mbedtls_timing_hr_time timer1, timer2;
Gilles Peskine2a26d622017-10-18 20:00:32 +0200143 unsigned long millis1 = 0, millis2 = 0;
144
145 /* Skip this test if it looks like timers don't work at all, to avoid an
146 infinite loop below. */
147 TEST_ASSERT( !timers_are_badly_broken );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200148
149 /* Start the first timer and wait for a short time. */
150 (void) mbedtls_timing_get_timer( &timer1, 1 );
151 do
152 {
153 millis1 = mbedtls_timing_get_timer( &timer1, 0 );
154 }
155 while( millis1 < TIMING_SHORT_TEST_MS );
156
157 /* Do a short busy-wait, so that the difference between timer1 and timer2
158 doesn't practically always end up being very close to a whole number of
159 milliseconds. */
160 while( delta > 0 )
161 --delta;
162
163 /* Start the second timer and compare it with the first. */
164 mbedtls_timing_get_timer( &timer2, 1 );
165 do
166 {
167 millis1 = mbedtls_timing_get_timer( &timer1, 0 );
168 millis2 = mbedtls_timing_get_timer( &timer2, 0 );
169 /* The first timer should always be ahead of the first. */
170 TEST_ASSERT( millis1 > millis2 );
171 /* The timers shouldn't drift apart, i.e. millis2-millis1 should stay
172 roughly constant, but this is hard to test reliably, especially in
173 a busy environment such as an overloaded continuous integration
174 system, so we don't test it it. */
175 }
176 while( millis2 < TIMING_SHORT_TEST_MS );
177
178 return;
179
180exit:
181 /* No cleanup needed, but show some diagnostic iterations, because timing
182 problems can be hard to reproduce. */
Gilles Peskine2a26d622017-10-18 20:00:32 +0200183 if( !timers_are_badly_broken )
184 mbedtls_fprintf( stdout, " Finished with millis1=%lu get(timer1)<=%lu millis2=%lu get(timer2)<=%lu\n",
185 millis1, mbedtls_timing_get_timer( &timer1, 0 ),
186 millis2, mbedtls_timing_get_timer( &timer2, 0 ) );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200187}
188/* END_CASE */
189
190/* BEGIN_CASE */
191void timing_alarm( int seconds )
192{
193 struct mbedtls_timing_hr_time timer;
194 unsigned long millis = 0;
195 /* We check that about the desired number of seconds has elapsed. Be
196 slightly liberal with the lower bound, so as to allow platforms where
197 the alarm (with second resolution) and the timer (with millisecond
198 resolution) are based on different clocks. Be very liberal with the
199 upper bound, because the platform might be busy. */
200 unsigned long millis_min = ( seconds > 0 ?
201 seconds * 900 :
202 0 );
203 unsigned long millis_max = ( seconds > 0 ?
204 seconds * 1100 + 400 :
205 TIMING_ALARM_0_DELAY_MS );
206 unsigned long iterations = 0;
Gilles Peskine2a26d622017-10-18 20:00:32 +0200207
208 /* Skip this test if it looks like timers don't work at all, to avoid an
209 infinite loop below. */
210 TEST_ASSERT( !timers_are_badly_broken );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200211
212 /* Set an alarm and count how long it takes with a timer. */
213 (void) mbedtls_timing_get_timer( &timer, 1 );
214 mbedtls_set_alarm( seconds );
215
216 if( seconds > 0 )
217 {
218 /* We set the alarm for at least 1 second. It should not have fired
219 immediately, even on a slow and busy platform. */
220 TEST_ASSERT( !mbedtls_timing_alarmed );
221 }
222 /* A 0-second alarm should fire quickly, but we don't guarantee that it
223 fires immediately, so mbedtls_timing_alarmed may or may not be set at
224 this point. */
225
226 /* Busy-wait until the alarm rings */
227 do
228 {
229 ++iterations;
230 millis = mbedtls_timing_get_timer( &timer, 0 );
231 }
232 while( !mbedtls_timing_alarmed && millis <= millis_max );
233
234 TEST_ASSERT( mbedtls_timing_alarmed );
235 TEST_ASSERT( millis >= millis_min );
236 TEST_ASSERT( millis <= millis_max );
237
238 mbedtls_timing_alarmed = 0;
239 return;
240
241exit:
242 /* Show some diagnostic iterations, because timing
243 problems can be hard to reproduce. */
Gilles Peskine2a26d622017-10-18 20:00:32 +0200244 if( !timers_are_badly_broken )
245 mbedtls_fprintf( stdout, " Finished with alarmed=%d millis=%lu get(timer)<=%lu iterations=%lu\n",
246 mbedtls_timing_alarmed,
247 millis, mbedtls_timing_get_timer( &timer, 0 ),
248 iterations );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200249 /* Cleanup */
250 mbedtls_timing_alarmed = 0;
251}
252/* END_CASE */
253
254/* BEGIN_CASE */
255void timing_delay( int int_ms, int fin_ms )
256{
257 /* This function assumes that if int_ms is nonzero then it is large
258 enough that we have time to read all timers at least once in an
259 interval of time lasting int_ms milliseconds, and likewise for (fin_ms
260 - int_ms). So don't call it with arguments that are too small. */
261
262 mbedtls_timing_delay_context delay;
263 struct mbedtls_timing_hr_time timer;
Gilles Peskine2a26d622017-10-18 20:00:32 +0200264 unsigned long delta = 0; /* delay started between timer=0 and timer=delta */
Gilles Peskine8064bf32017-10-10 19:56:06 +0200265 unsigned long before = 0, after = 0;
266 unsigned long iterations = 0;
267 int status = -2;
268 int saw_status_1 = 0;
269 int warn_inconclusive = 0;
270
271 assert( int_ms >= 0 );
272 assert( fin_ms >= 0 );
Gilles Peskine2a26d622017-10-18 20:00:32 +0200273
274 /* Skip this test if it looks like timers don't work at all, to avoid an
275 infinite loop below. */
276 TEST_ASSERT( !timers_are_badly_broken );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200277
278 /* Start a reference timer. Program a delay, and verify that the status of
279 the delay is consistent with the time given by the reference timer. */
280 (void) mbedtls_timing_get_timer( &timer, 1 );
281 mbedtls_timing_set_delay( &delay, int_ms, fin_ms );
282 /* Set delta to an upper bound for the interval between the start of timer
283 and the start of delay. Reading timer after starting delay gives us an
284 upper bound for the interval, rounded to a 1ms precision. Since this
285 might have been rounded down, but we need an upper bound, we add 1. */
286 delta = mbedtls_timing_get_timer( &timer, 0 ) + 1;
287
288 status = mbedtls_timing_get_delay( &delay );
289 if( fin_ms == 0 )
290 {
291 /* Cancelled timer. Just check the correct status for this case. */
292 TEST_ASSERT( status == -1 );
293 return;
294 }
295
296 /* Initially, none of the delays must be passed yet if they're nonzero.
297 This could fail for very small values of int_ms and fin_ms, where "very
298 small" depends how fast and how busy the platform is. */
299 if( int_ms > 0 )
300 {
301 TEST_ASSERT( status == 0 );
302 }
303 else
304 {
305 TEST_ASSERT( status == 1 );
306 }
307
308 do
309 {
310 unsigned long delay_min, delay_max;
311 int status_min, status_max;
312 ++iterations;
313 before = mbedtls_timing_get_timer( &timer, 0 );
314 status = mbedtls_timing_get_delay( &delay );
315 after = mbedtls_timing_get_timer( &timer, 0 );
316 /* At a time between before and after, the delay's status was status.
317 Check that this is consistent given that the delay was started
318 between times 0 and delta. */
319 delay_min = ( before > delta ? before - delta : 0 );
320 status_min = expected_delay_status( int_ms, fin_ms, delay_min );
321 delay_max = after;
322 status_max = expected_delay_status( int_ms, fin_ms, delay_max );
323 TEST_ASSERT( status >= status_min );
324 TEST_ASSERT( status <= status_max );
325 if( status == 1 )
326 saw_status_1 = 1;
327 }
328 while ( before <= fin_ms + delta && status != 2 );
329
330 /* Since we've waited at least fin_ms, the delay must have fully
331 expired. */
332 TEST_ASSERT( status == 2 );
333
334 /* If the second delay is more than the first, then there must have been a
335 point in time when the first delay was passed but not the second delay.
336 This could fail for very small values of (fin_ms - int_ms), where "very
337 small" depends how fast and how busy the platform is. In practice, this
338 is the test that's most likely to fail on a heavily loaded machine. */
339 if( fin_ms > int_ms )
340 {
341 warn_inconclusive = 1;
342 TEST_ASSERT( saw_status_1 );
343 }
344
345 return;
346
347exit:
348 /* No cleanup needed, but show some diagnostic iterations, because timing
349 problems can be hard to reproduce. */
Gilles Peskine2a26d622017-10-18 20:00:32 +0200350 if( !timers_are_badly_broken )
351 mbedtls_fprintf( stdout, " Finished with delta=%lu before=%lu after=%lu status=%d iterations=%lu\n",
352 delta, before, after, status, iterations );
Gilles Peskine8064bf32017-10-10 19:56:06 +0200353 if( warn_inconclusive )
354 mbedtls_fprintf( stdout, " Inconclusive test, try running it on a less heavily loaded machine.\n" );
355 }
356/* END_CASE */
Gilles Peskine078f1a12017-10-11 16:13:13 +0200357
358/* BEGIN_CASE */
359void timing_hardclock( )
360{
361 /* We make very few guarantees about mbedtls_timing_hardclock: its rate is
362 platform-dependent, it can wrap around. So there isn't much we can
363 test. But we do at least test that it doesn't crash, stall or return
364 completely nonsensical values. */
365
366 struct mbedtls_timing_hr_time timer;
Gilles Peskine2a26d622017-10-18 20:00:32 +0200367 unsigned long hardclock0 = -1, hardclock1 = -1, delta1 = -1;
368
369 /* Skip this test if it looks like timers don't work at all, to avoid an
370 infinite loop below. */
371 TEST_ASSERT( !timers_are_badly_broken );
Gilles Peskine078f1a12017-10-11 16:13:13 +0200372
373 hardclock0 = mbedtls_timing_hardclock( );
374 /* Wait 2ms to ensure a nonzero delay. Since the timer interface has 1ms
375 resolution and unspecified precision, waiting 1ms might be a very small
376 delay that's rounded up. */
377 (void) mbedtls_timing_get_timer( &timer, 1 );
378 while( mbedtls_timing_get_timer( &timer, 0 ) < 2 )
379 /*busy-wait loop*/;
380 hardclock1 = mbedtls_timing_hardclock( );
381
382 /* Although the hardclock counter can wrap around, the difference
383 (hardclock1 - hardclock0) is taken modulo the type size, so it is
384 correct as long as the counter only wrapped around at most once. We
385 further require the difference to be nonzero (after a wait of more than
386 1ms, the counter must have changed), and not to be overly large (after
387 a wait of less than 3ms, plus time lost because other processes were
388 scheduled on the CPU). If the hardclock counter runs at 4GHz, then
389 1000000000 (which is 1/4 of the counter wraparound on a 32-bit machine)
390 allows 250ms. */
391 delta1 = hardclock1 - hardclock0;
392 TEST_ASSERT( delta1 > 0 );
393 TEST_ASSERT( delta1 < 1000000000 );
394 return;
395
396exit:
397 /* No cleanup needed, but show some diagnostic iterations, because timing
398 problems can be hard to reproduce. */
Gilles Peskine2a26d622017-10-18 20:00:32 +0200399 if( !timers_are_badly_broken )
400 mbedtls_fprintf( stdout, " Finished with hardclock=%lu,%lu\n",
401 hardclock0, hardclock1 );
Gilles Peskine078f1a12017-10-11 16:13:13 +0200402}
403/* END_CASE */