diff --git a/library/ecp.c b/library/ecp.c index 1358a3f8c..987739f56 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -99,6 +99,22 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ) { ecp_max_ops = max_ops; } + +/* + * Saved context type for restarting operations. + * + * XXX: this is a temporary place for the definition + */ +typedef struct { + unsigned char fake_it; /* for tests: should we fake early return? */ +} ecp_restart_context; + +/* + * Saved context fro restarting operations. + * + * XXX: temporary place for the allocation + */ +static ecp_restart_context ecp_restart; #endif /* MBEDTLS_ECP_EARLY_RETURN */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ @@ -1376,6 +1392,11 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_ecp_point *T; mbedtls_mpi M, mm; +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( ecp_restart.fake_it++ != 0 && ecp_max_ops != 0 ) + return( MBEDTLS_ERR_ECP_IN_PROGRESS ); +#endif + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &mm ); diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index a43e7d75d..f96be5a51 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -344,3 +344,11 @@ ecp_test_vect:MBEDTLS_ECP_DP_SECP256K1:"923C6D4756CD940CD1E13A359F6E0F0698791938 ECP selftest ecp_selftest: + +ECP early return secp256r1 restart disabled +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":0:0:0 + +ECP early return secp256r1 restart enabled +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":1:1:5000 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 99780c0de..c8daef990 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -51,6 +51,107 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_ECP_EARLY_RETURN */ +void ecp_test_vect_restart( int id, + char *dA_str, char *xA_str, char *yA_str, + char *dB_str, char *xZ_str, char *yZ_str, + int max_ops, int min_restarts, int max_restarts ) +{ + /* + * Test for early restart. Based on test vectors like ecp_test_vect(), + * but for the sake of simplicity only does half of each side. It's + * important to test both base point and random point, though, as memory + * management is different in each case. + * + * Don't try using too precise bounds for restarts as the exact number + * will depend on settings such as MBEDTLS_ECP_FIXED_POINT_OPTIM and + * MBEDTLS_ECP_WINDOW_SIZE, as well as implementation details that may + * change in the future. A factor 2 is a minimum safety margin. + * + * For reference, with mbed TLS 2.4 and default settings, for P-256: + * - Random point mult: ~3600M + * - Cold base point mult: ~3600M + * - Hot base point mult: ~1200M + * With MBEDTLS_ECP_WINDOW_SIZE set to 2 (minimum): + * - Random point mult: ~4200M + */ + mbedtls_ecp_group grp; + mbedtls_ecp_point R; + mbedtls_mpi dA, xA, yA, dB, xZ, yZ; + int cnt_restarts; + int ret; + + mbedtls_ecp_group_init( &grp ); mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &dA ); mbedtls_mpi_init( &xA ); mbedtls_mpi_init( &yA ); + mbedtls_mpi_init( &dB ); mbedtls_mpi_init( &xZ ); mbedtls_mpi_init( &yZ ); + + TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 ); + + TEST_ASSERT( mbedtls_mpi_read_string( &dA, 16, dA_str ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &xA, 16, xA_str ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &yA, 16, yA_str ) == 0 ); + + TEST_ASSERT( mbedtls_mpi_read_string( &dB, 16, dB_str ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &xZ, 16, xZ_str ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &yZ, 16, yZ_str ) == 0 ); + + mbedtls_ecp_set_max_ops( (unsigned) max_ops ); + + /* Base point case */ + cnt_restarts = 0; + do { + ret = mbedtls_ecp_mul( &grp, &R, &dA, &grp.G, NULL, NULL ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + cnt_restarts++; + } + while( ret != 0 ); + + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.X, &xA ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.Y, &yA ) == 0 ); + + TEST_ASSERT( cnt_restarts >= min_restarts ); + TEST_ASSERT( cnt_restarts <= max_restarts ); + + /* Do we leak memory when doing it twice in a row? */ + do { + ret = mbedtls_ecp_mul( &grp, &R, &dA, &grp.G, NULL, NULL ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + } + while( ret != 0 ); + + /* Non-base point case */ + cnt_restarts = 0; + do { + ret = mbedtls_ecp_mul( &grp, &R, &dB, &R, NULL, NULL ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + cnt_restarts++; + } + while( ret != 0 ); + + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.X, &xZ ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.Y, &yZ ) == 0 ); + + TEST_ASSERT( cnt_restarts >= min_restarts ); + TEST_ASSERT( cnt_restarts <= max_restarts ); + + /* Do we leak memory when doing it twice in a row? */ + do { + ret = mbedtls_ecp_mul( &grp, &R, &dB, &R, NULL, NULL ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + } + while( ret != 0 ); + +exit: + mbedtls_ecp_group_free( &grp ); mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &dA ); mbedtls_mpi_free( &xA ); mbedtls_mpi_free( &yA ); + mbedtls_mpi_free( &dB ); mbedtls_mpi_free( &xZ ); mbedtls_mpi_free( &yZ ); +} +/* END_CASE */ + /* BEGIN_CASE */ void ecp_test_vect( int id, char *dA_str, char *xA_str, char *yA_str, char *dB_str, char *xB_str, char *yB_str, char *xZ_str,