@@ -408,6 +408,101 @@ static void pstrcat(abts_case *tc, void *data)
408408 "abcdefghij12345" );
409409}
410410
411+ #define TIMINGSAFE_RANDS_NUM 20u
412+ #define TIMINGSAFE_RANDS_LEN 32u
413+ static void timingsafe (abts_case * tc , void * data )
414+ {
415+ struct {
416+ const char * sec ;
417+ const char * str ;
418+ int eq_res ;
419+ int neq_res ;
420+ apr_size_t neq_n ;
421+ } sample [] = {
422+ {"" , "" , 1 , 1 , 0 },
423+ {"" , "" , 1 , 1 , 1 },
424+ {"a" , "a" , 1 , 1 , 1 },
425+ {"a" , "a" , 1 , 1 , 2 },
426+ {"a" , "b" , 0 , 0 , 1 },
427+ {"a" , "aa" , 0 , 1 , 1 },
428+ {"a" , "aa" , 0 , 0 , 2 },
429+ {"a" , "aa" , 0 , 0 , 3 },
430+ {"aa" , "a" , 0 , 1 , 1 },
431+ {"aa" , "a" , 0 , 0 , 2 },
432+ {"aa" , "a" , 0 , 0 , 3 },
433+ {"aa" , "aa" , 1 , 1 , 1 },
434+ {"aa" , "aa" , 1 , 1 , 2 },
435+ {"aa" , "aa" , 1 , 1 , 3 },
436+ {"ab" , "ba" , 0 , 0 , 1 },
437+ {"ab" , "ba" , 0 , 0 , 2 },
438+ {"ab" , "ba" , 0 , 0 , 3 },
439+ {NULL ,}
440+ }, * sp ;
441+ struct {
442+ char str [TIMINGSAFE_RANDS_LEN + 1 ];
443+ apr_size_t len ;
444+ } rands [TIMINGSAFE_RANDS_NUM ];
445+ apr_size_t i , j , k ;
446+ int res ;
447+
448+ /* test the sample */
449+ for (sp = sample ; sp -> sec ; ++ sp ) {
450+ res = apr_streq_timingsafe (sp -> sec , sp -> str );
451+ ABTS_INT_EQUAL (tc , strcmp (sp -> sec , sp -> str ) == 0 , res );
452+ ABTS_INT_EQUAL (tc , sp -> eq_res , res );
453+
454+ res = apr_strneq_timingsafe (sp -> sec , sp -> str , sp -> neq_n );
455+ ABTS_INT_EQUAL (tc , strncmp (sp -> sec , sp -> str , sp -> neq_n ) == 0 , res );
456+ ABTS_INT_EQUAL (tc , sp -> neq_res , res );
457+
458+ if (strlen (sp -> sec ) == strlen (sp -> str )) {
459+ res = apr_memeq_timingsafe (sp -> sec , sp -> str , strlen (sp -> sec ));
460+ ABTS_INT_EQUAL (tc , memcmp (sp -> sec , sp -> str , strlen (sp -> sec )) == 0 , res );
461+ ABTS_INT_EQUAL (tc , sp -> eq_res , res );
462+ }
463+ }
464+
465+ /* test random strings */
466+ memset (rands , 0 , sizeof (rands )); /* zero init/pad the whole */
467+ for (i = 0 ; i < TIMINGSAFE_RANDS_NUM ; ++ i ) {
468+ unsigned char randlen = 0 ;
469+ apr_generate_random_bytes ((void * )& randlen , sizeof (randlen ));
470+ rands [i ].len = (unsigned int )randlen % TIMINGSAFE_RANDS_LEN ;
471+ apr_generate_random_bytes ((void * )rands [i ].str , rands [i ].len );
472+ }
473+ for (i = 0 ; i < TIMINGSAFE_RANDS_NUM ; ++ i ) {
474+ for (j = i ; j < TIMINGSAFE_RANDS_NUM ; ++ j ) {
475+ for (k = (j == i ); k < 2 ; ++ k ) { /* both ways for j != i */
476+ apr_size_t i1 = (k ) ? j : i ,
477+ i2 = (k ) ? i : j ;
478+ const char * s1 = rands [i1 ].str ,
479+ * s2 = rands [i2 ].str ;
480+ unsigned int n1 = rands [i1 ].len ,
481+ n2 = rands [i2 ].len ;
482+
483+ ABTS_INT_EQUAL (tc , strcmp (s1 , s2 ) == 0 ,
484+ apr_streq_timingsafe (s1 , s2 ));
485+
486+ ABTS_INT_EQUAL (tc , strncmp (s1 , s2 , n1 ) == 0 ,
487+ apr_strneq_timingsafe (s1 , s2 , n1 ));
488+ ABTS_INT_EQUAL (tc , strncmp (s1 , s2 , n2 ) == 0 ,
489+ apr_strneq_timingsafe (s1 , s2 , n2 ));
490+
491+ /* including trailing \0 */
492+ ABTS_INT_EQUAL (tc , strncmp (s1 , s2 , n1 + 1 ) == 0 ,
493+ apr_strneq_timingsafe (s1 , s2 , n1 + 1 ));
494+ ABTS_INT_EQUAL (tc , strncmp (s1 , s2 , n2 + 1 ) == 0 ,
495+ apr_strneq_timingsafe (s1 , s2 , n2 + 1 ));
496+
497+ ABTS_INT_EQUAL (tc , memcmp (s1 , s2 , n1 ) == 0 ,
498+ apr_memeq_timingsafe (s1 , s2 , n1 ));
499+ ABTS_INT_EQUAL (tc , memcmp (s1 , s2 , n2 ) == 0 ,
500+ apr_memeq_timingsafe (s1 , s2 , n2 ));
501+ }
502+ }
503+ }
504+ }
505+
411506abts_suite * teststr (abts_suite * suite )
412507{
413508 suite = ADD_SUITE (suite )
@@ -427,6 +522,7 @@ abts_suite *teststr(abts_suite *suite)
427522 abts_run_test (suite , snprintf_overflow , NULL );
428523 abts_run_test (suite , skip_prefix , NULL );
429524 abts_run_test (suite , pstrcat , NULL );
525+ abts_run_test (suite , timingsafe , NULL );
430526
431527 return suite ;
432528}
0 commit comments