#line 2 "suites/helpers.function" /*----------------------------------------------------------------------------*/ /* Headers */ #include #include #include #if defined(MBEDTLS_PSA_CRYPTO_C) #include #endif #include #if defined(MBEDTLS_PLATFORM_C) #include "mbedtls/platform.h" #else #include #define mbedtls_fprintf fprintf #define mbedtls_snprintf snprintf #define mbedtls_calloc calloc #define mbedtls_free free #define mbedtls_exit exit #define mbedtls_time time #define mbedtls_time_t time_t #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE #endif #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) #include "mbedtls/memory_buffer_alloc.h" #endif #if defined(MBEDTLS_CHECK_PARAMS) #include "mbedtls/platform_util.h" #include #endif #ifdef _MSC_VER #include typedef UINT8 uint8_t; typedef INT32 int32_t; typedef UINT32 uint32_t; #define strncasecmp _strnicmp #define strcasecmp _stricmp #else #include #endif #include #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) #include #include #endif /* Type for Hex parameters */ typedef struct data_tag { uint8_t * x; uint32_t len; } data_t; /*----------------------------------------------------------------------------*/ /* Status and error constants */ #define DEPENDENCY_SUPPORTED 0 /* Dependency supported by build */ #define KEY_VALUE_MAPPING_FOUND 0 /* Integer expression found */ #define DISPATCH_TEST_SUCCESS 0 /* Test dispatch successful */ #define KEY_VALUE_MAPPING_NOT_FOUND -1 /* Integer expression not found */ #define DEPENDENCY_NOT_SUPPORTED -2 /* Dependency not supported */ #define DISPATCH_TEST_FN_NOT_FOUND -3 /* Test function not found */ #define DISPATCH_INVALID_TEST_DATA -4 /* Invalid test parameter type. Only int, string, binary data and integer expressions are allowed */ #define DISPATCH_UNSUPPORTED_SUITE -5 /* Test suite not supported by the build */ /*----------------------------------------------------------------------------*/ /* Macros */ /** * \brief This macro tests the expression passed to it as a test step or * individual test in a test case. * * It allows a library function to return a value and return an error * code that can be tested. * * When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure * callback, MBEDTLS_PARAM_FAILED(), will be assumed to be a test * failure. * * This macro is not suitable for negative parameter validation tests, * as it assumes the test step will not create an error. * * Failing the test means: * - Mark this test case as failed. * - Print a message identifying the failure. * - Jump to the \c exit label. * * This macro expands to an instruction, not an expression. * It may jump to the \c exit label. * * \param TEST The test expression to be tested. */ #define TEST_ASSERT( TEST ) \ do { \ if( ! (TEST) ) \ { \ test_fail( #TEST, __LINE__, __FILE__ ); \ goto exit; \ } \ } while( 0 ) /** Evaluate two expressions and fail the test case if they have different * values. * * \param expr1 An expression to evaluate. * \param expr2 The expected value of \p expr1. This can be any * expression, but it is typically a constant. */ #define TEST_EQUAL( expr1, expr2 ) \ TEST_ASSERT( ( expr1 ) == ( expr2 ) ) /** Allocate memory dynamically and fail the test case if this fails. * The allocated memory will be filled with zeros. * * You must set \p pointer to \c NULL before calling this macro and * put `mbedtls_free( pointer )` in the test's cleanup code. * * If \p length is zero, the resulting \p pointer will be \c NULL. * This is usually what we want in tests since API functions are * supposed to accept null pointers when a buffer size is zero. * * This macro expands to an instruction, not an expression. * It may jump to the \c exit label. * * \param pointer An lvalue where the address of the allocated buffer * will be stored. * This expression may be evaluated multiple times. * \param length Number of elements to allocate. * This expression may be evaluated multiple times. * */ #define ASSERT_ALLOC( pointer, length ) \ do \ { \ TEST_ASSERT( ( pointer ) == NULL ); \ if( ( length ) != 0 ) \ { \ ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \ ( length ) ); \ TEST_ASSERT( ( pointer ) != NULL ); \ } \ } \ while( 0 ) /** Allocate memory dynamically. If the allocation fails, skip the test case. * * This macro behaves like #ASSERT_ALLOC, except that if the allocation * fails, it marks the test as skipped rather than failed. */ #define ASSERT_ALLOC_WEAK( pointer, length ) \ do \ { \ TEST_ASSERT( ( pointer ) == NULL ); \ if( ( length ) != 0 ) \ { \ ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \ ( length ) ); \ TEST_ASSUME( ( pointer ) != NULL ); \ } \ } \ while( 0 ) /** Compare two buffers and fail the test case if they differ. * * This macro expands to an instruction, not an expression. * It may jump to the \c exit label. * * \param p1 Pointer to the start of the first buffer. * \param size1 Size of the first buffer in bytes. * This expression may be evaluated multiple times. * \param p2 Pointer to the start of the second buffer. * \param size2 Size of the second buffer in bytes. * This expression may be evaluated multiple times. */ #define ASSERT_COMPARE( p1, size1, p2, size2 ) \ do \ { \ TEST_ASSERT( ( size1 ) == ( size2 ) ); \ if( ( size1 ) != 0 ) \ TEST_ASSERT( memcmp( ( p1 ), ( p2 ), ( size1 ) ) == 0 ); \ } \ while( 0 ) /** * \brief This macro tests the expression passed to it and skips the * running test if it doesn't evaluate to 'true'. * * \param TEST The test expression to be tested. */ #define TEST_ASSUME( TEST ) \ do { \ if( ! (TEST) ) \ { \ test_skip( #TEST, __LINE__, __FILE__ ); \ goto exit; \ } \ } while( 0 ) #if defined(MBEDTLS_CHECK_PARAMS) && !defined(MBEDTLS_PARAM_FAILED_ALT) /** * \brief This macro tests the statement passed to it as a test step or * individual test in a test case. The macro assumes the test will fail * and will generate an error. * * It allows a library function to return a value and tests the return * code on return to confirm the given error code was returned. * * When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure * callback, MBEDTLS_PARAM_FAILED(), are assumed to indicate the * expected failure, and the test will pass. * * This macro is intended for negative parameter validation tests, * where the failing function may return an error value or call * MBEDTLS_PARAM_FAILED() to indicate the error. * * \param PARAM_ERROR_VALUE The expected error code. * * \param TEST The test expression to be tested. */ #define TEST_INVALID_PARAM_RET( PARAM_ERR_VALUE, TEST ) \ do { \ mbedtls_test_param_failed_expect_call( ); \ if( ( ( TEST ) != ( PARAM_ERR_VALUE ) ) || \ ( mbedtls_test_param_failed_check_expected_call( ) != 0 ) ) \ { \ test_fail( #TEST, __LINE__, __FILE__ ); \ goto exit; \ } \ mbedtls_test_param_failed_check_expected_call( ); \ } while( 0 ) /** * \brief This macro tests the statement passed to it as a test step or * individual test in a test case. The macro assumes the test will fail * and will generate an error. * * It assumes the library function under test cannot return a value and * assumes errors can only be indicated byt calls to * MBEDTLS_PARAM_FAILED(). * * When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure * callback, MBEDTLS_PARAM_FAILED(), are assumed to indicate the * expected failure. If MBEDTLS_CHECK_PARAMS is not enabled, no test * can be made. * * This macro is intended for negative parameter validation tests, * where the failing function can only return an error by calling * MBEDTLS_PARAM_FAILED() to indicate the error. * * \param TEST The test expression to be tested. */ #define TEST_INVALID_PARAM( TEST ) \ do { \ memcpy( jmp_tmp, mbedtls_test_param_failed_get_state_buf( ), \ sizeof( jmp_tmp ) ); \ if( setjmp( mbedtls_test_param_failed_get_state_buf( ) ) == 0 ) \ { \ TEST; \ test_fail( #TEST, __LINE__, __FILE__ ); \ goto exit; \ } \ mbedtls_test_param_failed_reset_state( ); \ } while( 0 ) #endif /* MBEDTLS_CHECK_PARAMS && !MBEDTLS_PARAM_FAILED_ALT */ /** * \brief This macro tests the statement passed to it as a test step or * individual test in a test case. The macro assumes the test will not fail. * * It assumes the library function under test cannot return a value and * assumes errors can only be indicated by calls to * MBEDTLS_PARAM_FAILED(). * * When MBEDTLS_CHECK_PARAMS is enabled, calls to the parameter failure * callback, MBEDTLS_PARAM_FAILED(), are assumed to indicate the * expected failure. If MBEDTLS_CHECK_PARAMS is not enabled, no test * can be made. * * This macro is intended to test that functions returning void * accept all of the parameter values they're supposed to accept - eg * that they don't call MBEDTLS_PARAM_FAILED() when a parameter * that's allowed to be NULL happens to be NULL. * * Note: for functions that return something other that void, * checking that they accept all the parameters they're supposed to * accept is best done by using TEST_ASSERT() and checking the return * value as well. * * Note: this macro is available even when #MBEDTLS_CHECK_PARAMS is * disabled, as it makes sense to check that the functions accept all * legal values even if this option is disabled - only in that case, * the test is more about whether the function segfaults than about * whether it invokes MBEDTLS_PARAM_FAILED(). * * \param TEST The test expression to be tested. */ #define TEST_VALID_PARAM( TEST ) \ TEST_ASSERT( ( TEST, 1 ) ); /** Allocate memory dynamically and fail the test case if this fails. * * You must set \p pointer to \c NULL before calling this macro and * put `mbedtls_free( pointer )` in the test's cleanup code. * * If \p length is zero, the resulting \p pointer will be \c NULL. * This is usually what we want in tests since API functions are * supposed to accept null pointers when a buffer size is zero. * * This macro expands to an instruction, not an expression. * It may jump to the \c exit label. * * \param pointer An lvalue where the address of the allocated buffer * will be stored. * This expression may be evaluated multiple times. * \param length Number of elements to allocate. * This expression may be evaluated multiple times. * */ #define ASSERT_ALLOC( pointer, length ) \ do \ { \ TEST_ASSERT( ( pointer ) == NULL ); \ if( ( length ) != 0 ) \ { \ ( pointer ) = mbedtls_calloc( sizeof( *( pointer ) ), \ ( length ) ); \ TEST_ASSERT( ( pointer ) != NULL ); \ } \ } \ while( 0 ) /*----------------------------------------------------------------------------*/ /* Global variables */ typedef enum { TEST_RESULT_SUCCESS = 0, TEST_RESULT_FAILED, TEST_RESULT_SKIPPED } test_result_t; typedef struct { test_result_t result; const char *test; const char *filename; int line_no; unsigned long step; } test_info_t; static test_info_t test_info; #if defined(MBEDTLS_CHECK_PARAMS) jmp_buf jmp_tmp; #endif /*----------------------------------------------------------------------------*/ /* Helper flags for complex dependencies */ /* Indicates whether we expect mbedtls_entropy_init * to initialize some strong entropy source. */ #if defined(MBEDTLS_TEST_NULL_ENTROPY) || \ ( !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) && \ ( !defined(MBEDTLS_NO_PLATFORM_ENTROPY) || \ defined(MBEDTLS_HAVEGE_C) || \ defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ defined(ENTROPY_NV_SEED) ) ) #define ENTROPY_HAVE_STRONG #endif /*----------------------------------------------------------------------------*/ /* Helper Functions */ /** Set the test step number for failure reports. * * Call this function to display "step NNN" in addition to the line number * and file name if a test fails. Typically the "step number" is the index * of a for loop but it can be whatever you want. * * \param step The step number to report. */ void test_set_step( unsigned long step ) { test_info.step = step; } void test_fail( const char *test, int line_no, const char* filename ) { if( test_info.result == TEST_RESULT_FAILED ) { /* We've already recorded the test as having failed. Don't * overwrite any previous information about the failure. */ return; } test_info.result = TEST_RESULT_FAILED; test_info.test = test; test_info.line_no = line_no; test_info.filename = filename; } void test_skip( const char *test, int line_no, const char* filename ) { test_info.result = TEST_RESULT_SKIPPED; test_info.test = test; test_info.line_no = line_no; test_info.filename = filename; } #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) static int redirect_output( FILE* out_stream, const char* path ) { int out_fd, dup_fd; FILE* path_stream; out_fd = fileno( out_stream ); dup_fd = dup( out_fd ); if( dup_fd == -1 ) { return( -1 ); } path_stream = fopen( path, "w" ); if( path_stream == NULL ) { close( dup_fd ); return( -1 ); } fflush( out_stream ); if( dup2( fileno( path_stream ), out_fd ) == -1 ) { close( dup_fd ); fclose( path_stream ); return( -1 ); } fclose( path_stream ); return( dup_fd ); } static int restore_output( FILE* out_stream, int dup_fd ) { int out_fd = fileno( out_stream ); fflush( out_stream ); if( dup2( dup_fd, out_fd ) == -1 ) { close( out_fd ); close( dup_fd ); return( -1 ); } close( dup_fd ); return( 0 ); } #endif /* __unix__ || __APPLE__ __MACH__ */