From 225b37a5437919f3aa92cde364d6584f476ba1ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 8 Mar 2017 10:22:54 +0100 Subject: [PATCH 001/148] Fix typos in comment --- include/mbedtls/ecp.h | 1 - library/ecp.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index bf9abeff6..944b7f82d 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -205,7 +205,6 @@ mbedtls_ecp_keypair; * 521 145 141 135 120 97 * 384 214 209 198 177 146 * 256 320 320 303 262 226 - * 224 475 475 453 398 342 * 192 640 640 633 587 476 */ diff --git a/library/ecp.c b/library/ecp.c index 5ad686398..c7f4b04bb 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1363,7 +1363,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_mpi_init( &M ); mbedtls_mpi_init( &mm ); - /* we need N to be odd to trnaform m in an odd number, check now */ + /* we need N to be odd to transform m in an odd number, check now */ if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); From c3a3bc7636ea1e6bce8ed922af9a5d74890564db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 22 Mar 2017 11:17:51 +0100 Subject: [PATCH 002/148] Add config flag MBEDTLS_ECP_EARLY_RETURN --- include/mbedtls/config.h | 15 +++++++++++++++ library/version_features.c | 3 +++ 2 files changed, 18 insertions(+) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 47c719640..9040bb71b 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -561,6 +561,21 @@ */ #define MBEDTLS_ECP_NIST_OPTIM +/** + * \def MBEDTLS_ECP_EARLY_RETURN + * + * Enable "non-blocking" ECC operations that can return early and be resumed. + * + * This enables \c mbedtls_ecp_set_max_ops() and allows various ECC functions + * to return \c MBEDTLS_ERR_ECP_IN_PROGRESS when needed. + * + * TODO: depending on other choices, this might need to be disabled by default + * in order to avoid changing the ABI. Revisit that later. + * + * Comment this macro to disable non-blocking ECC computations. + */ +#define MBEDTLS_ECP_EARLY_RETURN + /** * \def MBEDTLS_ECDSA_DETERMINISTIC * diff --git a/library/version_features.c b/library/version_features.c index 5cbe8aca3..2668eaed5 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -276,6 +276,9 @@ static const char *features[] = { #if defined(MBEDTLS_ECP_NIST_OPTIM) "MBEDTLS_ECP_NIST_OPTIM", #endif /* MBEDTLS_ECP_NIST_OPTIM */ +#if defined(MBEDTLS_ECP_EARLY_RETURN) + "MBEDTLS_ECP_EARLY_RETURN", +#endif /* MBEDTLS_ECP_EARLY_RETURN */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) "MBEDTLS_ECDSA_DETERMINISTIC", #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ From 5e3c62fd1de6ecade242e03907d90d85d59b8ac1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 8 Mar 2017 10:14:11 +0100 Subject: [PATCH 003/148] Add MBEDTLS_ERR_ECP_IN_PROGRESS --- include/mbedtls/ecp.h | 1 + include/mbedtls/error.h | 2 +- library/error.c | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 944b7f82d..f821690ef 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -36,6 +36,7 @@ #define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as (ephemeral) key, failed. */ #define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ #define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< Signature is valid but shorter than the user-supplied length. */ +#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B80 /**< Operation in progress, try again with the same parameters. */ #if !defined(MBEDTLS_ECP_ALT) /* diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 31591e2d6..6c580676d 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -76,7 +76,7 @@ * DHM 3 9 * PK 3 14 (Started from top) * RSA 4 9 - * ECP 4 8 (Started from top) + * ECP 4 9 (Started from top) * MD 5 4 * CIPHER 6 6 * SSL 6 17 (Started from top) diff --git a/library/error.c b/library/error.c index db42381c4..5845303c7 100644 --- a/library/error.c +++ b/library/error.c @@ -225,6 +225,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) mbedtls_snprintf( buf, buflen, "ECP - Signature is valid but shorter than the user-supplied length" ); + if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, try again with the same parameters" ); #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_MD_C) From 054433c4935709df80ea1cb0d01849b6c745d009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 22 Mar 2017 11:18:33 +0100 Subject: [PATCH 004/148] Add mbedtls_ecp_set_max_ops() The plan is to count basic operations as follows: - call to ecp_add_mixed() -> 11 - call to ecp_double_jac() -> 8 - call to mpi_mul_mpi() -> 1 - call to mpi_inv_mod() -> 120 - everything else -> not counted The counts for ecp_add_mixed() and ecp_double_jac() are based on the actual number of calls to mpi_mul_mpi() they they make. The count for mpi_inv_mod() is based on timing measurements on K64F and LPC1768 boards, and are consistent with the usual very rough estimate of one inversion = 100 multiplications. It could be useful to repeat that measurement on a Cortex-M0 board as those have smaller divider and multipliers, so the result could be a bit different but should be the same order of magnitude. The documented limitation of 120 basic ops is due to the calls to mpi_inv_mod() which are currently not interruptible nor planned to be so far. --- include/mbedtls/ecp.h | 34 +++++++++++++++++++++++++++++++++- library/ecp.c | 16 ++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index f821690ef..7bcc69c01 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -240,6 +240,33 @@ mbedtls_ecp_keypair; */ #define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ +#if defined(MBEDTLS_ECP_EARLY_RETURN) +/** + * \brief Set the maximum number of basic operations done in a row. + * + * If more operations are needed to complete a computation, + * MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the + * function performing the computation. That function will + * then need to be called again with the same arguments until + * it returns 0 or an other error code. + * + * \param max_ops Maximum number of basic operations done in a row. + * Default: 0 (unlimited). + * Lower (non-zero) values mean ECC functions will block for + * a lesser maximum amount of time. + * + * \note A "basic operation" is roughly multiplication in GF(p), + * or whatever takes a roughly equivalent amount of time. + * As an indication, a scalar multiplication on P-256 is + * of the order of 3600 "basic operations" with default + * settings. + * + * \warning Values lower than 120 are currently not well-supported, in + * that sometimes functions will have to block for longer. + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ); +#endif /* MBEDTLS_ECP_EARLY_RETURN */ + /** * \brief Get the list of supported curves in order of preferrence * (full information) @@ -525,7 +552,12 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, * \return 0 if successful, * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey * or P is not a valid pubkey, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached (see \c mbedtls_ecp_set_max_ops()), + * indicating the function should be called again with the + * exact same arguments. + * */ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, diff --git a/library/ecp.c b/library/ecp.c index c7f4b04bb..1358a3f8c 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -85,6 +85,22 @@ static void mbedtls_zeroize( void *v, size_t n ) { static unsigned long add_count, dbl_count, mul_count; #endif + +#if defined(MBEDTLS_ECP_EARLY_RETURN) +/* + * Maximum number of "basic operations" to be done in a row. + */ +static unsigned ecp_max_ops = 0; + +/* + * Set ecp_max_ops + */ +void mbedtls_ecp_set_max_ops( unsigned max_ops ) +{ + ecp_max_ops = max_ops; +} +#endif /* MBEDTLS_ECP_EARLY_RETURN */ + #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ From 510d5caece90e35be004a77dc8171f110d2a9787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 8 Mar 2017 11:41:47 +0100 Subject: [PATCH 005/148] Add early return test + fake implementation --- library/ecp.c | 21 ++++++ tests/suites/test_suite_ecp.data | 8 +++ tests/suites/test_suite_ecp.function | 101 +++++++++++++++++++++++++++ 3 files changed, 130 insertions(+) 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, From 7306dff01faf9fcac42d855c9e3ad54c23caeb32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 9 Mar 2017 12:23:45 +0100 Subject: [PATCH 006/148] Group related code together This will be split to a new function next. --- library/ecp.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 987739f56..c85b8ae49 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1389,7 +1389,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, unsigned char w, m_is_odd, p_eq_g, pre_len, i; size_t d; unsigned char k[COMB_MAX_D + 1]; - mbedtls_ecp_point *T; + mbedtls_ecp_point *T = NULL; mbedtls_mpi M, mm; #if defined(MBEDTLS_ECP_EARLY_RETURN) @@ -1404,6 +1404,15 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + /* + * Make sure M is odd (M = m or M = N - m, since N is odd) + * using the fact that m * P = - (N - m) * P + */ + m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); + /* * Minimize the number of multiplications, that is minimize * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) @@ -1462,15 +1471,6 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, } } - /* - * Make sure M is odd (M = m or M = N - m, since N is odd) - * using the fact that m * P = - (N - m) * P - */ - m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); - /* * Go for comb multiplication, R = M * P */ From ec5606ad0c8907527b95048e5faad270256d2d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 9 Mar 2017 12:46:45 +0100 Subject: [PATCH 007/148] Extract code to separate function ecp_mul_comb() is already 110 lines long and we're going to add complexity with the early-return+restart code, so let's try to make it simpler first. --- library/ecp.c | 47 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index c85b8ae49..c0b6a1b7b 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1376,6 +1376,37 @@ cleanup: return( ret ); } +/* + * Set M to either m or -m, depending on which one is odd + */ +static int ecp_make_scalar_odd( const mbedtls_ecp_group *grp, + mbedtls_mpi *M, + const mbedtls_mpi *m, + const unsigned char m_is_odd ) +{ + int ret; + mbedtls_mpi mm; + + mbedtls_mpi_init( &mm ); + + /* we need N to be odd to transform m in an odd number, check now */ + if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Make sure M is odd (M = m or M = N - m, since N is odd) + * using the fact that m * P = - (N - m) * P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( M, &mm, ! m_is_odd ) ); + +cleanup: + mbedtls_mpi_free( &mm ); + + return( ret ); +} + /* * Multiplication using the comb method, * for curves in short Weierstrass form @@ -1390,7 +1421,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, size_t d; unsigned char k[COMB_MAX_D + 1]; mbedtls_ecp_point *T = NULL; - mbedtls_mpi M, mm; + mbedtls_mpi M; #if defined(MBEDTLS_ECP_EARLY_RETURN) if( ecp_restart.fake_it++ != 0 && ecp_max_ops != 0 ) @@ -1398,20 +1429,13 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif mbedtls_mpi_init( &M ); - mbedtls_mpi_init( &mm ); - - /* we need N to be odd to transform m in an odd number, check now */ - if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); /* - * Make sure M is odd (M = m or M = N - m, since N is odd) - * using the fact that m * P = - (N - m) * P + * We need an odd scalar for recoding. Ensure that by replacing it with + * its opposite, then negating the result to compensate if needed. */ m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); + MBEDTLS_MPI_CHK( ecp_make_scalar_odd( grp, &M, m, m_is_odd ) ); /* * Minimize the number of multiplications, that is minimize @@ -1493,7 +1517,6 @@ cleanup: } mbedtls_mpi_free( &M ); - mbedtls_mpi_free( &mm ); if( ret != 0 ) mbedtls_ecp_point_free( R ); From 22be635d13929acba60ada6a018059105b6c74ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 9 Mar 2017 13:02:35 +0100 Subject: [PATCH 008/148] Re-order some more code --- library/ecp.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index c0b6a1b7b..cea835d15 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1437,6 +1437,14 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); MBEDTLS_MPI_CHK( ecp_make_scalar_odd( grp, &M, m, m_is_odd ) ); + /* Is P the base point ? */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); +#else + p_eq_g = 0; +#endif + /* * Minimize the number of multiplications, that is minimize * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) @@ -1449,14 +1457,8 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * Just adding one avoids upping the cost of the first mul too much, * and the memory cost too. */ -#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 - p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && - mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); if( p_eq_g ) w++; -#else - p_eq_g = 0; -#endif /* * Make sure w is within bounds. From 4b2336d7f69ba5e6ad1ec4937f62b96f138f6c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 9 Mar 2017 13:23:50 +0100 Subject: [PATCH 009/148] Move some more code to new function --- library/ecp.c | 62 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 25 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index cea835d15..2cbe4f069 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1407,6 +1407,41 @@ cleanup: return( ret ); } +/* + * Pick window size based on curve size and whether we optimize for base point + */ +static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, + unsigned char p_eq_g ) +{ + unsigned char w; + + /* + * Minimize the number of multiplications, that is minimize + * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) + * (see costs of the various parts, with 1S = 1M) + */ + w = grp->nbits >= 384 ? 5 : 4; + + /* + * If P == G, pre-compute a bit more, since this may be re-used later. + * Just adding one avoids upping the cost of the first mul too much, + * and the memory cost too. + */ + if( p_eq_g ) + w++; + + /* + * Make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + */ + if( w > MBEDTLS_ECP_WINDOW_SIZE ) + w = MBEDTLS_ECP_WINDOW_SIZE; + if( w >= grp->nbits ) + w = 2; + + return( w ); +} + /* * Multiplication using the comb method, * for curves in short Weierstrass form @@ -1445,31 +1480,8 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, p_eq_g = 0; #endif - /* - * Minimize the number of multiplications, that is minimize - * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) - * (see costs of the various parts, with 1S = 1M) - */ - w = grp->nbits >= 384 ? 5 : 4; - - /* - * If P == G, pre-compute a bit more, since this may be re-used later. - * Just adding one avoids upping the cost of the first mul too much, - * and the memory cost too. - */ - if( p_eq_g ) - w++; - - /* - * Make sure w is within bounds. - * (The last test is useful only for very small curves in the test suite.) - */ - if( w > MBEDTLS_ECP_WINDOW_SIZE ) - w = MBEDTLS_ECP_WINDOW_SIZE; - if( w >= grp->nbits ) - w = 2; - - /* Other sizes that depend on w */ + /* Window size and others that depend on it */ + w = ecp_pick_window_size( grp, p_eq_g ); pre_len = 1U << ( w - 1 ); d = ( grp->nbits + w - 1 ) / w; From 24be79588d363290bf253a67edad9ac06f9c62b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 13 Mar 2017 12:03:33 +0100 Subject: [PATCH 010/148] Group related code together --- library/ecp.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 2cbe4f069..4d3448c7e 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1465,13 +1465,6 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_mpi_init( &M ); - /* - * We need an odd scalar for recoding. Ensure that by replacing it with - * its opposite, then negating the result to compensate if needed. - */ - m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); - MBEDTLS_MPI_CHK( ecp_make_scalar_odd( grp, &M, m, m_is_odd ) ); - /* Is P the base point ? */ #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && @@ -1509,6 +1502,13 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, } } + /* + * We need an odd scalar for recoding. Ensure that by replacing it with + * its opposite, then negating the result to compensate if needed. + */ + m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); + MBEDTLS_MPI_CHK( ecp_make_scalar_odd( grp, &M, m, m_is_odd ) ); + /* * Go for comb multiplication, R = M * P */ From 391f44153dc18331d1bcf79a8420a15a4a8109ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 13 Mar 2017 12:26:21 +0100 Subject: [PATCH 011/148] Move more code to separate function This reduces the scope of some variables (M, k), clarifying where they're used. --- library/ecp.c | 79 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 4d3448c7e..932e4e58a 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1407,6 +1407,53 @@ cleanup: return( ret ); } +/* + * Perform comb multiplication (for short Weierstrass curves) + * once the auxiliary table has been pre-computed. + */ +static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *T, + unsigned char pre_len, + unsigned char w, + size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char m_is_odd; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_mpi M; + + mbedtls_mpi_init( &M ); + + /* + * We need an odd scalar for recoding. Ensure that by replacing it with + * its opposite, then negating the result to compensate if needed. + */ + m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); + MBEDTLS_MPI_CHK( ecp_make_scalar_odd( grp, &M, m, m_is_odd ) ); + ecp_comb_fixed( k, d, w, &M ); + + /* + * Go for comb multiplication, R = M * P + */ + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); + + /* + * Now get m * P from M * P and normalize it + */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + mbedtls_mpi_free( &M ); + + return( ret ); +} + + /* * Pick window size based on curve size and whether we optimize for base point */ @@ -1452,19 +1499,15 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, void *p_rng ) { int ret; - unsigned char w, m_is_odd, p_eq_g, pre_len, i; + unsigned char w, p_eq_g, pre_len, i; size_t d; - unsigned char k[COMB_MAX_D + 1]; mbedtls_ecp_point *T = NULL; - mbedtls_mpi M; #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 ); - /* Is P the base point ? */ #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && @@ -1473,7 +1516,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, p_eq_g = 0; #endif - /* Window size and others that depend on it */ + /* Pick window size and deduce related sizes */ w = ecp_pick_window_size( grp, p_eq_g ); pre_len = 1U << ( w - 1 ); d = ( grp->nbits + w - 1 ) / w; @@ -1502,24 +1545,10 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, } } - /* - * We need an odd scalar for recoding. Ensure that by replacing it with - * its opposite, then negating the result to compensate if needed. - */ - m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); - MBEDTLS_MPI_CHK( ecp_make_scalar_odd( grp, &M, m, m_is_odd ) ); - - /* - * Go for comb multiplication, R = M * P - */ - ecp_comb_fixed( k, d, w, &M ); - MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); - - /* - * Now get m * P from M * P and normalize it - */ - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + /* Actual comb multiplication using precomputed points */ + MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m, + T, pre_len, w, d, + f_rng, p_rng ) ); cleanup: @@ -1530,8 +1559,6 @@ cleanup: mbedtls_free( T ); } - mbedtls_mpi_free( &M ); - if( ret != 0 ) mbedtls_ecp_point_free( R ); From 62738e9b170705059ff878aeeba7e3f4f6582c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 14 Mar 2017 10:00:21 +0100 Subject: [PATCH 012/148] Further restrict variable scope by moving code --- library/ecp.c | 68 +++++++++++++++++++++++++-------------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 932e4e58a..71f8700b5 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1220,8 +1220,8 @@ cleanup: * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d * (the result will be incorrect if these assumptions are not satisfied) */ -static void ecp_comb_fixed( unsigned char x[], size_t d, - unsigned char w, const mbedtls_mpi *m ) +static void ecp_comb_recode_core( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) { size_t i, j; unsigned char c, cc, adjust; @@ -1377,32 +1377,43 @@ cleanup: } /* - * Set M to either m or -m, depending on which one is odd + * Recode the scalar to get constant-time comb multiplication + * + * As the actual scalar recoding needs an odd scalar as a starting point, + * this wrapper ensures that by replacing m by N - m if necessary, and + * informs the caller that the result of multiplication will be negated. */ -static int ecp_make_scalar_odd( const mbedtls_ecp_group *grp, - mbedtls_mpi *M, - const mbedtls_mpi *m, - const unsigned char m_is_odd ) +static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, + const mbedtls_mpi *m, + unsigned char k[COMB_MAX_D + 1], + size_t d, + unsigned char w, + unsigned char *parity_trick ) { int ret; - mbedtls_mpi mm; + mbedtls_mpi M, mm; + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &mm ); - /* we need N to be odd to transform m in an odd number, check now */ + /* N is odd with all real-world curves, just make extra sure */ if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - /* - * Make sure M is odd (M = m or M = N - m, since N is odd) - * using the fact that m * P = - (N - m) * P - */ - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( M, m ) ); + /* do we need the parity trick? */ + *parity_trick = ( mbedtls_mpi_get_bit( m, 0 ) == 0 ); + + /* execute parity fix in constant time */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( M, &mm, ! m_is_odd ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, *parity_trick ) ); + + /* actual scalar recoding */ + ecp_comb_recode_core( k, d, w, &M ); cleanup: mbedtls_mpi_free( &mm ); + mbedtls_mpi_free( &M ); return( ret ); } @@ -1410,6 +1421,9 @@ cleanup: /* * Perform comb multiplication (for short Weierstrass curves) * once the auxiliary table has been pre-computed. + * + * Scalar recoding may use a parity trick that makes us compute -m * P, + * if that is the case we'll need to recover m * P at the end. */ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, @@ -1422,34 +1436,18 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, void *p_rng ) { int ret; - unsigned char m_is_odd; + unsigned char parity_trick; unsigned char k[COMB_MAX_D + 1]; - mbedtls_mpi M; - mbedtls_mpi_init( &M ); + MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, &parity_trick ) ); - /* - * We need an odd scalar for recoding. Ensure that by replacing it with - * its opposite, then negating the result to compensate if needed. - */ - m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); - MBEDTLS_MPI_CHK( ecp_make_scalar_odd( grp, &M, m, m_is_odd ) ); - ecp_comb_fixed( k, d, w, &M ); - - /* - * Go for comb multiplication, R = M * P - */ MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); - /* - * Now get m * P from M * P and normalize it - */ - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, parity_trick ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); cleanup: - mbedtls_mpi_free( &M ); - return( ret ); } From 77af79a324f8d340ef5595d92e1782eb3125ccc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 14 Mar 2017 10:58:00 +0100 Subject: [PATCH 013/148] Add proper allocation of restart context We'll need to store MPIs and other things that allocate memory in this context, so we need a place to free it. We can't rely on doing it before returning from ecp_mul() as we might return MBEDTLS_ERR_ECP_IN_PROGRESS (thus preserving the context) and never be called again (for example, TLS handshake aborted for another reason). So, ecp_group_free() looks like a good place to do this, if the restart context is part of struct ecp_group. This means it's not possible to use the same ecp_group structure in different threads concurrently, but: - that's already the case (and documented) for other reasons - this feature is precisely intended for environments that lack threading An alternative option would be for the caller to have to allocate/free the restart context and pass it explicitly, but this means creating new functions that take a context argument, and putting a burden on the user. --- include/mbedtls/ecp.h | 13 +++++++ library/ecp.c | 55 +++++++++++++++++++++++----- tests/suites/test_suite_ecp.function | 4 ++ 3 files changed, 62 insertions(+), 10 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 7bcc69c01..d44e65843 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -112,6 +112,16 @@ typedef struct } mbedtls_ecp_point; +#if defined(MBEDTLS_ECP_EARLY_RETURN) +/** + * \brief ECP context for resuming operations after returning + * \c MBEDTLS_ERR_ECP_IN_PROGRESS + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart mbedtls_ecp_restart_ctx; +#endif + /** * \brief ECP group structure * @@ -153,6 +163,9 @@ typedef struct void *t_data; /*!< unused */ mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ size_t T_size; /*!< number for pre-computed points */ +#if defined(MBEDTLS_ECP_EARLY_RETURN) + mbedtls_ecp_restart_ctx *rs; /*!< context for resuming operation */ +#endif } mbedtls_ecp_group; diff --git a/library/ecp.c b/library/ecp.c index 71f8700b5..60aa0a3cd 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -101,20 +101,28 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ) } /* - * Saved context type for restarting operations. - * - * XXX: this is a temporary place for the definition + * Restart context type for interrupted operations */ -typedef struct { +struct mbedtls_ecp_restart { 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 + * Init restart context */ -static ecp_restart_context ecp_restart; +static void ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ecp_restart_ctx ) ); +} + +/* + * Free the components of a restart context + */ +static void ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; +} #endif /* MBEDTLS_ECP_EARLY_RETURN */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ @@ -378,6 +386,11 @@ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) mbedtls_free( grp->T ); } +#if defined(MBEDTLS_ECP_EARLY_RETURN) + ecp_restart_free( grp->rs ); + mbedtls_free( grp->rs ); +#endif + mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) ); } @@ -1501,8 +1514,22 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, size_t d; mbedtls_ecp_point *T = NULL; + /* set up restart context if needed */ #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( ecp_restart.fake_it++ != 0 && ecp_max_ops != 0 ) + if( ecp_max_ops != 0 && grp->rs == NULL ) + { + grp->rs = mbedtls_calloc( 1, sizeof( mbedtls_ecp_restart_ctx ) ); + if( grp->rs == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + ecp_restart_init( grp->rs ); + + grp->rs->fake_it = 1; + } +#endif + + /* XXX: temporary */ +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs && grp->rs->fake_it++ != 0 ) return( MBEDTLS_ERR_ECP_IN_PROGRESS ); #endif @@ -1560,6 +1587,14 @@ cleanup: if( ret != 0 ) mbedtls_ecp_point_free( R ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + ecp_restart_free( grp->rs ); + mbedtls_free( grp->rs ); + grp->rs = NULL; + } +#endif + return( ret ); } diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index c8daef990..74e23875d 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -145,6 +145,10 @@ void ecp_test_vect_restart( int id, } while( ret != 0 ); + /* Do we leak memory when not finishing an operation? */ + ret = mbedtls_ecp_mul( &grp, &R, &dB, &R, NULL, NULL ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + exit: mbedtls_ecp_group_free( &grp ); mbedtls_ecp_point_free( &R ); mbedtls_mpi_free( &dA ); mbedtls_mpi_free( &xA ); mbedtls_mpi_free( &yA ); From 78d564a84156974580895e5a1aa6c24b8dd2ac64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 14 Mar 2017 11:48:38 +0100 Subject: [PATCH 014/148] Add check for changing arguments In case of argument change, freeing everything is not the most efficient (wastes one free()+calloc()) but makes the code simpler, which is probably more important here --- library/ecp.c | 24 +++++++++++++++++++++--- tests/suites/test_suite_ecp.function | 7 +++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 60aa0a3cd..0a0239cc3 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -105,6 +105,8 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ) */ struct mbedtls_ecp_restart { unsigned char fake_it; /* for tests: should we fake early return? */ + mbedtls_mpi m; /* saved argument: scalar */ + mbedtls_ecp_point P; /* saved argument: point */ }; /* @@ -122,6 +124,9 @@ static void ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) { if( ctx == NULL ) return; + + mbedtls_mpi_free( &ctx->m ); + mbedtls_ecp_point_free( &ctx->P ); } #endif /* MBEDTLS_ECP_EARLY_RETURN */ @@ -1514,22 +1519,35 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, size_t d; mbedtls_ecp_point *T = NULL; - /* set up restart context if needed */ #if defined(MBEDTLS_ECP_EARLY_RETURN) + /* check for restart with new arguments */ + if( grp->rs != NULL && + ( mbedtls_mpi_cmp_mpi( m, &grp->rs->m ) != 0 || + mbedtls_mpi_cmp_mpi( &P->X, &grp->rs->P.X ) != 0 || + mbedtls_mpi_cmp_mpi( &P->Y, &grp->rs->P.Y ) != 0 ) ) + { + ecp_restart_free( grp->rs ); + mbedtls_free( grp->rs ); + grp->rs = NULL; + } + + /* set up restart context if needed */ if( ecp_max_ops != 0 && grp->rs == NULL ) { grp->rs = mbedtls_calloc( 1, sizeof( mbedtls_ecp_restart_ctx ) ); if( grp->rs == NULL ) return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + ecp_restart_init( grp->rs ); - grp->rs->fake_it = 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &grp->rs->m, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &grp->rs->P, P ) ); } #endif /* XXX: temporary */ #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs && grp->rs->fake_it++ != 0 ) + if( grp->rs && ++grp->rs->fake_it != 0 ) return( MBEDTLS_ERR_ECP_IN_PROGRESS ); #endif diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 74e23875d..caf983e72 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -121,6 +121,13 @@ void ecp_test_vect_restart( int id, } while( ret != 0 ); + /* Ok, now start an operation with some arguments, and drop it. + * We'll see if the result of the next operation, with different args, + * are correct regardless (do we discard old context on new args?). + * This also tests that we don't write to R prematurely */ + ret = mbedtls_ecp_mul( &grp, &R, &dA, &grp.G, NULL, NULL ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + /* Non-base point case */ cnt_restarts = 0; do { From 8962ddbb2327764284d17100ff5d6946ae63f0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 14 Mar 2017 12:11:21 +0100 Subject: [PATCH 015/148] Don't write to destination until we're done --- library/ecp.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 0a0239cc3..d402e5c10 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -107,6 +107,7 @@ struct mbedtls_ecp_restart { unsigned char fake_it; /* for tests: should we fake early return? */ mbedtls_mpi m; /* saved argument: scalar */ mbedtls_ecp_point P; /* saved argument: point */ + mbedtls_ecp_point R; /* current intermediate result */ }; /* @@ -127,6 +128,7 @@ static void ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) mbedtls_mpi_free( &ctx->m ); mbedtls_ecp_point_free( &ctx->P ); + mbedtls_ecp_point_free( &ctx->R ); } #endif /* MBEDTLS_ECP_EARLY_RETURN */ @@ -1456,14 +1458,24 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, int ret; unsigned char parity_trick; unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *RR = R; + +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL ) + RR = &grp->rs->R; +#endif MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, &parity_trick ) ); - MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, pre_len, k, d, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, parity_trick ) ); + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); + +#if defined(MBEDTLS_ECP_EARLY_RETURN) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); +#endif cleanup: return( ret ); From 2fad7ae02a6e2dcc75f5c8f83e2fc3d2acd60442 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 14 Mar 2017 13:13:13 +0100 Subject: [PATCH 016/148] Start actually splitting computation Temporary state is quite inefficient: pre-computed table is recomputed every single time. This is WIP obviously. --- library/ecp.c | 68 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 9 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index d402e5c10..3505b2041 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -104,10 +104,14 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ) * Restart context type for interrupted operations */ struct mbedtls_ecp_restart { - unsigned char fake_it; /* for tests: should we fake early return? */ + unsigned ops_done; /* number of operations done this time */ mbedtls_mpi m; /* saved argument: scalar */ mbedtls_ecp_point P; /* saved argument: point */ mbedtls_ecp_point R; /* current intermediate result */ + enum { + ecp_rs_init = 0, + ecp_rs_final_norm, + } state; }; /* @@ -129,7 +133,37 @@ static void ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) mbedtls_mpi_free( &ctx->m ); mbedtls_ecp_point_free( &ctx->P ); mbedtls_ecp_point_free( &ctx->R ); + + memset( ctx, 0, sizeof( mbedtls_ecp_restart_ctx ) ); } + +/* + * Operation counts + */ +#define ECP_OPS_DBL 8 /* see ecp_double_jac() */ +#define ECP_OPS_ADD 11 /* see ecp_add_mixed() */ +#define ECP_OPS_INV 120 /* empirical equivalent */ + +/* + * Check if we can do the next step + */ +static int ecp_check_budget( const mbedtls_ecp_group *grp, unsigned ops ) +{ + if( grp->rs != NULL ) + { + /* avoid infinite loops: always allow first step */ + if( grp->rs->ops_done != 0 && grp->rs->ops_done + ops > ecp_max_ops ) + return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + + grp->rs->ops_done += ops; + } + + return( 0 ); +} + +#define ECP_BUDGET( ops ) MBEDTLS_MPI_CHK( ecp_check_budget( grp, ops ) ); +#else +#define ECP_BUDGET( ops ) #endif /* MBEDTLS_ECP_EARLY_RETURN */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ @@ -1465,12 +1499,26 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, RR = &grp->rs->R; #endif - MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, &parity_trick ) ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs == NULL || grp->rs->state < ecp_rs_final_norm ) +#endif + { + MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, + &parity_trick ) ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, pre_len, k, d, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); - MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, pre_len, k, d, f_rng, p_rng ) ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL ) + grp->rs->state++; +#endif - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); + /* XXX: temporary: should have counted some ops */ + ECP_BUDGET( 42 ); + } + ECP_BUDGET( ECP_OPS_INV ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) @@ -1555,12 +1603,10 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &grp->rs->m, m ) ); MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &grp->rs->P, P ) ); } -#endif - /* XXX: temporary */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs && ++grp->rs->fake_it != 0 ) - return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + /* new start for ops counts */ + if( grp->rs != NULL ) + grp->rs->ops_done = 0; #endif /* Is P the base point ? */ @@ -1614,6 +1660,10 @@ cleanup: mbedtls_free( T ); } + /* don't free R while in progress in case R == P */ +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif if( ret != 0 ) mbedtls_ecp_point_free( R ); From c5d844b999c03379bb4b8fc5903791d13ba6231e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 15 Mar 2017 13:06:28 +0100 Subject: [PATCH 017/148] Full restart support in ecp_mul_comb_core() Still recomputing table every time, though. --- library/ecp.c | 44 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 3505b2041..785093f7a 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -108,6 +108,7 @@ struct mbedtls_ecp_restart { mbedtls_mpi m; /* saved argument: scalar */ mbedtls_ecp_point P; /* saved argument: point */ mbedtls_ecp_point R; /* current intermediate result */ + size_t i; /* current index in various loops, 0 outside */ enum { ecp_rs_init = 0, ecp_rs_final_norm, @@ -1409,15 +1410,26 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R mbedtls_ecp_point_init( &Txi ); - /* Start with a non-zero point and randomize its coordinates */ - i = d; - MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); - if( f_rng != 0 ) - MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL && grp->rs->i != 0 ) + { + /* restore current index (R already pointing to grp->rs->R) */ + i = grp->rs->i; + } + else +#endif + { + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); + if( f_rng != 0 ) + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + } while( i-- != 0 ) { + ECP_BUDGET( ECP_OPS_DBL + ECP_OPS_ADD ); MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); @@ -1427,6 +1439,23 @@ cleanup: mbedtls_ecp_point_free( &Txi ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL ) + { + if( ret == 0 ) + { + grp->rs->state++; + grp->rs->i = 0; + } + else if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* was decreased before actually doing it */ + grp->rs->i = i + 1; + /* no need to save R, already pointing to grp->rs->R */ + } + } +#endif + return( ret ); } @@ -1513,9 +1542,6 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, if( grp->rs != NULL ) grp->rs->state++; #endif - - /* XXX: temporary: should have counted some ops */ - ECP_BUDGET( 42 ); } ECP_BUDGET( ECP_OPS_INV ); From c9c0aa6306fc1480a601ad1de5ecf9228068dde8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 16 Mar 2017 14:53:26 +0100 Subject: [PATCH 018/148] Remember precomputed table Free it as soon as it's no longer needed, but as a backup free it in ecp_group_free(), in case ecp_mul() is not called again after returning ECP_IN_PROGRESS. So far we only remember it when it's fully computed, next step is to be able to compute it in multiple steps. --- library/ecp.c | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 785093f7a..653c60f3b 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -109,9 +109,11 @@ struct mbedtls_ecp_restart { mbedtls_ecp_point P; /* saved argument: point */ mbedtls_ecp_point R; /* current intermediate result */ size_t i; /* current index in various loops, 0 outside */ - enum { - ecp_rs_init = 0, - ecp_rs_final_norm, + mbedtls_ecp_point *T; /* table for precomputed points */ + unsigned char T_size; /* number of points in table T */ + enum { /* what's the next step ? */ + ecp_rs_init = 0, /* just getting started */ + ecp_rs_final_norm, /* do the final normalization */ } state; }; @@ -128,6 +130,8 @@ static void ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) */ static void ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) { + unsigned char i; + if( ctx == NULL ) return; @@ -135,6 +139,12 @@ static void ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) mbedtls_ecp_point_free( &ctx->P ); mbedtls_ecp_point_free( &ctx->R ); + if( ctx->T != NULL ) { + for( i = 0; i < ctx->T_size; i++ ) + mbedtls_ecp_point_free( ctx->T + i ); + mbedtls_free( ctx->T ); + } + memset( ctx, 0, sizeof( mbedtls_ecp_restart_ctx ) ); } @@ -1601,8 +1611,9 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, void *p_rng ) { int ret; - unsigned char w, p_eq_g, pre_len, i; + unsigned char w, p_eq_g = 0, i; size_t d; + unsigned char pre_len = 0; mbedtls_ecp_point *T = NULL; #if defined(MBEDTLS_ECP_EARLY_RETURN) @@ -1639,8 +1650,6 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); -#else - p_eq_g = 0; #endif /* Pick window size and deduce related sizes */ @@ -1654,6 +1663,16 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, */ T = p_eq_g ? grp->T : NULL; +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL && grp->rs->T != NULL && T == NULL ) + { + /* transfer "ownership" of T from rs to local function */ + T = grp->rs->T; + grp->rs->T = NULL; + grp->rs->T_size = 0; + } +#endif + if( T == NULL ) { T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); @@ -1679,6 +1698,16 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, cleanup: +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != grp->T ) + { + /* transfer "ownership" of T from local function to rs */ + grp->rs->T_size = pre_len; + grp->rs->T = T; + T = NULL; + } +#endif + if( T != NULL && ! p_eq_g ) { for( i = 0; i < pre_len; i++ ) From 085b1dff40ad1a2bcccc0b9da062bd580b8d2961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 16 Mar 2017 16:56:04 +0100 Subject: [PATCH 019/148] Allow T to be computed in multiple steps Previously there were only two states: - T unallocated - T allocated and valid Now there are three: - T unallocated - T allocated and in progress - T allocated and valid Introduce new bool T_ok to distinguish the last two states. --- library/ecp.c | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 653c60f3b..71fb314cc 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -113,6 +113,8 @@ struct mbedtls_ecp_restart { unsigned char T_size; /* number of points in table T */ enum { /* what's the next step ? */ ecp_rs_init = 0, /* just getting started */ + ecp_rs_tmp_dummy, /* temporary for incremental testing */ + ecp_rs_T_done, /* call ecp_mul_comb_after_precomp() */ ecp_rs_final_norm, /* do the final normalization */ } state; }; @@ -1334,6 +1336,15 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, size_t j; mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; +#if defined(MBEDTLS_ECP_EARLY_RETURN) + /* XXX: dummy "in_progress" return for testing caller */ + if( grp->rs != NULL && grp->rs->state == ecp_rs_init ) + { + grp->rs->state++; + return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + } +#endif + /* * Set T[0] = P and * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) @@ -1370,6 +1381,11 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL ) + grp->rs->state++; +#endif + cleanup: return( ret ); @@ -1613,7 +1629,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, int ret; unsigned char w, p_eq_g = 0, i; size_t d; - unsigned char pre_len = 0; + unsigned char pre_len = 0, T_ok = 0; mbedtls_ecp_point *T = NULL; #if defined(MBEDTLS_ECP_EARLY_RETURN) @@ -1657,22 +1673,28 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, pre_len = 1U << ( w - 1 ); d = ( grp->nbits + w - 1 ) / w; - /* - * Prepare precomputed points: if P == G we want to - * use grp->T if already initialized, or initialize it. - */ - T = p_eq_g ? grp->T : NULL; + /* Pre-computed table: do we have it already for the base point? */ + if( p_eq_g && grp->T != NULL ) + { + T = grp->T; + T_ok = 1; + } #if defined(MBEDTLS_ECP_EARLY_RETURN) + /* Pre-computed table: do we have one in progress? complete? */ if( grp->rs != NULL && grp->rs->T != NULL && T == NULL ) { /* transfer "ownership" of T from rs to local function */ T = grp->rs->T; grp->rs->T = NULL; grp->rs->T_size = 0; + + if( grp->rs->state >= ecp_rs_T_done ) + T_ok = 1; } #endif + /* Allocate table if we didn't have any */ if( T == NULL ) { T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); @@ -1681,7 +1703,11 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } + } + /* Compute table (or finish computing it) if not done already */ + if( !T_ok ) + { MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); if( p_eq_g ) From 07bf6f52c1e3317a12e53b523199fd9474831aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 16 Mar 2017 17:21:38 +0100 Subject: [PATCH 020/148] Tune T ownership code + comments Don't miss the little code changes among all those comments change :) --- library/ecp.c | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 71fb314cc..f852c9988 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1618,8 +1618,17 @@ static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, } /* - * Multiplication using the comb method, - * for curves in short Weierstrass form + * Multiplication using the comb method - for curves in short Weierstrass form + * + * This function is mainly responsible for administrative work: + * - managing the restart context if enabled + * - managing the table of precomputed points (passed between the above two + * functions): allocation, computation, ownership tranfer, freeing. + * + * It delegates the actual arithmetic work to: + * ecp_precompute_comb() and ecp_mul_comb_with_precomp() + * + * See comments on ecp_comb_recode_core() regarding the computation strategy. */ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, @@ -1657,7 +1666,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &grp->rs->P, P ) ); } - /* new start for ops counts */ + /* reset ops count for this call */ if( grp->rs != NULL ) grp->rs->ops_done = 0; #endif @@ -1676,6 +1685,8 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* Pre-computed table: do we have it already for the base point? */ if( p_eq_g && grp->T != NULL ) { + /* second pointer to the same table + * no ownership transfer as other threads might be using T too */ T = grp->T; T_ok = 1; } @@ -1684,7 +1695,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* Pre-computed table: do we have one in progress? complete? */ if( grp->rs != NULL && grp->rs->T != NULL && T == NULL ) { - /* transfer "ownership" of T from rs to local function */ + /* transfer ownership of T from rs to local function */ T = grp->rs->T; grp->rs->T = NULL; grp->rs->T_size = 0; @@ -1714,6 +1725,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, { grp->T = T; grp->T_size = pre_len; + /* now have two pointers to the same table */ } } @@ -1724,17 +1736,23 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, cleanup: + /* does T belong to the group? */ + if( T == grp->T ) + T = NULL; + + /* does T belong to the restart context? */ #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != grp->T ) + if( grp->rs != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) { - /* transfer "ownership" of T from local function to rs */ + /* transfer ownership of T from local function to rs */ grp->rs->T_size = pre_len; grp->rs->T = T; T = NULL; } #endif - if( T != NULL && ! p_eq_g ) + /* did T belong to us? then let's destroy it! */ + if( T != NULL ) { for( i = 0; i < pre_len; i++ ) mbedtls_ecp_point_free( &T[i] ); @@ -1745,9 +1763,11 @@ cleanup: #if defined(MBEDTLS_ECP_EARLY_RETURN) if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) #endif + /* prevent caller from using invalid value */ if( ret != 0 ) mbedtls_ecp_point_free( R ); + /* clear restart context when not in progress (done or error) */ #if defined(MBEDTLS_ECP_EARLY_RETURN) if( grp->rs != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { ecp_restart_free( grp->rs ); From fc3e0beabfa7b97476bc90fad32167ea04fb5341 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Mar 2017 09:29:31 +0100 Subject: [PATCH 021/148] Separate auxiliary array in precompute_comb() Separating main computation from filling of the auxiliary array makes things clearer and easier to restart as we don't have to remember the in-progress auxiliary array. --- library/ecp.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index f852c9988..47c7da2a2 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1332,7 +1332,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, unsigned char w, size_t d ) { int ret; - unsigned char i, k; + unsigned char i; size_t j; mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; @@ -1351,35 +1351,44 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, */ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); - k = 0; for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) { cur = T + i; MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); for( j = 0; j < d; j++ ) MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); - - TT[k++] = cur; } - MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + /* + * Normalize current elements in T. As T has holes, + * use an auxiliary array of pointers to elements in T. + */ + j = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + TT[j++] = T + i; + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); /* * Compute the remaining ones using the minimal number of additions * Be careful to update T[2^l] only after using it! */ - k = 0; for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) { j = i; while( j-- ) - { MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); - TT[k++] = &T[i + j]; - } } - MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + /* + * Normalize final elements in T. Even though there are no holes now, + * we still need the auxiliary array for homogeneity with last time. + * Also skip T[0] which is already normalised, being a copy of P. + */ + for( j = 0; j + 1 < ( 1U << ( w - 1 ) ); j++ ) + TT[j] = T + j + 1; + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) if( grp->rs != NULL ) From 67c83fb8710520a8c402f76396f3b0111330cebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Mar 2017 10:08:53 +0100 Subject: [PATCH 022/148] Give a constant a name --- library/ecp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 47c7da2a2..7bcf25626 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1334,6 +1334,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, int ret; unsigned char i; size_t j; + const unsigned char T_len = 1U << ( w - 1 ); mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; #if defined(MBEDTLS_ECP_EARLY_RETURN) @@ -1351,7 +1352,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, */ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + for( i = 1; i < T_len; i <<= 1 ) { cur = T + i; MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); @@ -1364,7 +1365,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, * use an auxiliary array of pointers to elements in T. */ j = 0; - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + for( i = 1; i < T_len; i <<= 1 ) TT[j++] = T + i; MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); @@ -1373,7 +1374,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, * Compute the remaining ones using the minimal number of additions * Be careful to update T[2^l] only after using it! */ - for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + for( i = 1; i < T_len; i <<= 1 ) { j = i; while( j-- ) @@ -1383,9 +1384,9 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, /* * Normalize final elements in T. Even though there are no holes now, * we still need the auxiliary array for homogeneity with last time. - * Also skip T[0] which is already normalised, being a copy of P. + * Also, skip T[0] which is already normalised, being a copy of P. */ - for( j = 0; j + 1 < ( 1U << ( w - 1 ) ); j++ ) + for( j = 0; j + 1 < T_len; j++ ) TT[j] = T + j + 1; MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); From e2d7cb3f10a5e19f0448f010c8bc4008679f143a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Mar 2017 10:24:17 +0100 Subject: [PATCH 023/148] Start splitting precompute_comb() This is the easy part: with the current steps, all information between steps is passed via T which is already saved. Next we'll need to split at least the first loop, and maybe calls to normalize_jac_many() and/or the second loop. --- library/ecp.c | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 7bcf25626..2d473d9b4 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -113,7 +113,9 @@ struct mbedtls_ecp_restart { unsigned char T_size; /* number of points in table T */ enum { /* what's the next step ? */ ecp_rs_init = 0, /* just getting started */ - ecp_rs_tmp_dummy, /* temporary for incremental testing */ + ecp_rs_pre_norm_dbl, /* normalize precomputed 2^n multiples */ + ecp_rs_pre_add, /* precompute remaining points by adding */ + ecp_rs_pre_norm_add, /* normalize all precomputed points */ ecp_rs_T_done, /* call ecp_mul_comb_after_precomp() */ ecp_rs_final_norm, /* do the final normalization */ } state; @@ -1338,11 +1340,14 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; #if defined(MBEDTLS_ECP_EARLY_RETURN) - /* XXX: dummy "in_progress" return for testing caller */ - if( grp->rs != NULL && grp->rs->state == ecp_rs_init ) + if( grp->rs != NULL ) { - grp->rs->state++; - return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + if( grp->rs->state == ecp_rs_pre_norm_add ) + goto norm_add; + if( grp->rs->state == ecp_rs_pre_add ) + goto add; + if( grp->rs->state == ecp_rs_pre_norm_dbl ) + goto norm_dbl; } #endif @@ -1350,6 +1355,8 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, * Set T[0] = P and * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) */ + ECP_BUDGET( ( w - 1 ) * d * ECP_OPS_DBL ); // XXX: split loop + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); for( i = 1; i < T_len; i <<= 1 ) @@ -1360,20 +1367,42 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); } +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL ) + grp->rs->state++; +#endif + /* * Normalize current elements in T. As T has holes, * use an auxiliary array of pointers to elements in T. */ +#if defined(MBEDTLS_ECP_EARLY_RETURN) +norm_dbl: +#endif + j = 0; for( i = 1; i < T_len; i <<= 1 ) TT[j++] = T + i; + ECP_BUDGET( ECP_OPS_INV + 6 * j - 2 ); // XXX: split next function? + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL ) + grp->rs->state++; +#endif + /* * Compute the remaining ones using the minimal number of additions * Be careful to update T[2^l] only after using it! */ +#if defined(MBEDTLS_ECP_EARLY_RETURN) +add: +#endif + + ECP_BUDGET( ( T_len - 1 ) * ECP_OPS_ADD ); // XXX: split loop? + for( i = 1; i < T_len; i <<= 1 ) { j = i; @@ -1381,14 +1410,25 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); } +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL ) + grp->rs->state++; +#endif + /* * Normalize final elements in T. Even though there are no holes now, * we still need the auxiliary array for homogeneity with last time. * Also, skip T[0] which is already normalised, being a copy of P. */ +#if defined(MBEDTLS_ECP_EARLY_RETURN) +norm_add: +#endif + for( j = 0; j + 1 < T_len; j++ ) TT[j] = T + j + 1; + ECP_BUDGET( ECP_OPS_INV + 6 * j - 2 ); // XXX: split next function? + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) From ae55707b2859ca1abf2d349213670283aeec59f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Mar 2017 12:21:24 +0100 Subject: [PATCH 024/148] Turn double loop into single loop In preparation for making the loop restartable --- library/ecp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 2d473d9b4..5ee97c895 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1359,12 +1359,15 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); - for( i = 1; i < T_len; i <<= 1 ) + for( j = 0; j < d * ( w - 1 ); j++ ) { + i = 1U << ( j / d ); cur = T + i; - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); - for( j = 0; j < d; j++ ) - MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + + if( j % d == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); } #if defined(MBEDTLS_ECP_EARLY_RETURN) From 213541a548ca56bd9adc9b4ed3a2ac68a11a76cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Mar 2017 12:50:41 +0100 Subject: [PATCH 025/148] Make the first precomp loop restartable --- library/ecp.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 5ee97c895..a1f019d39 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1335,7 +1335,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, { int ret; unsigned char i; - size_t j; + size_t j = 0; const unsigned char T_len = 1U << ( w - 1 ); mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; @@ -1355,12 +1355,19 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, * Set T[0] = P and * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) */ - ECP_BUDGET( ( w - 1 ) * d * ECP_OPS_DBL ); // XXX: split loop - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); - for( j = 0; j < d * ( w - 1 ); j++ ) +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL && grp->rs->i != 0 ) + j = grp->rs->i; + else +#endif + j = 0; + + for( ; j < d * ( w - 1 ); j++ ) { + ECP_BUDGET( ECP_OPS_DBL ); + i = 1U << ( j / d ); cur = T + i; @@ -1372,7 +1379,10 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, #if defined(MBEDTLS_ECP_EARLY_RETURN) if( grp->rs != NULL ) + { + grp->rs->i = 0; grp->rs->state++; + } #endif /* @@ -1440,6 +1450,13 @@ norm_add: #endif cleanup: +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( grp->rs != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + if( grp->rs->state == ecp_rs_init ) + grp->rs->i = j; + } +#endif return( ret ); } From 1c678e0e0603c376ba265d38bc572e1ddc2f182d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Mar 2017 13:39:39 +0100 Subject: [PATCH 026/148] Update doc about minimum max_ops value Ok, so the original plan was to make mpi_inv_mod() the smallest block that could not be divided. Updated plan is that the smallest block will be either: - ecp_normalize_jac_many() (one mpi_inv_mod() + a number or mpi_mul_mpi()s) - or the second loop in ecp_precompute_comb() With default settings, the minimum non-restartable sequence is: - for P-256: 222M - for P-384: 341M This is within a 2-3x factor of originally planned value of 120M. However, that value can be approached, at the cost of some performance, by setting ECP_WINDOW_SIZE (w below) lower than the default of 6. For example: - w=4 -> 166M for any curve (perf. impact < 10%) - w=2 -> 130M for any curve (perf. impact ~ 30%) My opinion is that the current state with w=4 is a good compromise, and the code complexity need to attain 120M is not warranted by the 1.4 factor between that and the current minimum with w=4 (which is close to optimal perf). --- include/mbedtls/ecp.h | 10 ++++++++-- library/ecp.c | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index d44e65843..810cb9f78 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -274,8 +274,14 @@ mbedtls_ecp_keypair; * of the order of 3600 "basic operations" with default * settings. * - * \warning Values lower than 120 are currently not well-supported, in - * that sometimes functions will have to block for longer. + * \warning Very low values are not always respected: sometimes + * functions need to block for a minimum number of + * operations, and will do so even if max_ops is set to a + * lower value. That minimum depends on the curve size, and + * can be made lower by decreasing the value of + * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, the minimum + * is around 160 for P-256 with \c MBEDTLS_ECP_WINDOW_SIZE + * set to 4. */ void mbedtls_ecp_set_max_ops( unsigned max_ops ); #endif /* MBEDTLS_ECP_EARLY_RETURN */ diff --git a/library/ecp.c b/library/ecp.c index a1f019d39..b3bddbfc6 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1397,7 +1397,7 @@ norm_dbl: for( i = 1; i < T_len; i <<= 1 ) TT[j++] = T + i; - ECP_BUDGET( ECP_OPS_INV + 6 * j - 2 ); // XXX: split next function? + ECP_BUDGET( ECP_OPS_INV + 6 * j - 2 ); MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); @@ -1414,7 +1414,7 @@ norm_dbl: add: #endif - ECP_BUDGET( ( T_len - 1 ) * ECP_OPS_ADD ); // XXX: split loop? + ECP_BUDGET( ( T_len - 1 ) * ECP_OPS_ADD ); for( i = 1; i < T_len; i <<= 1 ) { @@ -1440,7 +1440,7 @@ norm_add: for( j = 0; j + 1 < T_len; j++ ) TT[j] = T + j + 1; - ECP_BUDGET( ECP_OPS_INV + 6 * j - 2 ); // XXX: split next function? + ECP_BUDGET( ECP_OPS_INV + 6 * j - 2 ); MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); From 9c5c78ff5c3d259b8fea0bed2af67e26042aea38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Mar 2017 14:13:07 +0100 Subject: [PATCH 027/148] Fix indicative values of ops counts Previous measurements were wrong due to counting multiplication by a small constant as a full multiplication, which it is not. --- include/mbedtls/ecp.h | 2 +- tests/suites/test_suite_ecp.function | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 810cb9f78..314e4b257 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -271,7 +271,7 @@ mbedtls_ecp_keypair; * \note A "basic operation" is roughly multiplication in GF(p), * or whatever takes a roughly equivalent amount of time. * As an indication, a scalar multiplication on P-256 is - * of the order of 3600 "basic operations" with default + * of the order of 3300 "basic operations" with default * settings. * * \warning Very low values are not always respected: sometimes diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index caf983e72..3dfef1877 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -69,11 +69,11 @@ void ecp_test_vect_restart( int id, * 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 + * - Random point mult: ~3250M + * - Cold base point mult: ~3300M + * - Hot base point mult: ~1100M * With MBEDTLS_ECP_WINDOW_SIZE set to 2 (minimum): - * - Random point mult: ~4200M + * - Random point mult: ~3850M */ mbedtls_ecp_group grp; mbedtls_ecp_point R; From d3a0ca850031012908fee4d7af2edd27649bb4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Mar 2017 14:20:38 +0100 Subject: [PATCH 028/148] Add tests about number of restarts --- tests/suites/test_suite_ecp.data | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index f96be5a51..82ffec57b 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -349,6 +349,14 @@ 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 +ECP early return secp256r1 restart max_ops=1 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":1:1:5000 + +ECP early return secp256r1 restart max_ops=10000 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":10000:0:0 + +ECP early return secp256r1 restart max_ops=250 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":250:2:32 From e685449004eccc58f327cbde5f9808f78c38471c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Mar 2017 14:35:19 +0100 Subject: [PATCH 029/148] Scale ops count for larger curves From a user's perspective, you want a "basic operation" to take approximately the same amount of time regardless of the curve size, especially since max_ops is a global setting: otherwise if you pick a limit suitable for P-384 then when you do an operation on P-256 it will return way more often than needed. Said otherwise, a user is actually interested in actual running time, and we do the API in terms of "basic ops" for practical reasons (no timers) but then we should make sure it's a good proxy for running time. --- include/mbedtls/ecp.h | 18 ++++++++++-------- library/ecp.c | 8 ++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 314e4b257..9521875df 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -268,20 +268,22 @@ mbedtls_ecp_keypair; * Lower (non-zero) values mean ECC functions will block for * a lesser maximum amount of time. * - * \note A "basic operation" is roughly multiplication in GF(p), - * or whatever takes a roughly equivalent amount of time. - * As an indication, a scalar multiplication on P-256 is - * of the order of 3300 "basic operations" with default - * settings. + * \note A "basic operation" is defined as a rough equivalent of a + * multiplication in GF(p) for the NIST P-256 curve. + * As an indication, with default settings, a scalar + * multiplication (full run of \c mbedtls_ecp_mul()) is: + * - about 3300 basic operations for P-256 + * - about 9400 basic operations for P-384 * * \warning Very low values are not always respected: sometimes * functions need to block for a minimum number of * operations, and will do so even if max_ops is set to a * lower value. That minimum depends on the curve size, and * can be made lower by decreasing the value of - * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, the minimum - * is around 160 for P-256 with \c MBEDTLS_ECP_WINDOW_SIZE - * set to 4. + * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, with that + * parameter set to 4, the minimum amount of blocking is: + * - around 165 basic operations for P-256 + * - around 330 basic operations for P-384 */ void mbedtls_ecp_set_max_ops( unsigned max_ops ); #endif /* MBEDTLS_ECP_EARLY_RETURN */ diff --git a/library/ecp.c b/library/ecp.c index b3bddbfc6..ec2e3cd7d 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -166,10 +166,18 @@ static int ecp_check_budget( const mbedtls_ecp_group *grp, unsigned ops ) { if( grp->rs != NULL ) { + /* scale depending on curve size: the chosen reference is 256-bit, + * and multiplication is quadratic. Round to the closest integer. */ + if( grp->pbits >= 512 ) + ops *= 4; + else if( grp->pbits >= 384 ) + ops *= 2; + /* avoid infinite loops: always allow first step */ if( grp->rs->ops_done != 0 && grp->rs->ops_done + ops > ecp_max_ops ) return( MBEDTLS_ERR_ECP_IN_PROGRESS ); + /* update running count */ grp->rs->ops_done += ops; } From e58f65a04bb30412b03dc1192a9f122ae82cf013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 20 Mar 2017 14:59:54 +0100 Subject: [PATCH 030/148] Expand documentation with notes and warnings --- include/mbedtls/ecp.h | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 9521875df..c7370339a 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -275,7 +275,7 @@ mbedtls_ecp_keypair; * - about 3300 basic operations for P-256 * - about 9400 basic operations for P-384 * - * \warning Very low values are not always respected: sometimes + * \note Very low values are not always respected: sometimes * functions need to block for a minimum number of * operations, and will do so even if max_ops is set to a * lower value. That minimum depends on the curve size, and @@ -284,6 +284,21 @@ mbedtls_ecp_keypair; * parameter set to 4, the minimum amount of blocking is: * - around 165 basic operations for P-256 * - around 330 basic operations for P-384 + * + * \note This setting is currently ignored by Curve25519 + * + * \warning The ECJPAKE module is currently not compatible with this + * feature. \c max_ops must always be 0 while using ECJPAKE. + * + * \warning NOT thread-safe: when \c max_ops is not zero, sharing a + * \c mbedtls_ecp_group structure, or a + * \c mbedtls_pk_context structure wrapping an ECC key, + * between concurrent threads of execution is NOT supported. + * For (D)TLS, that means it's not safe to concurrently run + * two handshakes that use the same private EC key for + * authenticating ourselves; it is however safe to maintain + * multiple simultaneous connections as long as the + * handshakes are not concurrent or don't use the same key. */ void mbedtls_ecp_set_max_ops( unsigned max_ops ); #endif /* MBEDTLS_ECP_EARLY_RETURN */ From 45fd0164dd23de06d3618a6809c7ad9863d2e711 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 22 Mar 2017 08:24:42 +0100 Subject: [PATCH 031/148] Rename multiplication-specific restart context It's going to be convenient for each function that can generate a MBEDTLS_ERR_ECP_IN_PROGRESS on its own (as opposed to just passing it around) to have its own restart context that they can allocate and free as needed independently of the restart context of other functions. For example ecp_muladd() is going to have its own restart_muladd context that in can managed, then when it calls ecp_mul() this will manage a restart_mul context without interfering with the caller's context. So, things need to be renames to avoid future name clashes. --- include/mbedtls/ecp.h | 6 +- library/ecp.c | 156 +++++++++++++++++++++--------------------- 2 files changed, 81 insertions(+), 81 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index c7370339a..c5664a84b 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -114,12 +114,12 @@ mbedtls_ecp_point; #if defined(MBEDTLS_ECP_EARLY_RETURN) /** - * \brief ECP context for resuming operations after returning + * \brief ECP context for resuming multiplication after returning * \c MBEDTLS_ERR_ECP_IN_PROGRESS * * \note Opaque struct */ -typedef struct mbedtls_ecp_restart mbedtls_ecp_restart_ctx; +typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; #endif /** @@ -164,7 +164,7 @@ typedef struct mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ size_t T_size; /*!< number for pre-computed points */ #if defined(MBEDTLS_ECP_EARLY_RETURN) - mbedtls_ecp_restart_ctx *rs; /*!< context for resuming operation */ + mbedtls_ecp_restart_mul_ctx *rsm; /*!< restart context for ecp_mul() */ #endif } mbedtls_ecp_group; diff --git a/library/ecp.c b/library/ecp.c index ec2e3cd7d..19d6af08c 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -103,7 +103,7 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ) /* * Restart context type for interrupted operations */ -struct mbedtls_ecp_restart { +struct mbedtls_ecp_restart_mul { unsigned ops_done; /* number of operations done this time */ mbedtls_mpi m; /* saved argument: scalar */ mbedtls_ecp_point P; /* saved argument: point */ @@ -112,27 +112,27 @@ struct mbedtls_ecp_restart { mbedtls_ecp_point *T; /* table for precomputed points */ unsigned char T_size; /* number of points in table T */ enum { /* what's the next step ? */ - ecp_rs_init = 0, /* just getting started */ - ecp_rs_pre_norm_dbl, /* normalize precomputed 2^n multiples */ - ecp_rs_pre_add, /* precompute remaining points by adding */ - ecp_rs_pre_norm_add, /* normalize all precomputed points */ - ecp_rs_T_done, /* call ecp_mul_comb_after_precomp() */ - ecp_rs_final_norm, /* do the final normalization */ + ecp_rsm_init = 0, /* just getting started */ + ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ + ecp_rsm_pre_add, /* precompute remaining points by adding */ + ecp_rsm_pre_norm_add, /* normalize all precomputed points */ + ecp_rsm_T_done, /* call ecp_mul_comb_after_precomp() */ + ecp_rsm_final_norm, /* do the final normalization */ } state; }; /* - * Init restart context + * Init restart_mul context */ -static void ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) +static void ecp_restart_mul_init( mbedtls_ecp_restart_mul_ctx *ctx ) { - memset( ctx, 0, sizeof( mbedtls_ecp_restart_ctx ) ); + memset( ctx, 0, sizeof( mbedtls_ecp_restart_mul_ctx ) ); } /* - * Free the components of a restart context + * Free the components of a restart_mul context */ -static void ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) +static void ecp_restart_mul_free( mbedtls_ecp_restart_mul_ctx *ctx ) { unsigned char i; @@ -149,7 +149,7 @@ static void ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) mbedtls_free( ctx->T ); } - memset( ctx, 0, sizeof( mbedtls_ecp_restart_ctx ) ); + memset( ctx, 0, sizeof( mbedtls_ecp_restart_mul_ctx ) ); } /* @@ -164,7 +164,7 @@ static void ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) */ static int ecp_check_budget( const mbedtls_ecp_group *grp, unsigned ops ) { - if( grp->rs != NULL ) + if( grp->rsm != NULL ) { /* scale depending on curve size: the chosen reference is 256-bit, * and multiplication is quadratic. Round to the closest integer. */ @@ -174,11 +174,11 @@ static int ecp_check_budget( const mbedtls_ecp_group *grp, unsigned ops ) ops *= 2; /* avoid infinite loops: always allow first step */ - if( grp->rs->ops_done != 0 && grp->rs->ops_done + ops > ecp_max_ops ) + if( grp->rsm->ops_done != 0 && grp->rsm->ops_done + ops > ecp_max_ops ) return( MBEDTLS_ERR_ECP_IN_PROGRESS ); /* update running count */ - grp->rs->ops_done += ops; + grp->rsm->ops_done += ops; } return( 0 ); @@ -451,8 +451,8 @@ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) } #if defined(MBEDTLS_ECP_EARLY_RETURN) - ecp_restart_free( grp->rs ); - mbedtls_free( grp->rs ); + ecp_restart_mul_free( grp->rsm ); + mbedtls_free( grp->rsm ); #endif mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) ); @@ -1348,13 +1348,13 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL ) + if( grp->rsm != NULL ) { - if( grp->rs->state == ecp_rs_pre_norm_add ) + if( grp->rsm->state == ecp_rsm_pre_norm_add ) goto norm_add; - if( grp->rs->state == ecp_rs_pre_add ) + if( grp->rsm->state == ecp_rsm_pre_add ) goto add; - if( grp->rs->state == ecp_rs_pre_norm_dbl ) + if( grp->rsm->state == ecp_rsm_pre_norm_dbl ) goto norm_dbl; } #endif @@ -1366,8 +1366,8 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL && grp->rs->i != 0 ) - j = grp->rs->i; + if( grp->rsm != NULL && grp->rsm->i != 0 ) + j = grp->rsm->i; else #endif j = 0; @@ -1386,10 +1386,10 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, } #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL ) + if( grp->rsm != NULL ) { - grp->rs->i = 0; - grp->rs->state++; + grp->rsm->i = 0; + grp->rsm->state++; } #endif @@ -1410,8 +1410,8 @@ norm_dbl: MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL ) - grp->rs->state++; + if( grp->rsm != NULL ) + grp->rsm->state++; #endif /* @@ -1432,8 +1432,8 @@ add: } #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL ) - grp->rs->state++; + if( grp->rsm != NULL ) + grp->rsm->state++; #endif /* @@ -1453,16 +1453,16 @@ norm_add: MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL ) - grp->rs->state++; + if( grp->rsm != NULL ) + grp->rsm->state++; #endif cleanup: #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + if( grp->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - if( grp->rs->state == ecp_rs_init ) - grp->rs->i = j; + if( grp->rsm->state == ecp_rsm_init ) + grp->rsm->i = j; } #endif @@ -1515,10 +1515,10 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R mbedtls_ecp_point_init( &Txi ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL && grp->rs->i != 0 ) + if( grp->rsm != NULL && grp->rsm->i != 0 ) { - /* restore current index (R already pointing to grp->rs->R) */ - i = grp->rs->i; + /* restore current index (R already pointing to grp->rsm->R) */ + i = grp->rsm->i; } else #endif @@ -1544,18 +1544,18 @@ cleanup: mbedtls_ecp_point_free( &Txi ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL ) + if( grp->rsm != NULL ) { if( ret == 0 ) { - grp->rs->state++; - grp->rs->i = 0; + grp->rsm->state++; + grp->rsm->i = 0; } else if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { /* was decreased before actually doing it */ - grp->rs->i = i + 1; - /* no need to save R, already pointing to grp->rs->R */ + grp->rsm->i = i + 1; + /* no need to save R, already pointing to grp->rsm->R */ } } #endif @@ -1628,12 +1628,12 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, mbedtls_ecp_point *RR = R; #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL ) - RR = &grp->rs->R; + if( grp->rsm != NULL ) + RR = &grp->rsm->R; #endif #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs == NULL || grp->rs->state < ecp_rs_final_norm ) + if( grp->rsm == NULL || grp->rsm->state < ecp_rsm_final_norm ) #endif { MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, @@ -1643,8 +1643,8 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL ) - grp->rs->state++; + if( grp->rsm != NULL ) + grp->rsm->state++; #endif } @@ -1721,32 +1721,32 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #if defined(MBEDTLS_ECP_EARLY_RETURN) /* check for restart with new arguments */ - if( grp->rs != NULL && - ( mbedtls_mpi_cmp_mpi( m, &grp->rs->m ) != 0 || - mbedtls_mpi_cmp_mpi( &P->X, &grp->rs->P.X ) != 0 || - mbedtls_mpi_cmp_mpi( &P->Y, &grp->rs->P.Y ) != 0 ) ) + if( grp->rsm != NULL && + ( mbedtls_mpi_cmp_mpi( m, &grp->rsm->m ) != 0 || + mbedtls_mpi_cmp_mpi( &P->X, &grp->rsm->P.X ) != 0 || + mbedtls_mpi_cmp_mpi( &P->Y, &grp->rsm->P.Y ) != 0 ) ) { - ecp_restart_free( grp->rs ); - mbedtls_free( grp->rs ); - grp->rs = NULL; + ecp_restart_mul_free( grp->rsm ); + mbedtls_free( grp->rsm ); + grp->rsm = NULL; } /* set up restart context if needed */ - if( ecp_max_ops != 0 && grp->rs == NULL ) + if( ecp_max_ops != 0 && grp->rsm == NULL ) { - grp->rs = mbedtls_calloc( 1, sizeof( mbedtls_ecp_restart_ctx ) ); - if( grp->rs == NULL ) + grp->rsm = mbedtls_calloc( 1, sizeof( mbedtls_ecp_restart_mul_ctx ) ); + if( grp->rsm == NULL ) return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); - ecp_restart_init( grp->rs ); + ecp_restart_mul_init( grp->rsm ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &grp->rs->m, m ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &grp->rs->P, P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &grp->rsm->m, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &grp->rsm->P, P ) ); } /* reset ops count for this call */ - if( grp->rs != NULL ) - grp->rs->ops_done = 0; + if( grp->rsm != NULL ) + grp->rsm->ops_done = 0; #endif /* Is P the base point ? */ @@ -1771,14 +1771,14 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #if defined(MBEDTLS_ECP_EARLY_RETURN) /* Pre-computed table: do we have one in progress? complete? */ - if( grp->rs != NULL && grp->rs->T != NULL && T == NULL ) + if( grp->rsm != NULL && grp->rsm->T != NULL && T == NULL ) { - /* transfer ownership of T from rs to local function */ - T = grp->rs->T; - grp->rs->T = NULL; - grp->rs->T_size = 0; + /* transfer ownership of T from rsm to local function */ + T = grp->rsm->T; + grp->rsm->T = NULL; + grp->rsm->T_size = 0; - if( grp->rs->state >= ecp_rs_T_done ) + if( grp->rsm->state >= ecp_rsm_T_done ) T_ok = 1; } #endif @@ -1820,11 +1820,11 @@ cleanup: /* does T belong to the restart context? */ #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) + if( grp->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) { - /* transfer ownership of T from local function to rs */ - grp->rs->T_size = pre_len; - grp->rs->T = T; + /* transfer ownership of T from local function to rsm */ + grp->rsm->T_size = pre_len; + grp->rsm->T = T; T = NULL; } #endif @@ -1847,10 +1847,10 @@ cleanup: /* clear restart context when not in progress (done or error) */ #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rs != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { - ecp_restart_free( grp->rs ); - mbedtls_free( grp->rs ); - grp->rs = NULL; + if( grp->rsm != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + ecp_restart_mul_free( grp->rsm ); + mbedtls_free( grp->rsm ); + grp->rsm = NULL; } #endif From b739a712d1caa5e27fc49b45cf7d71b8636e4053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 19 Apr 2017 10:11:56 +0200 Subject: [PATCH 032/148] Start moving to new design/API Following discussion in the team, it was deemed preferable for the restart context to be explicitly managed by the caller. This commits in the first in a series moving in that directly: it starts by only changing the public API, while still internally using the old design. Future commits in that series will change to the new design internally. The test function was simplified as it no longer makes sense to test for some memory management errors since that responsibility shifted to the caller. --- include/mbedtls/ecp.h | 54 +++++++++++++++++++++++++--- library/ecp.c | 35 ++++++++++++++++++ tests/suites/test_suite_ecp.function | 31 +++++----------- 3 files changed, 93 insertions(+), 27 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index c5664a84b..86d7c5906 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -164,7 +164,7 @@ typedef struct mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ size_t T_size; /*!< number for pre-computed points */ #if defined(MBEDTLS_ECP_EARLY_RETURN) - mbedtls_ecp_restart_mul_ctx *rsm; /*!< restart context for ecp_mul() */ + mbedtls_ecp_restart_mul_ctx *rsm; /*!< temporary */ #endif } mbedtls_ecp_group; @@ -184,6 +184,16 @@ typedef struct } mbedtls_ecp_keypair; +#if defined(MBEDTLS_ECP_EARLY_RETURN) +/** + * \brief General context for resuming ECC operations + */ +typedef struct +{ + mbedtls_ecp_restart_mul_ctx *rsm; /*!< restart context for ecp_mul() */ +} mbedtls_ecp_restart_ctx; +#endif /* MBEDTLS_ECP_EARLY_RETURN */ + /** * \name SECTION: Module settings * @@ -377,6 +387,18 @@ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); */ void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) +/** + * \brief Initialize a restart context + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_EARLY_RETURN */ + /** * \brief Copy the contents of point Q into P * @@ -588,16 +610,40 @@ int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, * \return 0 if successful, * MBEDTLS_ERR_ECP_INVALID_KEY if m is not a valid privkey * or P is not a valid pubkey, - * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_ECP_EARLY_RETURN) +/** + * \brief Restartable version of \c mbedtls_ecp_mul() + * + * \note Performs the same job as \c mbedtls_ecp_mul(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply + * \param P Point to multiply + * \param f_rng RNG function (see notes) + * \param p_rng RNG parameter + * \param rs_ctx Restart context - must be non-NULL to enable early-return + * + * \return See \c mbedtls_ecp_mul(), or * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached (see \c mbedtls_ecp_set_max_ops()), * indicating the function should be called again with the * exact same arguments. * */ -int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ); +#endif /* MBEDTLS_ECP_EARLY_RETURN */ /** * \brief Multiplication and addition of two points by integers: diff --git a/library/ecp.c b/library/ecp.c index 19d6af08c..b2c2f53c2 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -152,6 +152,27 @@ static void ecp_restart_mul_free( mbedtls_ecp_restart_mul_ctx *ctx ) memset( ctx, 0, sizeof( mbedtls_ecp_restart_mul_ctx ) ); } +/* + * Initialize a restart context + */ +void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) +{ + memset( ctx, 0, sizeof( *ctx ) ); +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + ecp_restart_mul_free( ctx->rsm ); + mbedtls_free( ctx->rsm ); + ctx->rsm = NULL; +} + /* * Operation counts */ @@ -2111,6 +2132,20 @@ cleanup: return( ret ); } +#if defined(MBEDTLS_ECP_EARLY_RETURN) +/* + * Restartable multiplication R = m * P + */ +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + (void) rs_ctx; /* cheating for now */ + return( mbedtls_ecp_mul( grp, R, m, P, f_rng, p_rng ) ); +} +#endif + #if defined(ECP_SHORTWEIERSTRASS) /* * Check that an affine point is valid as a public key, diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 3dfef1877..195146c54 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -75,12 +75,14 @@ void ecp_test_vect_restart( int id, * With MBEDTLS_ECP_WINDOW_SIZE set to 2 (minimum): * - Random point mult: ~3850M */ + mbedtls_ecp_restart_ctx ctx; mbedtls_ecp_group grp; mbedtls_ecp_point R; mbedtls_mpi dA, xA, yA, dB, xZ, yZ; int cnt_restarts; int ret; + mbedtls_ecp_restart_init( &ctx ); 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 ); @@ -100,7 +102,7 @@ void ecp_test_vect_restart( int id, /* Base point case */ cnt_restarts = 0; do { - ret = mbedtls_ecp_mul( &grp, &R, &dA, &grp.G, NULL, NULL ); + ret = mbedtls_ecp_mul_restartable( &grp, &R, &dA, &grp.G, NULL, NULL, &ctx ); TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) @@ -114,24 +116,13 @@ void ecp_test_vect_restart( int id, 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 ); - - /* Ok, now start an operation with some arguments, and drop it. - * We'll see if the result of the next operation, with different args, - * are correct regardless (do we discard old context on new args?). - * This also tests that we don't write to R prematurely */ - ret = mbedtls_ecp_mul( &grp, &R, &dA, &grp.G, NULL, NULL ); - TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + /* Prepare context for new operation */ + mbedtls_ecp_restart_free( &ctx ); /* Non-base point case */ cnt_restarts = 0; do { - ret = mbedtls_ecp_mul( &grp, &R, &dB, &R, NULL, NULL ); + ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &R, NULL, NULL, &ctx ); TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) @@ -145,18 +136,12 @@ void ecp_test_vect_restart( int id, 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 ); - /* Do we leak memory when not finishing an operation? */ - ret = mbedtls_ecp_mul( &grp, &R, &dB, &R, NULL, NULL ); + ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &R, NULL, NULL, &ctx ); TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); exit: + mbedtls_ecp_restart_free( &ctx ); 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 ); From 8f28addb27da8f4e04a3d5d9c2e4bb3100947a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 19 Apr 2017 10:20:49 +0200 Subject: [PATCH 033/148] Update documentation for new design/API EC-JPAKE warning is no longer needed as we now have separate _restartable() functions, and JPAKE will just call the non-restartable version. Concurrency warning removed as this is one of the reasons why this design was chosen. --- include/mbedtls/ecp.h | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 86d7c5906..111ef03bb 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -273,6 +273,10 @@ typedef struct * then need to be called again with the same arguments until * it returns 0 or an other error code. * + * This only affects functions that accept a pointer to a + * \c mbedtls_ecp_restart_ctx as an argument, and only works + * if that pointer valid (in particular, not NULL). + * * \param max_ops Maximum number of basic operations done in a row. * Default: 0 (unlimited). * Lower (non-zero) values mean ECC functions will block for @@ -296,19 +300,6 @@ typedef struct * - around 330 basic operations for P-384 * * \note This setting is currently ignored by Curve25519 - * - * \warning The ECJPAKE module is currently not compatible with this - * feature. \c max_ops must always be 0 while using ECJPAKE. - * - * \warning NOT thread-safe: when \c max_ops is not zero, sharing a - * \c mbedtls_ecp_group structure, or a - * \c mbedtls_pk_context structure wrapping an ECC key, - * between concurrent threads of execution is NOT supported. - * For (D)TLS, that means it's not safe to concurrently run - * two handshakes that use the same private EC key for - * authenticating ourselves; it is however safe to maintain - * multiple simultaneous connections as long as the - * handshakes are not concurrent or don't use the same key. */ void mbedtls_ecp_set_max_ops( unsigned max_ops ); #endif /* MBEDTLS_ECP_EARLY_RETURN */ From 3cade22f96b17862cccdf1cef7e20f8ea03b971b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 09:31:00 +0200 Subject: [PATCH 034/148] Switch to restart context internally --- include/mbedtls/ecp.h | 20 ++--- library/ecp.c | 200 +++++++++++++++++++++++++----------------- 2 files changed, 127 insertions(+), 93 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 111ef03bb..59d9d3dea 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -112,16 +112,6 @@ typedef struct } mbedtls_ecp_point; -#if defined(MBEDTLS_ECP_EARLY_RETURN) -/** - * \brief ECP context for resuming multiplication after returning - * \c MBEDTLS_ERR_ECP_IN_PROGRESS - * - * \note Opaque struct - */ -typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; -#endif - /** * \brief ECP group structure * @@ -163,9 +153,6 @@ typedef struct void *t_data; /*!< unused */ mbedtls_ecp_point *T; /*!< pre-computed points for ecp_mul_comb() */ size_t T_size; /*!< number for pre-computed points */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) - mbedtls_ecp_restart_mul_ctx *rsm; /*!< temporary */ -#endif } mbedtls_ecp_group; @@ -185,6 +172,13 @@ typedef struct mbedtls_ecp_keypair; #if defined(MBEDTLS_ECP_EARLY_RETURN) +/** + * \brief Internal restart context for multiplication + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; + /** * \brief General context for resuming ECC operations */ diff --git a/library/ecp.c b/library/ecp.c index b2c2f53c2..21ce22f85 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -183,9 +183,11 @@ void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) /* * Check if we can do the next step */ -static int ecp_check_budget( const mbedtls_ecp_group *grp, unsigned ops ) +static int ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ) { - if( grp->rsm != NULL ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { /* scale depending on curve size: the chosen reference is 256-bit, * and multiplication is quadratic. Round to the closest integer. */ @@ -195,19 +197,22 @@ static int ecp_check_budget( const mbedtls_ecp_group *grp, unsigned ops ) ops *= 2; /* avoid infinite loops: always allow first step */ - if( grp->rsm->ops_done != 0 && grp->rsm->ops_done + ops > ecp_max_ops ) + if( rs_ctx->rsm->ops_done != 0 && rs_ctx->rsm->ops_done + ops > ecp_max_ops ) return( MBEDTLS_ERR_ECP_IN_PROGRESS ); /* update running count */ - grp->rsm->ops_done += ops; + rs_ctx->rsm->ops_done += ops; } return( 0 ); } -#define ECP_BUDGET( ops ) MBEDTLS_MPI_CHK( ecp_check_budget( grp, ops ) ); +#define ECP_BUDGET( ops ) MBEDTLS_MPI_CHK( ecp_check_budget( grp, rs_ctx, ops ) ); #else -#define ECP_BUDGET( ops ) +#define ECP_BUDGET( ops ) /* no-op */ + +/* We also need that type to make our life simpler for internal functions */ +typedef void mbedtls_ecp_restart_ctx; #endif /* MBEDTLS_ECP_EARLY_RETURN */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ @@ -471,11 +476,6 @@ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) mbedtls_free( grp->T ); } -#if defined(MBEDTLS_ECP_EARLY_RETURN) - ecp_restart_mul_free( grp->rsm ); - mbedtls_free( grp->rsm ); -#endif - mbedtls_zeroize( grp, sizeof( mbedtls_ecp_group ) ); } @@ -1360,7 +1360,8 @@ static void ecp_comb_recode_core( unsigned char x[], size_t d, */ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point T[], const mbedtls_ecp_point *P, - unsigned char w, size_t d ) + unsigned char w, size_t d, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; unsigned char i; @@ -1368,14 +1369,18 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, const unsigned char T_len = 1U << ( w - 1 ); mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; +#if !defined(MBEDTLS_ECP_EARLY_RETURN) + (void) rs_ctx; +#endif + #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { - if( grp->rsm->state == ecp_rsm_pre_norm_add ) + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) goto norm_add; - if( grp->rsm->state == ecp_rsm_pre_add ) + if( rs_ctx->rsm->state == ecp_rsm_pre_add ) goto add; - if( grp->rsm->state == ecp_rsm_pre_norm_dbl ) + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl ) goto norm_dbl; } #endif @@ -1387,8 +1392,8 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL && grp->rsm->i != 0 ) - j = grp->rsm->i; + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) + j = rs_ctx->rsm->i; else #endif j = 0; @@ -1407,10 +1412,10 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, } #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { - grp->rsm->i = 0; - grp->rsm->state++; + rs_ctx->rsm->i = 0; + rs_ctx->rsm->state++; } #endif @@ -1431,8 +1436,8 @@ norm_dbl: MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL ) - grp->rsm->state++; + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state++; #endif /* @@ -1453,8 +1458,8 @@ add: } #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL ) - grp->rsm->state++; + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state++; #endif /* @@ -1474,16 +1479,17 @@ norm_add: MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL ) - grp->rsm->state++; + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state++; #endif cleanup: #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - if( grp->rsm->state == ecp_rsm_init ) - grp->rsm->i = j; + if( rs_ctx->rsm->state == ecp_rsm_init ) + rs_ctx->rsm->i = j; } #endif @@ -1527,7 +1533,8 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R const mbedtls_ecp_point T[], unsigned char t_len, const unsigned char x[], size_t d, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; mbedtls_ecp_point Txi; @@ -1535,11 +1542,15 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R mbedtls_ecp_point_init( &Txi ); +#if !defined(MBEDTLS_ECP_EARLY_RETURN) + (void) rs_ctx; +#endif + #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL && grp->rsm->i != 0 ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) { - /* restore current index (R already pointing to grp->rsm->R) */ - i = grp->rsm->i; + /* restore current index (R already pointing to rs_ctx->rsm->R) */ + i = rs_ctx->rsm->i; } else #endif @@ -1565,18 +1576,18 @@ cleanup: mbedtls_ecp_point_free( &Txi ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { if( ret == 0 ) { - grp->rsm->state++; - grp->rsm->i = 0; + rs_ctx->rsm->state++; + rs_ctx->rsm->i = 0; } else if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { /* was decreased before actually doing it */ - grp->rsm->i = i + 1; - /* no need to save R, already pointing to grp->rsm->R */ + rs_ctx->rsm->i = i + 1; + /* no need to save R, already pointing to rs_ctx->rsm->R */ } } #endif @@ -1641,31 +1652,37 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, unsigned char w, size_t d, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; unsigned char parity_trick; unsigned char k[COMB_MAX_D + 1]; mbedtls_ecp_point *RR = R; -#if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL ) - RR = &grp->rsm->R; +#if !defined(MBEDTLS_ECP_EARLY_RETURN) + (void) rs_ctx; #endif #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm == NULL || grp->rsm->state < ecp_rsm_final_norm ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + RR = &rs_ctx->rsm->R; +#endif + +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( rs_ctx == NULL || rs_ctx->rsm == NULL || + rs_ctx->rsm->state < ecp_rsm_final_norm ) #endif { MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, &parity_trick ) ); MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, pre_len, k, d, - f_rng, p_rng ) ); + f_rng, p_rng, rs_ctx ) ); MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL ) - grp->rsm->state++; + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state++; #endif } @@ -1732,7 +1749,8 @@ static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; unsigned char w, p_eq_g = 0, i; @@ -1740,34 +1758,38 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, unsigned char pre_len = 0, T_ok = 0; mbedtls_ecp_point *T = NULL; +#if !defined(MBEDTLS_ECP_EARLY_RETURN) + (void) rs_ctx; +#endif + #if defined(MBEDTLS_ECP_EARLY_RETURN) /* check for restart with new arguments */ - if( grp->rsm != NULL && - ( mbedtls_mpi_cmp_mpi( m, &grp->rsm->m ) != 0 || - mbedtls_mpi_cmp_mpi( &P->X, &grp->rsm->P.X ) != 0 || - mbedtls_mpi_cmp_mpi( &P->Y, &grp->rsm->P.Y ) != 0 ) ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm != NULL && + ( mbedtls_mpi_cmp_mpi( m, &rs_ctx->rsm->m ) != 0 || + mbedtls_mpi_cmp_mpi( &P->X, &rs_ctx->rsm->P.X ) != 0 || + mbedtls_mpi_cmp_mpi( &P->Y, &rs_ctx->rsm->P.Y ) != 0 ) ) { - ecp_restart_mul_free( grp->rsm ); - mbedtls_free( grp->rsm ); - grp->rsm = NULL; + ecp_restart_mul_free( rs_ctx->rsm ); + mbedtls_free( rs_ctx->rsm ); + rs_ctx->rsm = NULL; } /* set up restart context if needed */ - if( ecp_max_ops != 0 && grp->rsm == NULL ) + if( ecp_max_ops != 0 && rs_ctx != NULL && rs_ctx->rsm == NULL ) { - grp->rsm = mbedtls_calloc( 1, sizeof( mbedtls_ecp_restart_mul_ctx ) ); - if( grp->rsm == NULL ) + rs_ctx->rsm = mbedtls_calloc( 1, sizeof( mbedtls_ecp_restart_mul_ctx ) ); + if( rs_ctx->rsm == NULL ) return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); - ecp_restart_mul_init( grp->rsm ); + ecp_restart_mul_init( rs_ctx->rsm ); - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &grp->rsm->m, m ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &grp->rsm->P, P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &rs_ctx->rsm->m, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &rs_ctx->rsm->P, P ) ); } /* reset ops count for this call */ - if( grp->rsm != NULL ) - grp->rsm->ops_done = 0; + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->ops_done = 0; #endif /* Is P the base point ? */ @@ -1792,14 +1814,14 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #if defined(MBEDTLS_ECP_EARLY_RETURN) /* Pre-computed table: do we have one in progress? complete? */ - if( grp->rsm != NULL && grp->rsm->T != NULL && T == NULL ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL && T == NULL ) { /* transfer ownership of T from rsm to local function */ - T = grp->rsm->T; - grp->rsm->T = NULL; - grp->rsm->T_size = 0; + T = rs_ctx->rsm->T; + rs_ctx->rsm->T = NULL; + rs_ctx->rsm->T_size = 0; - if( grp->rsm->state >= ecp_rsm_T_done ) + if( rs_ctx->rsm->state >= ecp_rsm_T_done ) T_ok = 1; } #endif @@ -1818,7 +1840,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* Compute table (or finish computing it) if not done already */ if( !T_ok ) { - MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d, rs_ctx ) ); if( p_eq_g ) { @@ -1831,7 +1853,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* Actual comb multiplication using precomputed points */ MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m, T, pre_len, w, d, - f_rng, p_rng ) ); + f_rng, p_rng, rs_ctx ) ); cleanup: @@ -1841,11 +1863,11 @@ cleanup: /* does T belong to the restart context? */ #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) { /* transfer ownership of T from local function to rsm */ - grp->rsm->T_size = pre_len; - grp->rsm->T = T; + rs_ctx->rsm->T_size = pre_len; + rs_ctx->rsm->T = T; T = NULL; } #endif @@ -1868,10 +1890,10 @@ cleanup: /* clear restart context when not in progress (done or error) */ #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( grp->rsm != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { - ecp_restart_mul_free( grp->rsm ); - mbedtls_free( grp->rsm ); - grp->rsm = NULL; + if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + ecp_restart_mul_free( rs_ctx->rsm ); + mbedtls_free( rs_ctx->rsm ); + rs_ctx->rsm = NULL; } #endif @@ -2117,7 +2139,7 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif #if defined(ECP_SHORTWEIERSTRASS) if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng ); + ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng, NULL ); #endif #if defined(MBEDTLS_ECP_INTERNAL_ALT) @@ -2141,8 +2163,26 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx ) { - (void) rs_ctx; /* cheating for now */ - return( mbedtls_ecp_mul( grp, R, m, P, f_rng, p_rng ) ); + /* temporary code duplication with non-restartable version */ + int ret; + + /* Common sanity checks */ + if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || + ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) + return( ret ); + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + return( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); +#endif + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); } #endif From 8467e6848d9137abc175c54456d279240f6c4318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 09:47:06 +0200 Subject: [PATCH 035/148] Stop checking for argument change This was intended to detect aborted operations, but now that case is handled by the caller freeing the restart context. Also, as the internal sub-context is managed by the callee, no need for the caller to free/reset the restart context between successful calls. --- include/mbedtls/ecp.h | 14 ++++++-------- library/ecp.c | 18 ------------------ tests/suites/test_suite_ecp.function | 3 --- 3 files changed, 6 insertions(+), 29 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 59d9d3dea..d9e62f079 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -263,9 +263,10 @@ typedef struct * * If more operations are needed to complete a computation, * MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the - * function performing the computation. That function will - * then need to be called again with the same arguments until - * it returns 0 or an other error code. + * function performing the computation. It is then the + * caller's responsibility to either call again with the same + * arguments until it returns 0 or an error code; or to free + * the restart context if the operation is to be aborted. * * This only affects functions that accept a pointer to a * \c mbedtls_ecp_restart_ctx as an argument, and only works @@ -615,14 +616,11 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * \param P Point to multiply * \param f_rng RNG function (see notes) * \param p_rng RNG parameter - * \param rs_ctx Restart context - must be non-NULL to enable early-return + * \param rs_ctx Restart context * * \return See \c mbedtls_ecp_mul(), or * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of - * operations was reached (see \c mbedtls_ecp_set_max_ops()), - * indicating the function should be called again with the - * exact same arguments. - * + * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, diff --git a/library/ecp.c b/library/ecp.c index 21ce22f85..fcc3ae077 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -105,8 +105,6 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ) */ struct mbedtls_ecp_restart_mul { unsigned ops_done; /* number of operations done this time */ - mbedtls_mpi m; /* saved argument: scalar */ - mbedtls_ecp_point P; /* saved argument: point */ mbedtls_ecp_point R; /* current intermediate result */ size_t i; /* current index in various loops, 0 outside */ mbedtls_ecp_point *T; /* table for precomputed points */ @@ -139,8 +137,6 @@ static void ecp_restart_mul_free( mbedtls_ecp_restart_mul_ctx *ctx ) if( ctx == NULL ) return; - mbedtls_mpi_free( &ctx->m ); - mbedtls_ecp_point_free( &ctx->P ); mbedtls_ecp_point_free( &ctx->R ); if( ctx->T != NULL ) { @@ -1763,17 +1759,6 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif #if defined(MBEDTLS_ECP_EARLY_RETURN) - /* check for restart with new arguments */ - if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm != NULL && - ( mbedtls_mpi_cmp_mpi( m, &rs_ctx->rsm->m ) != 0 || - mbedtls_mpi_cmp_mpi( &P->X, &rs_ctx->rsm->P.X ) != 0 || - mbedtls_mpi_cmp_mpi( &P->Y, &rs_ctx->rsm->P.Y ) != 0 ) ) - { - ecp_restart_mul_free( rs_ctx->rsm ); - mbedtls_free( rs_ctx->rsm ); - rs_ctx->rsm = NULL; - } - /* set up restart context if needed */ if( ecp_max_ops != 0 && rs_ctx != NULL && rs_ctx->rsm == NULL ) { @@ -1782,9 +1767,6 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); ecp_restart_mul_init( rs_ctx->rsm ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &rs_ctx->rsm->m, m ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &rs_ctx->rsm->P, P ) ); } /* reset ops count for this call */ diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 195146c54..23905cef9 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -116,9 +116,6 @@ void ecp_test_vect_restart( int id, TEST_ASSERT( cnt_restarts >= min_restarts ); TEST_ASSERT( cnt_restarts <= max_restarts ); - /* Prepare context for new operation */ - mbedtls_ecp_restart_free( &ctx ); - /* Non-base point case */ cnt_restarts = 0; do { From 646393bb1e6b4d30a8119eea28ae520af5e2b7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 10:03:45 +0200 Subject: [PATCH 036/148] Move ops count to top-level context When a restartable function calls another restartable function, the current ops_count needs to be shared to avoid either doing too many operations or returning IN_PROGRESS uselessly. So it needs to be in the top-level context rather than a specific sub-context. --- include/mbedtls/ecp.h | 3 ++- library/ecp.c | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index d9e62f079..9193b77b9 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -184,7 +184,8 @@ typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; */ typedef struct { - mbedtls_ecp_restart_mul_ctx *rsm; /*!< restart context for ecp_mul() */ + unsigned ops_done; /*!< current ops count */ + mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ } mbedtls_ecp_restart_ctx; #endif /* MBEDTLS_ECP_EARLY_RETURN */ diff --git a/library/ecp.c b/library/ecp.c index fcc3ae077..ecc18152d 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -104,7 +104,6 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ) * Restart context type for interrupted operations */ struct mbedtls_ecp_restart_mul { - unsigned ops_done; /* number of operations done this time */ mbedtls_ecp_point R; /* current intermediate result */ size_t i; /* current index in various loops, 0 outside */ mbedtls_ecp_point *T; /* table for precomputed points */ @@ -164,6 +163,8 @@ void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) if( ctx == NULL ) return; + ctx->ops_done = 0; + ecp_restart_mul_free( ctx->rsm ); mbedtls_free( ctx->rsm ); ctx->rsm = NULL; @@ -183,7 +184,7 @@ static int ecp_check_budget( const mbedtls_ecp_group *grp, mbedtls_ecp_restart_ctx *rs_ctx, unsigned ops ) { - if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + if( rs_ctx != NULL && ecp_max_ops != 0 ) { /* scale depending on curve size: the chosen reference is 256-bit, * and multiplication is quadratic. Round to the closest integer. */ @@ -193,11 +194,11 @@ static int ecp_check_budget( const mbedtls_ecp_group *grp, ops *= 2; /* avoid infinite loops: always allow first step */ - if( rs_ctx->rsm->ops_done != 0 && rs_ctx->rsm->ops_done + ops > ecp_max_ops ) + if( rs_ctx->ops_done != 0 && rs_ctx->ops_done + ops > ecp_max_ops ) return( MBEDTLS_ERR_ECP_IN_PROGRESS ); /* update running count */ - rs_ctx->rsm->ops_done += ops; + rs_ctx->ops_done += ops; } return( 0 ); @@ -1759,7 +1760,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif #if defined(MBEDTLS_ECP_EARLY_RETURN) - /* set up restart context if needed */ + /* set up our own sub-context if needed */ if( ecp_max_ops != 0 && rs_ctx != NULL && rs_ctx->rsm == NULL ) { rs_ctx->rsm = mbedtls_calloc( 1, sizeof( mbedtls_ecp_restart_mul_ctx ) ); @@ -1770,8 +1771,8 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, } /* reset ops count for this call */ - if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - rs_ctx->rsm->ops_done = 0; + if( rs_ctx != NULL ) + rs_ctx->ops_done = 0; #endif /* Is P the base point ? */ From 884569cdb40b58fa98d375deba55ed38431d2ba2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 10:10:59 +0200 Subject: [PATCH 037/148] Avoid code duplication in ecp_mul() --- library/ecp.c | 42 ++++++++++++------------------------------ 1 file changed, 12 insertions(+), 30 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index ecc18152d..3df9d7634 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -2089,11 +2089,15 @@ cleanup: #endif /* ECP_MONTGOMERY */ /* - * Multiplication R = m * P + * Restartable multiplication R = m * P */ -int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, +#if !defined(MBEDTLS_ECP_EARLY_RETURN) +static +#endif +int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #if defined(MBEDTLS_ECP_INTERNAL_ALT) @@ -2122,7 +2126,7 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif #if defined(ECP_SHORTWEIERSTRASS) if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng, NULL ); + ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ); #endif #if defined(MBEDTLS_ECP_INTERNAL_ALT) @@ -2137,37 +2141,15 @@ cleanup: return( ret ); } -#if defined(MBEDTLS_ECP_EARLY_RETURN) /* - * Restartable multiplication R = m * P + * Multiplication R = m * P */ -int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - mbedtls_ecp_restart_ctx *rs_ctx ) + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - /* temporary code duplication with non-restartable version */ - int ret; - - /* Common sanity checks */ - if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - - if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || - ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) - return( ret ); - -#if defined(ECP_MONTGOMERY) - if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - return( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); -#endif -#if defined(ECP_SHORTWEIERSTRASS) - if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - return( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); -#endif - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + return( mbedtls_ecp_mul_restartable( grp, R, m, P, f_rng, p_rng, NULL ) ); } -#endif #if defined(ECP_SHORTWEIERSTRASS) /* From 53fbd63eb44a3ce09a7972b571ab6ce68023e461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 10:22:22 +0200 Subject: [PATCH 038/148] Remove redundant check Checked by check_pubkey(), called 2 lines later. --- library/ecp.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 3df9d7634..673b54705 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -2105,9 +2105,6 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif /* Common sanity checks */ - if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) return( ret ); From 3a256128d696322497f69f81b866d4fe75164ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 11:20:26 +0200 Subject: [PATCH 039/148] Reset ops_done at the right time This should only be done in the top-level function. Also, we need to know if we indeed are the top-level function or not: for example, when mbedtls_ecp_muladd() calls mbedtls_ecp_mul(), the later should not reset ops_done. This is handled by the "depth" parameter in the restart context. --- include/mbedtls/ecp.h | 1 + library/ecp.c | 35 ++++++++++++++++++++++------------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 9193b77b9..7d0abc032 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -185,6 +185,7 @@ typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; typedef struct { unsigned ops_done; /*!< current ops count */ + unsigned depth; /*!< call depth (0 = top-level) */ mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ } mbedtls_ecp_restart_ctx; #endif /* MBEDTLS_ECP_EARLY_RETURN */ diff --git a/library/ecp.c b/library/ecp.c index 673b54705..2f6c1e8f9 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -164,6 +164,7 @@ void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) return; ctx->ops_done = 0; + ctx->depth = 0; ecp_restart_mul_free( ctx->rsm ); mbedtls_free( ctx->rsm ); @@ -1769,10 +1770,6 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, ecp_restart_mul_init( rs_ctx->rsm ); } - - /* reset ops count for this call */ - if( rs_ctx != NULL ) - rs_ctx->ops_done = 0; #endif /* Is P the base point ? */ @@ -2104,10 +2101,11 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, char is_grp_capable = 0; #endif - /* Common sanity checks */ - if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || - ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) - return( ret ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + /* reset ops count for this call if top-level */ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) + rs_ctx->ops_done = 0; +#endif #if defined(MBEDTLS_ECP_INTERNAL_ALT) if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) @@ -2116,25 +2114,36 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ + + /* Common sanity checks */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); + + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #if defined(ECP_MONTGOMERY) if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) - ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ); - + MBEDTLS_MPI_CHK( ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ) ); #endif #if defined(ECP_SHORTWEIERSTRASS) if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) - ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ); - + MBEDTLS_MPI_CHK( ecp_mul_comb( grp, R, m, P, f_rng, p_rng, rs_ctx ) ); #endif -#if defined(MBEDTLS_ECP_INTERNAL_ALT) + cleanup: +#if defined(MBEDTLS_ECP_INTERNAL_ALT) if ( is_grp_capable ) { mbedtls_internal_ecp_free( grp ); } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( rs_ctx != NULL ) + rs_ctx->depth--; +#endif + return( ret ); } From a08cd1a77fa03865db46c0068ad2dc270a329a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 11:29:43 +0200 Subject: [PATCH 040/148] Avoid re-checking argument on restart --- library/ecp.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 2f6c1e8f9..4e637d732 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -2115,9 +2115,19 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif /* MBEDTLS_ECP_INTERNAL_ALT */ - /* Common sanity checks */ - MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) && defined(ECP_SHORTWEIERSTRASS) + /* skip argument check when restarting */ + if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS || + rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + { + /* Common sanity checks */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); + + /* check_privkey is 0M and check_pubkey is 3M */ + ECP_BUDGET( 3 ); + } ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; #if defined(ECP_MONTGOMERY) From 54dd6527f0ffe980aa5c0eb03bbb0ed9d8c01ba5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 13:36:18 +0200 Subject: [PATCH 041/148] Introduce muladd_restartable() and its sub-context Only the administrative parts for now, not actually restartable so far. --- include/mbedtls/ecp.h | 35 +++++++++++ library/ecp.c | 94 +++++++++++++++++++++++++--- tests/suites/test_suite_ecp.data | 12 ++-- tests/suites/test_suite_ecp.function | 71 +++++++++++++++++++++ 4 files changed, 199 insertions(+), 13 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 7d0abc032..e2c605b0d 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -179,6 +179,13 @@ mbedtls_ecp_keypair; */ typedef struct mbedtls_ecp_restart_mul mbedtls_ecp_restart_mul_ctx; +/** + * \brief Internal restart context for ecp_muladd() + * + * \note Opaque struct + */ +typedef struct mbedtls_ecp_restart_muladd mbedtls_ecp_restart_muladd_ctx; + /** * \brief General context for resuming ECC operations */ @@ -187,6 +194,7 @@ typedef struct unsigned ops_done; /*!< current ops count */ unsigned depth; /*!< call depth (0 = top-level) */ mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ + mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ } mbedtls_ecp_restart_ctx; #endif /* MBEDTLS_ECP_EARLY_RETURN */ @@ -654,6 +662,33 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) +/** + * \brief Restartable version of \c mbedtls_ecp_muladd() + * + * \note Performs the same job as \c mbedtls_ecp_muladd(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param grp ECP group + * \param R Destination point + * \param m Integer by which to multiply P + * \param P Point to multiply by m + * \param n Integer by which to multiply Q + * \param Q Point to be multiplied by n + * \param rs_ctx Restart context + * + * \return See \c mbedtls_ecp_muladd(), or + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ); +#endif + /** * \brief Check that a point is a valid public key on this curve * diff --git a/library/ecp.c b/library/ecp.c index 4e637d732..493346006 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -101,9 +101,10 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ) } /* - * Restart context type for interrupted operations + * Restart sub-context for ecp_mul_comb() */ -struct mbedtls_ecp_restart_mul { +struct mbedtls_ecp_restart_mul +{ mbedtls_ecp_point R; /* current intermediate result */ size_t i; /* current index in various loops, 0 outside */ mbedtls_ecp_point *T; /* table for precomputed points */ @@ -119,7 +120,7 @@ struct mbedtls_ecp_restart_mul { }; /* - * Init restart_mul context + * Init restart_mul sub-context */ static void ecp_restart_mul_init( mbedtls_ecp_restart_mul_ctx *ctx ) { @@ -127,7 +128,7 @@ static void ecp_restart_mul_init( mbedtls_ecp_restart_mul_ctx *ctx ) } /* - * Free the components of a restart_mul context + * Free the components of a restart_mul sub-context */ static void ecp_restart_mul_free( mbedtls_ecp_restart_mul_ctx *ctx ) { @@ -147,6 +148,33 @@ static void ecp_restart_mul_free( mbedtls_ecp_restart_mul_ctx *ctx ) memset( ctx, 0, sizeof( mbedtls_ecp_restart_mul_ctx ) ); } +/* + * Restart context for ecp_muladd() + */ +struct mbedtls_ecp_restart_muladd +{ + int state; /* dummy for now */ +}; + +/* + * Init restart_muladd sub-context + */ +static void ecp_restart_muladd_init( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + memset( ctx, 0, sizeof( *ctx ) ); +} + +/* + * Free the components of a restart_muladd sub-context + */ +static void ecp_restart_muladd_free( mbedtls_ecp_restart_muladd_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + memset( ctx, 0, sizeof( *ctx ) ); +} + /* * Initialize a restart context */ @@ -1868,9 +1896,9 @@ cleanup: if( ret != 0 ) mbedtls_ecp_point_free( R ); - /* clear restart context when not in progress (done or error) */ + /* clear our sub-context when not in progress (done or error) */ #if defined(MBEDTLS_ECP_EARLY_RETURN) - if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { ecp_restart_mul_free( rs_ctx->rsm ); mbedtls_free( rs_ctx->rsm ); rs_ctx->rsm = NULL; @@ -2248,12 +2276,17 @@ cleanup: } /* - * Linear combination + * Restartable linear combination * NOT constant-time */ -int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, +#if !defined(MBEDTLS_ECP_EARLY_RETURN) +static +#endif +int mbedtls_ecp_muladd_restartable( + mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, - const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) + const mbedtls_mpi *n, const mbedtls_ecp_point *Q, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; mbedtls_ecp_point mP; @@ -2261,9 +2294,29 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, char is_grp_capable = 0; #endif +#if !defined(MBEDTLS_ECP_EARLY_RETURN) + (void) rs_ctx; +#endif + if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + /* reset ops count for this call if top-level */ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) + rs_ctx->ops_done = 0; + + /* set up our own sub-context if needed */ + if( ecp_max_ops != 0 && rs_ctx != NULL && rs_ctx->ma == NULL ) + { + rs_ctx->ma = mbedtls_calloc( 1, sizeof( mbedtls_ecp_restart_muladd_ctx ) ); + if( rs_ctx->ma == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + ecp_restart_muladd_init( rs_ctx->ma ); + } +#endif /* MBEDTLS_ECP_EARLY_RETURN */ + mbedtls_ecp_point_init( &mP ); MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); @@ -2290,9 +2343,32 @@ cleanup: #endif /* MBEDTLS_ECP_INTERNAL_ALT */ mbedtls_ecp_point_free( &mP ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + /* clear our sub-context when not in progress (done or error) */ + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + ecp_restart_muladd_free( rs_ctx->ma ); + mbedtls_free( rs_ctx->ma ); + rs_ctx->ma = NULL; + } + + + if( rs_ctx != NULL ) + rs_ctx->depth--; +#endif /* MBEDTLS_ECP_EARLY_RETURN */ + return( ret ); } +/* + * Linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) +{ + return( mbedtls_ecp_muladd_restartable( grp, R, m, P, n, Q, NULL ) ); +} #if defined(ECP_MONTGOMERY) /* diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 82ffec57b..9d25d2261 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -345,18 +345,22 @@ ecp_test_vect:MBEDTLS_ECP_DP_SECP256K1:"923C6D4756CD940CD1E13A359F6E0F0698791938 ECP selftest ecp_selftest: -ECP early return secp256r1 restart disabled +ECP early return mul 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 max_ops=1 +ECP early return mul secp256r1 restart max_ops=1 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":1:1:5000 -ECP early return secp256r1 restart max_ops=10000 +ECP early return mul secp256r1 restart max_ops=10000 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":10000:0:0 -ECP early return secp256r1 restart max_ops=250 +ECP early return mul secp256r1 restart max_ops=250 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":250:2:32 + +ECP early return muladd secp256r1 restart disabled +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":0:0:0 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 23905cef9..659830e5d 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -145,6 +145,77 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_ECP_EARLY_RETURN */ +void ecp_muladd_restart( int id, char *xR_str, char *yR_str, + char *u1_str, char *u2_str, + char *xQ_str, char *yQ_str, + int max_ops, int min_restarts, int max_restarts ) +{ + /* + * Compute R = u1 * G + u2 * Q + * (test vectors mostly taken from ECDSA intermediate results) + * + * See comments at the top of ecp_test_vect_restart() + */ + mbedtls_ecp_restart_ctx ctx; + mbedtls_ecp_group grp; + mbedtls_ecp_point R, Q; + mbedtls_mpi u1, u2, xR, yR; + int cnt_restarts; + int ret; + + mbedtls_ecp_restart_init( &ctx ); + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &R ); + mbedtls_ecp_point_init( &Q ); + mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + mbedtls_mpi_init( &xR ); mbedtls_mpi_init( &yR ); + + TEST_ASSERT( mbedtls_ecp_group_load( &grp, id ) == 0 ); + + TEST_ASSERT( mbedtls_mpi_read_string( &u1, 16, u1_str ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &u2, 16, u2_str ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &xR, 16, xR_str ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &yR, 16, yR_str ) == 0 ); + + TEST_ASSERT( mbedtls_mpi_read_string( &Q.X, 16, xQ_str ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &Q.Y, 16, yQ_str ) == 0 ); + TEST_ASSERT( mbedtls_mpi_lset( &Q.Z, 1 ) == 0 ); + + mbedtls_ecp_set_max_ops( (unsigned) max_ops ); + + cnt_restarts = 0; + do { + ret = mbedtls_ecp_muladd_restartable( &grp, &R, + &u1, &grp.G, &u2, &Q, &ctx ); + 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, &xR ) == 0 ); + TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.Y, &yR ) == 0 ); + + TEST_ASSERT( cnt_restarts >= min_restarts ); + TEST_ASSERT( cnt_restarts <= max_restarts ); + + /* Do we leak memory when aborting? */ + ret = mbedtls_ecp_muladd_restartable( &grp, &R, + &u1, &grp.G, &u2, &Q, &ctx ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + +exit: + mbedtls_ecp_restart_free( &ctx ); + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); + mbedtls_ecp_point_free( &Q ); + mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + mbedtls_mpi_free( &xR ); mbedtls_mpi_free( &yR ); +} +/* 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, From 1631d63d0c7d31b3e68246c3b9713c37ae060b8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 14:48:56 +0200 Subject: [PATCH 042/148] Make muladd_restartable() actually restartable --- library/ecp.c | 89 ++++++++++++++++++++++++++------ tests/suites/test_suite_ecp.data | 12 +++++ 2 files changed, 85 insertions(+), 16 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 493346006..f520b9caf 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -153,7 +153,14 @@ static void ecp_restart_mul_free( mbedtls_ecp_restart_mul_ctx *ctx ) */ struct mbedtls_ecp_restart_muladd { - int state; /* dummy for now */ + mbedtls_ecp_point mP; /* mP value */ + mbedtls_ecp_point R; /* R intermediate result */ + enum { /* what should we do next? */ + ecp_rsma_mul1 = 0, /* first multiplication */ + ecp_rsma_mul2, /* second multiplication */ + ecp_rsma_add, /* addition */ + ecp_rsma_norm, /* normalization */ + } state; }; /* @@ -172,6 +179,9 @@ static void ecp_restart_muladd_free( mbedtls_ecp_restart_muladd_ctx *ctx ) if( ctx == NULL ) return; + mbedtls_ecp_point_free( &ctx->mP ); + mbedtls_ecp_point_free( &ctx->R ); + memset( ctx, 0, sizeof( *ctx ) ); } @@ -197,6 +207,10 @@ void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) ecp_restart_mul_free( ctx->rsm ); mbedtls_free( ctx->rsm ); ctx->rsm = NULL; + + ecp_restart_muladd_free( ctx->ma ); + mbedtls_free( ctx->ma ); + ctx->ma = NULL; } /* @@ -2252,7 +2266,8 @@ cleanup: static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, - const mbedtls_ecp_point *P ) + const mbedtls_ecp_point *P, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; @@ -2268,7 +2283,8 @@ static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, } else { - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, R, m, P, + NULL, NULL, rs_ctx ) ); } cleanup: @@ -2290,6 +2306,8 @@ int mbedtls_ecp_muladd_restartable( { int ret; mbedtls_ecp_point mP; + mbedtls_ecp_point *pmP = &mP; + mbedtls_ecp_point *pR = R; #if defined(MBEDTLS_ECP_INTERNAL_ALT) char is_grp_capable = 0; #endif @@ -2301,6 +2319,16 @@ int mbedtls_ecp_muladd_restartable( if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + mbedtls_ecp_point_init( &mP ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) + { + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + #if defined(MBEDTLS_ECP_EARLY_RETURN) /* reset ops count for this call if top-level */ if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) @@ -2315,25 +2343,54 @@ int mbedtls_ecp_muladd_restartable( ecp_restart_muladd_init( rs_ctx->ma ); } + + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + { + /* redirect intermediate results to restart context */ + pmP = &rs_ctx->ma->mP; + pR = &rs_ctx->ma->R; + + /* jump to next operation */ + if( rs_ctx->ma->state == ecp_rsma_mul2 ) + goto mul2; + if( rs_ctx->ma->state == ecp_rsma_add ) + goto add; + if( rs_ctx->ma->state == ecp_rsma_norm ) + goto norm; + } #endif /* MBEDTLS_ECP_EARLY_RETURN */ - mbedtls_ecp_point_init( &mP ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state++; - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); +mul2: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state++; -#if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) - { - MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); - } +add: +#endif + ECP_BUDGET( ECP_OPS_ADD ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + rs_ctx->ma->state++; -#endif /* MBEDTLS_ECP_INTERNAL_ALT */ - MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); - MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); +norm: +#endif + ECP_BUDGET( ECP_OPS_INV ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) ); + +#if defined(MBEDTLS_ECP_EARLY_RETURN) + if( rs_ctx != NULL && rs_ctx->ma != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) ); +#endif cleanup: - #if defined(MBEDTLS_ECP_INTERNAL_ALT) if ( is_grp_capable ) { @@ -2341,6 +2398,7 @@ cleanup: } #endif /* MBEDTLS_ECP_INTERNAL_ALT */ + mbedtls_ecp_point_free( &mP ); #if defined(MBEDTLS_ECP_EARLY_RETURN) @@ -2351,7 +2409,6 @@ cleanup: rs_ctx->ma = NULL; } - if( rs_ctx != NULL ) rs_ctx->depth--; #endif /* MBEDTLS_ECP_EARLY_RETURN */ diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 9d25d2261..f76f93b66 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -364,3 +364,15 @@ ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A128499 ECP early return muladd secp256r1 restart disabled depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":0:0:0 + +ECP early return muladd secp256r1 restart max_ops=1 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":1:1:10000 + +ECP early return muladd secp256r1 restart max_ops=10000 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":10000:0:0 + +ECP early return muladd secp256r1 restart max_ops=250 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":250:4:64 From a7937f99673ecb1040d3b57353581abbb280c104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 15:37:46 +0200 Subject: [PATCH 043/148] Add public function generating private keys This will be useful for restartable ECDH and ECDSA. Currently they call mbedtls_ecp_gen_keypair(); one could make that one restartable, but that means adding its own sub-context, while ECDH and ECDSA (will) have their own contexts already, so switching to this saves one extra context. --- include/mbedtls/ecp.h | 16 ++++++++++++++++ library/ecp.c | 34 +++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index e2c605b0d..1cf3ab119 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -727,6 +727,22 @@ int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_po */ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); +/** + * \brief Generate a private key + * + * \param grp ECP group + * \param d Destination MPI (secret part) + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + */ +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + /** * \brief Generate a keypair with configurable base point * diff --git a/library/ecp.c b/library/ecp.c index f520b9caf..dfc5dd8dd 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -2495,15 +2495,14 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi * } /* - * Generate a keypair with configurable base point + * Generate a private key */ -int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, - const mbedtls_ecp_point *G, - mbedtls_mpi *d, mbedtls_ecp_point *Q, +int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, + mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - int ret; + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; size_t n_size = ( grp->nbits + 7 ) / 8; #if defined(ECP_MONTGOMERY) @@ -2528,8 +2527,8 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); } - else #endif /* ECP_MONTGOMERY */ + #if defined(ECP_SHORTWEIERSTRASS) if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) { @@ -2565,15 +2564,28 @@ int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); } - else #endif /* ECP_SHORTWEIERSTRASS */ - return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); cleanup: - if( ret != 0 ) - return( ret ); + return( ret ); +} - return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); + +cleanup: + return( ret ); } /* From 411079fc34a20f3db58f3cf0060e3d6537a02582 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 15:41:08 +0200 Subject: [PATCH 044/148] Rm obsolete comment Refers to ecp_mul() while we're now calling ecp_muladd(). Wrap long lines while at it. --- library/ecdsa.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index 4156f3c3c..6873757a0 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -205,7 +205,8 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, mbedtls_ecp_point R; mbedtls_ecp_point_init( &R ); - mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); + mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) @@ -244,9 +245,6 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, /* * Step 5: R = u1 G + u2 Q - * - * Since we're not using any secret data, no need to pass a RNG to - * mbedtls_ecp_mul() for countermesures. */ MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); @@ -273,7 +271,8 @@ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, cleanup: mbedtls_ecp_point_free( &R ); - mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); + mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); return( ret ); } From 4b9c51ef32d04043997de1ffed286d4535974593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 15:50:26 +0200 Subject: [PATCH 045/148] Rename EARLY_RETURN -> RESTARTABLE This is more consistent with function and context names. --- include/mbedtls/config.h | 4 +- include/mbedtls/ecp.h | 18 +++--- library/ecp.c | 82 ++++++++++++++-------------- library/version_features.c | 6 +- tests/suites/test_suite_ecp.data | 16 +++--- tests/suites/test_suite_ecp.function | 4 +- 6 files changed, 65 insertions(+), 65 deletions(-) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 9040bb71b..f4c565ebb 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -562,7 +562,7 @@ #define MBEDTLS_ECP_NIST_OPTIM /** - * \def MBEDTLS_ECP_EARLY_RETURN + * \def MBEDTLS_ECP_RESTARTABLE * * Enable "non-blocking" ECC operations that can return early and be resumed. * @@ -574,7 +574,7 @@ * * Comment this macro to disable non-blocking ECC computations. */ -#define MBEDTLS_ECP_EARLY_RETURN +#define MBEDTLS_ECP_RESTARTABLE /** * \def MBEDTLS_ECDSA_DETERMINISTIC diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 1cf3ab119..325392b02 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -171,7 +171,7 @@ typedef struct } mbedtls_ecp_keypair; -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Internal restart context for multiplication * @@ -196,7 +196,7 @@ typedef struct mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ } mbedtls_ecp_restart_ctx; -#endif /* MBEDTLS_ECP_EARLY_RETURN */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \name SECTION: Module settings @@ -267,7 +267,7 @@ typedef struct */ #define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< ECCurveType's named_curve */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Set the maximum number of basic operations done in a row. * @@ -307,7 +307,7 @@ typedef struct * \note This setting is currently ignored by Curve25519 */ void mbedtls_ecp_set_max_ops( unsigned max_ops ); -#endif /* MBEDTLS_ECP_EARLY_RETURN */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief Get the list of supported curves in order of preferrence @@ -383,7 +383,7 @@ void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); */ void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Initialize a restart context */ @@ -393,7 +393,7 @@ void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ); * \brief Free the components of a restart context */ void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ); -#endif /* MBEDTLS_ECP_EARLY_RETURN */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief Copy the contents of point Q into P @@ -612,7 +612,7 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Restartable version of \c mbedtls_ecp_mul() * @@ -636,7 +636,7 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx ); -#endif /* MBEDTLS_ECP_EARLY_RETURN */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief Multiplication and addition of two points by integers: @@ -662,7 +662,7 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Restartable version of \c mbedtls_ecp_muladd() * diff --git a/library/ecp.c b/library/ecp.c index dfc5dd8dd..03b1476a4 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -86,7 +86,7 @@ static unsigned long add_count, dbl_count, mul_count; #endif -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /* * Maximum number of "basic operations" to be done in a row. */ @@ -253,7 +253,7 @@ static int ecp_check_budget( const mbedtls_ecp_group *grp, /* We also need that type to make our life simpler for internal functions */ typedef void mbedtls_ecp_restart_ctx; -#endif /* MBEDTLS_ECP_EARLY_RETURN */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ @@ -1409,11 +1409,11 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, const unsigned char T_len = 1U << ( w - 1 ); mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; -#if !defined(MBEDTLS_ECP_EARLY_RETURN) +#if !defined(MBEDTLS_ECP_RESTARTABLE) (void) rs_ctx; #endif -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) @@ -1431,7 +1431,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, */ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) j = rs_ctx->rsm->i; else @@ -1451,7 +1451,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); } -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { rs_ctx->rsm->i = 0; @@ -1463,7 +1463,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, * Normalize current elements in T. As T has holes, * use an auxiliary array of pointers to elements in T. */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) norm_dbl: #endif @@ -1475,7 +1475,7 @@ norm_dbl: MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) rs_ctx->rsm->state++; #endif @@ -1484,7 +1484,7 @@ norm_dbl: * Compute the remaining ones using the minimal number of additions * Be careful to update T[2^l] only after using it! */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) add: #endif @@ -1497,7 +1497,7 @@ add: MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); } -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) rs_ctx->rsm->state++; #endif @@ -1507,7 +1507,7 @@ add: * we still need the auxiliary array for homogeneity with last time. * Also, skip T[0] which is already normalised, being a copy of P. */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) norm_add: #endif @@ -1518,13 +1518,13 @@ norm_add: MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) rs_ctx->rsm->state++; #endif cleanup: -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { @@ -1582,11 +1582,11 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R mbedtls_ecp_point_init( &Txi ); -#if !defined(MBEDTLS_ECP_EARLY_RETURN) +#if !defined(MBEDTLS_ECP_RESTARTABLE) (void) rs_ctx; #endif -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) { /* restore current index (R already pointing to rs_ctx->rsm->R) */ @@ -1615,7 +1615,7 @@ cleanup: mbedtls_ecp_point_free( &Txi ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { if( ret == 0 ) @@ -1700,16 +1700,16 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, unsigned char k[COMB_MAX_D + 1]; mbedtls_ecp_point *RR = R; -#if !defined(MBEDTLS_ECP_EARLY_RETURN) +#if !defined(MBEDTLS_ECP_RESTARTABLE) (void) rs_ctx; #endif -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) RR = &rs_ctx->rsm->R; #endif -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx == NULL || rs_ctx->rsm == NULL || rs_ctx->rsm->state < ecp_rsm_final_norm ) #endif @@ -1720,7 +1720,7 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, f_rng, p_rng, rs_ctx ) ); MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) rs_ctx->rsm->state++; #endif @@ -1729,7 +1729,7 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, ECP_BUDGET( ECP_OPS_INV ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); #endif @@ -1798,11 +1798,11 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, unsigned char pre_len = 0, T_ok = 0; mbedtls_ecp_point *T = NULL; -#if !defined(MBEDTLS_ECP_EARLY_RETURN) +#if !defined(MBEDTLS_ECP_RESTARTABLE) (void) rs_ctx; #endif -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /* set up our own sub-context if needed */ if( ecp_max_ops != 0 && rs_ctx != NULL && rs_ctx->rsm == NULL ) { @@ -1834,7 +1834,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, T_ok = 1; } -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /* Pre-computed table: do we have one in progress? complete? */ if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL && T == NULL ) { @@ -1884,7 +1884,7 @@ cleanup: T = NULL; /* does T belong to the restart context? */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) { /* transfer ownership of T from local function to rsm */ @@ -1903,7 +1903,7 @@ cleanup: } /* don't free R while in progress in case R == P */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) #endif /* prevent caller from using invalid value */ @@ -1911,7 +1911,7 @@ cleanup: mbedtls_ecp_point_free( R ); /* clear our sub-context when not in progress (done or error) */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { ecp_restart_mul_free( rs_ctx->rsm ); mbedtls_free( rs_ctx->rsm ); @@ -2130,7 +2130,7 @@ cleanup: /* * Restartable multiplication R = m * P */ -#if !defined(MBEDTLS_ECP_EARLY_RETURN) +#if !defined(MBEDTLS_ECP_RESTARTABLE) static #endif int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, @@ -2143,7 +2143,7 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, char is_grp_capable = 0; #endif -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /* reset ops count for this call if top-level */ if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) rs_ctx->ops_done = 0; @@ -2157,7 +2157,7 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif /* MBEDTLS_ECP_INTERNAL_ALT */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) && defined(ECP_SHORTWEIERSTRASS) +#if defined(MBEDTLS_ECP_RESTARTABLE) && defined(ECP_SHORTWEIERSTRASS) /* skip argument check when restarting */ if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS || rs_ctx == NULL || rs_ctx->rsm == NULL ) @@ -2191,7 +2191,7 @@ cleanup: #endif /* MBEDTLS_ECP_INTERNAL_ALT */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL ) rs_ctx->depth--; #endif @@ -2295,7 +2295,7 @@ cleanup: * Restartable linear combination * NOT constant-time */ -#if !defined(MBEDTLS_ECP_EARLY_RETURN) +#if !defined(MBEDTLS_ECP_RESTARTABLE) static #endif int mbedtls_ecp_muladd_restartable( @@ -2312,7 +2312,7 @@ int mbedtls_ecp_muladd_restartable( char is_grp_capable = 0; #endif -#if !defined(MBEDTLS_ECP_EARLY_RETURN) +#if !defined(MBEDTLS_ECP_RESTARTABLE) (void) rs_ctx; #endif @@ -2329,7 +2329,7 @@ int mbedtls_ecp_muladd_restartable( #endif /* MBEDTLS_ECP_INTERNAL_ALT */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /* reset ops count for this call if top-level */ if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) rs_ctx->ops_done = 0; @@ -2358,17 +2358,17 @@ int mbedtls_ecp_muladd_restartable( if( rs_ctx->ma->state == ecp_rsma_norm ) goto norm; } -#endif /* MBEDTLS_ECP_EARLY_RETURN */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ma != NULL ) rs_ctx->ma->state++; mul2: #endif MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ma != NULL ) rs_ctx->ma->state++; @@ -2376,7 +2376,7 @@ add: #endif ECP_BUDGET( ECP_OPS_ADD ); MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ma != NULL ) rs_ctx->ma->state++; @@ -2385,7 +2385,7 @@ norm: ECP_BUDGET( ECP_OPS_INV ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ma != NULL ) MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, pR ) ); #endif @@ -2401,7 +2401,7 @@ cleanup: mbedtls_ecp_point_free( &mP ); -#if defined(MBEDTLS_ECP_EARLY_RETURN) +#if defined(MBEDTLS_ECP_RESTARTABLE) /* clear our sub-context when not in progress (done or error) */ if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { ecp_restart_muladd_free( rs_ctx->ma ); @@ -2411,7 +2411,7 @@ cleanup: if( rs_ctx != NULL ) rs_ctx->depth--; -#endif /* MBEDTLS_ECP_EARLY_RETURN */ +#endif /* MBEDTLS_ECP_RESTARTABLE */ return( ret ); } diff --git a/library/version_features.c b/library/version_features.c index 2668eaed5..ec355e1ff 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -276,9 +276,9 @@ static const char *features[] = { #if defined(MBEDTLS_ECP_NIST_OPTIM) "MBEDTLS_ECP_NIST_OPTIM", #endif /* MBEDTLS_ECP_NIST_OPTIM */ -#if defined(MBEDTLS_ECP_EARLY_RETURN) - "MBEDTLS_ECP_EARLY_RETURN", -#endif /* MBEDTLS_ECP_EARLY_RETURN */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + "MBEDTLS_ECP_RESTARTABLE", +#endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) "MBEDTLS_ECDSA_DETERMINISTIC", #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index f76f93b66..5bb8d024d 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -345,34 +345,34 @@ ecp_test_vect:MBEDTLS_ECP_DP_SECP256K1:"923C6D4756CD940CD1E13A359F6E0F0698791938 ECP selftest ecp_selftest: -ECP early return mul secp256r1 restart disabled +ECP restartable mul 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 mul secp256r1 restart max_ops=1 +ECP restartable mul secp256r1 max_ops=1 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":1:1:5000 -ECP early return mul secp256r1 restart max_ops=10000 +ECP restartable mul secp256r1 max_ops=10000 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":10000:0:0 -ECP early return mul secp256r1 restart max_ops=250 +ECP restartable mul secp256r1 max_ops=250 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":250:2:32 -ECP early return muladd secp256r1 restart disabled +ECP restartable muladd secp256r1 restart disabled depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":0:0:0 -ECP early return muladd secp256r1 restart max_ops=1 +ECP restartable muladd secp256r1 max_ops=1 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":1:1:10000 -ECP early return muladd secp256r1 restart max_ops=10000 +ECP restartable muladd secp256r1 max_ops=10000 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":10000:0:0 -ECP early return muladd secp256r1 restart max_ops=250 +ECP restartable muladd secp256r1 max_ops=250 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":250:4:64 diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 659830e5d..3ec7caf54 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -51,7 +51,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_ECP_EARLY_RETURN */ +/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */ 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, @@ -145,7 +145,7 @@ exit: } /* END_CASE */ -/* BEGIN_CASE depends_on:MBEDTLS_ECP_EARLY_RETURN */ +/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */ void ecp_muladd_restart( int id, char *xR_str, char *yR_str, char *u1_str, char *u2_str, char *xQ_str, char *yQ_str, From 0ff17df081cd34394427e47e41c64323571fd109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 15:51:52 +0200 Subject: [PATCH 046/148] Fix ECDSA test descriptions The rename script was a bit zealous during the Great Renaming. --- tests/suites/test_suite_ecdsa.data | 60 +++++++++++++++--------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data index d9640765e..c0fab761a 100644 --- a/tests/suites/test_suite_ecdsa.data +++ b/tests/suites/test_suite_ecdsa.data @@ -50,7 +50,7 @@ ECDSA write-read random #5 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED ecdsa_write_read_random:MBEDTLS_ECP_DP_SECP521R1 -ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha1 +ECDSA deterministic test vector rfc 6979 p192 sha1 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA1_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA1:"sample":"98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF":"57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64" @@ -58,7 +58,7 @@ ECDSA deterministic test vector rfc 6979 p192 sha224 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA224:"sample":"A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5":"E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A" -ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha256 +ECDSA deterministic test vector rfc 6979 p192 sha256 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA256:"sample":"4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55":"CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85" @@ -66,11 +66,11 @@ ECDSA deterministic test vector rfc 6979 p192 sha384 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA384:"sample":"DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5":"C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E" -ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha512 +ECDSA deterministic test vector rfc 6979 p192 sha512 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA512:"sample":"4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8":"3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67" -ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha1 +ECDSA deterministic test vector rfc 6979 p192 sha1 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA1_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA1:"test":"0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D":"EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7" @@ -78,7 +78,7 @@ ECDSA deterministic test vector rfc 6979 p192 sha224 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA224:"test":"6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34":"B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293" -ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha256 +ECDSA deterministic test vector rfc 6979 p192 sha256 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA256:"test":"3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE":"5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F" @@ -86,11 +86,11 @@ ECDSA deterministic test vector rfc 6979 p192 sha384 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA384:"test":"B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367":"7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A" -ECDSA deterministic test vector rfc 6979 p192 mbedtls_sha512 +ECDSA deterministic test vector rfc 6979 p192 sha512 depends_on:MBEDTLS_ECP_DP_SECP192R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP192R1:"6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4":MBEDTLS_MD_SHA512:"test":"FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739":"74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290" -ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha1 +ECDSA deterministic test vector rfc 6979 p224 sha1 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA1_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA1:"sample":"22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC":"66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69" @@ -98,7 +98,7 @@ ECDSA deterministic test vector rfc 6979 p224 sha224 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA224:"sample":"1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E":"A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC" -ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha256 +ECDSA deterministic test vector rfc 6979 p224 sha256 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA256:"sample":"61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA":"BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101" @@ -106,11 +106,11 @@ ECDSA deterministic test vector rfc 6979 p224 sha384 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA384:"sample":"0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953":"830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D" -ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha512 +ECDSA deterministic test vector rfc 6979 p224 sha512 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA512:"sample":"074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397":"A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084" -ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha1 +ECDSA deterministic test vector rfc 6979 p224 sha1 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA1_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA1:"test":"DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C":"95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2" @@ -118,7 +118,7 @@ ECDSA deterministic test vector rfc 6979 p224 sha224 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA224:"test":"C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019":"902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4" -ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha256 +ECDSA deterministic test vector rfc 6979 p224 sha256 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA256:"test":"AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6":"178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD" @@ -126,11 +126,11 @@ ECDSA deterministic test vector rfc 6979 p224 sha384 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA384:"test":"389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4":"414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB" -ECDSA deterministic test vector rfc 6979 p224 mbedtls_sha512 +ECDSA deterministic test vector rfc 6979 p224 sha512 depends_on:MBEDTLS_ECP_DP_SECP224R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP224R1:"F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1":MBEDTLS_MD_SHA512:"test":"049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C":"077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF" -ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha1 +ECDSA deterministic test vector rfc 6979 p256 sha1 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA1_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA1:"sample":"61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32":"6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB" @@ -138,7 +138,7 @@ ECDSA deterministic test vector rfc 6979 p256 sha224 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA224:"sample":"53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F":"B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C" -ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha256 +ECDSA deterministic test vector rfc 6979 p256 sha256 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"sample":"EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716":"F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8" @@ -146,11 +146,11 @@ ECDSA deterministic test vector rfc 6979 p256 sha384 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA384:"sample":"0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719":"4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954" -ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha512 +ECDSA deterministic test vector rfc 6979 p256 sha512 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA512:"sample":"8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00":"2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE" -ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha1 +ECDSA deterministic test vector rfc 6979 p256 sha1 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA1_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA1:"test":"0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89":"01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1" @@ -158,7 +158,7 @@ ECDSA deterministic test vector rfc 6979 p256 sha224 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA224:"test":"C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692":"C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D" -ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha256 +ECDSA deterministic test vector rfc 6979 p256 sha256 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367":"019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083" @@ -166,11 +166,11 @@ ECDSA deterministic test vector rfc 6979 p256 sha384 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA384:"test":"83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6":"8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C" -ECDSA deterministic test vector rfc 6979 p256 mbedtls_sha512 +ECDSA deterministic test vector rfc 6979 p256 sha512 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA512:"test":"461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04":"39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55" -ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha1 +ECDSA deterministic test vector rfc 6979 p384 sha1 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA1_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA1:"sample":"EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA37B9BA002899F6FDA3A4A9386790D4EB2":"A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF26F49CA031D4857570CCB5CA4424A443" @@ -178,7 +178,7 @@ ECDSA deterministic test vector rfc 6979 p384 sha224 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA224:"sample":"42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366450F76EE3DE43F5A125333A6BE060122":"9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E4834C082C03D83028EFBF93A3C23940CA8D" -ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha256 +ECDSA deterministic test vector rfc 6979 p384 sha256 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA256:"sample":"21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33BDE1E888E63355D92FA2B3C36D8FB2CD":"F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEBEFDC63ECCD1AC42EC0CB8668A4FA0AB0" @@ -186,11 +186,11 @@ ECDSA deterministic test vector rfc 6979 p384 sha384 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA384:"sample":"94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C81A648152E44ACF96E36DD1E80FABE46":"99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94FA329C145786E679E7B82C71A38628AC8" -ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha512 +ECDSA deterministic test vector rfc 6979 p384 sha512 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA512:"sample":"ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799CFE30F35CC900056D7C99CD7882433709":"512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112DC7CC3EF3446DEFCEB01A45C2667FDD5" -ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha1 +ECDSA deterministic test vector rfc 6979 p384 sha1 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA1_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA1:"test":"4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678ACD9D29876DAF46638645F7F404B11C7":"D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A2991695BA1C84541327E966FA7B50F7382282" @@ -198,7 +198,7 @@ ECDSA deterministic test vector rfc 6979 p384 sha224 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA224:"test":"E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E62464A9A817C47FF78B8C11066B24080E72":"07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C6141C53EA5ABEF0D8231077A04540A96B66" -ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha256 +ECDSA deterministic test vector rfc 6979 p384 sha256 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA256:"test":"6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559F918EEDAF2293BE5B475CC8F0188636B":"2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D51AB373F9845C0514EEFB14024787265" @@ -206,11 +206,11 @@ ECDSA deterministic test vector rfc 6979 p384 sha384 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA384:"test":"8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB0542A7F0812998DA8F1DD3CA3CF023DB":"DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E06A739F040649A667BF3B828246BAA5A5" -ECDSA deterministic test vector rfc 6979 p384 mbedtls_sha512 +ECDSA deterministic test vector rfc 6979 p384 sha512 depends_on:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP384R1:"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D896D5724E4C70A825F872C9EA60D2EDF5":MBEDTLS_MD_SHA512:"test":"A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D06FB6495CD21B4B6E340FC236584FB277":"976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B224634A2092CD3792E0159AD9CEE37659C736" -ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha1 +ECDSA deterministic test vector rfc 6979 p521 sha1 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA1_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA1:"sample":"0343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D75D":"0E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5D16" @@ -218,7 +218,7 @@ ECDSA deterministic test vector rfc 6979 p521 sha224 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA224:"sample":"1776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A30715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2ED2E":"050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17BA41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B41F" -ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha256 +ECDSA deterministic test vector rfc 6979 p521 sha256 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA256:"sample":"1511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E1A7":"04A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7ECFC" @@ -226,11 +226,11 @@ ECDSA deterministic test vector rfc 6979 p521 sha384 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA384:"sample":"1EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67451":"1F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65D61" -ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha512 +ECDSA deterministic test vector rfc 6979 p521 sha512 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA512:"sample":"0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F174E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E377FA":"0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF282623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A67A" -ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha1 +ECDSA deterministic test vector rfc 6979 p521 sha1 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA1_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA1:"test":"13BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0367":"1E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC916797FF" @@ -238,7 +238,7 @@ ECDSA deterministic test vector rfc 6979 p521 sha224 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA224:"test":"1C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE17FB":"177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD519A4" -ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha256 +ECDSA deterministic test vector rfc 6979 p521 sha256 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA256_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA256:"test":"00E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D8071042EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656AA8":"0CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694E86" @@ -246,7 +246,7 @@ ECDSA deterministic test vector rfc 6979 p521 sha384 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA384:"test":"14BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF6075578C":"133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0ED94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B979" -ECDSA deterministic test vector rfc 6979 p521 mbedtls_sha512 +ECDSA deterministic test vector rfc 6979 p521 sha512 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA512:"test":"13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D":"1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3" From b5a50e754dd3d61f49eb798a23279ce0b74f9cf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 16:06:13 +0200 Subject: [PATCH 047/148] Always declare restartable function variants Otherwise code that uses these functions in other modules will have to do: #if defined(MBEDTLS_ECP_RESTARTABLE) ret = do_stuff( there, may, be, many, args ); #else ret = do_stuff( their, may, be, namy, args, rs_ctx ); #fi and there is a risk that the arg list will differ when code is updated, and this might not be caught immediately by tests because this depends on a config.h compile-time option which are harder to test. Always declaring the restartable variants of the API functions avoids this problem; the cost in ROM size should be negligible. --- include/mbedtls/ecp.h | 11 +++++++---- library/ecp.c | 9 --------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 325392b02..532124dc7 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -172,6 +172,7 @@ typedef struct mbedtls_ecp_keypair; #if defined(MBEDTLS_ECP_RESTARTABLE) + /** * \brief Internal restart context for multiplication * @@ -196,6 +197,12 @@ typedef struct mbedtls_ecp_restart_mul_ctx *rsm; /*!< ecp_mul_comb() sub-context */ mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ } mbedtls_ecp_restart_ctx; + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +/* We want to declare restartable versions of existing functions anyway */ +typedef void mbedtls_ecp_restart_ctx; + #endif /* MBEDTLS_ECP_RESTARTABLE */ /** @@ -612,7 +619,6 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); -#if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Restartable version of \c mbedtls_ecp_mul() * @@ -636,7 +642,6 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecp_restart_ctx *rs_ctx ); -#endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief Multiplication and addition of two points by integers: @@ -662,7 +667,6 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); -#if defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Restartable version of \c mbedtls_ecp_muladd() * @@ -687,7 +691,6 @@ int mbedtls_ecp_muladd_restartable( const mbedtls_mpi *m, const mbedtls_ecp_point *P, const mbedtls_mpi *n, const mbedtls_ecp_point *Q, mbedtls_ecp_restart_ctx *rs_ctx ); -#endif /** * \brief Check that a point is a valid public key on this curve diff --git a/library/ecp.c b/library/ecp.c index 03b1476a4..92397244a 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -250,9 +250,6 @@ static int ecp_check_budget( const mbedtls_ecp_group *grp, #define ECP_BUDGET( ops ) MBEDTLS_MPI_CHK( ecp_check_budget( grp, rs_ctx, ops ) ); #else #define ECP_BUDGET( ops ) /* no-op */ - -/* We also need that type to make our life simpler for internal functions */ -typedef void mbedtls_ecp_restart_ctx; #endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ @@ -2130,9 +2127,6 @@ cleanup: /* * Restartable multiplication R = m * P */ -#if !defined(MBEDTLS_ECP_RESTARTABLE) -static -#endif int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, @@ -2295,9 +2289,6 @@ cleanup: * Restartable linear combination * NOT constant-time */ -#if !defined(MBEDTLS_ECP_RESTARTABLE) -static -#endif int mbedtls_ecp_muladd_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *P, From c751148cc5772b55c172ae9e8ec92380630c6fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 20 Apr 2017 16:31:00 +0200 Subject: [PATCH 048/148] Make some macros/functions public These will be needed in other modules that already include ecp.h --- include/mbedtls/ecp.h | 27 +++++++++++++++++++++++++++ library/ecp.c | 34 ++++++++++++---------------------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 532124dc7..420c6d07b 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -198,8 +198,35 @@ typedef struct mbedtls_ecp_restart_muladd_ctx *ma; /*!< ecp_muladd() sub-context */ } mbedtls_ecp_restart_ctx; +/* + * Operation counts for restartable functions + */ +#define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ +#define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ +#define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ + +/** + * \brief Internal; for restartable functions in other modules. + * Check and update basic ops budget. + * + * \param grp Group structure + * \param rs_ctx Restart context + * \param ops Number of basic ops to do + * + * \return 0 is doing 'ops' basic ops is still allowed, + * MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. + */ +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ); + +/* Utility macro for checking and updating ops budget */ +#define MBEDTLS_ECP_BUDGET( ops ) MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, rs_ctx, ops ) ); + #else /* MBEDTLS_ECP_RESTARTABLE */ +#define MBEDTLS_ECP_BUDGET( ops ) /* no-op; for compatibility */ + /* We want to declare restartable versions of existing functions anyway */ typedef void mbedtls_ecp_restart_ctx; diff --git a/library/ecp.c b/library/ecp.c index 92397244a..9d4721ec5 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -213,19 +213,12 @@ void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) ctx->ma = NULL; } -/* - * Operation counts - */ -#define ECP_OPS_DBL 8 /* see ecp_double_jac() */ -#define ECP_OPS_ADD 11 /* see ecp_add_mixed() */ -#define ECP_OPS_INV 120 /* empirical equivalent */ - /* * Check if we can do the next step */ -static int ecp_check_budget( const mbedtls_ecp_group *grp, - mbedtls_ecp_restart_ctx *rs_ctx, - unsigned ops ) +int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, + mbedtls_ecp_restart_ctx *rs_ctx, + unsigned ops ) { if( rs_ctx != NULL && ecp_max_ops != 0 ) { @@ -247,9 +240,6 @@ static int ecp_check_budget( const mbedtls_ecp_group *grp, return( 0 ); } -#define ECP_BUDGET( ops ) MBEDTLS_MPI_CHK( ecp_check_budget( grp, rs_ctx, ops ) ); -#else -#define ECP_BUDGET( ops ) /* no-op */ #endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ @@ -1437,7 +1427,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, for( ; j < d * ( w - 1 ); j++ ) { - ECP_BUDGET( ECP_OPS_DBL ); + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL ); i = 1U << ( j / d ); cur = T + i; @@ -1468,7 +1458,7 @@ norm_dbl: for( i = 1; i < T_len; i <<= 1 ) TT[j++] = T + i; - ECP_BUDGET( ECP_OPS_INV + 6 * j - 2 ); + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); @@ -1485,7 +1475,7 @@ norm_dbl: add: #endif - ECP_BUDGET( ( T_len - 1 ) * ECP_OPS_ADD ); + MBEDTLS_ECP_BUDGET( ( T_len - 1 ) * MBEDTLS_ECP_OPS_ADD ); for( i = 1; i < T_len; i <<= 1 ) { @@ -1511,7 +1501,7 @@ norm_add: for( j = 0; j + 1 < T_len; j++ ) TT[j] = T + j + 1; - ECP_BUDGET( ECP_OPS_INV + 6 * j - 2 ); + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); @@ -1602,7 +1592,7 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R while( i-- != 0 ) { - ECP_BUDGET( ECP_OPS_DBL + ECP_OPS_ADD ); + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD ); MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); @@ -1723,7 +1713,7 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, #endif } - ECP_BUDGET( ECP_OPS_INV ); + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) @@ -2162,7 +2152,7 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); /* check_privkey is 0M and check_pubkey is 3M */ - ECP_BUDGET( 3 ); + MBEDTLS_ECP_BUDGET( 3 ); } ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; @@ -2365,7 +2355,7 @@ mul2: add: #endif - ECP_BUDGET( ECP_OPS_ADD ); + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_ADD ); MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ma != NULL ) @@ -2373,7 +2363,7 @@ add: norm: #endif - ECP_BUDGET( ECP_OPS_INV ); + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, pR ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) From 1ed2505f854b5e9be20578079e37a29d896f5673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 21 Apr 2017 10:04:02 +0200 Subject: [PATCH 049/148] Add some negative testing for ecdsa_verify() --- include/mbedtls/ecdsa.h | 2 +- tests/suites/test_suite_ecdsa.function | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index a277715b3..259948dfc 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -120,7 +120,7 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi * prescribed by SEC1 4.1.4 step 3. * * \return 0 if successful, - * MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid + * MBEDTLS_ERR_ECP_VERIFY_FAILED if signature is invalid * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code */ int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index 88e07a9e6..491ab43b4 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -87,6 +87,16 @@ void ecdsa_prim_test_vectors( int id, char *d_str, char *xQ_str, char *yQ_str, TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, &Q, &r_check, &s_check ) == 0 ); + TEST_ASSERT( mbedtls_mpi_sub_int( &r, &r, 1 ) == 0 ); + TEST_ASSERT( mbedtls_mpi_add_int( &s, &s, 1 ) == 0 ); + + TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, + &Q, &r, &s_check ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); + TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, + &Q, &r_check, &s ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); + TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, + &grp.G, &r_check, &s_check ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); + exit: mbedtls_ecp_group_free( &grp ); mbedtls_ecp_point_free( &Q ); @@ -178,13 +188,13 @@ void ecdsa_write_read_random( int id ) /* try modifying r */ sig[10]++; TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ), - sig, sig_len ) != 0 ); + sig, sig_len ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); sig[10]--; /* try modifying s */ sig[sig_len - 1]++; TEST_ASSERT( mbedtls_ecdsa_read_signature( &ctx, hash, sizeof( hash ), - sig, sig_len ) != 0 ); + sig, sig_len ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); sig[sig_len - 1]--; exit: From 32aa4375cca6a9f645e9ae9b03d40c0d48f259b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 21 Apr 2017 10:29:13 +0200 Subject: [PATCH 050/148] Declare ecdsa_read_signature_restartable() Not making ecdsa_verify_restartable() public, as it isn't called from any other module. --- include/mbedtls/ecdsa.h | 58 ++++++++++++++++++++++++++++++++++++++--- library/ecdsa.c | 54 ++++++++++++++++++++++++++++++++++---- 2 files changed, 104 insertions(+), 8 deletions(-) diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index 259948dfc..f09e75490 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -46,14 +46,31 @@ /** Maximum size of an ECDSA signature in bytes */ #define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) +#ifdef __cplusplus +extern "C" { +#endif + /** * \brief ECDSA context structure */ typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; -#ifdef __cplusplus -extern "C" { -#endif +#if defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief General context for resuming ECDSA operations + */ +typedef struct +{ + mbedtls_ecp_restart_ctx rs_ecp; /*!< base context (admin+ecp info) */ +} mbedtls_ecdsa_restart_ctx; + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_ecdsa_restart_ctx; + +#endif /* MBEDTLS_ECP_RESTARTABLE */ /** * \brief Compute ECDSA signature of a previously hashed message @@ -227,6 +244,29 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen ); +/** + * \brief Restartable version of \c mbedtls_ecdsa_read_signature() + * + * \note Performs the same job as \c mbedtls_ecdsa_read_signature() + * but can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx ECDSA context + * \param hash Message hash + * \param hlen Size of hash + * \param sig Signature to read and verify + * \param slen Size of sig + * \param rs_ctx Restart context + * + * \return See \c mbedtls_ecdsa_read_signature(), or + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + /** * \brief Generate an ECDSA keypair on the given curve * @@ -265,6 +305,18 @@ void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); */ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #ifdef __cplusplus } #endif diff --git a/library/ecdsa.c b/library/ecdsa.c index 6873757a0..3003812e9 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -196,14 +196,18 @@ cleanup: * Verify ECDSA signature of hashed message (SEC1 4.1.4) * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) */ -int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, - const unsigned char *buf, size_t blen, - const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) +static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, + const mbedtls_mpi *r, const mbedtls_mpi *s, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_mpi e, s_inv, u1, u2; mbedtls_ecp_point R; + (void) rs_ctx; // temporary + mbedtls_ecp_point_init( &R ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); @@ -277,6 +281,16 @@ cleanup: return( ret ); } +/* + * Verify ECDSA signature of hashed message + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) +{ + return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) ); +} + /* * Convert a signature (given by context) to ASN.1 */ @@ -356,6 +370,18 @@ int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, const unsigned char *sig, size_t slen ) +{ + return( mbedtls_ecdsa_read_signature_restartable( + ctx, hash, hlen, sig, slen, NULL ) ); +} + +/* + * Restartable read and check signature + */ +int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; unsigned char *p = (unsigned char *) sig; @@ -387,8 +413,8 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, goto cleanup; } - if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, - &ctx->Q, &r, &s ) ) != 0 ) + if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s, rs_ctx ) ) != 0 ) goto cleanup; if( p != end ) @@ -444,4 +470,22 @@ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) mbedtls_ecp_keypair_free( ctx ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) +{ + mbedtls_ecp_restart_init( &ctx->rs_ecp ); +} + +/* + * Free the components of a restart context + */ +void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) +{ + mbedtls_ecp_restart_free( &ctx->rs_ecp ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #endif /* MBEDTLS_ECDSA_C */ From 722e5156fd1cf0eebfec849a080f3b556b840e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 21 Apr 2017 11:04:47 +0200 Subject: [PATCH 051/148] Add test for ecdsa_read_signature_restartable() Test values taken from a random signature as generated in ecdsa_write_read_random() test function --- include/mbedtls/ecdsa.h | 2 +- library/ecdsa.c | 4 +- tests/suites/test_suite_ecdsa.data | 3 ++ tests/suites/test_suite_ecdsa.function | 62 ++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index f09e75490..c7b9f27da 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -62,7 +62,7 @@ typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; */ typedef struct { - mbedtls_ecp_restart_ctx rs_ecp; /*!< base context (admin+ecp info) */ + mbedtls_ecp_restart_ctx ecp; /*!< base context (admin+ecp info) */ } mbedtls_ecdsa_restart_ctx; #else /* MBEDTLS_ECP_RESTARTABLE */ diff --git a/library/ecdsa.c b/library/ecdsa.c index 3003812e9..19f9d5e2e 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -476,7 +476,7 @@ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) */ void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) { - mbedtls_ecp_restart_init( &ctx->rs_ecp ); + mbedtls_ecp_restart_init( &ctx->ecp ); } /* @@ -484,7 +484,7 @@ void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) */ void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) { - mbedtls_ecp_restart_free( &ctx->rs_ecp ); + mbedtls_ecp_restart_free( &ctx->ecp ); } #endif /* MBEDTLS_ECP_RESTARTABLE */ diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data index c0fab761a..6ca912a46 100644 --- a/tests/suites/test_suite_ecdsa.data +++ b/tests/suites/test_suite_ecdsa.data @@ -250,3 +250,6 @@ ECDSA deterministic test vector rfc 6979 p521 sha512 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA512:"test":"13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D":"1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3" +ECDSA restartable read-verify: restart disabled +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":0:0:0 diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index 491ab43b4..d5cb65480 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -202,3 +202,65 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */ +void ecdsa_read_restart( int id, char *k_str, char *h_str, char *s_str, + int max_ops, int min_restart, int max_restart ) +{ + mbedtls_ecdsa_context ctx; + mbedtls_ecdsa_restart_ctx rs_ctx; + unsigned char hash[64]; + unsigned char sig[200]; + unsigned char pk[65]; + size_t sig_len, hash_len, pk_len; + int ret, cnt_restart; + + mbedtls_ecdsa_init( &ctx ); + mbedtls_ecdsa_restart_init( &rs_ctx ); + + hash_len = unhexify(hash, h_str); + sig_len = unhexify(sig, s_str); + pk_len = unhexify(pk, k_str); + + TEST_ASSERT( mbedtls_ecp_group_load( &ctx.grp, id ) == 0 ); + TEST_ASSERT( mbedtls_ecp_point_read_binary( &ctx.grp, &ctx.Q, pk, pk_len ) == 0 ); + + mbedtls_ecp_set_max_ops( max_ops ); + + cnt_restart = 0; + do { + ret = mbedtls_ecdsa_read_signature_restartable( &ctx, + hash, hash_len, sig, sig_len, &rs_ctx ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); + + TEST_ASSERT( ret == 0 ); + TEST_ASSERT( cnt_restart >= min_restart ); + TEST_ASSERT( cnt_restart <= max_restart ); + + /* try modifying r */ + sig[10]++; + do { + ret = mbedtls_ecdsa_read_signature_restartable( &ctx, + hash, hash_len, sig, sig_len, &rs_ctx ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + TEST_ASSERT( ret == MBEDTLS_ERR_ECP_VERIFY_FAILED ); + sig[10]--; + + /* try modifying s */ + sig[sig_len - 1]++; + do { + ret = mbedtls_ecdsa_read_signature_restartable( &ctx, + hash, hash_len, sig, sig_len, &rs_ctx ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + TEST_ASSERT( ret == MBEDTLS_ERR_ECP_VERIFY_FAILED ); + sig[sig_len - 1]--; + + /* do we leak memory when aborting? */ + ret = mbedtls_ecdsa_read_signature_restartable( &ctx, + hash, hash_len, sig, sig_len, &rs_ctx ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + +exit: + mbedtls_ecdsa_free( &ctx ); + mbedtls_ecdsa_restart_free( &rs_ctx ); +} +/* END_CASE */ From a0c5bcc2bc09bd1a096172d9ffd03c0626e8dada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 21 Apr 2017 11:33:57 +0200 Subject: [PATCH 052/148] Add infrastructure for ecdsa_verify_restartable() --- include/mbedtls/ecdsa.h | 8 ++++ include/mbedtls/ecp.h | 8 ++++ library/ecdsa.c | 85 ++++++++++++++++++++++++++++++++++++++++- library/ecp.c | 8 ++++ 4 files changed, 107 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index c7b9f27da..d2f83b224 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -57,12 +57,20 @@ typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; #if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Internal restart context for ecdsa_verify() + * + * \note Opaque struct + */ +typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; + /** * \brief General context for resuming ECDSA operations */ typedef struct { mbedtls_ecp_restart_ctx ecp; /*!< base context (admin+ecp info) */ + mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */ } mbedtls_ecdsa_restart_ctx; #else /* MBEDTLS_ECP_RESTARTABLE */ diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 420c6d07b..3e5c60530 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -341,6 +341,14 @@ typedef void mbedtls_ecp_restart_ctx; * \note This setting is currently ignored by Curve25519 */ void mbedtls_ecp_set_max_ops( unsigned max_ops ); + +/** + * \brief Check if restart is enabled (max_ops != 0) + * + * \return 0 if max_ops == 0 (restart disabled) + * 1 otherwise (restart enabled) + */ +int mbedtls_ecp_restart_enabled( void ); #endif /* MBEDTLS_ECP_RESTARTABLE */ /** diff --git a/library/ecdsa.c b/library/ecdsa.c index 19f9d5e2e..8e1f62a8e 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -42,6 +42,50 @@ #include "mbedtls/hmac_drbg.h" #endif +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Sub-contect for ecdsa_verify() + */ +struct mbedtls_ecdsa_restart_ver +{ + int state; /* dummy */ +}; + +/* + * Init verify restart sub-context + */ +static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + memset( ctx, 0, sizeof( *ctx ) ); +} + +/* + * Free the components of a verify restart sub-context + */ +static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + memset( ctx, 0, sizeof( *ctx ) ); +} + +#define ECDSA_RS_ECP &rs_ctx->ecp + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECDSA_RS_ECP NULL + +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* * Derive a suitable integer for group grp from a buffer of length len * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 @@ -206,7 +250,9 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, mbedtls_mpi e, s_inv, u1, u2; mbedtls_ecp_point R; - (void) rs_ctx; // temporary +#if !defined(MBEDTLS_ECP_RESTARTABLE) + (void) rs_ctx; +#endif mbedtls_ecp_point_init( &R ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); @@ -216,6 +262,22 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, if( grp->N.p == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* reset ops count for this call if top-level */ + if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) + rs_ctx->ecp.ops_done = 0; + + /* set up our own sub-context if needed */ + if( mbedtls_ecp_restart_enabled() && rs_ctx != NULL && rs_ctx->ver == NULL ) + { + rs_ctx->ver = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ver_ctx ) ); + if( rs_ctx->ver == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + ecdsa_restart_ver_init( rs_ctx->ver ); + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* * Step 1: make sure r and s are in range 1..n-1 */ @@ -250,7 +312,8 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, /* * Step 5: R = u1 G + u2 Q */ - MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp, + &R, &u1, &grp->G, &u2, Q, ECDSA_RS_ECP ) ); if( mbedtls_ecp_is_zero( &R ) ) { @@ -278,6 +341,18 @@ cleanup: mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + /* clear our sub-context when not in progress (done or error) */ + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + ecdsa_restart_ver_free( rs_ctx->ver ); + mbedtls_free( rs_ctx->ver ); + rs_ctx->ver = NULL; + } + + if( rs_ctx != NULL ) + rs_ctx->ecp.depth--; +#endif /* MBEDTLS_ECP_RESTARTABLE */ + return( ret ); } @@ -477,6 +552,8 @@ void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) { mbedtls_ecp_restart_init( &ctx->ecp ); + + ctx->ver = NULL; } /* @@ -485,6 +562,10 @@ void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) { mbedtls_ecp_restart_free( &ctx->ecp ); + + ecdsa_restart_ver_free( ctx->ver ); + mbedtls_free( ctx->ver ); + ctx->ver = NULL; } #endif /* MBEDTLS_ECP_RESTARTABLE */ diff --git a/library/ecp.c b/library/ecp.c index 9d4721ec5..40daa6710 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -100,6 +100,14 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ) ecp_max_ops = max_ops; } +/* + * Check if restart is enabled + */ +int mbedtls_ecp_restart_enabled( void ) +{ + return( ecp_max_ops != 0 ); +} + /* * Restart sub-context for ecp_mul_comb() */ From 5314f234ca303e2a2770bb1718e88c62b80bc6d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 21 Apr 2017 12:36:59 +0200 Subject: [PATCH 053/148] Make verify_restartable() actually restartable --- include/mbedtls/ecp.h | 1 + library/ecdsa.c | 46 ++++++++++++++++++++++++++---- library/ecp.c | 6 ++-- tests/suites/test_suite_ecdsa.data | 12 ++++++++ 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 3e5c60530..04a557bdb 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -201,6 +201,7 @@ typedef struct /* * Operation counts for restartable functions */ +#define MBEDTLS_ECP_OPS_CHK 3 /*!< basic ops count for ecp_check_pubkey() */ #define MBEDTLS_ECP_OPS_DBL 8 /*!< basic ops count for ecp_double_jac() */ #define MBEDTLS_ECP_OPS_ADD 11 /*!< basic ops count for see ecp_add_mixed() */ #define MBEDTLS_ECP_OPS_INV 120 /*!< empirical equivalent for mpi_mod_inv() */ diff --git a/library/ecdsa.c b/library/ecdsa.c index 8e1f62a8e..f7f7a01af 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -51,12 +51,17 @@ #endif #if defined(MBEDTLS_ECP_RESTARTABLE) + /* * Sub-contect for ecdsa_verify() */ struct mbedtls_ecdsa_restart_ver { - int state; /* dummy */ + mbedtls_mpi u1, u2; /* intermediate values */ + enum { /* what to do next? */ + ecdsa_ver_init = 0, /* getting started */ + ecdsa_ver_muladd, /* muladd step */ + } state; }; /* @@ -75,15 +80,24 @@ static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) if( ctx == NULL ) return; + mbedtls_mpi_free( &ctx->u1 ); + mbedtls_mpi_free( &ctx->u2 ); + memset( ctx, 0, sizeof( *ctx ) ); } #define ECDSA_RS_ECP &rs_ctx->ecp +/* Utility macro for checking and updating ops budget */ +#define ECDSA_BUDGET( ops ) \ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) ); + #else /* MBEDTLS_ECP_RESTARTABLE */ #define ECDSA_RS_ECP NULL +#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */ + #endif /* MBEDTLS_ECP_RESTARTABLE */ /* @@ -249,6 +263,7 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, int ret; mbedtls_mpi e, s_inv, u1, u2; mbedtls_ecp_point R; + mbedtls_mpi *pu1 = &u1, *pu2 = &u2; #if !defined(MBEDTLS_ECP_RESTARTABLE) (void) rs_ctx; @@ -276,6 +291,17 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, ecdsa_restart_ver_init( rs_ctx->ver ); } + + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + { + /* redirect to our context */ + pu1 = &rs_ctx->ver->u1; + pu2 = &rs_ctx->ver->u2; + + /* jump to current step */ + if( rs_ctx->ver->state == ecdsa_ver_muladd ) + goto muladd; + } #endif /* MBEDTLS_ECP_RESTARTABLE */ /* @@ -290,7 +316,9 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, /* * Additional precaution: make sure Q is valid + * For ops count, group that together with step 4 */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); /* @@ -303,17 +331,23 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, */ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->ver != NULL ) + rs_ctx->ver->state++; + +muladd: +#endif /* * Step 5: R = u1 G + u2 Q */ MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp, - &R, &u1, &grp->G, &u2, Q, ECDSA_RS_ECP ) ); + &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) ); if( mbedtls_ecp_is_zero( &R ) ) { diff --git a/library/ecp.c b/library/ecp.c index 40daa6710..0f1cbfce4 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -2155,12 +2155,12 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, rs_ctx == NULL || rs_ctx->rsm == NULL ) #endif { + /* check_privkey is free */ + MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_CHK ); + /* Common sanity checks */ MBEDTLS_MPI_CHK( mbedtls_ecp_check_privkey( grp, m ) ); MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, P ) ); - - /* check_privkey is 0M and check_pubkey is 3M */ - MBEDTLS_ECP_BUDGET( 3 ); } ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data index 6ca912a46..f2cf214cc 100644 --- a/tests/suites/test_suite_ecdsa.data +++ b/tests/suites/test_suite_ecdsa.data @@ -253,3 +253,15 @@ ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757 ECDSA restartable read-verify: restart disabled depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":0:0:0 + +ECDSA restartable read-verify: max_ops=1 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":1:42:10000 + +ECDSA restartable read-verify: max_ops=10000 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":10000:0:0 + +ECDSA restartable read-verify: max_ops=250 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":250:4:64 From addb10efac68cccf16918ba9798dc3dad8754729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 21 Apr 2017 12:54:46 +0200 Subject: [PATCH 054/148] Create functions for restartable sign --- include/mbedtls/ecdsa.h | 29 +++++++++++++++++++ library/ecdsa.c | 64 ++++++++++++++++++++++++++++++++++------- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index d2f83b224..f557a4de2 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -187,6 +187,35 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +/** + * \brief Restartable version of \c mbedtls_ecdsa_write_signature() + * + * \note Performs the same job as \c mbedtls_ecdsa_write_signature() + * but can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param ctx ECDSA context + * \param md_alg Algorithm that was used to hash the message + * \param hash Message hash + * \param hlen Length of hash + * \param sig Buffer that will hold the signature + * \param slen Length of the signature written + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param rs_ctx Restart context + * + * \return See \c mbedtls_ecdsa_write_signature(), or + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ); + #if defined(MBEDTLS_ECDSA_DETERMINISTIC) #if ! defined(MBEDTLS_DEPRECATED_REMOVED) #if defined(MBEDTLS_DEPRECATED_WARNING) diff --git a/library/ecdsa.c b/library/ecdsa.c index f7f7a01af..ec1e5872d 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -127,14 +127,18 @@ cleanup: * Compute ECDSA signature of a hashed message (SEC1 4.1.3) * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) */ -int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, +static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret, key_tries, sign_tries, blind_tries; mbedtls_ecp_point R; mbedtls_mpi k, e, t; + (void) rs_ctx; // temporary + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); @@ -212,13 +216,26 @@ cleanup: return( ret ); } +/* + * Compute ECDSA signature of a hashed message + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( ecdsa_sign_restartable( grp, r, s, d, buf, blen, + f_rng, p_rng, NULL ) ); +} + #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /* * Deterministic signature wrapper */ -int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, +static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *r, mbedtls_mpi *s, const mbedtls_mpi *d, const unsigned char *buf, size_t blen, - mbedtls_md_type_t md_alg ) + mbedtls_md_type_t md_alg, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_hmac_drbg_context rng_ctx; @@ -227,6 +244,8 @@ int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi const mbedtls_md_info_t *md_info; mbedtls_mpi h; + (void) rs_ctx; // temporary + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); @@ -248,6 +267,16 @@ cleanup: return( ret ); } + +/* + * Deterministic signature wrapper + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) +{ + return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) ); +} #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ /* @@ -427,11 +456,13 @@ static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, /* * Compute and write signature */ -int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, +int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, + mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hlen, unsigned char *sig, size_t *slen, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret; mbedtls_mpi r, s; @@ -443,13 +474,13 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t (void) f_rng; (void) p_rng; - MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, - hash, hlen, md_alg ) ); + MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg, rs_ctx ) ); #else (void) md_alg; - MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, - hash, hlen, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng, rs_ctx ) ); #endif MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); @@ -461,6 +492,19 @@ cleanup: return( ret ); } +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return( mbedtls_ecdsa_write_signature_restartable( + ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) ); +} + #if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ defined(MBEDTLS_ECDSA_DETERMINISTIC) int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, From eb402f3cd39bae8689a927fb61499cbee0283a0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 25 Apr 2017 10:57:30 +0200 Subject: [PATCH 055/148] Add test for restartable signature Test relies on deterministic signature as this uses plain sig internally, so if deterministic works, then so does non-deterministic, while the reciprocal is false. (Also, deterministic is enabled by default in config.h.) Test case is taken from a RFC 6979 test vector, just manually converting (r,s) to the encoded signature. --- tests/suites/test_suite_ecdsa.data | 4 ++ tests/suites/test_suite_ecdsa.function | 57 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data index f2cf214cc..c236c28c6 100644 --- a/tests/suites/test_suite_ecdsa.data +++ b/tests/suites/test_suite_ecdsa.data @@ -265,3 +265,7 @@ ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387 ECDSA restartable read-verify: max_ops=250 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":250:4:64 + +ECDSA restartable sign-write: secp256r1 restart disabled +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ecdsa_write_restart:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0 diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index d5cb65480..9205627be 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -264,3 +264,60 @@ exit: mbedtls_ecdsa_restart_free( &rs_ctx ); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE:MBEDTLS_ECDSA_DETERMINISTIC */ +void ecdsa_write_restart( int id, char *d_str, int md_alg, + char *msg, char *sig_str, + int max_ops, int min_restart, int max_restart ) +{ + int ret, cnt_restart; + mbedtls_ecdsa_restart_ctx rs_ctx; + mbedtls_ecdsa_context ctx; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + unsigned char sig[MBEDTLS_ECDSA_MAX_LEN]; + unsigned char sig_check[MBEDTLS_ECDSA_MAX_LEN]; + size_t hlen, slen, slen_check; + const mbedtls_md_info_t *md_info; + + mbedtls_ecdsa_restart_init( &rs_ctx ); + mbedtls_ecdsa_init( &ctx ); + memset( hash, 0, sizeof( hash ) ); + memset( sig, 0, sizeof( sig ) ); + memset( sig_check, 0, sizeof( sig_check ) ); + + TEST_ASSERT( mbedtls_ecp_group_load( &ctx.grp, id ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &ctx.d, 16, d_str ) == 0 ); + slen_check = unhexify( sig_check, sig_str ); + + md_info = mbedtls_md_info_from_type( md_alg ); + TEST_ASSERT( md_info != NULL ); + + hlen = mbedtls_md_get_size( md_info ); + mbedtls_md( md_info, (const unsigned char *) msg, strlen( msg ), hash ); + + mbedtls_ecp_set_max_ops( max_ops ); + + slen = sizeof( sig ); + cnt_restart = 0; + do { + ret = mbedtls_ecdsa_write_signature_restartable( &ctx, + md_alg, hash, hlen, sig, &slen, NULL, NULL, &rs_ctx ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); + + TEST_ASSERT( ret == 0 ); + TEST_ASSERT( slen == slen_check ); + TEST_ASSERT( memcmp( sig, sig_check, slen ) == 0 ); + + TEST_ASSERT( cnt_restart >= min_restart ); + TEST_ASSERT( cnt_restart <= max_restart ); + + /* do we leak memory when aborting? */ + ret = mbedtls_ecdsa_write_signature_restartable( &ctx, + md_alg, hash, hlen, sig, &slen, NULL, NULL, &rs_ctx ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + +exit: + mbedtls_ecdsa_restart_free( &rs_ctx ); + mbedtls_ecdsa_free( &ctx ); +} +/* END_CASE */ From b90883dc1dc42891354c0f40a908e298d8d0af32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 25 Apr 2017 11:33:10 +0200 Subject: [PATCH 056/148] Prepare infra for restartable sign --- include/mbedtls/ecdsa.h | 20 +++++ library/ecdsa.c | 176 ++++++++++++++++++++++++++++++++-------- 2 files changed, 161 insertions(+), 35 deletions(-) diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index f557a4de2..ce94af871 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -64,6 +64,22 @@ typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; */ typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; +/** + * \brief Internal restart context for ecdsa_sign() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_sig mbedtls_ecdsa_restart_sig_ctx; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief Internal restart context for ecdsa_sign_det() + * + * \note Opaque struct, defined in ecdsa.c + */ +typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; +#endif + /** * \brief General context for resuming ECDSA operations */ @@ -71,6 +87,10 @@ typedef struct { mbedtls_ecp_restart_ctx ecp; /*!< base context (admin+ecp info) */ mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */ + mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */ +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */ +#endif } mbedtls_ecdsa_restart_ctx; #else /* MBEDTLS_ECP_RESTARTABLE */ diff --git a/library/ecdsa.c b/library/ecdsa.c index ec1e5872d..4c0b61462 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -86,18 +86,110 @@ static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) memset( ctx, 0, sizeof( *ctx ) ); } +/* + * Sub-contect for ecdsa_sign() + */ +struct mbedtls_ecdsa_restart_sig +{ + enum { /* what to do next? */ + ecdsa_sig_init = 0, /* getting started */ + } state; +}; + +/* + * Init verify sign sub-context + */ +static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + memset( ctx, 0, sizeof( *ctx ) ); +} + +/* + * Free the components of a sign restart sub-context + */ +static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + memset( ctx, 0, sizeof( *ctx ) ); +} + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Sub-contect for ecdsa_sign_det() + */ +struct mbedtls_ecdsa_restart_det +{ + enum { /* what to do next? */ + ecdsa_det_init = 0, /* getting started */ + } state; +}; + +/* + * Init verify sign_det sub-context + */ +static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + memset( ctx, 0, sizeof( *ctx ) ); +} + +/* + * Free the components of a sign_det restart sub-context + */ +static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + memset( ctx, 0, sizeof( *ctx ) ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + #define ECDSA_RS_ECP &rs_ctx->ecp /* Utility macro for checking and updating ops budget */ #define ECDSA_BUDGET( ops ) \ MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) ); +#define ECDSA_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \ + rs_ctx->ecp.ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +#define ECDSA_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { \ + ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->ecp.depth--; \ +} while( 0 ) + #else /* MBEDTLS_ECP_RESTARTABLE */ #define ECDSA_RS_ECP NULL #define ECDSA_BUDGET( ops ) /* no-op; for compatibility */ +#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx +#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx + #endif /* MBEDTLS_ECP_RESTARTABLE */ /* @@ -137,8 +229,6 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point R; mbedtls_mpi k, e, t; - (void) rs_ctx; // temporary - /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); @@ -146,6 +236,19 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point_init( &R ); mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); + ECDSA_RS_ENTER( sig ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + { + /* redirect to our context */ + // TODO + + /* jump to current step */ + // TODO + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + sign_tries = 0; do { @@ -213,6 +316,8 @@ cleanup: mbedtls_ecp_point_free( &R ); mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); + ECDSA_RS_LEAVE( sig ); + return( ret ); } @@ -244,27 +349,40 @@ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, const mbedtls_md_info_t *md_info; mbedtls_mpi h; - (void) rs_ctx; // temporary - if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); mbedtls_mpi_init( &h ); mbedtls_hmac_drbg_init( &rng_ctx ); + ECDSA_RS_ENTER( det ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + { + /* redirect to our context */ + // TODO + + /* jump to current step */ + // TODO + } +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); - ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, - mbedtls_hmac_drbg_random, &rng_ctx ); + ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, &rng_ctx, rs_ctx ); cleanup: mbedtls_hmac_drbg_free( &rng_ctx ); mbedtls_mpi_free( &h ); + ECDSA_RS_LEAVE( det ); + return( ret ); } @@ -294,10 +412,6 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point R; mbedtls_mpi *pu1 = &u1, *pu2 = &u2; -#if !defined(MBEDTLS_ECP_RESTARTABLE) - (void) rs_ctx; -#endif - mbedtls_ecp_point_init( &R ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); @@ -306,21 +420,9 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, if( grp->N.p == NULL ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + ECDSA_RS_ENTER( ver ); + #if defined(MBEDTLS_ECP_RESTARTABLE) - /* reset ops count for this call if top-level */ - if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) - rs_ctx->ecp.ops_done = 0; - - /* set up our own sub-context if needed */ - if( mbedtls_ecp_restart_enabled() && rs_ctx != NULL && rs_ctx->ver == NULL ) - { - rs_ctx->ver = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ver_ctx ) ); - if( rs_ctx->ver == NULL ) - return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); - - ecdsa_restart_ver_init( rs_ctx->ver ); - } - if( rs_ctx != NULL && rs_ctx->ver != NULL ) { /* redirect to our context */ @@ -404,17 +506,7 @@ cleanup: mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); -#if defined(MBEDTLS_ECP_RESTARTABLE) - /* clear our sub-context when not in progress (done or error) */ - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { - ecdsa_restart_ver_free( rs_ctx->ver ); - mbedtls_free( rs_ctx->ver ); - rs_ctx->ver = NULL; - } - - if( rs_ctx != NULL ) - rs_ctx->ecp.depth--; -#endif /* MBEDTLS_ECP_RESTARTABLE */ + ECDSA_RS_LEAVE( ver ); return( ret ); } @@ -632,6 +724,10 @@ void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) mbedtls_ecp_restart_init( &ctx->ecp ); ctx->ver = NULL; + ctx->sig = NULL; +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ctx->det = NULL; +#endif } /* @@ -644,6 +740,16 @@ void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) ecdsa_restart_ver_free( ctx->ver ); mbedtls_free( ctx->ver ); ctx->ver = NULL; + + ecdsa_restart_sig_free( ctx->sig ); + mbedtls_free( ctx->sig ); + ctx->sig = NULL; + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + ecdsa_restart_det_free( ctx->det ); + mbedtls_free( ctx->det ); + ctx->det = NULL; +#endif } #endif /* MBEDTLS_ECP_RESTARTABLE */ From 675439620d3029c313e0a804e0ae1e24d6ef376a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 21 Apr 2017 13:19:43 +0200 Subject: [PATCH 057/148] Improve sign/key_tries handling (Unrelated to restartable work, just noticed while staring at the code.) Checking at the end is inefficient as we might give up when we just generated a valid signature or key. --- library/ecdsa.c | 18 +++++++++--------- library/ecp.c | 23 +++++++++++------------ 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index 4c0b61462..14854ffac 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -252,6 +252,12 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, sign_tries = 0; do { + if( sign_tries++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + /* * Steps 1-3: generate a suitable ephemeral keypair * and set r = xR mod n @@ -259,14 +265,14 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, key_tries = 0; do { - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); - if( key_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } + + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); } while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); @@ -303,12 +309,6 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); - - if( sign_tries++ > 10 ) - { - ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; - goto cleanup; - } } while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); diff --git a/library/ecp.c b/library/ecp.c index 0f1cbfce4..9b586eebe 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -2531,24 +2531,23 @@ int mbedtls_ecp_gen_privkey( const mbedtls_ecp_group *grp, * - keep the leftmost nbits bits of the generated octet string; * - try until result is in the desired range. * This also avoids any biais, which is especially important for ECDSA. + * + * Each try has at worst a probability 1/2 of failing (the msb has + * a probability 1/2 of being 0, and then the result will be < N), + * so after 30 tries failure probability is a most 2**(-30). + * + * For most curves, 1 try is enough with overwhelming probability, + * since N starts with a lot of 1s in binary, but some curves + * such as secp224k1 are actually very close to the worst case. */ do { + if( ++count > 30 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + MBEDTLS_MPI_CHK( f_rng( p_rng, rnd, n_size ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( d, rnd, n_size ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); - - /* - * Each try has at worst a probability 1/2 of failing (the msb has - * a probability 1/2 of being 0, and then the result will be < N), - * so after 30 tries failure probability is a most 2**(-30). - * - * For most curves, 1 try is enough with overwhelming probability, - * since N starts with a lot of 1s in binary, but some curves - * such as secp224k1 are actually very close to the worst case. - */ - if( ++count > 30 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); } while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); From 50b63ba2f588910123f4366c5145435ea9df3c9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 25 Apr 2017 12:57:22 +0200 Subject: [PATCH 058/148] Use ecp_gen_privkey() in ECDSA sign Two different changes: - the first one will allow us to store k in the restart context while restarting the following ecp_mul() operation - the second one is an simplification, unrelated to restartability, made possible by the fact that ecp_gen_privkey() is now public --- library/ecdsa.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index 14854ffac..b8aef5d30 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -225,7 +225,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, mbedtls_ecdsa_restart_ctx *rs_ctx ) { - int ret, key_tries, sign_tries, blind_tries; + int ret, key_tries, sign_tries; mbedtls_ecp_point R; mbedtls_mpi k, e, t; @@ -271,7 +271,10 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, goto cleanup; } - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &k, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &R, &k, &grp->G, + f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); } while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); @@ -285,19 +288,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, * Generate a random value to blind inv_mod in next step, * avoiding a potential timing leak. */ - blind_tries = 0; - do - { - size_t n_size = ( grp->nbits + 7 ) / 8; - MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); - - /* See mbedtls_ecp_gen_keypair() */ - if( ++blind_tries > 30 ) - return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); - } - while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || - mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) ); /* * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n From af081f546076b76cabb19cf88a35e75a44943499 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 25 Apr 2017 13:44:19 +0200 Subject: [PATCH 059/148] Make ECDSA sign actually restartable --- library/ecdsa.c | 98 ++++++++++++++++++++++++------ tests/suites/test_suite_ecdsa.data | 12 ++++ 2 files changed, 91 insertions(+), 19 deletions(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index b8aef5d30..e137a0074 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -91,8 +91,14 @@ static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) */ struct mbedtls_ecdsa_restart_sig { + int sign_tries; + int key_tries; + mbedtls_mpi k; /* per-signature random */ + mbedtls_mpi r; /* r value */ enum { /* what to do next? */ ecdsa_sig_init = 0, /* getting started */ + ecdsa_sig_mul, /* doing ecp_mul() */ + ecdsa_sig_modn, /* mod N computations */ } state; }; @@ -102,6 +108,9 @@ struct mbedtls_ecdsa_restart_sig static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) { memset( ctx, 0, sizeof( *ctx ) ); + + mbedtls_mpi_init( &ctx->k ); + mbedtls_mpi_init( &ctx->r ); } /* @@ -112,6 +121,9 @@ static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) if( ctx == NULL ) return; + mbedtls_mpi_free( &ctx->k ); + mbedtls_mpi_free( &ctx->r ); + memset( ctx, 0, sizeof( *ctx ) ); } @@ -121,8 +133,10 @@ static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) */ struct mbedtls_ecdsa_restart_det { + mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */ enum { /* what to do next? */ - ecdsa_det_init = 0, /* getting started */ + ecdsa_det_init = 0, /* getting started */ + ecdsa_det_sign, /* make signature */ } state; }; @@ -132,6 +146,8 @@ struct mbedtls_ecdsa_restart_det static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx ) { memset( ctx, 0, sizeof( *ctx ) ); + + mbedtls_hmac_drbg_init( &ctx->rng_ctx ); } /* @@ -142,6 +158,8 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) if( ctx == NULL ) return; + mbedtls_hmac_drbg_free( &ctx->rng_ctx ); + memset( ctx, 0, sizeof( *ctx ) ); } #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ @@ -226,8 +244,10 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, mbedtls_ecdsa_restart_ctx *rs_ctx ) { int ret, key_tries, sign_tries; + int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries; mbedtls_ecp_point R; mbedtls_mpi k, e, t; + mbedtls_mpi *pk = &k, *pr = r; /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ if( grp->N.p == NULL ) @@ -242,17 +262,24 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, if( rs_ctx != NULL && rs_ctx->sig != NULL ) { /* redirect to our context */ - // TODO + p_sign_tries = &rs_ctx->sig->sign_tries; + p_key_tries = &rs_ctx->sig->key_tries; + pk = &rs_ctx->sig->k; + pr = &rs_ctx->sig->r; + /* jump to current step */ - // TODO + if( rs_ctx->sig->state == ecdsa_sig_mul ) + goto mul; + if( rs_ctx->sig->state == ecdsa_sig_modn ) + goto modn; } #endif /* MBEDTLS_ECP_RESTARTABLE */ - sign_tries = 0; + *p_sign_tries = 0; do { - if( sign_tries++ > 10 ) + if( *p_sign_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; @@ -262,22 +289,43 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, * Steps 1-3: generate a suitable ephemeral keypair * and set r = xR mod n */ - key_tries = 0; + *p_key_tries = 0; do { - if( key_tries++ > 10 ) + if( *p_key_tries++ > 10 ) { ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; goto cleanup; } - MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &k, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &R, &k, &grp->G, - f_rng, p_rng ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + { + rs_ctx->sig->state++; + } + +mul: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G, + f_rng, p_rng, ECDSA_RS_ECP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) ); } - while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); + while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 ); + + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + rs_ctx->sig->state++; + +modn: +#endif + /* + * Accounting for everything up to the end of the loop + * (step 6, but checking now avoids saving e and t) + */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 ); /* * Step 5: derive MPI from hashed message @@ -293,16 +341,20 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, /* * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n */ - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); } while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_mpi_copy( r, pr ); +#endif + cleanup: mbedtls_ecp_point_free( &R ); mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); @@ -335,6 +387,7 @@ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, { int ret; mbedtls_hmac_drbg_context rng_ctx; + mbedtls_hmac_drbg_context *p_rng = &rng_ctx; unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; size_t grp_len = ( grp->nbits + 7 ) / 8; const mbedtls_md_info_t *md_info; @@ -352,10 +405,11 @@ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, if( rs_ctx != NULL && rs_ctx->det != NULL ) { /* redirect to our context */ - // TODO + p_rng = &rs_ctx->det->rng_ctx; /* jump to current step */ - // TODO + if( rs_ctx->det->state == ecdsa_det_sign ) + goto sign; } #endif /* MBEDTLS_ECP_RESTARTABLE */ @@ -363,10 +417,16 @@ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); - mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); + mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->det != NULL ) + rs_ctx->det->state++; + +sign: +#endif ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen, - mbedtls_hmac_drbg_random, &rng_ctx, rs_ctx ); + mbedtls_hmac_drbg_random, p_rng, rs_ctx ); cleanup: mbedtls_hmac_drbg_free( &rng_ctx ); diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data index c236c28c6..f9c8f6068 100644 --- a/tests/suites/test_suite_ecdsa.data +++ b/tests/suites/test_suite_ecdsa.data @@ -269,3 +269,15 @@ ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387 ECDSA restartable sign-write: secp256r1 restart disabled depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C ecdsa_write_restart:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0 + +ECDSA restartable sign-write: secp256r1 restart max_ops=1 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ecdsa_write_restart:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":1:1:10000 + +ECDSA restartable sign-write: secp256r1 restart max_ops=10000 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ecdsa_write_restart:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":10000:0:0 + +ECDSA restartable sign-write: secp256r1 restart max_ops=250 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +ecdsa_write_restart:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":250:2:32 From c90d3b0f896761dc4c7830cdd01cb894c5536cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 27 Apr 2017 10:48:29 +0200 Subject: [PATCH 060/148] Update doc for restartable ECDH functions --- include/mbedtls/ecdh.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h index 625a28192..506a1cfb9 100644 --- a/include/mbedtls/ecdh.h +++ b/include/mbedtls/ecdh.h @@ -67,6 +67,8 @@ mbedtls_ecdh_context; * * \return 0 if successful, * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), @@ -85,6 +87,8 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp * * \return 0 if successful, * or a MBEDTLS_ERR_ECP_XXX or MBEDTLS_MPI_XXX error code + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). * * \note If f_rng is not NULL, it is used to implement * countermeasures against potential elaborate timing @@ -124,6 +128,8 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); * properly set (for example using mbedtls_ecp_group_load). * * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, @@ -170,6 +176,8 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypai * \param p_rng RNG parameter * * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, @@ -201,6 +209,8 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, * \param p_rng RNG parameter * * \return 0 if successful, or an MBEDTLS_ERR_ECP_XXX error code + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, From 71b2c53254b670ae2639d33c415bdfc446d9ef95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 27 Apr 2017 10:38:52 +0200 Subject: [PATCH 061/148] Add tests for restartable ECDH --- tests/suites/test_suite_ecdh.data | 4 + tests/suites/test_suite_ecdh.function | 110 ++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/tests/suites/test_suite_ecdh.data b/tests/suites/test_suite_ecdh.data index f7119de41..98c4f60c1 100644 --- a/tests/suites/test_suite_ecdh.data +++ b/tests/suites/test_suite_ecdh.data @@ -37,3 +37,7 @@ ecdh_exchange:MBEDTLS_ECP_DP_SECP192R1 ECDH exchange #2 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED ecdh_exchange:MBEDTLS_ECP_DP_SECP521R1 + +ECDH restartable rfc 5903 p256 restart disabled +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:0:0 diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function index 4c6a97baf..911464ad0 100644 --- a/tests/suites/test_suite_ecdh.function +++ b/tests/suites/test_suite_ecdh.function @@ -158,3 +158,113 @@ exit: mbedtls_ecdh_free( &cli ); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */ +void ecdh_restart( int id, char *dA_str, char *dB_str, char *z_str, + int max_ops, int min_restart, int max_restart ) +{ + int ret; + mbedtls_ecdh_context srv, cli; + unsigned char buf[1000]; + const unsigned char *vbuf; + size_t len; + unsigned char z[MBEDTLS_ECP_MAX_BYTES]; + size_t z_len; + unsigned char rnd_buf_A[MBEDTLS_ECP_MAX_BYTES]; + unsigned char rnd_buf_B[MBEDTLS_ECP_MAX_BYTES]; + rnd_buf_info rnd_info_A, rnd_info_B; + int cnt_restart; + + mbedtls_ecdh_init( &srv ); + mbedtls_ecdh_init( &cli ); + + z_len = unhexify( z, z_str ); + + rnd_info_A.buf = rnd_buf_A; + rnd_info_A.length = unhexify( rnd_buf_A, dA_str ); + + rnd_info_B.buf = rnd_buf_B; + rnd_info_B.length = unhexify( rnd_buf_B, dB_str ); + + TEST_ASSERT( mbedtls_ecp_group_load( &srv.grp, id ) == 0 ); + + /* otherwise we would have to fix the random buffer, + * as in ecdh_primitive_test_vec */ + TEST_ASSERT( srv.grp.nbits % 8 == 0 ); + + mbedtls_ecp_set_max_ops( max_ops ); + + /* server writes its paramaters */ + memset( buf, 0x00, sizeof( buf ) ); + len = 0; + + cnt_restart = 0; + do { + ret = mbedtls_ecdh_make_params( &srv, &len, buf, sizeof( buf ), + rnd_buffer_rand, &rnd_info_A ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); + + TEST_ASSERT( ret == 0 ); + TEST_ASSERT( cnt_restart >= min_restart ); + TEST_ASSERT( cnt_restart <= max_restart ); + + /* client read server params */ + vbuf = buf; + TEST_ASSERT( mbedtls_ecdh_read_params( &cli, &vbuf, buf + len ) == 0 ); + + /* client writes its key share */ + memset( buf, 0x00, sizeof( buf ) ); + len = 0; + + cnt_restart = 0; + do { + ret = mbedtls_ecdh_make_public( &cli, &len, buf, sizeof( buf ), + rnd_buffer_rand, &rnd_info_B ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); + + TEST_ASSERT( ret == 0 ); + TEST_ASSERT( cnt_restart >= min_restart ); + TEST_ASSERT( cnt_restart <= max_restart ); + + /* server reads client key share */ + TEST_ASSERT( mbedtls_ecdh_read_public( &srv, buf, len ) == 0 ); + + /* server computes shared secret */ + memset( buf, 0, sizeof( buf ) ); + len = 0; + + cnt_restart = 0; + do { + ret = mbedtls_ecdh_calc_secret( &srv, &len, buf, sizeof( buf ), + NULL, NULL ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); + + TEST_ASSERT( ret == 0 ); + TEST_ASSERT( cnt_restart >= min_restart ); + TEST_ASSERT( cnt_restart <= max_restart ); + + TEST_ASSERT( len == z_len ); + TEST_ASSERT( memcmp( buf, z, len ) == 0 ); + + /* client computes shared secret */ + memset( buf, 0, sizeof( buf ) ); + len = 0; + + cnt_restart = 0; + do { + ret = mbedtls_ecdh_calc_secret( &cli, &len, buf, sizeof( buf ), + NULL, NULL ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); + + TEST_ASSERT( ret == 0 ); + TEST_ASSERT( cnt_restart >= min_restart ); + TEST_ASSERT( cnt_restart <= max_restart ); + + TEST_ASSERT( len == z_len ); + TEST_ASSERT( memcmp( buf, z, len ) == 0 ); + +exit: + mbedtls_ecdh_free( &srv ); + mbedtls_ecdh_free( &cli ); +} +/* END_CASE */ From 66ba48a3c8e6522b48acffca9cb6beb7c9d7a23e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 27 Apr 2017 11:38:26 +0200 Subject: [PATCH 062/148] Make ECDH functions actually restartable --- include/mbedtls/ecdh.h | 3 ++ library/ecdh.c | 86 ++++++++++++++++++++++++++----- tests/suites/test_suite_ecdh.data | 12 +++++ 3 files changed, 89 insertions(+), 12 deletions(-) diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h index 506a1cfb9..e707558a8 100644 --- a/include/mbedtls/ecdh.h +++ b/include/mbedtls/ecdh.h @@ -52,6 +52,9 @@ typedef struct mbedtls_ecp_point Vi; /*!< blinding value (for later) */ mbedtls_ecp_point Vf; /*!< un-blinding value (for later) */ mbedtls_mpi _d; /*!< previous d (for later) */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_ctx rs; /*!< restart context for EC computations */ +#endif } mbedtls_ecdh_context; diff --git a/library/ecdh.c b/library/ecdh.c index c0a814731..b2859c4b6 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -39,22 +39,48 @@ #include /* - * Generate public key: simple wrapper around mbedtls_ecp_gen_keypair + * Generate public key (restartable version) + */ +static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) +{ + int ret; + + /* If multiplication is in progress, we already generated a privkey */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G, + f_rng, p_rng, rs_ctx ) ); + +cleanup: + return( ret ); +} + +/* + * Generate public key */ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - return mbedtls_ecp_gen_keypair( grp, d, Q, f_rng, p_rng ); + return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); } /* * Compute shared secret (SEC1 3.3.1) */ -int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, +static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, + mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) + void *p_rng, + mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; mbedtls_ecp_point P; @@ -66,7 +92,8 @@ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, */ MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, + f_rng, p_rng, rs_ctx ) ); if( mbedtls_ecp_is_zero( &P ) ) { @@ -82,12 +109,28 @@ cleanup: return( ret ); } +/* + * Compute shared secret (SEC1 3.3.1) + */ +int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return( ecdh_compute_shared_restartable( grp, z, Q, d, + f_rng, p_rng, NULL ) ); +} + /* * Initialize context */ void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) { memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_init( &ctx->rs ); +#endif } /* @@ -106,6 +149,10 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) mbedtls_mpi_free( &ctx->d ); mbedtls_mpi_free( &ctx->z ); mbedtls_mpi_free( &ctx->_d ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecp_restart_free( &ctx->rs ); +#endif } /* @@ -122,12 +169,17 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, { int ret; size_t grp_len, pt_len; + mbedtls_ecp_restart_ctx *rs_ctx = NULL; if( ctx == NULL || ctx->grp.pbits == 0 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) - != 0 ) +#if defined(MBEDTLS_ECP_RESTARTABLE) + rs_ctx = &ctx->rs; +#endif + + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) return( ret ); if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) @@ -202,12 +254,17 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, void *p_rng ) { int ret; + mbedtls_ecp_restart_ctx *rs_ctx = NULL; if( ctx == NULL || ctx->grp.pbits == 0 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ) - != 0 ) +#if defined(MBEDTLS_ECP_RESTARTABLE) + rs_ctx = &ctx->rs; +#endif + + if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, + f_rng, p_rng, rs_ctx ) ) != 0 ) return( ret ); return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, @@ -244,12 +301,17 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, void *p_rng ) { int ret; + mbedtls_ecp_restart_ctx *rs_ctx = NULL; - if( ctx == NULL ) + if( ctx == NULL || ctx->grp.pbits == 0 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); - if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, &ctx->d, - f_rng, p_rng ) ) != 0 ) +#if defined(MBEDTLS_ECP_RESTARTABLE) + rs_ctx = &ctx->rs; +#endif + + if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, + &ctx->z, &ctx->Qp, &ctx->d, f_rng, p_rng, rs_ctx ) ) != 0 ) { return( ret ); } diff --git a/tests/suites/test_suite_ecdh.data b/tests/suites/test_suite_ecdh.data index 98c4f60c1..991d11388 100644 --- a/tests/suites/test_suite_ecdh.data +++ b/tests/suites/test_suite_ecdh.data @@ -41,3 +41,15 @@ ecdh_exchange:MBEDTLS_ECP_DP_SECP521R1 ECDH restartable rfc 5903 p256 restart disabled depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:0:0 + +ECDH restartable rfc 5903 p256 restart max_ops=1 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:1:10000 + +ECDH restartable rfc 5903 p256 restart max_ops=10000 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":10000:0:0 + +ECDH restartable rfc 5903 p256 restart max_ops=250 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":250:2:32 From fd838dab5cdc13c831851cf6bc00e4d8ff3f167c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 27 Apr 2017 11:38:51 +0200 Subject: [PATCH 063/148] Comment cosmetics --- include/mbedtls/ecdh.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h index e707558a8..2e344a8c9 100644 --- a/include/mbedtls/ecdh.h +++ b/include/mbedtls/ecdh.h @@ -43,15 +43,15 @@ typedef enum */ typedef struct { - mbedtls_ecp_group grp; /*!< elliptic curve used */ - mbedtls_mpi d; /*!< our secret value (private key) */ - mbedtls_ecp_point Q; /*!< our public value (public key) */ - mbedtls_ecp_point Qp; /*!< peer's public value (public key) */ - mbedtls_mpi z; /*!< shared secret */ - int point_format; /*!< format for point export in TLS messages */ - mbedtls_ecp_point Vi; /*!< blinding value (for later) */ - mbedtls_ecp_point Vf; /*!< un-blinding value (for later) */ - mbedtls_mpi _d; /*!< previous d (for later) */ + mbedtls_ecp_group grp; /*!< elliptic curve used */ + mbedtls_mpi d; /*!< our secret value (private key) */ + mbedtls_ecp_point Q; /*!< our public value (public key) */ + mbedtls_ecp_point Qp; /*!< peer's public value (public key) */ + mbedtls_mpi z; /*!< shared secret */ + int point_format; /*!< format for point export in TLS */ + mbedtls_ecp_point Vi; /*!< blinding value (for later) */ + mbedtls_ecp_point Vf; /*!< un-blinding value (for later) */ + mbedtls_mpi _d; /*!< previous d (for later) */ #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_ctx rs; /*!< restart context for EC computations */ #endif From 82cb27b3db2b15e32937cbca9474afbd9e2ccd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 3 May 2017 10:59:45 +0200 Subject: [PATCH 064/148] PK: declare restartable sign/verify functions For RSA, we could either have the function return an error code like NOT_IMPLEMENTED or just run while disregarding ecp_max_ops. IMO the second option makes more sense, as otherwise the caller would need to check whether the key is EC or RSA before deciding to call either sign() or sign_restartable(), and having to do this kind of check feels contrary to the goal of the PK layer. --- include/mbedtls/pk.h | 57 ++++++++++++++++++++++++++++++++++++++++++++ library/pk.c | 43 ++++++++++++++++++++++++++++----- 2 files changed, 94 insertions(+), 6 deletions(-) diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index f9f9b9bb0..05c51d38d 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -284,6 +284,33 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len ); +/** + * \brief Restartable version of \c mbedtls_pk_verify() + * + * \note Performs the same job as \c mbedtls_pk_verify(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_verify(). + * + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * \param rs_ctx Restart context: for ECC, must be NULL (no restart) or a + * pointer to a \c mbedtls_ecdsa_restart_ctx. Ignored for RSA. + * + * \return See \c mbedtls_pk_verify(), or + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + /** * \brief Verify signature, with options. * (Includes verification of the padding depending on type.) @@ -347,6 +374,36 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +/** + * \brief Restartable version of \c mbedtls_pk_sign() + * + * \note Performs the same job as \c mbedtls_pk_sign(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_sign(). + * + * \param ctx PK context to use - must hold a private key + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * \param rs_ctx Restart context: for ECC, must be NULL (no restart) or a + * pointer to a \c mbedtls_ecdsa_restart_ctx. Ignored for RSA. + * + * \return See \c mbedtls_pk_sign(), or + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ); + /** * \brief Decrypt message (including padding if relevant). * diff --git a/library/pk.c b/library/pk.c index 8d13bc5ce..b5081f961 100644 --- a/library/pk.c +++ b/library/pk.c @@ -176,12 +176,16 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len } /* - * Verify a signature + * Verify a signature (restartable) */ -int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, - const unsigned char *sig, size_t sig_len ) + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) { + (void) rs_ctx; // XXX temporary + if( ctx == NULL || ctx->pk_info == NULL || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); @@ -193,6 +197,17 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, sig, sig_len ) ); } +/* + * Verify a signature + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, NULL ) ); +} + /* * Verify a signature with options */ @@ -252,13 +267,17 @@ int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, } /* - * Make a signature + * Make a signature (restartable) */ -int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t *sig_len, - int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) { + (void) rs_ctx; // XXX temporary + if( ctx == NULL || ctx->pk_info == NULL || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); @@ -270,6 +289,18 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, sig, sig_len, f_rng, p_rng ) ); } +/* + * Make a signature + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng, NULL ) ); +} + /* * Decrypt message */ From c4ee9acb7b58f05d360f881ac92372eb3d42eaa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 8 May 2017 10:09:36 +0200 Subject: [PATCH 065/148] Add tests for restartable PK sign/verify --- tests/suites/test_suite_pk.data | 8 ++ tests/suites/test_suite_pk.function | 160 +++++++++++++++++++++++++++- 2 files changed, 166 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data index dc24cfdd3..8ca9a2194 100644 --- a/tests/suites/test_suite_pk.data +++ b/tests/suites/test_suite_pk.data @@ -153,3 +153,11 @@ mbedtls_pk_check_pair:"data_files/ec_256_pub.pem":"data_files/server1.key":MBEDT RSA hash_len overflow (size_t vs unsigned int) depends_on:MBEDTLS_RSA_C:MBEDTLS_HAVE_INT64 pk_rsa_overflow: + +ECDSA restartable sign/verify: ECDSA, restart disabled +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0 + +ECDSA restartable sign/verify: ECKEY, restart disabled +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0 diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index 5fa8a693a..6e8c032c1 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -127,6 +127,14 @@ void pk_rsa_verify_test_vec( char *message_hex_string, int digest, mbedtls_rsa_context *rsa; mbedtls_pk_context pk; int msg_len; + void *rs_ctx = NULL; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecdsa_restart_ctx ctx; + + rs_ctx = &ctx; + mbedtls_ecdsa_restart_init( rs_ctx ); + mbedtls_ecp_set_max_ops( 42 ); +#endif mbedtls_pk_init( &pk ); @@ -150,7 +158,13 @@ void pk_rsa_verify_test_vec( char *message_hex_string, int digest, TEST_ASSERT( mbedtls_pk_verify( &pk, digest, hash_result, 0, result_str, mbedtls_pk_get_len( &pk ) ) == result ); + TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, digest, hash_result, 0, + result_str, mbedtls_pk_get_len( &pk ), rs_ctx ) == result ); + exit: +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecdsa_restart_free( rs_ctx ); +#endif mbedtls_pk_free( &pk ); } /* END_CASE */ @@ -253,12 +267,118 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE:MBEDTLS_ECDSA_C:MBEDTLS_ECDSA_DETERMINISTIC */ +void pk_sign_verify_restart( int pk_type, int grp_id, char *d_str, + char *QX_str, char *QY_str, + int md_alg, char *msg, char *sig_str, + int max_ops, int min_restart, int max_restart ) +{ + int ret, cnt_restart; + mbedtls_ecdsa_restart_ctx rs_ctx; + mbedtls_pk_context prv, pub; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + unsigned char sig[MBEDTLS_ECDSA_MAX_LEN]; + unsigned char sig_check[MBEDTLS_ECDSA_MAX_LEN]; + size_t hlen, slen, slen_check; + const mbedtls_md_info_t *md_info; + + mbedtls_ecdsa_restart_init( &rs_ctx ); + mbedtls_pk_init( &prv ); + mbedtls_pk_init( &pub ); + memset( hash, 0, sizeof( hash ) ); + memset( sig, 0, sizeof( sig ) ); + memset( sig_check, 0, sizeof( sig_check ) ); + + TEST_ASSERT( mbedtls_pk_setup( &prv, mbedtls_pk_info_from_type( pk_type ) ) == 0 ); + TEST_ASSERT( mbedtls_ecp_group_load( &mbedtls_pk_ec( prv )->grp, grp_id ) == 0 ); + TEST_ASSERT( mbedtls_mpi_read_string( &mbedtls_pk_ec( prv )->d, 16, d_str ) == 0 ); + + TEST_ASSERT( mbedtls_pk_setup( &pub, mbedtls_pk_info_from_type( pk_type ) ) == 0 ); + TEST_ASSERT( mbedtls_ecp_group_load( &mbedtls_pk_ec( pub )->grp, grp_id ) == 0 ); + TEST_ASSERT( mbedtls_ecp_point_read_string( &mbedtls_pk_ec( pub )->Q, 16, QX_str, QY_str ) == 0 ); + + slen_check = unhexify( sig_check, sig_str ); + + md_info = mbedtls_md_info_from_type( md_alg ); + TEST_ASSERT( md_info != NULL ); + + hlen = mbedtls_md_get_size( md_info ); + mbedtls_md( md_info, (const unsigned char *) msg, strlen( msg ), hash ); + + mbedtls_ecp_set_max_ops( max_ops ); + + slen = sizeof( sig ); + cnt_restart = 0; + do { + ret = mbedtls_pk_sign_restartable( &prv, md_alg, hash, hlen, + sig, &slen, NULL, NULL, &rs_ctx ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); + + TEST_ASSERT( ret == 0 ); + TEST_ASSERT( slen == slen_check ); + TEST_ASSERT( memcmp( sig, sig_check, slen ) == 0 ); + + TEST_ASSERT( cnt_restart >= min_restart ); + TEST_ASSERT( cnt_restart <= max_restart ); + + cnt_restart = 0; + do { + ret = mbedtls_pk_verify_restartable( &pub, md_alg, + hash, hlen, sig, slen, &rs_ctx ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); + + TEST_ASSERT( ret == 0 ); + TEST_ASSERT( cnt_restart >= min_restart ); + TEST_ASSERT( cnt_restart <= max_restart ); + + hash[0]++; + do { + ret = mbedtls_pk_verify_restartable( &pub, md_alg, + hash, hlen, sig, slen, &rs_ctx ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + TEST_ASSERT( ret != 0 ); + hash[0]--; + + sig[0]++; + do { + ret = mbedtls_pk_verify_restartable( &pub, md_alg, + hash, hlen, sig, slen, &rs_ctx ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + TEST_ASSERT( ret != 0 ); + sig[0]--; + + /* Do we leak memory when aborting? try verify then sign */ + ret = mbedtls_pk_verify_restartable( &pub, md_alg, + hash, hlen, sig, slen, &rs_ctx ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + mbedtls_ecdsa_restart_free( &rs_ctx ); + + slen = sizeof( sig ); + ret = mbedtls_pk_sign_restartable( &prv, md_alg, hash, hlen, + sig, &slen, NULL, NULL, &rs_ctx ); + TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + +exit: + mbedtls_ecdsa_restart_free( &rs_ctx ); + mbedtls_pk_free( &prv ); + mbedtls_pk_free( &pub ); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_SHA256_C */ void pk_sign_verify( int type, int sign_ret, int verify_ret ) { mbedtls_pk_context pk; unsigned char hash[50], sig[5000]; size_t sig_len; + void *rs_ctx = NULL; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecdsa_restart_ctx ctx; + + rs_ctx = &ctx; + mbedtls_ecdsa_restart_init( rs_ctx ); + mbedtls_ecp_set_max_ops( 42000 ); +#endif mbedtls_pk_init( &pk ); @@ -268,13 +388,49 @@ void pk_sign_verify( int type, int sign_ret, int verify_ret ) TEST_ASSERT( mbedtls_pk_setup( &pk, mbedtls_pk_info_from_type( type ) ) == 0 ); TEST_ASSERT( pk_genkey( &pk ) == 0 ); - TEST_ASSERT( mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash, - sig, &sig_len, rnd_std_rand, NULL ) == sign_ret ); + TEST_ASSERT( mbedtls_pk_sign_restartable( &pk, MBEDTLS_MD_SHA256, + hash, sizeof hash, sig, &sig_len, + rnd_std_rand, NULL, rs_ctx ) == sign_ret ); TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash, sig, sig_len ) == verify_ret ); + if( verify_ret == 0 ) + { + hash[0]++; + TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, + hash, sizeof hash, sig, sig_len ) != 0 ); + hash[0]--; + + sig[0]++; + TEST_ASSERT( mbedtls_pk_verify( &pk, MBEDTLS_MD_SHA256, + hash, sizeof hash, sig, sig_len ) != 0 ); + sig[0]--; + } + + TEST_ASSERT( mbedtls_pk_sign( &pk, MBEDTLS_MD_SHA256, hash, sizeof hash, + sig, &sig_len, rnd_std_rand, NULL ) == sign_ret ); + + TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256, + hash, sizeof hash, sig, sig_len, rs_ctx ) == verify_ret ); + + if( verify_ret == 0 ) + { + hash[0]++; + TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256, + hash, sizeof hash, sig, sig_len, rs_ctx ) != 0 ); + hash[0]--; + + sig[0]++; + TEST_ASSERT( mbedtls_pk_verify_restartable( &pk, MBEDTLS_MD_SHA256, + hash, sizeof hash, sig, sig_len, rs_ctx ) != 0 ); + sig[0]--; + } + exit: +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + mbedtls_ecdsa_restart_free( rs_ctx ); +#endif mbedtls_pk_free( &pk ); } /* END_CASE */ From 1f596064bc3683f6214a87dd0f6b7cb3f97be004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 9 May 2017 10:42:40 +0200 Subject: [PATCH 066/148] Make PK EC sign/verify actually restartable --- include/mbedtls/ecdsa.h | 3 + include/mbedtls/pk_internal.h | 15 +++ library/ecdsa.c | 9 ++ library/pk.c | 24 ++++- library/pk_wrap.c | 172 +++++++++++++++++++++++++++++++- tests/suites/test_suite_pk.data | 24 +++++ 6 files changed, 242 insertions(+), 5 deletions(-) diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index ce94af871..77842526c 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -91,6 +91,9 @@ typedef struct #if defined(MBEDTLS_ECDSA_DETERMINISTIC) mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */ #endif +#if defined(MBEDTLS_PK_C) + mbedtls_ecdsa_context *ecdsa; /*!< used by the PK layer */ +#endif } mbedtls_ecdsa_restart_ctx; #else /* MBEDTLS_ECP_RESTARTABLE */ diff --git a/include/mbedtls/pk_internal.h b/include/mbedtls/pk_internal.h index 01d0f214b..e996b6cad 100644 --- a/include/mbedtls/pk_internal.h +++ b/include/mbedtls/pk_internal.h @@ -58,6 +58,21 @@ struct mbedtls_pk_info_t int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + /** Verify signature (restartable) */ + int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + + /** Make signature (restartable) */ + int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, void *rs_ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /** Decrypt message */ int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, unsigned char *output, size_t *olen, size_t osize, diff --git a/library/ecdsa.c b/library/ecdsa.c index e137a0074..673076275 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -779,6 +779,9 @@ void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) #if defined(MBEDTLS_ECDSA_DETERMINISTIC) ctx->det = NULL; #endif +#if defined(MBEDTLS_PK_C) + ctx->ecdsa = NULL; +#endif } /* @@ -801,6 +804,12 @@ void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) mbedtls_free( ctx->det ); ctx->det = NULL; #endif + +#if defined(MBEDTLS_PK_C) + mbedtls_ecdsa_free( ctx->ecdsa ); + mbedtls_free( ctx->ecdsa ); + ctx->ecdsa = NULL; +#endif } #endif /* MBEDTLS_ECP_RESTARTABLE */ diff --git a/library/pk.c b/library/pk.c index b5081f961..e439c7ad8 100644 --- a/library/pk.c +++ b/library/pk.c @@ -184,12 +184,20 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, const unsigned char *sig, size_t sig_len, void *rs_ctx ) { - (void) rs_ctx; // XXX temporary - if( ctx == NULL || ctx->pk_info == NULL || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ctx->pk_info->verify_rs_func != NULL ) + { + return( ctx->pk_info->verify_rs_func( ctx->pk_ctx, + md_alg, hash, hash_len, sig, sig_len, rs_ctx ) ); + } +#else + (void) rs_ctx; +#endif /* MBEDTLS_ECP_RESTARTABLE */ + if( ctx->pk_info->verify_func == NULL ) return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); @@ -276,12 +284,20 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx ) { - (void) rs_ctx; // XXX temporary - if( ctx == NULL || ctx->pk_info == NULL || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ctx->pk_info->sign_rs_func != NULL ) + { + return( ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, + hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx ) ); + } +#else + (void) rs_ctx; +#endif /* MBEDTLS_ECP_RESTARTABLE */ + if( ctx->pk_info->sign_func == NULL ) return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); diff --git a/library/pk_wrap.c b/library/pk_wrap.c index db6274cbf..d3933a0f1 100644 --- a/library/pk_wrap.c +++ b/library/pk_wrap.c @@ -180,6 +180,10 @@ const mbedtls_pk_info_t mbedtls_rsa_info = { rsa_can_do, rsa_verify_wrap, rsa_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif rsa_decrypt_wrap, rsa_encrypt_wrap, rsa_check_pair_wrap, @@ -252,6 +256,118 @@ static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, return( ret ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* Forward declarations */ +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ); + +static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *p_rs_ctx ) +{ + int ret; + mbedtls_ecdsa_context ecdsa, *p_ecdsa = &ecdsa; + mbedtls_ecdsa_restart_ctx *rs_ctx = p_rs_ctx; + + mbedtls_ecdsa_init( &ecdsa ); + + /* set up our own sub-context if needed */ + if( mbedtls_ecp_restart_enabled() && + rs_ctx != NULL && rs_ctx->ecdsa == NULL ) + { + rs_ctx->ecdsa = mbedtls_calloc( 1, sizeof( *rs_ctx->ecdsa ) ); + if( rs_ctx->ecdsa == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + mbedtls_ecdsa_init( rs_ctx->ecdsa ); + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( rs_ctx->ecdsa, ctx ) ); + } + + if( rs_ctx != NULL && rs_ctx->ecdsa != NULL ) + { + /* redirect to our context */ + p_ecdsa = rs_ctx->ecdsa; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( p_ecdsa, ctx ) ); + } + + MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( p_ecdsa, md_alg, hash, hash_len, + sig, sig_len, rs_ctx ) ); + +cleanup: + /* clear our sub-context when not in progress (done or error) */ + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + mbedtls_ecdsa_free( rs_ctx->ecdsa ); + mbedtls_free( rs_ctx->ecdsa ); + rs_ctx->ecdsa = NULL; + } + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *p_rs_ctx ) +{ + int ret; + mbedtls_ecdsa_context ecdsa, *p_ecdsa = &ecdsa; + mbedtls_ecdsa_restart_ctx *rs_ctx = p_rs_ctx; + + mbedtls_ecdsa_init( &ecdsa ); + + /* set up our own sub-context if needed */ + if( mbedtls_ecp_restart_enabled() && + rs_ctx != NULL && rs_ctx->ecdsa == NULL ) + { + rs_ctx->ecdsa = mbedtls_calloc( 1, sizeof( *rs_ctx->ecdsa ) ); + if( rs_ctx->ecdsa == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + mbedtls_ecdsa_init( rs_ctx->ecdsa ); + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( rs_ctx->ecdsa, ctx ) ); + } + + if( rs_ctx != NULL && rs_ctx->ecdsa != NULL ) + { + /* redirect to our context */ + p_ecdsa = rs_ctx->ecdsa; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( p_ecdsa, ctx ) ); + } + + MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( p_ecdsa, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng, rs_ctx ) ); + +cleanup: + /* clear our sub-context when not in progress (done or error) */ + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + mbedtls_ecdsa_free( rs_ctx->ecdsa ); + mbedtls_free( rs_ctx->ecdsa ); + rs_ctx->ecdsa = NULL; + } + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_ECDSA_C */ static int eckey_check_pair( const void *pub, const void *prv ) @@ -291,10 +407,18 @@ const mbedtls_pk_info_t mbedtls_eckey_info = { #if defined(MBEDTLS_ECDSA_C) eckey_verify_wrap, eckey_sign_wrap, -#else +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_verify_rs_wrap, + eckey_sign_rs_wrap, +#endif +#else /* MBEDTLS_ECDSA_C */ + NULL, + NULL, +#if defined(MBEDTLS_ECP_RESTARTABLE) NULL, NULL, #endif +#endif /* MBEDTLS_ECDSA_C */ NULL, NULL, eckey_check_pair, @@ -319,6 +443,10 @@ const mbedtls_pk_info_t mbedtls_eckeydh_info = { eckeydh_can_do, NULL, NULL, +#if defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif NULL, NULL, eckey_check_pair, @@ -359,6 +487,40 @@ static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + return( mbedtls_ecdsa_write_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); + +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + static void *ecdsa_alloc_wrap( void ) { void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); @@ -382,6 +544,10 @@ const mbedtls_pk_info_t mbedtls_ecdsa_info = { ecdsa_can_do, ecdsa_verify_wrap, ecdsa_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_verify_rs_wrap, + ecdsa_sign_rs_wrap, +#endif NULL, NULL, eckey_check_pair, /* Compatible key structures */ @@ -496,6 +662,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = { rsa_alt_can_do, NULL, rsa_alt_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif rsa_alt_decrypt_wrap, NULL, #if defined(MBEDTLS_RSA_C) diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data index 8ca9a2194..bd3db182b 100644 --- a/tests/suites/test_suite_pk.data +++ b/tests/suites/test_suite_pk.data @@ -161,3 +161,27 @@ pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75 ECDSA restartable sign/verify: ECKEY, restart disabled depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0 + +ECDSA restartable sign/verify: ECDSA, max_ops=1 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":1:1:10000 + +ECDSA restartable sign/verify: ECKEY, max_ops=1 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":1:1:10000 + +ECDSA restartable sign/verify: ECDSA, max_ops=10000 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":10000:0:0 + +ECDSA restartable sign/verify: ECKEY, max_ops=10000 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":10000:0:0 + +ECDSA restartable sign/verify: ECDSA, max_ops=250 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":250:2:64 + +ECDSA restartable sign/verify: ECKEY, max_ops=1 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C +pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":250:2:64 From 31f0ef7b19fe4670a78eb1412b5d2e38a095aead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 17 May 2017 10:05:58 +0200 Subject: [PATCH 067/148] Fix style issues introduced earlier --- library/ecdsa.c | 3 ++- library/ecp.c | 9 ++++++--- library/pk_wrap.c | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index 673076275..8d1f9d632 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -189,7 +189,8 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) #define ECDSA_RS_LEAVE( SUB ) do { \ /* clear our sub-context when not in progress (done or error) */ \ - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { \ + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \ mbedtls_free( rs_ctx->SUB ); \ rs_ctx->SUB = NULL; \ diff --git a/library/ecp.c b/library/ecp.c index 9b586eebe..74a19eecb 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -147,7 +147,8 @@ static void ecp_restart_mul_free( mbedtls_ecp_restart_mul_ctx *ctx ) mbedtls_ecp_point_free( &ctx->R ); - if( ctx->T != NULL ) { + if( ctx->T != NULL ) + { for( i = 0; i < ctx->T_size; i++ ) mbedtls_ecp_point_free( ctx->T + i ); mbedtls_free( ctx->T ); @@ -1907,7 +1908,8 @@ cleanup: /* clear our sub-context when not in progress (done or error) */ #if defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + { ecp_restart_mul_free( rs_ctx->rsm ); mbedtls_free( rs_ctx->rsm ); rs_ctx->rsm = NULL; @@ -2392,7 +2394,8 @@ cleanup: #if defined(MBEDTLS_ECP_RESTARTABLE) /* clear our sub-context when not in progress (done or error) */ - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + { ecp_restart_muladd_free( rs_ctx->ma ); mbedtls_free( rs_ctx->ma ); rs_ctx->ma = NULL; diff --git a/library/pk_wrap.c b/library/pk_wrap.c index d3933a0f1..8b94d8129 100644 --- a/library/pk_wrap.c +++ b/library/pk_wrap.c @@ -307,7 +307,8 @@ static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, cleanup: /* clear our sub-context when not in progress (done or error) */ - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + { mbedtls_ecdsa_free( rs_ctx->ecdsa ); mbedtls_free( rs_ctx->ecdsa ); rs_ctx->ecdsa = NULL; @@ -357,7 +358,8 @@ static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, cleanup: /* clear our sub-context when not in progress (done or error) */ - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + { mbedtls_ecdsa_free( rs_ctx->ecdsa ); mbedtls_free( rs_ctx->ecdsa ); rs_ctx->ecdsa = NULL; From 171a481b9660a05d914d13c76754972d35a279b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 May 2017 17:23:37 +0200 Subject: [PATCH 068/148] Add a ChangeLog entry for changes so far --- ChangeLog | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ChangeLog b/ChangeLog index 55cccd5e6..a377bbb7c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ mbed TLS ChangeLog (Sorted per branch, date) += mbed TLS 2.y.0 released YYYY-MM-DD + +Features + * Add support for restartable ECC operations, controlled by + MBEDTLS_ECP_RESTARTABLE (disabled by default), using new xxx_restartable + functions in ECP, ECDSA, PK, and using existing functions in ECDH. + = mbed TLS x.x.x branch released xxxx-xx-xx Security From b3c8307960255a2d27788d0c40f118681bbb38b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 May 2017 08:50:24 +0200 Subject: [PATCH 069/148] Adapt ssl_client2 to restartable EC --- programs/ssl/ssl_client2.c | 43 +++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 5032a9f3d..84ce115cd 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -79,6 +79,7 @@ int main( void ) #define DFL_PSK "" #define DFL_PSK_IDENTITY "Client_identity" #define DFL_ECJPAKE_PW NULL +#define DFL_EC_MAX_OPS -1 #define DFL_FORCE_CIPHER 0 #define DFL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION_DISABLED #define DFL_ALLOW_LEGACY -2 @@ -235,6 +236,13 @@ int main( void ) #define USAGE_ECJPAKE "" #endif +#if defined(MBEDTLS_ECP_RESTARTABLE) +#define USAGE_ECRESTART \ + " ec_max_ops=%%s default: library default (restart disabled)\n" +#else +#define USAGE_ECRESTART "" +#endif + #define USAGE \ "\n usage: ssl_client2 param=<>...\n" \ "\n acceptable parameters:\n" \ @@ -258,6 +266,7 @@ int main( void ) "\n" \ USAGE_PSK \ USAGE_ECJPAKE \ + USAGE_ECRESTART \ "\n" \ " allow_legacy=%%d default: (library default: no)\n" \ USAGE_RENEGO \ @@ -310,6 +319,7 @@ struct options const char *psk; /* the pre-shared key */ const char *psk_identity; /* the pre-shared key identity */ const char *ecjpake_pw; /* the EC J-PAKE password */ + int ec_max_ops; /* EC consecutive operations limit */ int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ int renegotiation; /* enable / disable renegotiation */ int allow_legacy; /* allow legacy renegotiation */ @@ -527,6 +537,7 @@ int main( int argc, char *argv[] ) opt.psk = DFL_PSK; opt.psk_identity = DFL_PSK_IDENTITY; opt.ecjpake_pw = DFL_ECJPAKE_PW; + opt.ec_max_ops = DFL_EC_MAX_OPS; opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; opt.renegotiation = DFL_RENEGOTIATION; opt.allow_legacy = DFL_ALLOW_LEGACY; @@ -619,6 +630,8 @@ int main( int argc, char *argv[] ) opt.psk_identity = q; else if( strcmp( p, "ecjpake_pw" ) == 0 ) opt.ecjpake_pw = q; + else if( strcmp( p, "ec_max_ops" ) == 0 ) + opt.ec_max_ops = atoi( q ); else if( strcmp( p, "force_ciphersuite" ) == 0 ) { opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q ); @@ -1374,6 +1387,11 @@ int main( int argc, char *argv[] ) mbedtls_timing_get_delay ); #endif +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( opt.ec_max_ops != DFL_EC_MAX_OPS ) + mbedtls_ecp_set_max_ops( opt.ec_max_ops ); +#endif + mbedtls_printf( " ok\n" ); /* @@ -1384,7 +1402,9 @@ int main( int argc, char *argv[] ) while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) { - if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret ); if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) @@ -1476,7 +1496,8 @@ int main( int argc, char *argv[] ) while( ( ret = mbedtls_ssl_renegotiate( &ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret ); goto exit; @@ -1528,7 +1549,8 @@ send_request: <= 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret ); goto exit; @@ -1540,7 +1562,8 @@ send_request: { do ret = mbedtls_ssl_write( &ssl, buf, len ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || - ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + ret == MBEDTLS_ERR_SSL_WANT_WRITE || + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); if( ret < 0 ) { @@ -1573,7 +1596,8 @@ send_request: ret = mbedtls_ssl_read( &ssl, buf, len ); if( ret == MBEDTLS_ERR_SSL_WANT_READ || - ret == MBEDTLS_ERR_SSL_WANT_WRITE ) + ret == MBEDTLS_ERR_SSL_WANT_WRITE || + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) continue; if( ret <= 0 ) @@ -1618,7 +1642,8 @@ send_request: do ret = mbedtls_ssl_read( &ssl, buf, len ); while( ret == MBEDTLS_ERR_SSL_WANT_READ || - ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + ret == MBEDTLS_ERR_SSL_WANT_WRITE || + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); if( ret <= 0 ) { @@ -1666,7 +1691,8 @@ send_request: while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); goto exit; @@ -1749,7 +1775,8 @@ reconnect: while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && - ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); goto exit; From 2350b4ebdc20816df2b6fcfa7f88f75c20795eee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 May 2017 09:26:48 +0200 Subject: [PATCH 070/148] Adapt ECDHE_ECDSA key exchange to restartable EC For now some other key exchanges (ECDHE_PSK) will just fail to work, this will be either fixed or properly fixed later. --- include/mbedtls/ssl_internal.h | 16 +++++++++++++ library/ssl_cli.c | 16 +++++++++++++ tests/ssl-opt.sh | 42 ++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 756360b18..20e443630 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -88,6 +88,14 @@ #endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +/* Shorthand for restartable */ +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + defined(MBEDTLS_SSL_CLI_C) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) +#define MBEDTLS_SSL__ECP_RESTARTABLE +#endif + #define MBEDTLS_SSL_INITIAL_HANDSHAKE 0 #define MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS 1 /* In progress */ #define MBEDTLS_SSL_RENEGOTIATION_DONE 2 /* Done or aborted */ @@ -218,6 +226,14 @@ struct mbedtls_ssl_handshake_params mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */ #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + enum { + ssl_ecrs_init = 0, /*!< just getting started */ + ssl_ecrs_ecdh_public_done, /*!< wrote ECDHE public share */ + ssl_ecrs_ecdh_completed, /*!< completed ECDHE key exchange */ + } ecrs_state; /*!< state for restartable ECC */ + size_t ecrs_n; /*!< place for seving a length */ +#endif #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ unsigned int in_msg_seq; /*!< Incoming handshake sequence number */ diff --git a/library/ssl_cli.c b/library/ssl_cli.c index a2b9f8cfe..8d7bc45ce 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2861,6 +2861,11 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) */ i = 4; +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_state == ssl_ecrs_ecdh_public_done ) + goto ecdh_calc_secret; +#endif + ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, &n, &ssl->out_msg[i], 1000, @@ -2873,6 +2878,13 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + ssl->handshake->ecrs_n = n; + ssl->handshake->ecrs_state++; + +ecdh_calc_secret: + n = ssl->handshake->ecrs_n; +#endif if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &ssl->handshake->pmslen, ssl->handshake->premaster, @@ -2884,6 +2896,10 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) } MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + ssl->handshake->ecrs_state++; +#endif } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 280fc6348..05e882249 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -3441,6 +3441,48 @@ run_test "Large packet TLS 1.2 AEAD shorter tag" \ 0 \ -s "Read from client: 16384 bytes read" +# Tests for restartable ECC + +requires_config_enabled MBEDTLS_ECP_RESTARTABLE +run_test "EC restart: TLS, default" \ + "$P_SRV" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + debug_level=1" \ + 0 \ + -C "mbedtls_ecdh_make_public.*4b80" + +requires_config_enabled MBEDTLS_ECP_RESTARTABLE +run_test "EC restart: TLS, max_ops=0" \ + "$P_SRV" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + debug_level=1 ec_max_ops=0" \ + 0 \ + -C "mbedtls_ecdh_make_public.*4b80" + +requires_config_enabled MBEDTLS_ECP_RESTARTABLE +run_test "EC restart: TLS, max_ops=65535" \ + "$P_SRV" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + debug_level=1 ec_max_ops=65535" \ + 0 \ + -C "mbedtls_ecdh_make_public.*4b80" + +requires_config_enabled MBEDTLS_ECP_RESTARTABLE +run_test "EC restart: TLS, max_ops=1000" \ + "$P_SRV" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + debug_level=1 ec_max_ops=1000" \ + 0 \ + -c "mbedtls_ecdh_make_public.*4b80" + +requires_config_enabled MBEDTLS_ECP_RESTARTABLE +run_test "EC restart: DTLS, max_ops=1000" \ + "$P_SRV dtls=1" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + dtls=1 debug_level=1 ec_max_ops=1000" \ + 0 \ + -c "mbedtls_ecdh_make_public.*4b80" + # Tests for DTLS HelloVerifyRequest run_test "DTLS cookie: enabled" \ From 862cde5b8e728c78e52767b642d6783e22ec3dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 17 May 2017 11:56:15 +0200 Subject: [PATCH 071/148] Add restart support for ECDSA client auth --- include/mbedtls/ssl_internal.h | 6 +++++- library/ssl_cli.c | 34 +++++++++++++++++++++++++++++++--- library/ssl_tls.c | 8 ++++++++ tests/ssl-opt.sh | 30 ++++++++++++++++++++---------- 4 files changed, 64 insertions(+), 14 deletions(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 20e443630..af8728d5c 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -88,7 +88,7 @@ #endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -/* Shorthand for restartable */ +/* Shorthand for restartable ECC */ #if defined(MBEDTLS_ECP_RESTARTABLE) && \ defined(MBEDTLS_SSL_CLI_C) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ @@ -227,10 +227,14 @@ struct mbedtls_ssl_handshake_params #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + int ec_restart_enabled; /*!< Handshake supports EC restart? */ + mbedtls_ecdsa_restart_ctx rs_ctx; /*!< ECDSA restart context */ enum { ssl_ecrs_init = 0, /*!< just getting started */ ssl_ecrs_ecdh_public_done, /*!< wrote ECDHE public share */ ssl_ecrs_ecdh_completed, /*!< completed ECDHE key exchange */ + ssl_ecrs_keys_derived, /*!< ssl_derive_keys() done */ + ssl_ecrs_pk_sign_done, /*!< done writing CertificateVerify */ } ecrs_state; /*!< state for restartable ECC */ size_t ecrs_n; /*!< place for seving a length */ #endif diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 8d7bc45ce..77d376beb 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -1715,6 +1715,14 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) } } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ssl->handshake->ec_restart_enabled = 1; + } +#endif + if( comp != MBEDTLS_SSL_COMPRESS_NULL #if defined(MBEDTLS_ZLIB_SUPPORT) && comp != MBEDTLS_SSL_COMPRESS_DEFLATE @@ -3114,15 +3122,26 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) unsigned char *hash_start = hash; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; unsigned int hashlen; + void *rs_ctx = NULL; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_state == ssl_ecrs_keys_derived ) + goto keys_derived; +#endif + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); return( ret ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + ssl->handshake->ecrs_state++; + +keys_derived: +#endif if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || @@ -3226,14 +3245,24 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ec_restart_enabled ) + rs_ctx = &ssl->handshake->rs_ctx; +#endif + + if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), + md_alg, hash_start, hashlen, ssl->out_msg + 6 + offset, &n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); return( ret ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + ssl->handshake->ecrs_state++; +#endif + ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); ssl->out_msg[5 + offset] = (unsigned char)( n ); @@ -3242,7 +3271,6 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 661ae7065..50222c375 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -5472,6 +5472,10 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) #endif #endif +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + mbedtls_ecdsa_restart_init( &handshake->rs_ctx ); +#endif + #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; #endif @@ -7304,6 +7308,10 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) } #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + mbedtls_ecdsa_restart_free( &handshake->rs_ctx ); +#endif + #if defined(MBEDTLS_SSL_PROTO_DTLS) mbedtls_free( handshake->verify_cookie ); mbedtls_free( handshake->hs_msg ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 05e882249..b960df099 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -3445,43 +3445,53 @@ run_test "Large packet TLS 1.2 AEAD shorter tag" \ requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, default" \ - "$P_SRV" \ + "$P_SRV auth_mode=required" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1" \ 0 \ - -C "mbedtls_ecdh_make_public.*4b80" + -C "mbedtls_ecdh_make_public.*4b80" \ + -C "mbedtls_pk_sign.*4b80" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=0" \ - "$P_SRV" \ + "$P_SRV auth_mode=required" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=0" \ 0 \ - -C "mbedtls_ecdh_make_public.*4b80" + -C "mbedtls_ecdh_make_public.*4b80" \ + -C "mbedtls_pk_sign.*4b80" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=65535" \ - "$P_SRV" \ + "$P_SRV auth_mode=required" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=65535" \ 0 \ - -C "mbedtls_ecdh_make_public.*4b80" + -C "mbedtls_ecdh_make_public.*4b80" \ + -C "mbedtls_pk_sign.*4b80" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=1000" \ - "$P_SRV" \ + "$P_SRV auth_mode=required" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=1000" \ 0 \ - -c "mbedtls_ecdh_make_public.*4b80" + -c "mbedtls_ecdh_make_public.*4b80" \ + -c "mbedtls_pk_sign.*4b80" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: DTLS, max_ops=1000" \ - "$P_SRV dtls=1" \ + "$P_SRV auth_mode=required dtls=1" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ dtls=1 debug_level=1 ec_max_ops=1000" \ 0 \ - -c "mbedtls_ecdh_make_public.*4b80" + -c "mbedtls_ecdh_make_public.*4b80" \ + -c "mbedtls_pk_sign.*4b80" # Tests for DTLS HelloVerifyRequest From 1f1f2a1ca67b861c062587e3dbeef0bcfc819d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 18 May 2017 11:27:06 +0200 Subject: [PATCH 072/148] Adapt ServerKeyEchange processing to restart --- include/mbedtls/ssl_internal.h | 2 ++ library/ssl_cli.c | 40 ++++++++++++++++++++++++++++++---- tests/ssl-opt.sh | 5 +++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index af8728d5c..51dd4e1df 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -231,6 +231,8 @@ struct mbedtls_ssl_handshake_params mbedtls_ecdsa_restart_ctx rs_ctx; /*!< ECDSA restart context */ enum { ssl_ecrs_init = 0, /*!< just getting started */ + ssl_ecrs_ske_read, /*!< ServerKeyExchange was read */ + ssl_ecrs_ske_verified, /*!< ServerKeyExchange was verified */ ssl_ecrs_ecdh_public_done, /*!< wrote ECDHE public share */ ssl_ecrs_ecdh_completed, /*!< completed ECDHE key exchange */ ssl_ecrs_keys_derived, /*!< ssl_derive_keys() done */ diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 77d376beb..faaedb7f3 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -1697,6 +1697,14 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 3, ( "server hello, chosen ciphersuite: %s", suite_info->name ) ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ssl->handshake->ec_restart_enabled = 1; + } +#endif + i = 0; while( 1 ) { @@ -2303,12 +2311,22 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED || MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_state == ssl_ecrs_ske_read ) + goto ske_process; +#endif + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); return( ret ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + ssl->handshake->ecrs_state++; + +ske_process: +#endif if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); @@ -2432,6 +2450,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; unsigned char *params = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); size_t params_len = p - params; + void *rs_ctx = NULL; /* * Handle the digitally-signed structure @@ -2598,14 +2617,27 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH ); } - if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk, - md_alg, hash, hashlen, p, sig_len ) ) != 0 ) +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ec_restart_enabled ) + rs_ctx = &ssl->handshake->rs_ctx; +#endif + + if( ( ret = mbedtls_pk_verify_restartable( + &ssl->session_negotiate->peer_cert->pk, + md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 ) { - mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, - MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) +#endif + mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, + MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); return( ret ); } + +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + ssl->handshake->ecrs_state++; +#endif } #endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index b960df099..d1ad9bfc3 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -3450,6 +3450,7 @@ run_test "EC restart: TLS, default" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1" \ 0 \ + -C "mbedtls_pk_verify.*4b80" \ -C "mbedtls_ecdh_make_public.*4b80" \ -C "mbedtls_pk_sign.*4b80" @@ -3460,6 +3461,7 @@ run_test "EC restart: TLS, max_ops=0" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=0" \ 0 \ + -C "mbedtls_pk_verify.*4b80" \ -C "mbedtls_ecdh_make_public.*4b80" \ -C "mbedtls_pk_sign.*4b80" @@ -3470,6 +3472,7 @@ run_test "EC restart: TLS, max_ops=65535" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=65535" \ 0 \ + -C "mbedtls_pk_verify.*4b80" \ -C "mbedtls_ecdh_make_public.*4b80" \ -C "mbedtls_pk_sign.*4b80" @@ -3480,6 +3483,7 @@ run_test "EC restart: TLS, max_ops=1000" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=1000" \ 0 \ + -c "mbedtls_pk_verify.*4b80" \ -c "mbedtls_ecdh_make_public.*4b80" \ -c "mbedtls_pk_sign.*4b80" @@ -3490,6 +3494,7 @@ run_test "EC restart: DTLS, max_ops=1000" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ dtls=1 debug_level=1 ec_max_ops=1000" \ 0 \ + -c "mbedtls_pk_verify.*4b80" \ -c "mbedtls_ecdh_make_public.*4b80" \ -c "mbedtls_pk_sign.*4b80" From 23e416261c5dd1e7cb43db5c8c6766af56509d3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 18 May 2017 12:35:37 +0200 Subject: [PATCH 073/148] ECDH: not restartable unless explicitly enabled This is mainly for the benefit of SSL modules, which only supports restart in a limited number of cases. In the other cases (ECDHE_PSK) it would currently return ERR_ECP_IN_PROGRESS and the user would thus call ssl_handshake() again, but the SSL code wouldn't handle state properly and things would go wrong in possibly unexpected ways. This is undesirable, so it should be possible for the SSL module to choose if ECDHE should behave the old or the new way. Not that it also brings ECDHE more in line with the other modules which already have that choice available (by passing a NULL or valid restart context). --- include/mbedtls/ecdh.h | 17 ++++++++++++++ library/ecdh.c | 19 +++++++++++++--- library/ssl_cli.c | 3 +++ tests/suites/test_suite_ecdh.data | 32 ++++++++++++++++++++------- tests/suites/test_suite_ecdh.function | 9 +++++++- 5 files changed, 68 insertions(+), 12 deletions(-) diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h index 2e344a8c9..6f3fe137c 100644 --- a/include/mbedtls/ecdh.h +++ b/include/mbedtls/ecdh.h @@ -53,6 +53,7 @@ typedef struct mbedtls_ecp_point Vf; /*!< un-blinding value (for later) */ mbedtls_mpi _d; /*!< previous d (for later) */ #if defined(MBEDTLS_ECP_RESTARTABLE) + int restart_enabled; /*!< enable restartalbe EC computations? */ mbedtls_ecp_restart_ctx rs; /*!< restart context for EC computations */ #endif } @@ -220,6 +221,22 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Enable restartable EC computations for this context. + * (Default: disabled.) + * + * \sa \c mbedtls_ecp_set_max_ops() + * + * \note It is not possible to safely disable restartable + * computations once enabled, except by free-ing the context, + * which cancels possible in-progress operations. + * + * \param ctx ECDH context + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + #ifdef __cplusplus } #endif diff --git a/library/ecdh.c b/library/ecdh.c index b2859c4b6..cae3b290f 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -155,6 +155,16 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) #endif } +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Enable restartable operations for context + */ +void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) +{ + ctx->restart_enabled = 1; +} +#endif + /* * Setup and write the ServerKeyExhange parameters (RFC 4492) * struct { @@ -175,7 +185,8 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); #if defined(MBEDTLS_ECP_RESTARTABLE) - rs_ctx = &ctx->rs; + if( ctx->restart_enabled ) + rs_ctx = &ctx->rs; #endif if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, @@ -260,7 +271,8 @@ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); #if defined(MBEDTLS_ECP_RESTARTABLE) - rs_ctx = &ctx->rs; + if( ctx->restart_enabled ) + rs_ctx = &ctx->rs; #endif if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, @@ -307,7 +319,8 @@ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); #if defined(MBEDTLS_ECP_RESTARTABLE) - rs_ctx = &ctx->rs; + if( ctx->restart_enabled ) + rs_ctx = &ctx->rs; #endif if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, diff --git a/library/ssl_cli.c b/library/ssl_cli.c index faaedb7f3..cbd46475c 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2902,6 +2902,9 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) i = 4; #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ec_restart_enabled) + mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); + if( ssl->handshake->ecrs_state == ssl_ecrs_ecdh_public_done ) goto ecdh_calc_secret; #endif diff --git a/tests/suites/test_suite_ecdh.data b/tests/suites/test_suite_ecdh.data index 991d11388..da30633ac 100644 --- a/tests/suites/test_suite_ecdh.data +++ b/tests/suites/test_suite_ecdh.data @@ -38,18 +38,34 @@ ECDH exchange #2 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED ecdh_exchange:MBEDTLS_ECP_DP_SECP521R1 -ECDH restartable rfc 5903 p256 restart disabled +ECDH restartable rfc 5903 p256 restart enabled max_ops=0 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED -ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:0:0 +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:0:0:0 -ECDH restartable rfc 5903 p256 restart max_ops=1 +ECDH restartable rfc 5903 p256 restart enabled max_ops=1 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED -ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:1:10000 +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:1:1:10000 -ECDH restartable rfc 5903 p256 restart max_ops=10000 +ECDH restartable rfc 5903 p256 restart enabled max_ops=10000 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED -ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":10000:0:0 +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:10000:0:0 -ECDH restartable rfc 5903 p256 restart max_ops=250 +ECDH restartable rfc 5903 p256 restart enabled max_ops=250 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED -ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":250:2:32 +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:250:2:32 + +ECDH restartable rfc 5903 p256 restart disabled max_ops=0 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:0:0:0 + +ECDH restartable rfc 5903 p256 restart disabled max_ops=1 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:1:0:0 + +ECDH restartable rfc 5903 p256 restart disabled max_ops=10000 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:10000:0:0 + +ECDH restartable rfc 5903 p256 restart disabled max_ops=250 +depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED +ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:250:0:0 diff --git a/tests/suites/test_suite_ecdh.function b/tests/suites/test_suite_ecdh.function index 911464ad0..05e61e4eb 100644 --- a/tests/suites/test_suite_ecdh.function +++ b/tests/suites/test_suite_ecdh.function @@ -161,7 +161,7 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */ void ecdh_restart( int id, char *dA_str, char *dB_str, char *z_str, - int max_ops, int min_restart, int max_restart ) + int enable, int max_ops, int min_restart, int max_restart ) { int ret; mbedtls_ecdh_context srv, cli; @@ -192,8 +192,15 @@ void ecdh_restart( int id, char *dA_str, char *dB_str, char *z_str, * as in ecdh_primitive_test_vec */ TEST_ASSERT( srv.grp.nbits % 8 == 0 ); + /* set up restart parameters */ mbedtls_ecp_set_max_ops( max_ops ); + if( enable) + { + mbedtls_ecdh_enable_restart( &srv ); + mbedtls_ecdh_enable_restart( &cli ); + } + /* server writes its paramaters */ memset( buf, 0x00, sizeof( buf ) ); len = 0; From 32033da127e64d9035eb2b3170604e55098477d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 18 May 2017 12:49:27 +0200 Subject: [PATCH 074/148] Test some more handshake flows --- tests/ssl-opt.sh | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index d1ad9bfc3..2e03758e6 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -3498,6 +3498,26 @@ run_test "EC restart: DTLS, max_ops=1000" \ -c "mbedtls_ecdh_make_public.*4b80" \ -c "mbedtls_pk_sign.*4b80" +requires_config_enabled MBEDTLS_ECP_RESTARTABLE +run_test "EC restart: TLS, max_ops=1000 no client auth" \ + "$P_SRV" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + debug_level=1 ec_max_ops=1000" \ + 0 \ + -c "mbedtls_pk_verify.*4b80" \ + -c "mbedtls_ecdh_make_public.*4b80" \ + -C "mbedtls_pk_sign.*4b80" + +requires_config_enabled MBEDTLS_ECP_RESTARTABLE +run_test "EC restart: TLS, max_ops=1000, ECDHE-PSK" \ + "$P_SRV psk=abc123" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 \ + psk=abc123 debug_level=1 ec_max_ops=1000" \ + 0 \ + -C "mbedtls_pk_verify.*4b80" \ + -C "mbedtls_ecdh_make_public.*4b80" \ + -C "mbedtls_pk_sign.*4b80" + # Tests for DTLS HelloVerifyRequest run_test "DTLS cookie: enabled" \ From 21b7719fb2578dd4edf8d5b57c603e06c12f32c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 18 May 2017 12:54:56 +0200 Subject: [PATCH 075/148] Add ChangeLog entry for current progress --- ChangeLog | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index a377bbb7c..b80f53a25 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,9 +3,16 @@ mbed TLS ChangeLog (Sorted per branch, date) = mbed TLS 2.y.0 released YYYY-MM-DD Features - * Add support for restartable ECC operations, controlled by - MBEDTLS_ECP_RESTARTABLE (disabled by default), using new xxx_restartable - functions in ECP, ECDSA, PK, and using existing functions in ECDH. + * Add support for restartable ECC operations, enabled by + MBEDTLS_ECP_RESTARTABLE (disabled by default) at compile time and + mbedtls_ecp_set_max_ops() at runtime, using new xxx_restartable functions + in ECP, ECDSA, PK, and using existing functions in ECDH and SSL + (currently only implemented client-side, for ECDHE-ECDSA ciphersuites + with TLS 1.2, including client authentication). + TEMPORARY NOTE: server authentication currently not supported (WIP). + For now, MUST be disabled by calling + mbedtls_ssl_conf_authmode( MBEDTLS_SSL_VERIFY_NONE ) + (or blocking ECC operations will happen) = mbed TLS x.x.x branch released xxxx-xx-xx From bc3f44ae9c0f2615cc35e7b92cd6faf871e74a68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 11 Jul 2017 11:02:20 +0200 Subject: [PATCH 076/148] Introduce mbedtls_x509_crt_verify_restartable() --- include/mbedtls/x509_crt.h | 60 ++++++++++++++++++++++++++++++++++++ library/x509_crt.c | 62 +++++++++++++++++++++++++++++++------- 2 files changed, 111 insertions(+), 11 deletions(-) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 2b4d3533f..61a912459 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -142,6 +142,23 @@ typedef struct mbedtls_x509write_cert } mbedtls_x509write_cert; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + +/** + * \brief Context for resuming X.509 verify operations + */ +typedef struct +{ + mbedtls_ecdsa_restart_ctx ecdsa; /*!< ecdsa restart context */ +} mbedtls_x509_crt_restart_ctx; + +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_x509_crt_restart_ctx; + +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + #if defined(MBEDTLS_X509_CRT_PARSE_C) /** * Default security profile. Should provide a good balance between security @@ -352,6 +369,37 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ); +/** + * \brief Restartable version of \c mbedtls_crt_verify_with_profile() + * + * \note Performs the same job as \c mbedtls_crt_verify_with_profile() + * but can return early and restart according to the limit + * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * \param rs_ctx resart context + * + * \return See \c mbedtls_crt_verify_with_profile(), or + * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ); + #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) /** * \brief Check usage of certificate against keyUsage extension. @@ -422,6 +470,18 @@ void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); * \param crt Certificate chain to free */ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ /* \} name */ diff --git a/library/x509_crt.c b/library/x509_crt.c index f586fb452..8d5d06058 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2271,7 +2271,7 @@ static int x509_crt_merge_flags_with_cb( } /* - * Verify the certificate validity + * Verify the certificate validity (default profile, not restartable) */ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, @@ -2280,19 +2280,13 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, - &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); + return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, + &mbedtls_x509_crt_profile_default, cn, flags, + f_vrfy, p_vrfy, NULL ) ); } /* - * Verify the certificate validity, with profile - * - * This function: - * - checks the requested CN (if any) - * - checks the type and size of the EE cert's key, - * as that isn't done as part of chain building/verification currently - * - builds and verifies the chain - * - then calls the callback and merges the flags + * Verify the certificate validity (user-chosen profile, not restartable) */ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, @@ -2301,6 +2295,29 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, + profile, cn, flags, f_vrfy, p_vrfy, NULL ) ); +} + +/* + * Verify the certificate validity, with profile, restartable version + * + * This function: + * - checks the requested CN (if any) + * - checks the type and size of the EE cert's key, + * as that isn't done as part of chain building/verification currently + * - builds and verifies the chain + * - then calls the callback and merges the flags + */ +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { int ret; mbedtls_pk_type_t pk_type; @@ -2308,6 +2325,8 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, size_t chain_len; uint32_t *ee_flags = &ver_chain[0].flags; + (void) rs_ctx; + *flags = 0; memset( ver_chain, 0, sizeof( ver_chain ) ); chain_len = 0; @@ -2450,4 +2469,25 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) while( cert_cur != NULL ); } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) +{ + mbedtls_ecdsa_restart_init( &ctx->ecdsa ); +} + +/* + * Free the components of a restart context + */ +void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecdsa_restart_free( &ctx->ecdsa ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + #endif /* MBEDTLS_X509_CRT_PARSE_C */ From d19a41d9aaaa09fffe2ed7ace061e204a37a97fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 14 Jul 2017 11:05:59 +0200 Subject: [PATCH 077/148] Add tests for verify_restartable() For selection of test cases, see comments added in the commit. It makes the most sense to test with chains using ECC only, so for the chain of length 2 we use server10 -> int-ca3 -> int-ca2 and trust int-ca2 directly. Note: server10.crt was created by copying server10_int3_int-ca2.crt and manually truncating it to remove the intermediates. That base can now be used to create derived certs (without or with a chain) in a programmatic way. --- library/x509_crt.c | 10 +++++ tests/data_files/Makefile | 15 ++++++- tests/data_files/Readme-x509.txt | 1 + tests/data_files/server10-badsign.crt | 10 +++++ tests/data_files/server10-bs_int3.pem | 22 +++++++++++ tests/data_files/server10.crt | 10 +++++ tests/data_files/server10_int3-bs.pem | 22 +++++++++++ tests/data_files/test-int-ca3-badsign.crt | 12 ++++++ tests/suites/test_suite_x509parse.data | 23 +++++++++++ tests/suites/test_suite_x509parse.function | 46 ++++++++++++++++++++++ 10 files changed, 169 insertions(+), 2 deletions(-) create mode 100644 tests/data_files/server10-badsign.crt create mode 100644 tests/data_files/server10-bs_int3.pem create mode 100644 tests/data_files/server10.crt create mode 100644 tests/data_files/server10_int3-bs.pem create mode 100644 tests/data_files/test-int-ca3-badsign.crt diff --git a/library/x509_crt.c b/library/x509_crt.c index 8d5d06058..4e3296466 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2069,6 +2069,16 @@ static int x509_crt_check_ee_locally_trusted( * - EE, Ci1, ..., Ciq cannot be continued with a trusted root * -> return that chain with NOT_TRUSTED set on Ciq * + * Tests for (aspects of) this function should include at least: + * - trusted EE + * - EE -> trusted root + * - EE -> intermedate CA -> trusted root + * - if relevant: EE untrusted + * - if relevant: EE -> intermediate, untrusted + * with the aspect under test checked at each relevant level (EE, int, root). + * For some aspects longer chains are required, but usually length 2 is + * enough (but length 1 is not in general). + * * Arguments: * - [in] crt: the cert list EE, C1, ..., Cn * - [in] trust_ca: the trusted list R1, ..., Rp diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile index 40cbcbe4d..05d7d23ff 100644 --- a/tests/data_files/Makefile +++ b/tests/data_files/Makefile @@ -104,7 +104,7 @@ server7-future.crt: server7.csr $(test_ca_int_rsa1) $(FAKETIME) -f +3653d $(OPENSSL) x509 -req -extfile $(cli_crt_extensions_file) -extensions cli-rsa -CA $(test_ca_int_rsa1) -CAkey test-int-ca.key -set_serial 16 -days 3653 -sha256 -in server7.csr | cat - $(test_ca_int_rsa1) > $@ all_final += server7-future.crt server7-badsign.crt: server7.crt $(test_ca_int_rsa1) - { head -n-2 server7.crt; tail -n-2 server7.crt | sed -e '1s/0\(=*\)$$/_\1/' -e '1s/[^_=]\(=*\)$$/0\1/' -e '1s/_/1/'; cat test-int-ca.crt; } > server7-badsign.crt + { head -n-2 $<; tail -n-2 $< | sed -e '1s/0\(=*\)$$/_\1/' -e '1s/[^_=]\(=*\)$$/0\1/' -e '1s/_/1/'; cat $(test_ca_int_rsa1); } > $@ all_final += server7-badsign.crt server7_int-ca-exp.crt: server7.crt test-int-ca-exp.crt cat server7.crt test-int-ca-exp.crt > $@ @@ -119,7 +119,18 @@ server5-ss-forgeca.crt: server5.key $(FAKETIME) '2015-09-01 14:08:43' $(OPENSSL) req -x509 -new -subj "/C=UK/O=mbed TLS/CN=mbed TLS Test intermediate CA 3" -set_serial 77 -config $(test_ca_config_file) -extensions noext_ca -days 3650 -sha256 -key $< -out $@ all_final += server5-ss-forgeca.crt - +server10-badsign.crt: server10.crt + { head -n-2 $<; tail -n-2 $< | sed -e '1s/0\(=*\)$$/_\1/' -e '1s/[^_=]\(=*\)$$/0\1/' -e '1s/_/1/'; } > $@ +all_final += server10-badsign.crt +server10-bs_int3.pem: server10-badsign.crt test-int-ca3.crt + cat server10-badsign.crt test-int-ca3.crt > $@ +all_final += server10-bs_int3.pem +test-int-ca3-badsign.crt: test-int-ca3.crt + { head -n-2 $<; tail -n-2 $< | sed -e '1s/0\(=*\)$$/_\1/' -e '1s/[^_=]\(=*\)$$/0\1/' -e '1s/_/1/'; } > $@ +all_final += test-int-ca3-badsign.crt +server10_int3-bs.pem: server10.crt test-int-ca3-badsign.crt + cat server10.crt test-int-ca3-badsign.crt > $@ +all_final += server10-bs_int3-bs.pem ################################################################ diff --git a/tests/data_files/Readme-x509.txt b/tests/data_files/Readme-x509.txt index b56346ab3..d1a6c2d27 100644 --- a/tests/data_files/Readme-x509.txt +++ b/tests/data_files/Readme-x509.txt @@ -21,6 +21,7 @@ Two intermediate CAs are signed by them: A third intermediate CA is signed by test-int-ca2.crt: - test-int-ca3.crt "C=UK, O=mbed TLS, CN=mbed TLS Test intermediate CA 3" + uses an EC key with NIST P-256, signed by test-int-ca2 Finally, other CAs for specific purposes: - enco-ca-prstr.pem: has its CN encoded as a printable string, but child cert diff --git a/tests/data_files/server10-badsign.crt b/tests/data_files/server10-badsign.crt new file mode 100644 index 000000000..eca171f35 --- /dev/null +++ b/tests/data_files/server10-badsign.crt @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBWjCCAQCgAwIBAgIBSzAKBggqhkjOPQQDAjBKMQswCQYDVQQGEwJVSzERMA8G +A1UEChMIbWJlZCBUTFMxKDAmBgNVBAMTH21iZWQgVExTIFRlc3QgaW50ZXJtZWRp +YXRlIENBIDMwHhcNMTUwOTAxMTM0NzU1WhcNMjUwODI5MTM0NzU1WjAUMRIwEAYD +VQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQcbffp2qXq +oZyychmoCRxzrd4Vu96m47NPBehtEC46aTeXgDnBdf++znABrAtfXBRNQz8ARIeY +Bmskr22rlKjyow0wCzAJBgNVHRMEAjAAMAoGCCqGSM49BAMCA0gAMEUCIQDLc+Io +rg8VxEbCgVv8iH+kOIEn9MjhpvKzvwUoV+6rjQIgZU/RXAyc1a+H2+soGfNEIOBQ +AzO3pJx7WJAApZuBX10= +-----END CERTIFICATE----- diff --git a/tests/data_files/server10-bs_int3.pem b/tests/data_files/server10-bs_int3.pem new file mode 100644 index 000000000..b84cee7c3 --- /dev/null +++ b/tests/data_files/server10-bs_int3.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIBWjCCAQCgAwIBAgIBSzAKBggqhkjOPQQDAjBKMQswCQYDVQQGEwJVSzERMA8G +A1UEChMIbWJlZCBUTFMxKDAmBgNVBAMTH21iZWQgVExTIFRlc3QgaW50ZXJtZWRp +YXRlIENBIDMwHhcNMTUwOTAxMTM0NzU1WhcNMjUwODI5MTM0NzU1WjAUMRIwEAYD +VQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQcbffp2qXq +oZyychmoCRxzrd4Vu96m47NPBehtEC46aTeXgDnBdf++znABrAtfXBRNQz8ARIeY +Bmskr22rlKjyow0wCzAJBgNVHRMEAjAAMAoGCCqGSM49BAMCA0gAMEUCIQDLc+Io +rg8VxEbCgVv8iH+kOIEn9MjhpvKzvwUoV+6rjQIgZU/RXAyc1a+H2+soGfNEIOBQ +AzO3pJx7WJAApZuBX10= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIBtDCCATqgAwIBAgIBTTAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJOTDERMA8G +A1UEChMIUG9sYXJTU0wxKTAnBgNVBAMTIFBvbGFyU1NMIFRlc3QgSW50ZXJtZWRp +YXRlIEVDIENBMB4XDTE1MDkwMTE0MDg0M1oXDTI1MDgyOTE0MDg0M1owSjELMAkG +A1UEBhMCVUsxETAPBgNVBAoTCG1iZWQgVExTMSgwJgYDVQQDEx9tYmVkIFRMUyBU +ZXN0IGludGVybWVkaWF0ZSBDQSAzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +732fWHLNPMPsP1U1ibXvb55erlEVMlpXBGsj+KYwVqU1XCmW9Z9hhP7X/5js/DX9 +2J/utoHyjUtVpQOzdTrbsaMQMA4wDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAgNo +ADBlAjAJRxbGRas3NBmk9MnGWXg7PT1xnRELHRWWIvfLdVQt06l1/xFg3ZuPdQdt +Qh7CK80CMQD7wa1o1a8qyDKBfLN636uKmKGga0E+vYXBeFCy9oARBangGCB0B2vt +pz590JvGWfM= +-----END CERTIFICATE----- diff --git a/tests/data_files/server10.crt b/tests/data_files/server10.crt new file mode 100644 index 000000000..96a4040ce --- /dev/null +++ b/tests/data_files/server10.crt @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE----- +MIIBWjCCAQCgAwIBAgIBSzAKBggqhkjOPQQDAjBKMQswCQYDVQQGEwJVSzERMA8G +A1UEChMIbWJlZCBUTFMxKDAmBgNVBAMTH21iZWQgVExTIFRlc3QgaW50ZXJtZWRp +YXRlIENBIDMwHhcNMTUwOTAxMTM0NzU1WhcNMjUwODI5MTM0NzU1WjAUMRIwEAYD +VQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQcbffp2qXq +oZyychmoCRxzrd4Vu96m47NPBehtEC46aTeXgDnBdf++znABrAtfXBRNQz8ARIeY +Bmskr22rlKjyow0wCzAJBgNVHRMEAjAAMAoGCCqGSM49BAMCA0gAMEUCIQDLc+Io +rg8VxEbCgVv8iH+kOIEn9MjhpvKzvwUoV+6rjQIgZU/RXAyc1a+H2+soGfNEIOBQ +AzO3pJx7WJAApZuBX1Q= +-----END CERTIFICATE----- diff --git a/tests/data_files/server10_int3-bs.pem b/tests/data_files/server10_int3-bs.pem new file mode 100644 index 000000000..a9e06150b --- /dev/null +++ b/tests/data_files/server10_int3-bs.pem @@ -0,0 +1,22 @@ +-----BEGIN CERTIFICATE----- +MIIBWjCCAQCgAwIBAgIBSzAKBggqhkjOPQQDAjBKMQswCQYDVQQGEwJVSzERMA8G +A1UEChMIbWJlZCBUTFMxKDAmBgNVBAMTH21iZWQgVExTIFRlc3QgaW50ZXJtZWRp +YXRlIENBIDMwHhcNMTUwOTAxMTM0NzU1WhcNMjUwODI5MTM0NzU1WjAUMRIwEAYD +VQQDEwlsb2NhbGhvc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQcbffp2qXq +oZyychmoCRxzrd4Vu96m47NPBehtEC46aTeXgDnBdf++znABrAtfXBRNQz8ARIeY +Bmskr22rlKjyow0wCzAJBgNVHRMEAjAAMAoGCCqGSM49BAMCA0gAMEUCIQDLc+Io +rg8VxEbCgVv8iH+kOIEn9MjhpvKzvwUoV+6rjQIgZU/RXAyc1a+H2+soGfNEIOBQ +AzO3pJx7WJAApZuBX1Q= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIBtDCCATqgAwIBAgIBTTAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJOTDERMA8G +A1UEChMIUG9sYXJTU0wxKTAnBgNVBAMTIFBvbGFyU1NMIFRlc3QgSW50ZXJtZWRp +YXRlIEVDIENBMB4XDTE1MDkwMTE0MDg0M1oXDTI1MDgyOTE0MDg0M1owSjELMAkG +A1UEBhMCVUsxETAPBgNVBAoTCG1iZWQgVExTMSgwJgYDVQQDEx9tYmVkIFRMUyBU +ZXN0IGludGVybWVkaWF0ZSBDQSAzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +732fWHLNPMPsP1U1ibXvb55erlEVMlpXBGsj+KYwVqU1XCmW9Z9hhP7X/5js/DX9 +2J/utoHyjUtVpQOzdTrbsaMQMA4wDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAgNo +ADBlAjAJRxbGRas3NBmk9MnGWXg7PT1xnRELHRWWIvfLdVQt06l1/xFg3ZuPdQdt +Qh7CK80CMQD7wa1o1a8qyDKBfLN636uKmKGga0E+vYXBeFCy9oARBangGCB0B2vt +pz590JvGWf0= +-----END CERTIFICATE----- diff --git a/tests/data_files/test-int-ca3-badsign.crt b/tests/data_files/test-int-ca3-badsign.crt new file mode 100644 index 000000000..2087056e8 --- /dev/null +++ b/tests/data_files/test-int-ca3-badsign.crt @@ -0,0 +1,12 @@ +-----BEGIN CERTIFICATE----- +MIIBtDCCATqgAwIBAgIBTTAKBggqhkjOPQQDAjBLMQswCQYDVQQGEwJOTDERMA8G +A1UEChMIUG9sYXJTU0wxKTAnBgNVBAMTIFBvbGFyU1NMIFRlc3QgSW50ZXJtZWRp +YXRlIEVDIENBMB4XDTE1MDkwMTE0MDg0M1oXDTI1MDgyOTE0MDg0M1owSjELMAkG +A1UEBhMCVUsxETAPBgNVBAoTCG1iZWQgVExTMSgwJgYDVQQDEx9tYmVkIFRMUyBU +ZXN0IGludGVybWVkaWF0ZSBDQSAzMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +732fWHLNPMPsP1U1ibXvb55erlEVMlpXBGsj+KYwVqU1XCmW9Z9hhP7X/5js/DX9 +2J/utoHyjUtVpQOzdTrbsaMQMA4wDAYDVR0TBAUwAwEB/zAKBggqhkjOPQQDAgNo +ADBlAjAJRxbGRas3NBmk9MnGWXg7PT1xnRELHRWWIvfLdVQt06l1/xFg3ZuPdQdt +Qh7CK80CMQD7wa1o1a8qyDKBfLN636uKmKGga0E+vYXBeFCy9oARBangGCB0B2vt +pz590JvGWf0= +-----END CERTIFICATE----- diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index afa86a1d8..b3e1c1cdf 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -1806,3 +1806,26 @@ X509 Get time (UTC invalid character in sec) depends_on:MBEDTLS_X509_USE_C x509_get_time:MBEDTLS_ASN1_UTC_TIME:"0011302359n0Z":MBEDTLS_ERR_X509_INVALID_DATE:0:0:0:0:0:0 +X509 cert verify restart: trusted EE, max_ops=0 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +x509_verify_restart:"data_files/server5-selfsigned.crt":"data_files/server5-selfsigned.crt":0:0:0:0:0 + +X509 cert verify restart: no intermediate, max_ops=0 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED +x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:0:0:0 + +X509 cert verify restart: no intermediate, badsign, max_ops=0 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED +x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0 + +X509 cert verify restart: one intermediate, max_ops=0 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:0:0:0 + +X509 cert verify restart: one intermediate, EE badsign, max_ops=0 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0 + +X509 cert verify restart: one intermediate, int badsign, max_ops=0 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10_int3-bs.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0 diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index b3b6f4dce..f899eb018 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -261,6 +261,52 @@ void x509_verify_info( int flags, char *prefix, char *result_str ) } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_X509_CRL_PARSE_C:MBEDTLS_ECP_RESTARTABLE:MBEDTLS_ECDSA_C */ +void x509_verify_restart( char *crt_file, char *ca_file, + int result, int flags_result, + int max_ops, int min_restart, int max_restart ) +{ + int ret, cnt_restart; + mbedtls_x509_crt_restart_ctx rs_ctx; + mbedtls_x509_crt crt; + mbedtls_x509_crt ca; + uint32_t flags = 0; + + mbedtls_x509_crt_restart_init( &rs_ctx ); + mbedtls_x509_crt_init( &crt ); + mbedtls_x509_crt_init( &ca ); + + TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 ); + TEST_ASSERT( mbedtls_x509_crt_parse_file( &ca, ca_file ) == 0 ); + + mbedtls_ecp_set_max_ops( max_ops ); + + cnt_restart = 0; + do { + ret = mbedtls_x509_crt_verify_restartable( &crt, &ca, NULL, + &mbedtls_x509_crt_profile_default, NULL, &flags, + NULL, NULL, &rs_ctx ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); + + TEST_ASSERT( ret == result ); + TEST_ASSERT( flags == (uint32_t) flags_result ); + + TEST_ASSERT( cnt_restart >= min_restart ); + TEST_ASSERT( cnt_restart <= max_restart ); + + /* Do we leak memory when aborting? */ + ret = mbedtls_x509_crt_verify_restartable( &crt, &ca, NULL, + &mbedtls_x509_crt_profile_default, NULL, &flags, + NULL, NULL, &rs_ctx ); + TEST_ASSERT( ret == result || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + +exit: + mbedtls_x509_crt_restart_free( &rs_ctx ); + mbedtls_x509_crt_free( &crt ); + mbedtls_x509_crt_free( &ca ); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_X509_CRL_PARSE_C */ void x509_verify( char *crt_file, char *ca_file, char *crl_file, char *cn_name_str, int result, int flags_result, From be4ff42fe4fafe91df1405831d75515a1b0ea786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 14 Jul 2017 12:04:14 +0200 Subject: [PATCH 078/148] Call crt_check_signature from one place only --- library/x509_crt.c | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 4e3296466..91c444876 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1932,6 +1932,7 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, * 1. subject name matches child's issuer * 2. if necessary, the CA bit is set and key usage allows signing certs * 3. for trusted roots, the signature is correct + * (for intermediates, the signature is checked and the result reported) * 4. pathlen constraints are satisfied * * If there's a suitable candidate which is also time-valid, return the first @@ -1953,11 +1954,15 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, */ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, mbedtls_x509_crt *candidates, + int *signature_is_good, int top, int path_cnt, int self_cnt ) { - mbedtls_x509_crt *parent, *badtime_parent = NULL; + mbedtls_x509_crt *parent, *fallback_parent = NULL; + int fallback_sign_good = 0; + + *signature_is_good = 0; for( parent = candidates; parent != NULL; parent = parent->next ) { @@ -1973,17 +1978,19 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, } /* Signature */ - if( top && x509_crt_check_signature( child, parent ) != 0 ) - { + *signature_is_good = x509_crt_check_signature( child, parent ) == 0; + if( top && ! *signature_is_good ) continue; - } /* optional time check */ if( mbedtls_x509_time_is_past( &parent->valid_to ) || mbedtls_x509_time_is_future( &parent->valid_from ) ) { - if( badtime_parent == NULL ) - badtime_parent = parent; + if( fallback_parent == NULL ) + { + fallback_parent = parent; + fallback_sign_good = *signature_is_good; + } continue; } @@ -1992,7 +1999,10 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, } if( parent == NULL ) - parent = badtime_parent; + { + parent = fallback_parent; + *signature_is_good = fallback_sign_good; + } return parent; } @@ -2006,6 +2016,7 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child, mbedtls_x509_crt *trust_ca, int *parent_is_trusted, + int *signature_is_good, int path_cnt, int self_cnt ) { @@ -2013,14 +2024,16 @@ static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child, /* Look for a parent in trusted CAs */ *parent_is_trusted = 1; - parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt ); + parent = x509_crt_find_parent_in( child, trust_ca, signature_is_good, + 1, path_cnt, self_cnt ); if( parent != NULL ) return parent; /* Look for a parent upwards the chain */ *parent_is_trusted = 0; - return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) ); + return( x509_crt_find_parent_in( child, child->next, signature_is_good, + 0, path_cnt, self_cnt ) ); } /* @@ -2103,6 +2116,7 @@ static int x509_crt_verify_chain( mbedtls_x509_crt *parent; int parent_is_trusted = 0; int child_is_trusted = 0; + int signature_is_good = 0; int self_cnt = 0; child = crt; @@ -2140,7 +2154,8 @@ static int x509_crt_verify_chain( } /* Look for a parent in trusted CAs or up the chain */ - parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted, + parent = x509_crt_find_parent( child, trust_ca, + &parent_is_trusted, &signature_is_good, *chain_len - 1, self_cnt ); /* No parent? We're done here */ @@ -2168,8 +2183,8 @@ static int x509_crt_verify_chain( return( MBEDTLS_ERR_X509_FATAL_ERROR ); } - /* if parent is trusted, the signature was checked by find_parent() */ - if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 ) + /* signature was check while searching parent */ + if( ! signature_is_good ) *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; /* check size of signing key */ @@ -2187,6 +2202,7 @@ static int x509_crt_verify_chain( child = parent; parent = NULL; child_is_trusted = parent_is_trusted; + signature_is_good = 0; } } From a4a5d1dbe65913fe826ef714066f3853eb14d824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 17 Jul 2017 10:26:19 +0200 Subject: [PATCH 079/148] Adapt function signatures to rs_ctx + ret --- library/x509_crt.c | 147 ++++++++++++++++++++++++++++++++------------- 1 file changed, 105 insertions(+), 42 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 91c444876..e8fb627d4 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1866,7 +1866,8 @@ static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b * Check the signature of a certificate by its parent */ static int x509_crt_check_signature( const mbedtls_x509_crt *child, - mbedtls_x509_crt *parent ) + mbedtls_x509_crt *parent, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { const mbedtls_md_info_t *md_info; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; @@ -1878,14 +1879,24 @@ static int x509_crt_check_signature( const mbedtls_x509_crt *child, return( -1 ); } - if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, - child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len ) != 0 ) - { + /* Skip expensive computation on obvious mismatch */ + if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) ) return( -1 ); - } - return( 0 ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA ) + { + return( mbedtls_pk_verify_restartable( &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len, &rs_ctx->ecdsa ) ); + } +#else + (void) rs_ctx; +#endif + + return( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) ); } /* @@ -1952,17 +1963,19 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, * rely on key identifier extensions). (This is one way users might choose to * handle key rollover, another relies on self-issued certs, see [SIRO].) */ -static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, - mbedtls_x509_crt *candidates, - int *signature_is_good, - int top, - int path_cnt, - int self_cnt ) +static int x509_crt_find_parent_in( + mbedtls_x509_crt *child, + mbedtls_x509_crt *candidates, + mbedtls_x509_crt **r_parent, + int *r_signature_is_good, + int top, + int path_cnt, + int self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { + int ret; mbedtls_x509_crt *parent, *fallback_parent = NULL; - int fallback_sign_good = 0; - - *signature_is_good = 0; + int signature_is_good = 0, fallback_sign_good = 0; for( parent = candidates; parent != NULL; parent = parent->next ) { @@ -1978,8 +1991,17 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, } /* Signature */ - *signature_is_good = x509_crt_check_signature( child, parent ) == 0; - if( top && ! *signature_is_good ) + ret = x509_crt_check_signature( child, parent, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { + // TODO: stave state + return( ret ); + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + signature_is_good = ret == 0; + if( top && ! signature_is_good ) continue; /* optional time check */ @@ -1989,7 +2011,7 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, if( fallback_parent == NULL ) { fallback_parent = parent; - fallback_sign_good = *signature_is_good; + fallback_sign_good = signature_is_good; } continue; @@ -1998,13 +2020,18 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, break; } - if( parent == NULL ) + if( parent != NULL ) { - parent = fallback_parent; - *signature_is_good = fallback_sign_good; + *r_parent = parent; + *r_signature_is_good = signature_is_good; + } + else + { + *r_parent = fallback_parent; + *r_signature_is_good = fallback_sign_good; } - return parent; + return( 0 ); } /* @@ -2013,27 +2040,48 @@ static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, * Searches in trusted CAs first, and return the first suitable parent found * (see find_parent_in() for definition of suitable). */ -static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child, - mbedtls_x509_crt *trust_ca, - int *parent_is_trusted, - int *signature_is_good, - int path_cnt, - int self_cnt ) +static int x509_crt_find_parent( + mbedtls_x509_crt *child, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crt **parent, + int *parent_is_trusted, + int *signature_is_good, + int path_cnt, + int self_cnt, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { - mbedtls_x509_crt *parent; + int ret; /* Look for a parent in trusted CAs */ *parent_is_trusted = 1; - parent = x509_crt_find_parent_in( child, trust_ca, signature_is_good, - 1, path_cnt, self_cnt ); + ret = x509_crt_find_parent_in( child, trust_ca, + parent, signature_is_good, + 1, path_cnt, self_cnt, rs_ctx ); - if( parent != NULL ) - return parent; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { + // TODO: stave state + return( ret ); + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + if( *parent != NULL ) + return( 0 ); /* Look for a parent upwards the chain */ *parent_is_trusted = 0; - return( x509_crt_find_parent_in( child, child->next, signature_is_good, - 0, path_cnt, self_cnt ) ); + ret = x509_crt_find_parent_in( child, child->next, + parent, signature_is_good, + 0, path_cnt, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { + // TODO: stave state + return( ret ); + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + return( 0 ); } /* @@ -2109,8 +2157,10 @@ static int x509_crt_verify_chain( mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], - size_t *chain_len ) + size_t *chain_len, + mbedtls_x509_crt_restart_ctx *rs_ctx ) { + int ret; uint32_t *flags; mbedtls_x509_crt *child; mbedtls_x509_crt *parent; @@ -2154,9 +2204,16 @@ static int x509_crt_verify_chain( } /* Look for a parent in trusted CAs or up the chain */ - parent = x509_crt_find_parent( child, trust_ca, + ret = x509_crt_find_parent( child, trust_ca, &parent, &parent_is_trusted, &signature_is_good, - *chain_len - 1, self_cnt ); + *chain_len - 1, self_cnt, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { + // TODO: stave state + return( ret ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + } /* No parent? We're done here */ if( parent == NULL ) @@ -2351,8 +2408,6 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, size_t chain_len; uint32_t *ee_flags = &ver_chain[0].flags; - (void) rs_ctx; - *flags = 0; memset( ver_chain, 0, sizeof( ver_chain ) ); chain_len = 0; @@ -2378,7 +2433,15 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, /* Check the chain */ ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, - ver_chain, &chain_len ); + ver_chain, &chain_len, rs_ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { + // TODO: stave state + return( ret ); + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + if( ret != 0 ) goto exit; From 18547b5db62c4fc63513c545f38f10edf9541d85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 14 Aug 2017 16:11:43 +0200 Subject: [PATCH 080/148] Refactor find_parent() to merge two call sites --- library/x509_crt.c | 46 +++++++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index e8fb627d4..b6150e806 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2051,35 +2051,39 @@ static int x509_crt_find_parent( mbedtls_x509_crt_restart_ctx *rs_ctx ) { int ret; + mbedtls_x509_crt *search_list; - /* Look for a parent in trusted CAs */ *parent_is_trusted = 1; - ret = x509_crt_find_parent_in( child, trust_ca, - parent, signature_is_good, - 1, path_cnt, self_cnt, rs_ctx ); + + while( 1 ) { + search_list = *parent_is_trusted ? trust_ca : child->next; + + ret = x509_crt_find_parent_in( child, search_list, + parent, signature_is_good, + *parent_is_trusted, + path_cnt, self_cnt, rs_ctx ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - // TODO: stave state - return( ret ); - } + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { + // TODO: stave state + return( ret ); + } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - if( *parent != NULL ) - return( 0 ); + /* stop here if found or already in second iteration */ + if( *parent != NULL || *parent_is_trusted == 0 ) + break; - /* Look for a parent upwards the chain */ - *parent_is_trusted = 0; - ret = x509_crt_find_parent_in( child, child->next, - parent, signature_is_good, - 0, path_cnt, self_cnt, rs_ctx ); - -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - // TODO: stave state - return( ret ); + /* prepare second iteration */ + *parent_is_trusted = 0; + } + + /* extra precaution against mistakes in the caller */ + if( parent == NULL ) + { + parent_is_trusted = 0; + signature_is_good = 0; } -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ return( 0 ); } From c11e4baa6336073cf9432a7bca8ced78465c4a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 14 Aug 2017 17:17:14 +0200 Subject: [PATCH 081/148] Rework type for verify chain - create container with length + table - make types public (will be needed in restart context) --- include/mbedtls/x509_crt.h | 22 ++++++++++++++ library/x509_crt.c | 59 ++++++++++++++------------------------ 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 61a912459..eb929d7e5 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -142,6 +142,28 @@ typedef struct mbedtls_x509write_cert } mbedtls_x509write_cert; +/** + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} mbedtls_x509_crt_verify_chain_item; + +/** + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/** + * Verification chain as built by \c mbedtls_crt_verify_chain() + */ +typedef struct +{ + mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; + size_t len; +} mbedtls_x509_crt_verify_chain; + #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** diff --git a/library/x509_crt.c b/library/x509_crt.c index b6150e806..5c2d2c1b9 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -77,19 +77,6 @@ #endif /* !_WIN32 || EFIX64 || EFI32 */ #endif -/* - * Item in a verification chain: cert and flags for it - */ -typedef struct { - mbedtls_x509_crt *crt; - uint32_t flags; -} x509_crt_verify_chain_item; - -/* - * Max size of verification chain: end-entity + intermediates + trusted root - */ -#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) - /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; @@ -2148,7 +2135,7 @@ static int x509_crt_check_ee_locally_trusted( * - [in] crt: the cert list EE, C1, ..., Cn * - [in] trust_ca: the trusted list R1, ..., Rp * - [in] ca_crl, profile: as in verify_with_profile() - * - [out] ver_chain, chain_len: the built and verified chain + * - [out] ver_chain: the built and verified chain * * Return value: * - non-zero if the chain could not be fully built and examined @@ -2160,12 +2147,12 @@ static int x509_crt_verify_chain( mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, const mbedtls_x509_crt_profile *profile, - x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], - size_t *chain_len, + mbedtls_x509_crt_verify_chain *ver_chain, mbedtls_x509_crt_restart_ctx *rs_ctx ) { int ret; uint32_t *flags; + mbedtls_x509_crt_verify_chain_item *cur; mbedtls_x509_crt *child; mbedtls_x509_crt *parent; int parent_is_trusted = 0; @@ -2174,13 +2161,13 @@ static int x509_crt_verify_chain( int self_cnt = 0; child = crt; - *chain_len = 0; while( 1 ) { /* Add certificate to the verification chain */ - ver_chain[*chain_len].crt = child; - flags = &ver_chain[*chain_len].flags; - ++*chain_len; + cur = &ver_chain->items[ver_chain->len]; + cur->crt = child; + flags = &cur->flags; + ver_chain->len++; /* Check time-validity (all certificates) */ if( mbedtls_x509_time_is_past( &child->valid_to ) ) @@ -2201,7 +2188,7 @@ static int x509_crt_verify_chain( *flags |= MBEDTLS_X509_BADCERT_BAD_PK; /* Special case: EE certs that are locally trusted */ - if( *chain_len == 1 && + if( ver_chain->len == 1 && x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) { return( 0 ); @@ -2210,7 +2197,7 @@ static int x509_crt_verify_chain( /* Look for a parent in trusted CAs or up the chain */ ret = x509_crt_find_parent( child, trust_ca, &parent, &parent_is_trusted, &signature_is_good, - *chain_len - 1, self_cnt, rs_ctx ); + ver_chain->len - 1, self_cnt, rs_ctx ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { @@ -2229,7 +2216,7 @@ static int x509_crt_verify_chain( /* Count intermediate self-issued (not necessarily self-signed) certs. * These can occur with some strategies for key rollover, see [SIRO], * and should be excluded from max_pathlen checks. */ - if( *chain_len != 1 && + if( ver_chain->len != 1 && x509_name_cmp( &child->issuer, &child->subject ) == 0 ) { self_cnt++; @@ -2238,7 +2225,7 @@ static int x509_crt_verify_chain( /* path_cnt is 0 for the first intermediate CA, * and if parent is trusted it's not an intermediate CA */ if( ! parent_is_trusted && - *chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + ver_chain->len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) { /* return immediately to avoid overflow the chain array */ return( MBEDTLS_ERR_X509_FATAL_ERROR ); @@ -2334,21 +2321,22 @@ static void x509_crt_verify_name( const mbedtls_x509_crt *crt, */ static int x509_crt_merge_flags_with_cb( uint32_t *flags, - x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], - size_t chain_len, + const mbedtls_x509_crt_verify_chain *ver_chain, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { int ret; size_t i; uint32_t cur_flags; + const mbedtls_x509_crt_verify_chain_item *cur; - for( i = chain_len; i != 0; --i ) + for( i = ver_chain->len; i != 0; --i ) { - cur_flags = ver_chain[i-1].flags; + cur = &ver_chain->items[i-1]; + cur_flags = cur->flags; if( NULL != f_vrfy ) - if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, i-1, &cur_flags ) ) != 0 ) + if( ( ret = f_vrfy( p_vrfy, cur->crt, i-1, &cur_flags ) ) != 0 ) return( ret ); *flags |= cur_flags; @@ -2408,13 +2396,11 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, { int ret; mbedtls_pk_type_t pk_type; - x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE]; - size_t chain_len; - uint32_t *ee_flags = &ver_chain[0].flags; + mbedtls_x509_crt_verify_chain ver_chain; + uint32_t *ee_flags = &ver_chain.items[0].flags; *flags = 0; - memset( ver_chain, 0, sizeof( ver_chain ) ); - chain_len = 0; + memset( &ver_chain, 0, sizeof( ver_chain ) ); if( profile == NULL ) { @@ -2437,7 +2423,7 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, /* Check the chain */ ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, - ver_chain, &chain_len, rs_ctx ); + &ver_chain, rs_ctx ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { @@ -2450,8 +2436,7 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, goto exit; /* Build final flags, calling callback on the way if any */ - ret = x509_crt_merge_flags_with_cb( flags, - ver_chain, chain_len, f_vrfy, p_vrfy ); + ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); exit: /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by From 8b59049407f337cf9813f9012a81f6587e6c4d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 14 Aug 2017 18:04:19 +0200 Subject: [PATCH 082/148] Make verify() actually restartable --- include/mbedtls/x509_crt.h | 17 ++- library/x509_crt.c | 137 +++++++++++++++++---- tests/data_files/Readme-x509.txt | 2 +- tests/suites/test_suite_x509parse.data | 70 ++++++++++- tests/suites/test_suite_x509parse.function | 10 ++ 5 files changed, 208 insertions(+), 28 deletions(-) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index eb929d7e5..7487df619 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -171,7 +171,22 @@ typedef struct */ typedef struct { - mbedtls_ecdsa_restart_ctx ecdsa; /*!< ecdsa restart context */ + /* for check_signature() */ + mbedtls_ecdsa_restart_ctx ecdsa; + + /* for find_parent_in() */ + mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */ + mbedtls_x509_crt *fallback_parent; + int fallback_sign_good; + + /* for find_parent() */ + int parent_is_trusted; /* -1 if find_parent is not in progress */ + + /* for verify_chain() */ + mbedtls_x509_crt *child; /* non-null iff in progress */ + int self_cnt; + mbedtls_x509_crt_verify_chain ver_chain; + } mbedtls_x509_crt_restart_ctx; #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ diff --git a/library/x509_crt.c b/library/x509_crt.c index 5c2d2c1b9..a0d1956dc 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1870,7 +1870,7 @@ static int x509_crt_check_signature( const mbedtls_x509_crt *child, if( ! mbedtls_pk_can_do( &parent->pk, child->sig_pk ) ) return( -1 ); -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && child->sig_pk == MBEDTLS_PK_ECDSA ) { return( mbedtls_pk_verify_restartable( &parent->pk, @@ -1961,8 +1961,23 @@ static int x509_crt_find_parent_in( mbedtls_x509_crt_restart_ctx *rs_ctx ) { int ret; - mbedtls_x509_crt *parent, *fallback_parent = NULL; - int signature_is_good = 0, fallback_sign_good = 0; + mbedtls_x509_crt *parent, *fallback_parent; + int signature_is_good, fallback_sign_good; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* restore state if we have some stored */ + if( rs_ctx != NULL && rs_ctx->parent != NULL ) + { + parent = rs_ctx->parent; + fallback_parent = rs_ctx->fallback_parent; + fallback_sign_good = rs_ctx->fallback_sign_good; + + goto check_signature; + } +#endif + + fallback_parent = NULL; + fallback_sign_good = 0; for( parent = candidates; parent != NULL; parent = parent->next ) { @@ -1978,14 +1993,24 @@ static int x509_crt_find_parent_in( } /* Signature */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +check_signature: +#endif ret = x509_crt_check_signature( child, parent, rs_ctx ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - // TODO: stave state + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent = parent; + rs_ctx->fallback_parent = fallback_parent; + rs_ctx->fallback_sign_good = fallback_sign_good; + return( ret ); } -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +#else + (void) ret; +#endif signature_is_good = ret == 0; if( top && ! signature_is_good ) @@ -2018,6 +2043,16 @@ static int x509_crt_find_parent_in( *r_signature_is_good = fallback_sign_good; } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL ) + { + /* reset state */ + rs_ctx->parent = NULL; + rs_ctx->fallback_parent = NULL; + rs_ctx->fallback_sign_good = 0; + } +#endif + return( 0 ); } @@ -2042,6 +2077,12 @@ static int x509_crt_find_parent( *parent_is_trusted = 1; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* restore state if we have some stored */ + if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1) + *parent_is_trusted = rs_ctx->parent_is_trusted; +#endif + while( 1 ) { search_list = *parent_is_trusted ? trust_ca : child->next; @@ -2051,11 +2092,15 @@ static int x509_crt_find_parent( path_cnt, self_cnt, rs_ctx ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - // TODO: stave state + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->parent_is_trusted = *parent_is_trusted; return( ret ); } -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +#else + (void) ret; +#endif /* stop here if found or already in second iteration */ if( *parent != NULL || *parent_is_trusted == 0 ) @@ -2072,6 +2117,12 @@ static int x509_crt_find_parent( signature_is_good = 0; } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* reset state */ + if( rs_ctx != NULL ) + rs_ctx->parent_is_trusted = -1; +#endif + return( 0 ); } @@ -2155,12 +2206,31 @@ static int x509_crt_verify_chain( mbedtls_x509_crt_verify_chain_item *cur; mbedtls_x509_crt *child; mbedtls_x509_crt *parent; - int parent_is_trusted = 0; - int child_is_trusted = 0; - int signature_is_good = 0; - int self_cnt = 0; + int parent_is_trusted; + int child_is_trusted; + int signature_is_good; + int self_cnt; + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* resume if we had an operation in progress */ + if( rs_ctx != NULL && rs_ctx->child != NULL ) + { + /* save state */ + child = rs_ctx->child; + self_cnt = rs_ctx->self_cnt; + *ver_chain = rs_ctx->ver_chain; + + cur = &ver_chain->items[ver_chain->len - 1]; + flags = &cur->flags; + + goto find_parent; + } +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ child = crt; + self_cnt = 0; + parent_is_trusted = 0; + child_is_trusted = 0; while( 1 ) { /* Add certificate to the verification chain */ @@ -2194,17 +2264,27 @@ static int x509_crt_verify_chain( return( 0 ); } +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +find_parent: +#endif /* Look for a parent in trusted CAs or up the chain */ ret = x509_crt_find_parent( child, trust_ca, &parent, &parent_is_trusted, &signature_is_good, ver_chain->len - 1, self_cnt, rs_ctx ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - // TODO: stave state + if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + { + /* save state */ + rs_ctx->child = child; + rs_ctx->self_cnt = self_cnt; + rs_ctx-> ver_chain = *ver_chain; + return( ret ); -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ } +#else + (void) ret; +#endif /* No parent? We're done here */ if( parent == NULL ) @@ -2425,13 +2505,6 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, &ver_chain, rs_ctx ); -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - // TODO: stave state - return( ret ); - } -#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - if( ret != 0 ) goto exit; @@ -2439,6 +2512,11 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); exit: +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_x509_crt_restart_free( rs_ctx ); +#endif + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by * the SSL module for authmode optional, but non-zero return from the * callback means a fatal error so it shouldn't be ignored */ @@ -2554,6 +2632,17 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) { mbedtls_ecdsa_restart_init( &ctx->ecdsa ); + + ctx->parent = NULL; + ctx->fallback_parent = NULL; + ctx->fallback_sign_good = 0; + + ctx->parent_is_trusted = -1; + + ctx->child = NULL; + ctx->self_cnt = 0; + memset( ctx->ver_chain.items, 0, sizeof( ctx->ver_chain.items ) ); + ctx->ver_chain.len = 0; } /* @@ -2565,6 +2654,8 @@ void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) return; mbedtls_ecdsa_restart_free( &ctx->ecdsa ); + + mbedtls_x509_crt_restart_init( ctx ); } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ diff --git a/tests/data_files/Readme-x509.txt b/tests/data_files/Readme-x509.txt index d1a6c2d27..185fb3412 100644 --- a/tests/data_files/Readme-x509.txt +++ b/tests/data_files/Readme-x509.txt @@ -17,7 +17,7 @@ Two intermediate CAs are signed by them: - test-int-ca.crt "C=NL, O=PolarSSL, CN=PolarSSL Test Intermediate CA" uses RSA-4096, signed by test-ca2 - test-int-ca2.crt "C=NL, O=PolarSSL, CN=PolarSSL Test Intermediate EC CA" - uses an EC key with NIST P-256, signed by test-ca + uses an EC key with NIST P-384, signed by test-ca A third intermediate CA is signed by test-int-ca2.crt: - test-int-ca3.crt "C=UK, O=mbed TLS, CN=mbed TLS Test intermediate CA 3" diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index b3e1c1cdf..1c553b456 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -1810,22 +1810,86 @@ X509 cert verify restart: trusted EE, max_ops=0 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED x509_verify_restart:"data_files/server5-selfsigned.crt":"data_files/server5-selfsigned.crt":0:0:0:0:0 +X509 cert verify restart: trusted EE, max_ops=1 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED +x509_verify_restart:"data_files/server5-selfsigned.crt":"data_files/server5-selfsigned.crt":0:0:1:0:0 + X509 cert verify restart: no intermediate, max_ops=0 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:0:0:0 +X509 cert verify restart: no intermediate, max_ops=1 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED +x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:1:100:10000 + +X509 cert verify restart: no intermediate, max_ops=40000 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED +x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:40000:0:0 + +X509 cert verify restart: no intermediate, max_ops=500 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED +x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:500:20:80 + X509 cert verify restart: no intermediate, badsign, max_ops=0 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0 -X509 cert verify restart: one intermediate, max_ops=0 +X509 cert verify restart: no intermediate, badsign, max_ops=1 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED +x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:1:100:10000 + +X509 cert verify restart: no intermediate, badsign, max_ops=40000 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED +x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:40000:0:0 + +X509 cert verify restart: no intermediate, badsign, max_ops=500 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED +x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:500:20:80 + +X509 cert verify restart: one int, max_ops=0 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:0:0:0 -X509 cert verify restart: one intermediate, EE badsign, max_ops=0 +X509 cert verify restart: one int, max_ops=1 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:1:100:10000 + +X509 cert verify restart: one int, max_ops=30000 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:30000:0:0 + +X509 cert verify restart: one int, max_ops=500 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:500:25:100 + +X509 cert verify restart: one int, EE badsign, max_ops=0 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0 -X509 cert verify restart: one intermediate, int badsign, max_ops=0 +X509 cert verify restart: one int, EE badsign, max_ops=1 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:1:100:10000 + +X509 cert verify restart: one int, EE badsign, max_ops=30000 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:30000:0:0 + +X509 cert verify restart: one int, EE badsign, max_ops=500 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:500:25:100 + +X509 cert verify restart: one int, int badsign, max_ops=0 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C x509_verify_restart:"data_files/server10_int3-bs.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0 + +X509 cert verify restart: one int, int badsign, max_ops=1 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10_int3-bs.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:1:100:10000 + +X509 cert verify restart: one int, int badsign, max_ops=30000 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10_int3-bs.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:30000:0:0 + +X509 cert verify restart: one int, int badsign, max_ops=500 +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C +x509_verify_restart:"data_files/server10_int3-bs.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:500:25:100 diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index f899eb018..c12aaef0c 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -272,6 +272,16 @@ void x509_verify_restart( char *crt_file, char *ca_file, mbedtls_x509_crt ca; uint32_t flags = 0; + /* + * See comments on ecp_test_vect_restart() for op count precision. + * + * For reference, with mbed TLS 2.6 and default settings: + * - ecdsa_verify() for P-256: ~ 6700 + * - ecdsa_verify() for P-384: ~ 18800 + * - x509_verify() for server5 -> test-ca2: ~ 18800 + * - x509_verify() for server10 -> int-ca3 -> int-ca2: ~ 25500 + */ + mbedtls_x509_crt_restart_init( &rs_ctx ); mbedtls_x509_crt_init( &crt ); mbedtls_x509_crt_init( &ca ); From d27d1a5a82b4b0cf63cef05698bc8918883e7868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 15 Aug 2017 11:49:08 +0200 Subject: [PATCH 083/148] Clean up existing SSL restartable ECC code - more consistent naming with ecrs prefix for everything - always check it enabled before touching the rest - rm duplicated code in parse_server_hello() --- include/mbedtls/ssl_internal.h | 4 +-- library/ssl_cli.c | 63 +++++++++++++++++++--------------- library/ssl_tls.c | 4 +-- 3 files changed, 40 insertions(+), 31 deletions(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 51dd4e1df..bc38b8b03 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -227,8 +227,8 @@ struct mbedtls_ssl_handshake_params #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - int ec_restart_enabled; /*!< Handshake supports EC restart? */ - mbedtls_ecdsa_restart_ctx rs_ctx; /*!< ECDSA restart context */ + int ecrs_enabled; /*!< Handshake supports EC restart? */ + mbedtls_ecdsa_restart_ctx ecrs_ctx; /*!< ECDSA restart context */ enum { ssl_ecrs_init = 0, /*!< just getting started */ ssl_ecrs_ske_read, /*!< ServerKeyExchange was read */ diff --git a/library/ssl_cli.c b/library/ssl_cli.c index cbd46475c..db57713a6 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -1701,7 +1701,7 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { - ssl->handshake->ec_restart_enabled = 1; + ssl->handshake->ecrs_enabled = 1; } #endif @@ -1723,14 +1723,6 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) } } -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && - ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) - { - ssl->handshake->ec_restart_enabled = 1; - } -#endif - if( comp != MBEDTLS_SSL_COMPRESS_NULL #if defined(MBEDTLS_ZLIB_SUPPORT) && comp != MBEDTLS_SSL_COMPRESS_DEFLATE @@ -2312,8 +2304,11 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */ #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ecrs_state == ssl_ecrs_ske_read ) - goto ske_process; + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_ske_read ) + { + goto ske_process; + } #endif if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) @@ -2323,6 +2318,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) } #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) ssl->handshake->ecrs_state++; ske_process: @@ -2618,8 +2614,8 @@ ske_process: } #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ec_restart_enabled ) - rs_ctx = &ssl->handshake->rs_ctx; + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx; #endif if( ( ret = mbedtls_pk_verify_restartable( @@ -2636,7 +2632,8 @@ ske_process: } #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - ssl->handshake->ecrs_state++; + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state++; #endif } #endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ @@ -2902,11 +2899,13 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) i = 4; #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ec_restart_enabled) - mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); + if( ssl->handshake->ecrs_enabled ) + { + if( ssl->handshake->ecrs_state == ssl_ecrs_ecdh_public_done ) + goto ecdh_calc_secret; - if( ssl->handshake->ecrs_state == ssl_ecrs_ecdh_public_done ) - goto ecdh_calc_secret; + mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); + } #endif ret = mbedtls_ecdh_make_public( &ssl->handshake->ecdh_ctx, @@ -2922,11 +2921,15 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q", &ssl->handshake->ecdh_ctx.Q ); #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - ssl->handshake->ecrs_n = n; - ssl->handshake->ecrs_state++; + if( ssl->handshake->ecrs_enabled ) + { + ssl->handshake->ecrs_n = n; + ssl->handshake->ecrs_state++; + } ecdh_calc_secret: - n = ssl->handshake->ecrs_n; + if( ssl->handshake->ecrs_enabled ) + n = ssl->handshake->ecrs_n; #endif if( ( ret = mbedtls_ecdh_calc_secret( &ssl->handshake->ecdh_ctx, &ssl->handshake->pmslen, @@ -2941,7 +2944,8 @@ ecdh_calc_secret: MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - ssl->handshake->ecrs_state++; + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state++; #endif } else @@ -3162,8 +3166,11 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ecrs_state == ssl_ecrs_keys_derived ) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_keys_derived ) + { goto keys_derived; + } #endif if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) @@ -3173,7 +3180,8 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) } #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - ssl->handshake->ecrs_state++; + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state++; keys_derived: #endif @@ -3281,8 +3289,8 @@ keys_derived: } #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ec_restart_enabled ) - rs_ctx = &ssl->handshake->rs_ctx; + if( ssl->handshake->ecrs_enabled ) + rs_ctx = &ssl->handshake->ecrs_ctx; #endif if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), @@ -3295,7 +3303,8 @@ keys_derived: } #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - ssl->handshake->ecrs_state++; + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state++; #endif ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 50222c375..90331efa1 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -5473,7 +5473,7 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) #endif #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - mbedtls_ecdsa_restart_init( &handshake->rs_ctx ); + mbedtls_ecdsa_restart_init( &handshake->ecrs_ctx ); #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) @@ -7309,7 +7309,7 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - mbedtls_ecdsa_restart_free( &handshake->rs_ctx ); + mbedtls_ecdsa_restart_free( &handshake->ecrs_ctx ); #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) From 6b7301c8722e9fce24f1e17e3b716d15cca618d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 15 Aug 2017 12:08:45 +0200 Subject: [PATCH 084/148] Change restart context type. No need to have both x509 and ecdsa, as the former contains the later. --- include/mbedtls/ssl_internal.h | 2 +- library/ssl_cli.c | 4 ++-- library/ssl_tls.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index bc38b8b03..00a8db44e 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -228,7 +228,7 @@ struct mbedtls_ssl_handshake_params #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) int ecrs_enabled; /*!< Handshake supports EC restart? */ - mbedtls_ecdsa_restart_ctx ecrs_ctx; /*!< ECDSA restart context */ + mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ enum { ssl_ecrs_init = 0, /*!< just getting started */ ssl_ecrs_ske_read, /*!< ServerKeyExchange was read */ diff --git a/library/ssl_cli.c b/library/ssl_cli.c index db57713a6..7ffeb5bb4 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2615,7 +2615,7 @@ ske_process: #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled ) - rs_ctx = &ssl->handshake->ecrs_ctx; + rs_ctx = &ssl->handshake->ecrs_ctx.ecdsa; #endif if( ( ret = mbedtls_pk_verify_restartable( @@ -3290,7 +3290,7 @@ keys_derived: #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled ) - rs_ctx = &ssl->handshake->ecrs_ctx; + rs_ctx = &ssl->handshake->ecrs_ctx.ecdsa; #endif if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 90331efa1..221071b5e 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -5473,7 +5473,7 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) #endif #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - mbedtls_ecdsa_restart_init( &handshake->ecrs_ctx ); + mbedtls_x509_crt_restart_init( &handshake->ecrs_ctx ); #endif #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) @@ -7309,7 +7309,7 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - mbedtls_ecdsa_restart_free( &handshake->ecrs_ctx ); + mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx ); #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) From 39eda87382100565a890182ff9dffedd640cfa18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 15 Aug 2017 13:00:33 +0200 Subject: [PATCH 085/148] Make more auto variables const That way we know we don't have to worry about saving and restoring their value. --- library/ssl_tls.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 221071b5e..48bb33683 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4313,8 +4313,15 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) { int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; size_t i, n; - const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - int authmode = ssl->conf->authmode; + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET + ? ssl->handshake->sni_authmode + : ssl->conf->authmode; +#else + const int authmode = ssl->conf->authmode; +#endif uint8_t alert; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); @@ -4338,11 +4345,6 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) return( 0 ); } -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET ) - authmode = ssl->handshake->sni_authmode; -#endif - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && authmode == MBEDTLS_SSL_VERIFY_NONE ) { From fed37ed0391f5b25393d5802c5ef434314a53894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 15 Aug 2017 13:27:41 +0200 Subject: [PATCH 086/148] Extract some code to separate function Goals include: - reducing the number of local variables in the main function (so that we don't have to worry about saving/restoring them) - reducing the number exit points in the main function, making it easier to update ssl->state only right before we return --- library/ssl_tls.c | 141 ++++++++++++++++++++++++++-------------------- 1 file changed, 81 insertions(+), 60 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 48bb33683..f91e2a885 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4309,62 +4309,16 @@ write_msg: return( ret ); } -int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +/* + * Once the certificate message is read, parse it into a cert chain and + * perform basic checks, but leave actual verification to the caller + */ +static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl ) { - int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE; + int ret; size_t i, n; - const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = - ssl->transform_negotiate->ciphersuite_info; -#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET - ? ssl->handshake->sni_authmode - : ssl->conf->authmode; -#else - const int authmode = ssl->conf->authmode; -#endif uint8_t alert; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); - - if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - -#if defined(MBEDTLS_SSL_SRV_C) - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) - { - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } - - if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && - authmode == MBEDTLS_SSL_VERIFY_NONE ) - { - ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; - MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); - ssl->state++; - return( 0 ); - } -#endif - - if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) - { - /* mbedtls_ssl_read_record may have sent an alert already. We - let it decide whether to alert. */ - MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); - return( ret ); - } - - ssl->state++; - #if defined(MBEDTLS_SSL_SRV_C) #if defined(MBEDTLS_SSL_PROTO_SSL3) /* @@ -4384,10 +4338,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) one. The client should know what's going on, so we don't send an alert. */ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); } } #endif /* MBEDTLS_SSL_PROTO_SSL3 */ @@ -4408,10 +4359,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) one. The client should know what's going on, so we don't send an alert. */ ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING; - if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) - return( 0 ); - else - return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); + return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE ); } } #endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \ @@ -4555,6 +4503,75 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */ + return( 0 ); +} + +int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) +{ + int ret; + const mbedtls_ssl_ciphersuite_t * const ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; +#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET + ? ssl->handshake->sni_authmode + : ssl->conf->authmode; +#else + const int authmode = ssl->conf->authmode; +#endif + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); + + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + +#if defined(MBEDTLS_SSL_SRV_C) + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + { + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } + + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER && + authmode == MBEDTLS_SSL_VERIFY_NONE ) + { + ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; + return( 0 ); + } +#endif + + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) + { + /* mbedtls_ssl_read_record may have sent an alert already. We + let it decide whether to alert. */ + MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret ); + return( ret ); + } + + if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_SRV_C) + if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE && + authmode == MBEDTLS_SSL_VERIFY_OPTIONAL ) + { + ret = 0; + } +#endif + + ssl->state++; + return( ret ); + } + if( authmode != MBEDTLS_SSL_VERIFY_NONE ) { mbedtls_x509_crt *ca_chain; @@ -4641,6 +4658,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) if( ret != 0 ) { + uint8_t alert; + /* The certificate may have been rejected for several reasons. Pick one and send the corresponding alert. Which alert to send may be a subject of debate in some cases. */ @@ -4683,6 +4702,8 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_DEBUG_C */ } + ssl->state++; + MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); return( ret ); From 3bf49c45522ea5a3fed29966d32fece46c12afda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 15 Aug 2017 13:47:06 +0200 Subject: [PATCH 087/148] Enable restart for certificate verify --- include/mbedtls/ssl_internal.h | 2 ++ library/ssl_tls.c | 33 +++++++++++++++++-- tests/ssl-opt.sh | 58 ++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 00a8db44e..4cfe1540c 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -231,6 +231,8 @@ struct mbedtls_ssl_handshake_params mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ enum { ssl_ecrs_init = 0, /*!< just getting started */ + ssl_ecrs_crt_parsed, /*!< server certificate was parsed */ + ssl_ecrs_crt_verified, /*!< server certificate was verified*/ ssl_ecrs_ske_read, /*!< ServerKeyExchange was read */ ssl_ecrs_ske_verified, /*!< ServerKeyExchange was verified */ ssl_ecrs_ecdh_public_done, /*!< wrote ECDHE public share */ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index f91e2a885..f3cde7f0a 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4518,6 +4518,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) #else const int authmode = ssl->conf->authmode; #endif + void *rs_ctx = NULL; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) ); @@ -4545,11 +4546,20 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) { ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY; MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) ); + ssl->state++; return( 0 ); } #endif +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled && + ssl->handshake->ecrs_state == ssl_ecrs_crt_parsed ) + { + goto crt_verify; + } +#endif + if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 ) { /* mbedtls_ssl_read_record may have sent an alert already. We @@ -4572,6 +4582,15 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) return( ret ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled) + ssl->handshake->ecrs_state++; + +crt_verify: + if( ssl->handshake->ecrs_enabled) + rs_ctx = &ssl->handshake->ecrs_ctx; +#endif + if( authmode != MBEDTLS_SSL_VERIFY_NONE ) { mbedtls_x509_crt *ca_chain; @@ -4593,19 +4612,24 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) /* * Main check: verify certificate */ - ret = mbedtls_x509_crt_verify_with_profile( + ret = mbedtls_x509_crt_verify_restartable( ssl->session_negotiate->peer_cert, ca_chain, ca_crl, ssl->conf->cert_profile, ssl->hostname, &ssl->session_negotiate->verify_result, - ssl->conf->f_vrfy, ssl->conf->p_vrfy ); + ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "x509_verify_cert", ret ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + return( ret ); +#endif + /* * Secondary checks: always done, but change 'ret' only if it was 0 */ @@ -4702,6 +4726,11 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) #endif /* MBEDTLS_DEBUG_C */ } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled) + ssl->handshake->ecrs_state++; +#endif + ssl->state++; MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 2e03758e6..1dea049da 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -3450,6 +3450,7 @@ run_test "EC restart: TLS, default" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1" \ 0 \ + -C "x509_verify_cert.*4b80" \ -C "mbedtls_pk_verify.*4b80" \ -C "mbedtls_ecdh_make_public.*4b80" \ -C "mbedtls_pk_sign.*4b80" @@ -3461,6 +3462,7 @@ run_test "EC restart: TLS, max_ops=0" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=0" \ 0 \ + -C "x509_verify_cert.*4b80" \ -C "mbedtls_pk_verify.*4b80" \ -C "mbedtls_ecdh_make_public.*4b80" \ -C "mbedtls_pk_sign.*4b80" @@ -3472,6 +3474,7 @@ run_test "EC restart: TLS, max_ops=65535" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=65535" \ 0 \ + -C "x509_verify_cert.*4b80" \ -C "mbedtls_pk_verify.*4b80" \ -C "mbedtls_ecdh_make_public.*4b80" \ -C "mbedtls_pk_sign.*4b80" @@ -3483,10 +3486,62 @@ run_test "EC restart: TLS, max_ops=1000" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=1000" \ 0 \ + -c "x509_verify_cert.*4b80" \ -c "mbedtls_pk_verify.*4b80" \ -c "mbedtls_ecdh_make_public.*4b80" \ -c "mbedtls_pk_sign.*4b80" +requires_config_enabled MBEDTLS_ECP_RESTARTABLE +run_test "EC restart: TLS, max_ops=1000, badsign" \ + "$P_SRV auth_mode=required \ + crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ + debug_level=1 ec_max_ops=1000" \ + 1 \ + -c "x509_verify_cert.*4b80" \ + -C "mbedtls_pk_verify.*4b80" \ + -C "mbedtls_ecdh_make_public.*4b80" \ + -C "mbedtls_pk_sign.*4b80" \ + -c "! The certificate is not correctly signed by the trusted CA" \ + -c "! mbedtls_ssl_handshake returned" \ + -c "X509 - Certificate verification failed" + +requires_config_enabled MBEDTLS_ECP_RESTARTABLE +run_test "EC restart: TLS, max_ops=1000, auth_mode=optional badsign" \ + "$P_SRV auth_mode=required \ + crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ + debug_level=1 ec_max_ops=1000 auth_mode=optional" \ + 0 \ + -c "x509_verify_cert.*4b80" \ + -c "mbedtls_pk_verify.*4b80" \ + -c "mbedtls_ecdh_make_public.*4b80" \ + -c "mbedtls_pk_sign.*4b80" \ + -c "! The certificate is not correctly signed by the trusted CA" \ + -C "! mbedtls_ssl_handshake returned" \ + -C "X509 - Certificate verification failed" + +requires_config_enabled MBEDTLS_ECP_RESTARTABLE +run_test "EC restart: TLS, max_ops=1000, auth_mode=none badsign" \ + "$P_SRV auth_mode=required \ + crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ + debug_level=1 ec_max_ops=1000 auth_mode=none" \ + 0 \ + -C "x509_verify_cert.*4b80" \ + -c "mbedtls_pk_verify.*4b80" \ + -c "mbedtls_ecdh_make_public.*4b80" \ + -c "mbedtls_pk_sign.*4b80" \ + -C "! The certificate is not correctly signed by the trusted CA" \ + -C "! mbedtls_ssl_handshake returned" \ + -C "X509 - Certificate verification failed" + requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: DTLS, max_ops=1000" \ "$P_SRV auth_mode=required dtls=1" \ @@ -3494,6 +3549,7 @@ run_test "EC restart: DTLS, max_ops=1000" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ dtls=1 debug_level=1 ec_max_ops=1000" \ 0 \ + -c "x509_verify_cert.*4b80" \ -c "mbedtls_pk_verify.*4b80" \ -c "mbedtls_ecdh_make_public.*4b80" \ -c "mbedtls_pk_sign.*4b80" @@ -3504,6 +3560,7 @@ run_test "EC restart: TLS, max_ops=1000 no client auth" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ debug_level=1 ec_max_ops=1000" \ 0 \ + -c "x509_verify_cert.*4b80" \ -c "mbedtls_pk_verify.*4b80" \ -c "mbedtls_ecdh_make_public.*4b80" \ -C "mbedtls_pk_sign.*4b80" @@ -3514,6 +3571,7 @@ run_test "EC restart: TLS, max_ops=1000, ECDHE-PSK" \ "$P_CLI force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 \ psk=abc123 debug_level=1 ec_max_ops=1000" \ 0 \ + -C "x509_verify_cert.*4b80" \ -C "mbedtls_pk_verify.*4b80" \ -C "mbedtls_ecdh_make_public.*4b80" \ -C "mbedtls_pk_sign.*4b80" From 9897cc933db6d14860bd0ae31a6eb015b18450ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 15 Aug 2017 14:30:43 +0200 Subject: [PATCH 088/148] Update ChangeLog --- ChangeLog | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index b80f53a25..3acb972f7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,13 +6,9 @@ Features * Add support for restartable ECC operations, enabled by MBEDTLS_ECP_RESTARTABLE (disabled by default) at compile time and mbedtls_ecp_set_max_ops() at runtime, using new xxx_restartable functions - in ECP, ECDSA, PK, and using existing functions in ECDH and SSL - (currently only implemented client-side, for ECDHE-ECDSA ciphersuites - with TLS 1.2, including client authentication). - TEMPORARY NOTE: server authentication currently not supported (WIP). - For now, MUST be disabled by calling - mbedtls_ssl_conf_authmode( MBEDTLS_SSL_VERIFY_NONE ) - (or blocking ECC operations will happen) + in ECP, ECDSA, PK and X509 (CRL not supported yet), and using existing + functions in ECDH and SSL (currently only implemented client-side, for + ECDHE-ECDSA ciphersuites with TLS 1.2, including client authentication). = mbed TLS x.x.x branch released xxxx-xx-xx From c9e16a97da197abf687ff1a8a107c3d3d4497e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 15 Aug 2017 14:30:59 +0200 Subject: [PATCH 089/148] Disable restartable ECC by default --- include/mbedtls/config.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index f4c565ebb..fbfab63b0 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -566,15 +566,17 @@ * * Enable "non-blocking" ECC operations that can return early and be resumed. * - * This enables \c mbedtls_ecp_set_max_ops() and allows various ECC functions - * to return \c MBEDTLS_ERR_ECP_IN_PROGRESS when needed. + * This enables \c mbedtls_ecp_set_max_ops() and allows various functions + * to return \c MBEDTLS_ERR_ECP_IN_PROGRESS when needed, and then be called + * again later with the same arguments in order to further progress and + * eventually complete the operation, see \c mbedtls_ecp_set_max_ops(). * - * TODO: depending on other choices, this might need to be disabled by default - * in order to avoid changing the ABI. Revisit that later. + * This is usefull in non-threaded environments if you want to avoid blocking + * for too long on ECC (hence, X509 or SSL/TLS) operations. * - * Comment this macro to disable non-blocking ECC computations. + * Uncomment this macro to enable restartable ECC computations. */ -#define MBEDTLS_ECP_RESTARTABLE +//#define MBEDTLS_ECP_RESTARTABLE /** * \def MBEDTLS_ECDSA_DETERMINISTIC From 5faafa76cf925954f275a878302b660f0889912a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 17 Aug 2017 10:13:00 +0200 Subject: [PATCH 090/148] Update X.509 test certs' Readme --- tests/data_files/Readme-x509.txt | 39 ++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/tests/data_files/Readme-x509.txt b/tests/data_files/Readme-x509.txt index 185fb3412..6f54ed0c1 100644 --- a/tests/data_files/Readme-x509.txt +++ b/tests/data_files/Readme-x509.txt @@ -16,6 +16,7 @@ The files test-ca_cat12 and test-ca_cat21 contain them concatenated both ways. Two intermediate CAs are signed by them: - test-int-ca.crt "C=NL, O=PolarSSL, CN=PolarSSL Test Intermediate CA" uses RSA-4096, signed by test-ca2 + - test-int-ca-exp.crt is a copy that is expired - test-int-ca2.crt "C=NL, O=PolarSSL, CN=PolarSSL Test Intermediate EC CA" uses an EC key with NIST P-384, signed by test-ca @@ -66,21 +67,41 @@ List of certificates: - server2*.crt: 1 R L: misc - server3.crt: 1 E L: EC cert signed by RSA CA - server4.crt: 2 R L: RSA cert signed by EC CA -- server5*.crt: 2* E L: misc *(except server5-selfsigned) +- server5*.crt: 2* E L: misc *(except -selfsigned and -ss-*) -sha*: hashes - -eku*: extendeKeyUsage (cli/srv = www client/server, cs = codesign, etc) - -ku*: keyUsage (ds = signatures, ke/ka = key exchange/agreement) + .eku*: extendeKeyUsage (cli/srv = www client/server, cs = codesign, etc) + .ku*: keyUsage (ds = signatures, ke/ka = key exchange/agreement) + .req*: CSR, not certificate + -der*: trailing bytes in der (?) + -badsign.crt: S5 with corrupted signature + -expired.crt: S5 with "not after" date in the past + -future.crt: S5 with "not before" date in the future + -selfsigned.crt: Self-signed cert with S5 key + -ss-expired.crt: Self-signed cert with S5 key, expired + -ss-forgeca.crt: Copy of test-int-ca3 self-signed with S5 key - server6-ss-child.crt: O E: "child" of non-CA server5-selfsigned - server6.crt, server6.pem: 2 E L C: revoked -- server7*.crt: I1 E L P1*: EC signed by RSA signed by EC - *P1 except 7.crt, P2 _int-ca_ca2.crt - *_space: with PEM error(s) - _spurious: has spurious cert in its chain (S7 + I2 + I1) +- server7.crt: I1 E L P1(usually): EC signed by RSA signed by EC + -badsign.crt: S7 with corrupted signature + I1 + -expired.crt: S7 with "not after" date in the past + I1 + -future.crt: S7 with "not before" date in the future + I1 + _int-ca-exp.crt: S7 + expired I1 + _int-ca.crt: S7 + I1 + _int-ca_ca2.crt: S7 + I1 + 2 + _all_space.crt: S7 + I1 both with misplaced spaces (invalid PEM) + _pem_space.crt: S7 with misplace space (invalid PEM) + I1 + _trailing_space.crt: S7 + I1 both with trainling space (valid PEM) + _spurious_int-ca.crt: S7 + I2(spurious) + I1 - server8*.crt: I2 R L: RSA signed by EC signed by RSA (P1 for _int-ca2) - server9*.crt: 1 R C* L P1*: signed using RSASSA-PSS *CRL for: 9.crt, -badsign, -with-ca (P1) -- server10*.crt: I3 E L P2/P3 - _spurious: S10 + I3 + I1(spurious) + I2 +- server10.crt: I3 E L + -badsign.crt: S10 with corrupted signature + -bs_int3.pem: S10-badsign + I3 + _int3-bs.pem: S10 + I3-badsign + _int3_int-ca2.crt: S10 + I3 + I2 + _int3_int-ca2_ca.crt: S10 + I3 + I2 + 1 + _int3_spurious_int-ca2.crt: S10 + I3 + I1(spurious) + I2 Certificate revocation lists ---------------------------- From b889d3e5fbbb3ae16a2c23b77c6cd243486967dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 17 Aug 2017 10:25:18 +0200 Subject: [PATCH 091/148] Clarify & uniformise test comments --- tests/suites/test_suite_ecdh.data | 4 ++-- tests/suites/test_suite_ecdsa.data | 4 ++-- tests/suites/test_suite_ecp.data | 4 ++-- tests/suites/test_suite_pk.data | 6 +++--- tests/suites/test_suite_x509parse.data | 12 ++++++------ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/suites/test_suite_ecdh.data b/tests/suites/test_suite_ecdh.data index da30633ac..0165a7e0a 100644 --- a/tests/suites/test_suite_ecdh.data +++ b/tests/suites/test_suite_ecdh.data @@ -38,7 +38,7 @@ ECDH exchange #2 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED ecdh_exchange:MBEDTLS_ECP_DP_SECP521R1 -ECDH restartable rfc 5903 p256 restart enabled max_ops=0 +ECDH restartable rfc 5903 p256 restart enabled max_ops=0 (disabled) depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:0:0:0 @@ -54,7 +54,7 @@ ECDH restartable rfc 5903 p256 restart enabled max_ops=250 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":1:250:2:32 -ECDH restartable rfc 5903 p256 restart disabled max_ops=0 +ECDH restartable rfc 5903 p256 restart disabled max_ops=0 (disabled) depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecdh_restart:MBEDTLS_ECP_DP_SECP256R1:"C88F01F510D9AC3F70A292DAA2316DE544E9AAB8AFE84049C62A9C57862D1433":"C6EF9C5D78AE012A011164ACB397CE2088685D8F06BF9BE0B283AB46476BEE53":"D6840F6B42F6EDAFD13116E0E12565202FEF8E9ECE7DCE03812464D04B9442DE":0:0:0:0 diff --git a/tests/suites/test_suite_ecdsa.data b/tests/suites/test_suite_ecdsa.data index f9c8f6068..e07c4cd57 100644 --- a/tests/suites/test_suite_ecdsa.data +++ b/tests/suites/test_suite_ecdsa.data @@ -250,7 +250,7 @@ ECDSA deterministic test vector rfc 6979 p521 sha512 depends_on:MBEDTLS_ECP_DP_SECP521R1_ENABLED:MBEDTLS_SHA512_C ecdsa_det_test_vectors:MBEDTLS_ECP_DP_SECP521R1:"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83538":MBEDTLS_MD_SHA512:"test":"13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47EE6D":"1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4DCE3" -ECDSA restartable read-verify: restart disabled +ECDSA restartable read-verify: max_ops=0 (disabled) depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":0:0:0 @@ -266,7 +266,7 @@ ECDSA restartable read-verify: max_ops=250 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecdsa_read_restart:MBEDTLS_ECP_DP_SECP256R1:"04e8f573412a810c5f81ecd2d251bb94387e72f28af70dced90ebe75725c97a6428231069c2b1ef78509a22c59044319f6ed3cb750dfe64c2a282b35967a458ad6":"dee9d4d8b0e40a034602d6e638197998060f6e9f353ae1d10c94cd56476d3c92":"304502210098a5a1392abe29e4b0a4da3fefe9af0f8c32e5b839ab52ba6a05da9c3b7edd0f0220596f0e195ae1e58c1e53e9e7f0f030b274348a8c11232101778d89c4943f5ad2":250:4:64 -ECDSA restartable sign-write: secp256r1 restart disabled +ECDSA restartable sign-write: secp256r1 max_ops=0 (disabled) depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C ecdsa_write_restart:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0 diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data index 5bb8d024d..8c3e8f748 100644 --- a/tests/suites/test_suite_ecp.data +++ b/tests/suites/test_suite_ecp.data @@ -345,7 +345,7 @@ ecp_test_vect:MBEDTLS_ECP_DP_SECP256K1:"923C6D4756CD940CD1E13A359F6E0F0698791938 ECP selftest ecp_selftest: -ECP restartable mul secp256r1 restart disabled +ECP restartable mul secp256r1 max_ops=0 (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 @@ -361,7 +361,7 @@ ECP restartable mul secp256r1 max_ops=250 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_test_vect_restart:MBEDTLS_ECP_DP_SECP256R1:"814264145F2F56F2E96A8E337A1284993FAF432A5ABCE59E867B7291D507A3AF":"2AF502F3BE8952F2C9B5A8D4160D09E97165BE50BC42AE4A5E8D3B4BA83AEB15":"EB0FAF4CA986C4D38681A0F9872D79D56795BD4BFF6E6DE3C0F5015ECE5EFD85":"2CE1788EC197E096DB95A200CC0AB26A19CE6BCCAD562B8EEE1B593761CF7F41":"DD0F5396219D1EA393310412D19A08F1F5811E9DC8EC8EEA7F80D21C820C2788":"0357DCCD4C804D0D8D33AA42B848834AA5605F9AB0D37239A115BBB647936F50":250:2:32 -ECP restartable muladd secp256r1 restart disabled +ECP restartable muladd secp256r1 max_ops=0 (disabled) depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED ecp_muladd_restart:MBEDTLS_ECP_DP_SECP256R1:"CB28E0999B9C7715FD0A80D8E47A77079716CBBF917DD72E97566EA1C066957C":"2B57C0235FB7489768D058FF4911C20FDBE71E3699D91339AFBB903EE17255DC":"C3875E57C85038A0D60370A87505200DC8317C8C534948BEA6559C7C18E6D4CE":"3B4E49C4FDBFC006FF993C81A50EAE221149076D6EC09DDD9FB3B787F85B6483":"2442A5CC0ECD015FA3CA31DC8E2BBC70BF42D60CBCA20085E0822CB04235E970":"6FC98BD7E50211A4A27102FA3549DF79EBCB4BF246B80945CDDFE7D509BBFD7D":0:0:0 diff --git a/tests/suites/test_suite_pk.data b/tests/suites/test_suite_pk.data index bd3db182b..574011c90 100644 --- a/tests/suites/test_suite_pk.data +++ b/tests/suites/test_suite_pk.data @@ -154,11 +154,11 @@ RSA hash_len overflow (size_t vs unsigned int) depends_on:MBEDTLS_RSA_C:MBEDTLS_HAVE_INT64 pk_rsa_overflow: -ECDSA restartable sign/verify: ECDSA, restart disabled +ECDSA restartable sign/verify: ECDSA, max_ops=0 (disabled) depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0 -ECDSA restartable sign/verify: ECKEY, restart disabled +ECDSA restartable sign/verify: ECKEY, max_ops=0 (disabled) depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":0:0:0 @@ -182,6 +182,6 @@ ECDSA restartable sign/verify: ECDSA, max_ops=250 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C pk_sign_verify_restart:MBEDTLS_PK_ECDSA:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":250:2:64 -ECDSA restartable sign/verify: ECKEY, max_ops=1 +ECDSA restartable sign/verify: ECKEY, max_ops=250 depends_on:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C pk_sign_verify_restart:MBEDTLS_PK_ECKEY:MBEDTLS_ECP_DP_SECP256R1:"C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721":"60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6":"7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299":MBEDTLS_MD_SHA256:"test":"3045022100f1abb023518351cd71d881567b1ea663ed3efcf6c5132b354f28d3b0b7d383670220019f4113742a2b14bd25926b49c649155f267e60d3814b4c0cc84250e46f0083":250:2:64 diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 1c553b456..30274b58d 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -1806,7 +1806,7 @@ X509 Get time (UTC invalid character in sec) depends_on:MBEDTLS_X509_USE_C x509_get_time:MBEDTLS_ASN1_UTC_TIME:"0011302359n0Z":MBEDTLS_ERR_X509_INVALID_DATE:0:0:0:0:0:0 -X509 cert verify restart: trusted EE, max_ops=0 +X509 cert verify restart: trusted EE, max_ops=0 (disabled) depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED x509_verify_restart:"data_files/server5-selfsigned.crt":"data_files/server5-selfsigned.crt":0:0:0:0:0 @@ -1814,7 +1814,7 @@ X509 cert verify restart: trusted EE, max_ops=1 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED x509_verify_restart:"data_files/server5-selfsigned.crt":"data_files/server5-selfsigned.crt":0:0:1:0:0 -X509 cert verify restart: no intermediate, max_ops=0 +X509 cert verify restart: no intermediate, max_ops=0 (disabled) depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:0:0:0 @@ -1830,7 +1830,7 @@ X509 cert verify restart: no intermediate, max_ops=500 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED x509_verify_restart:"data_files/server5.crt":"data_files/test-ca2.crt":0:0:500:20:80 -X509 cert verify restart: no intermediate, badsign, max_ops=0 +X509 cert verify restart: no intermediate, badsign, max_ops=0 (disabled) depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0 @@ -1846,7 +1846,7 @@ X509 cert verify restart: no intermediate, badsign, max_ops=500 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED x509_verify_restart:"data_files/server5-badsign.crt":"data_files/test-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:500:20:80 -X509 cert verify restart: one int, max_ops=0 +X509 cert verify restart: one int, max_ops=0 (disabled) depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:0:0:0 @@ -1862,7 +1862,7 @@ X509 cert verify restart: one int, max_ops=500 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C x509_verify_restart:"data_files/server10_int3_int-ca2.crt":"data_files/test-int-ca2.crt":0:0:500:25:100 -X509 cert verify restart: one int, EE badsign, max_ops=0 +X509 cert verify restart: one int, EE badsign, max_ops=0 (disabled) depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0 @@ -1878,7 +1878,7 @@ X509 cert verify restart: one int, EE badsign, max_ops=500 depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C x509_verify_restart:"data_files/server10-bs_int3.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:500:25:100 -X509 cert verify restart: one int, int badsign, max_ops=0 +X509 cert verify restart: one int, int badsign, max_ops=0 (disabled) depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED:MBEDTLS_RSA_C x509_verify_restart:"data_files/server10_int3-bs.pem":"data_files/test-int-ca2.crt":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:MBEDTLS_X509_BADCERT_NOT_TRUSTED:0:0:0 From 98a6778d478b62423bbb6ba85ec638e9f10b2374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 17 Aug 2017 10:52:20 +0200 Subject: [PATCH 092/148] Better document some function arguments --- library/x509_crt.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index a0d1956dc..9ab376db2 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1949,6 +1949,16 @@ static int x509_crt_check_parent( const mbedtls_x509_crt *child, * way we select the correct one is by checking the signature (as we don't * rely on key identifier extensions). (This is one way users might choose to * handle key rollover, another relies on self-issued certs, see [SIRO].) + * + * Arguments: + * [in] child: certificate for which we want a parent + * [in] candidates: list of possible parents + * [out] r_parent: parent found (or NULL) + * [out] r_signature_is_good: 1 if child signature by parent is valid, or 0 + * [in] top: 1 if candidates are locally trusted, or 0 + * [in] path_cnt: number of links in the chain so far (EE -> ... -> child) + * [in] self_cnt: number of self-signed certs in the chain so far + * [in-out] rs_ctx: context for restarting operations */ static int x509_crt_find_parent_in( mbedtls_x509_crt *child, @@ -2061,6 +2071,17 @@ check_signature: * * Searches in trusted CAs first, and return the first suitable parent found * (see find_parent_in() for definition of suitable). + * + * Arguments: + * [in] child: certificate for which we want a parent, + * possibly followed by a list of ancestors + * [in] trust_ca: list of locally trusted certificates + * [out] parent: parent found (or NULL) + * [out] parent_is_trusted: 1 if returned `parent` is trusted, or 0 + * [out] signature_is_good: 1 if child signature by parent is valid, or 0 + * [in] path_cnt: number of links in the chain so far (EE -> ... -> child) + * [in] self_cnt: number of self-signed certs in the chain so far + * [in-out] rs_ctx: context for restarting operations */ static int x509_crt_find_parent( mbedtls_x509_crt *child, @@ -2187,6 +2208,7 @@ static int x509_crt_check_ee_locally_trusted( * - [in] trust_ca: the trusted list R1, ..., Rp * - [in] ca_crl, profile: as in verify_with_profile() * - [out] ver_chain: the built and verified chain + * - [in-out] rs_ctx: context for restarting operations * * Return value: * - non-zero if the chain could not be fully built and examined @@ -2311,7 +2333,7 @@ find_parent: return( MBEDTLS_ERR_X509_FATAL_ERROR ); } - /* signature was check while searching parent */ + /* signature was checked while searching parent */ if( ! signature_is_good ) *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; From 15d7df2ba8ca706b944b771958cd23b6c2163f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 17 Aug 2017 14:33:31 +0200 Subject: [PATCH 093/148] Introduce mbedtls_pk_restart_ctx and use it The fact that you needed to pass a pointer to mbedtls_ecdsa_restart_ctx (or that you needed to know the key type of the PK context) was a breach of abstraction. Change the API (and callers) now, and the implementation will be changed in the next commit. --- include/mbedtls/pk.h | 35 ++++++++++++++++++++++++----- include/mbedtls/x509_crt.h | 2 +- library/pk.c | 25 +++++++++++++++++++-- library/ssl_cli.c | 4 ++-- library/x509_crt.c | 6 ++--- tests/suites/test_suite_pk.function | 22 +++++++++--------- 6 files changed, 69 insertions(+), 25 deletions(-) diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index 05c51d38d..55b0668c2 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -129,6 +129,19 @@ typedef struct void * pk_ctx; /**< Underlying public key context */ } mbedtls_pk_context; +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Context for resuming operations + */ +typedef struct +{ + mbedtls_ecdsa_restart_ctx ecdsa; /* temporary */ +} mbedtls_pk_restart_ctx; +#else +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_pk_restart_ctx; +#endif + #if defined(MBEDTLS_RSA_C) /** * Quick access to an RSA context inside a PK context. @@ -188,6 +201,18 @@ void mbedtls_pk_init( mbedtls_pk_context *ctx ); */ void mbedtls_pk_free( mbedtls_pk_context *ctx ); +#if defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ); + +/** + * \brief Free the components of a restart context + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /** * \brief Initialize a PK context with the information given * and allocates the type-specific PK subcontext. @@ -298,8 +323,7 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, * \param hash_len Hash length or 0 (see notes) * \param sig Signature to verify * \param sig_len Signature length - * \param rs_ctx Restart context: for ECC, must be NULL (no restart) or a - * pointer to a \c mbedtls_ecdsa_restart_ctx. Ignored for RSA. + * \param rs_ctx Restart context (NULL to disable restart) * * \return See \c mbedtls_pk_verify(), or * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of @@ -309,7 +333,7 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, - void *rs_ctx ); + mbedtls_pk_restart_ctx *rs_ctx ); /** * \brief Verify signature, with options. @@ -390,8 +414,7 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, * \param sig_len Number of bytes written * \param f_rng RNG function * \param p_rng RNG parameter - * \param rs_ctx Restart context: for ECC, must be NULL (no restart) or a - * pointer to a \c mbedtls_ecdsa_restart_ctx. Ignored for RSA. + * \param rs_ctx Restart context (NULL to disable restart) * * \return See \c mbedtls_pk_sign(), or * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of @@ -402,7 +425,7 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - void *rs_ctx ); + mbedtls_pk_restart_ctx *rs_ctx ); /** * \brief Decrypt message (including padding if relevant). diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 7487df619..3388c3b93 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -172,7 +172,7 @@ typedef struct typedef struct { /* for check_signature() */ - mbedtls_ecdsa_restart_ctx ecdsa; + mbedtls_pk_restart_ctx pk; /* for find_parent_in() */ mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */ diff --git a/library/pk.c b/library/pk.c index e439c7ad8..27ca5f3eb 100644 --- a/library/pk.c +++ b/library/pk.c @@ -73,6 +73,27 @@ void mbedtls_pk_free( mbedtls_pk_context *ctx ) mbedtls_zeroize( ctx, sizeof( mbedtls_pk_context ) ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) +{ + mbedtls_ecdsa_restart_init( &ctx->ecdsa ); +} + +/* + * Free the components of a restart context + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_ecdsa_restart_free( &ctx->ecdsa ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* * Get pk_info structure from type */ @@ -182,7 +203,7 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, - void *rs_ctx ) + mbedtls_pk_restart_ctx *rs_ctx ) { if( ctx == NULL || ctx->pk_info == NULL || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) @@ -282,7 +303,7 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - void *rs_ctx ) + mbedtls_pk_restart_ctx *rs_ctx ) { if( ctx == NULL || ctx->pk_info == NULL || pk_hashlen_helper( md_alg, &hash_len ) != 0 ) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 7ffeb5bb4..d53f7b227 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2615,7 +2615,7 @@ ske_process: #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled ) - rs_ctx = &ssl->handshake->ecrs_ctx.ecdsa; + rs_ctx = &ssl->handshake->ecrs_ctx.pk; #endif if( ( ret = mbedtls_pk_verify_restartable( @@ -3290,7 +3290,7 @@ keys_derived: #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled ) - rs_ctx = &ssl->handshake->ecrs_ctx.ecdsa; + rs_ctx = &ssl->handshake->ecrs_ctx.pk; #endif if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), diff --git a/library/x509_crt.c b/library/x509_crt.c index 9ab376db2..a6f6a78d8 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1875,7 +1875,7 @@ static int x509_crt_check_signature( const mbedtls_x509_crt *child, { return( mbedtls_pk_verify_restartable( &parent->pk, child->sig_md, hash, mbedtls_md_get_size( md_info ), - child->sig.p, child->sig.len, &rs_ctx->ecdsa ) ); + child->sig.p, child->sig.len, &rs_ctx->pk ) ); } #else (void) rs_ctx; @@ -2653,7 +2653,7 @@ void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) */ void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) { - mbedtls_ecdsa_restart_init( &ctx->ecdsa ); + mbedtls_pk_restart_init( &ctx->pk ); ctx->parent = NULL; ctx->fallback_parent = NULL; @@ -2675,7 +2675,7 @@ void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) if( ctx == NULL ) return; - mbedtls_ecdsa_restart_free( &ctx->ecdsa ); + mbedtls_pk_restart_free( &ctx->pk ); mbedtls_x509_crt_restart_init( ctx ); } diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index 6e8c032c1..176b08f98 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -127,12 +127,12 @@ void pk_rsa_verify_test_vec( char *message_hex_string, int digest, mbedtls_rsa_context *rsa; mbedtls_pk_context pk; int msg_len; - void *rs_ctx = NULL; + mbedtls_pk_restart_ctx *rs_ctx = NULL; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - mbedtls_ecdsa_restart_ctx ctx; + mbedtls_pk_restart_ctx ctx; rs_ctx = &ctx; - mbedtls_ecdsa_restart_init( rs_ctx ); + mbedtls_pk_restart_init( rs_ctx ); mbedtls_ecp_set_max_ops( 42 ); #endif @@ -163,7 +163,7 @@ void pk_rsa_verify_test_vec( char *message_hex_string, int digest, exit: #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - mbedtls_ecdsa_restart_free( rs_ctx ); + mbedtls_pk_restart_free( rs_ctx ); #endif mbedtls_pk_free( &pk ); } @@ -274,7 +274,7 @@ void pk_sign_verify_restart( int pk_type, int grp_id, char *d_str, int max_ops, int min_restart, int max_restart ) { int ret, cnt_restart; - mbedtls_ecdsa_restart_ctx rs_ctx; + mbedtls_pk_restart_ctx rs_ctx; mbedtls_pk_context prv, pub; unsigned char hash[MBEDTLS_MD_MAX_SIZE]; unsigned char sig[MBEDTLS_ECDSA_MAX_LEN]; @@ -282,7 +282,7 @@ void pk_sign_verify_restart( int pk_type, int grp_id, char *d_str, size_t hlen, slen, slen_check; const mbedtls_md_info_t *md_info; - mbedtls_ecdsa_restart_init( &rs_ctx ); + mbedtls_pk_restart_init( &rs_ctx ); mbedtls_pk_init( &prv ); mbedtls_pk_init( &pub ); memset( hash, 0, sizeof( hash ) ); @@ -351,7 +351,7 @@ void pk_sign_verify_restart( int pk_type, int grp_id, char *d_str, ret = mbedtls_pk_verify_restartable( &pub, md_alg, hash, hlen, sig, slen, &rs_ctx ); TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); - mbedtls_ecdsa_restart_free( &rs_ctx ); + mbedtls_pk_restart_free( &rs_ctx ); slen = sizeof( sig ); ret = mbedtls_pk_sign_restartable( &prv, md_alg, hash, hlen, @@ -359,7 +359,7 @@ void pk_sign_verify_restart( int pk_type, int grp_id, char *d_str, TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); exit: - mbedtls_ecdsa_restart_free( &rs_ctx ); + mbedtls_pk_restart_free( &rs_ctx ); mbedtls_pk_free( &prv ); mbedtls_pk_free( &pub ); } @@ -373,10 +373,10 @@ void pk_sign_verify( int type, int sign_ret, int verify_ret ) size_t sig_len; void *rs_ctx = NULL; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - mbedtls_ecdsa_restart_ctx ctx; + mbedtls_pk_restart_ctx ctx; rs_ctx = &ctx; - mbedtls_ecdsa_restart_init( rs_ctx ); + mbedtls_pk_restart_init( rs_ctx ); mbedtls_ecp_set_max_ops( 42000 ); #endif @@ -429,7 +429,7 @@ void pk_sign_verify( int type, int sign_ret, int verify_ret ) exit: #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - mbedtls_ecdsa_restart_free( rs_ctx ); + mbedtls_pk_restart_free( rs_ctx ); #endif mbedtls_pk_free( &pk ); } From 0bbc66cc7695ede2f6efcb7eb3c8a1103f196a0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 18 Aug 2017 16:22:06 +0200 Subject: [PATCH 094/148] Dynamically allocate/free restart subcontext in PK --- include/mbedtls/pk.h | 3 +- include/mbedtls/pk_internal.h | 8 ++++ library/pk.c | 69 ++++++++++++++++++++++++++++++----- library/pk_wrap.c | 38 +++++++++++++++++++ 4 files changed, 108 insertions(+), 10 deletions(-) diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index 55b0668c2..8ec69856b 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -135,7 +135,8 @@ typedef struct */ typedef struct { - mbedtls_ecdsa_restart_ctx ecdsa; /* temporary */ + const mbedtls_pk_info_t * pk_info; /**< Public key informations */ + void * rs_ctx; /**< Underlying restart context */ } mbedtls_pk_restart_ctx; #else /* Now we can declare functions that take a pointer to that */ diff --git a/include/mbedtls/pk_internal.h b/include/mbedtls/pk_internal.h index e996b6cad..d56b0b334 100644 --- a/include/mbedtls/pk_internal.h +++ b/include/mbedtls/pk_internal.h @@ -94,6 +94,14 @@ struct mbedtls_pk_info_t /** Free the given context */ void (*ctx_free_func)( void *ctx ); +#if defined(MBEDTLS_ECP_RESTARTABLE) + /** Allocate the restart context */ + void * (*rs_alloc_func)( void ); + + /** Free the restart context */ + void (*rs_free_func)( void *rs_ctx ); +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /** Interface with the debug module */ void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); diff --git a/library/pk.c b/library/pk.c index 27ca5f3eb..70691d6e8 100644 --- a/library/pk.c +++ b/library/pk.c @@ -79,7 +79,8 @@ void mbedtls_pk_free( mbedtls_pk_context *ctx ) */ void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) { - mbedtls_ecdsa_restart_init( &ctx->ecdsa ); + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; } /* @@ -87,10 +88,16 @@ void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) */ void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) { - if( ctx == NULL ) + if( ctx == NULL || ctx->pk_info == NULL || + ctx->pk_info->rs_free_func == NULL ) + { return; + } - mbedtls_ecdsa_restart_free( &ctx->ecdsa ); + ctx->pk_info->rs_free_func( ctx->rs_ctx ); + + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; } #endif /* MBEDTLS_ECP_RESTARTABLE */ @@ -196,6 +203,30 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len return( 0 ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Helper to set up a restart context if needed + */ +static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, + const mbedtls_pk_info_t *info ) +{ + /* Don't do anything it already set up */ + if( ctx->pk_info != NULL ) + return( 0 ); + + /* Should never happen when we're called */ + if( info->rs_alloc_func == NULL || info->rs_free_func == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + /* * Verify a signature (restartable) */ @@ -210,10 +241,20 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); #if defined(MBEDTLS_ECP_RESTARTABLE) - if( ctx->pk_info->verify_rs_func != NULL ) + if( rs_ctx != NULL && ctx->pk_info->verify_rs_func != NULL ) { - return( ctx->pk_info->verify_rs_func( ctx->pk_ctx, - md_alg, hash, hash_len, sig, sig_len, rs_ctx ) ); + int ret; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx, + md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); } #else (void) rs_ctx; @@ -310,10 +351,20 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); #if defined(MBEDTLS_ECP_RESTARTABLE) - if( ctx->pk_info->sign_rs_func != NULL ) + if( rs_ctx != NULL && ctx->pk_info->sign_rs_func != NULL ) { - return( ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, - hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx ) ); + int ret; + + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); + + ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, + hash, hash_len, sig, sig_len, f_rng, p_rng, rs_ctx->rs_ctx ); + + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); + + return( ret ); } #else (void) rs_ctx; diff --git a/library/pk_wrap.c b/library/pk_wrap.c index 8b94d8129..0f935b2ad 100644 --- a/library/pk_wrap.c +++ b/library/pk_wrap.c @@ -189,6 +189,10 @@ const mbedtls_pk_info_t mbedtls_rsa_info = { rsa_check_pair_wrap, rsa_alloc_wrap, rsa_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif rsa_debug, }; #endif /* MBEDTLS_RSA_C */ @@ -401,6 +405,24 @@ static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +static void *eckey_rs_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_restart_init( ctx ); + + return( ctx ); +} + +static void eckey_rs_free( void *ctx ) +{ + mbedtls_ecdsa_restart_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + const mbedtls_pk_info_t mbedtls_eckey_info = { MBEDTLS_PK_ECKEY, "EC", @@ -426,6 +448,10 @@ const mbedtls_pk_info_t mbedtls_eckey_info = { eckey_check_pair, eckey_alloc_wrap, eckey_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_rs_alloc, + eckey_rs_free, +#endif eckey_debug, }; @@ -454,6 +480,10 @@ const mbedtls_pk_info_t mbedtls_eckeydh_info = { eckey_check_pair, eckey_alloc_wrap, /* Same underlying key structure */ eckey_free_wrap, /* Same underlying key structure */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif eckey_debug, /* Same underlying key structure */ }; #endif /* MBEDTLS_ECP_C */ @@ -555,6 +585,10 @@ const mbedtls_pk_info_t mbedtls_ecdsa_info = { eckey_check_pair, /* Compatible key structures */ ecdsa_alloc_wrap, ecdsa_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_rs_alloc, + eckey_rs_free, +#endif eckey_debug, /* Compatible key structures */ }; #endif /* MBEDTLS_ECDSA_C */ @@ -677,6 +711,10 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = { #endif rsa_alt_alloc_wrap, rsa_alt_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif NULL, }; From fe6877034d01306d073bbc3f8bee454ca7f2a58d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 18 Aug 2017 17:04:07 +0200 Subject: [PATCH 095/148] Keep PK layer context in the PK layer Previously we kept the ecdsa context created by the PK layer for ECDSA operations on ECKEY in the ecdsa_restart_ctx structure, which was wrong, and caused by the fact that we didn't have a proper handling of restart sub-contexts in the PK layer. --- include/mbedtls/ecdsa.h | 3 - library/ecdsa.c | 9 --- library/pk_wrap.c | 174 +++++++++++++++++++--------------------- 3 files changed, 82 insertions(+), 104 deletions(-) diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index 77842526c..ce94af871 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -91,9 +91,6 @@ typedef struct #if defined(MBEDTLS_ECDSA_DETERMINISTIC) mbedtls_ecdsa_restart_det_ctx *det; /*!< ecdsa_sign_det() sub-context */ #endif -#if defined(MBEDTLS_PK_C) - mbedtls_ecdsa_context *ecdsa; /*!< used by the PK layer */ -#endif } mbedtls_ecdsa_restart_ctx; #else /* MBEDTLS_ECP_RESTARTABLE */ diff --git a/library/ecdsa.c b/library/ecdsa.c index 8d1f9d632..487bbd8e5 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -780,9 +780,6 @@ void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx ) #if defined(MBEDTLS_ECDSA_DETERMINISTIC) ctx->det = NULL; #endif -#if defined(MBEDTLS_PK_C) - ctx->ecdsa = NULL; -#endif } /* @@ -805,12 +802,6 @@ void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx ) mbedtls_free( ctx->det ); ctx->det = NULL; #endif - -#if defined(MBEDTLS_PK_C) - mbedtls_ecdsa_free( ctx->ecdsa ); - mbedtls_free( ctx->ecdsa ); - ctx->ecdsa = NULL; -#endif } #endif /* MBEDTLS_ECP_RESTARTABLE */ diff --git a/library/pk_wrap.c b/library/pk_wrap.c index 0f935b2ad..824c9d435 100644 --- a/library/pk_wrap.c +++ b/library/pk_wrap.c @@ -273,53 +273,69 @@ static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx ); +/* + * Restart context for ECDSA operations with ECKEY context + * + * We need to store an actual ECDSA context, as we need to pass the same to + * the underlying ecdsa function, so we can't create it on the fly every time. + */ +typedef struct +{ + mbedtls_ecdsa_restart_ctx ecdsa_rs; + mbedtls_ecdsa_context ecdsa_ctx; +} eckey_restart_ctx; + +static void *eckey_rs_alloc( void ) +{ + eckey_restart_ctx *rs_ctx; + + void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); + + if( ctx != NULL ) + { + rs_ctx = ctx; + mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); + } + + return( ctx ); +} + +static void eckey_rs_free( void *ctx ) +{ + eckey_restart_ctx *rs_ctx; + + if( ctx == NULL) + return; + + rs_ctx = ctx; + mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); + + mbedtls_free( ctx ); +} + static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, const unsigned char *sig, size_t sig_len, - void *p_rs_ctx ) + void *rs_ctx ) { int ret; - mbedtls_ecdsa_context ecdsa, *p_ecdsa = &ecdsa; - mbedtls_ecdsa_restart_ctx *rs_ctx = p_rs_ctx; + eckey_restart_ctx *rs = rs_ctx; - mbedtls_ecdsa_init( &ecdsa ); + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); /* set up our own sub-context if needed */ - if( mbedtls_ecp_restart_enabled() && - rs_ctx != NULL && rs_ctx->ecdsa == NULL ) - { - rs_ctx->ecdsa = mbedtls_calloc( 1, sizeof( *rs_ctx->ecdsa ) ); - if( rs_ctx->ecdsa == NULL ) - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); - mbedtls_ecdsa_init( rs_ctx->ecdsa ); - MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( rs_ctx->ecdsa, ctx ) ); - } - - if( rs_ctx != NULL && rs_ctx->ecdsa != NULL ) - { - /* redirect to our context */ - p_ecdsa = rs_ctx->ecdsa; - } - else - { - MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( p_ecdsa, ctx ) ); - } - - MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( p_ecdsa, md_alg, hash, hash_len, - sig, sig_len, rs_ctx ) ); + MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, + md_alg, hash, hash_len, + sig, sig_len, &rs->ecdsa_rs ) ); cleanup: - /* clear our sub-context when not in progress (done or error) */ - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) - { - mbedtls_ecdsa_free( rs_ctx->ecdsa ); - mbedtls_free( rs_ctx->ecdsa ); - rs_ctx->ecdsa = NULL; - } - - mbedtls_ecdsa_free( &ecdsa ); - return( ret ); } @@ -327,50 +343,24 @@ static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, - void *p_rs_ctx ) + void *rs_ctx ) { int ret; - mbedtls_ecdsa_context ecdsa, *p_ecdsa = &ecdsa; - mbedtls_ecdsa_restart_ctx *rs_ctx = p_rs_ctx; + eckey_restart_ctx *rs = rs_ctx; - mbedtls_ecdsa_init( &ecdsa ); + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); /* set up our own sub-context if needed */ - if( mbedtls_ecp_restart_enabled() && - rs_ctx != NULL && rs_ctx->ecdsa == NULL ) - { - rs_ctx->ecdsa = mbedtls_calloc( 1, sizeof( *rs_ctx->ecdsa ) ); - if( rs_ctx->ecdsa == NULL ) - return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); - mbedtls_ecdsa_init( rs_ctx->ecdsa ); - MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( rs_ctx->ecdsa, ctx ) ); - } - - if( rs_ctx != NULL && rs_ctx->ecdsa != NULL ) - { - /* redirect to our context */ - p_ecdsa = rs_ctx->ecdsa; - } - else - { - MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( p_ecdsa, ctx ) ); - } - - MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( p_ecdsa, md_alg, hash, hash_len, - sig, sig_len, f_rng, p_rng, rs_ctx ) ); + MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, + hash, hash_len, sig, sig_len, + f_rng, p_rng, &rs->ecdsa_rs ) ); cleanup: - /* clear our sub-context when not in progress (done or error) */ - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) - { - mbedtls_ecdsa_free( rs_ctx->ecdsa ); - mbedtls_free( rs_ctx->ecdsa ); - rs_ctx->ecdsa = NULL; - } - - mbedtls_ecdsa_free( &ecdsa ); - return( ret ); } #endif /* MBEDTLS_ECP_RESTARTABLE */ @@ -405,24 +395,6 @@ static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); } -#if defined(MBEDTLS_ECP_RESTARTABLE) -static void *eckey_rs_alloc( void ) -{ - void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); - - if( ctx != NULL ) - mbedtls_ecdsa_restart_init( ctx ); - - return( ctx ); -} - -static void eckey_rs_free( void *ctx ) -{ - mbedtls_ecdsa_restart_free( ctx ); - mbedtls_free( ctx ); -} -#endif /* MBEDTLS_ECP_RESTARTABLE */ - const mbedtls_pk_info_t mbedtls_eckey_info = { MBEDTLS_PK_ECKEY, "EC", @@ -569,6 +541,24 @@ static void ecdsa_free_wrap( void *ctx ) mbedtls_free( ctx ); } +#if defined(MBEDTLS_ECP_RESTARTABLE) +static void *ecdsa_rs_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_restart_init( ctx ); + + return( ctx ); +} + +static void ecdsa_rs_free( void *ctx ) +{ + mbedtls_ecdsa_restart_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + const mbedtls_pk_info_t mbedtls_ecdsa_info = { MBEDTLS_PK_ECDSA, "ECDSA", @@ -586,8 +576,8 @@ const mbedtls_pk_info_t mbedtls_ecdsa_info = { ecdsa_alloc_wrap, ecdsa_free_wrap, #if defined(MBEDTLS_ECP_RESTARTABLE) - eckey_rs_alloc, - eckey_rs_free, + ecdsa_rs_alloc, + ecdsa_rs_free, #endif eckey_debug, /* Compatible key structures */ }; From aaa9814879d5a99d386a18b67a868d1f3e718cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 18 Aug 2017 17:30:37 +0200 Subject: [PATCH 096/148] Uniformize ifdefs to ECDSA_C+ECP_RESTARTABLE Some parts were already implicitly using this as the two ifdefs were nested, and some others didn't, which resulted in compile errors in some configs. This fixes those errors and saves a bit of code+RAM that was previously wasted when ECP_RESTARTABLE was defined but ECDSA_C wasn't --- include/mbedtls/pk.h | 10 +++++----- include/mbedtls/pk_internal.h | 8 ++++---- library/pk.c | 20 ++++++++++---------- library/pk_wrap.c | 18 +++++++----------- 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index 8ec69856b..1326b90d5 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -129,7 +129,7 @@ typedef struct void * pk_ctx; /**< Underlying public key context */ } mbedtls_pk_context; -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Context for resuming operations */ @@ -138,10 +138,10 @@ typedef struct const mbedtls_pk_info_t * pk_info; /**< Public key informations */ void * rs_ctx; /**< Underlying restart context */ } mbedtls_pk_restart_ctx; -#else +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* Now we can declare functions that take a pointer to that */ typedef void mbedtls_pk_restart_ctx; -#endif +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_RSA_C) /** @@ -202,7 +202,7 @@ void mbedtls_pk_init( mbedtls_pk_context *ctx ); */ void mbedtls_pk_free( mbedtls_pk_context *ctx ); -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** * \brief Initialize a restart context */ @@ -212,7 +212,7 @@ void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ); * \brief Free the components of a restart context */ void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); -#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** * \brief Initialize a PK context with the information given diff --git a/include/mbedtls/pk_internal.h b/include/mbedtls/pk_internal.h index d56b0b334..8370dc219 100644 --- a/include/mbedtls/pk_internal.h +++ b/include/mbedtls/pk_internal.h @@ -58,7 +58,7 @@ struct mbedtls_pk_info_t int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** Verify signature (restartable) */ int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg, const unsigned char *hash, size_t hash_len, @@ -71,7 +71,7 @@ struct mbedtls_pk_info_t unsigned char *sig, size_t *sig_len, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, void *rs_ctx ); -#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** Decrypt message */ int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, @@ -94,13 +94,13 @@ struct mbedtls_pk_info_t /** Free the given context */ void (*ctx_free_func)( void *ctx ); -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /** Allocate the restart context */ void * (*rs_alloc_func)( void ); /** Free the restart context */ void (*rs_free_func)( void *rs_ctx ); -#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /** Interface with the debug module */ void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); diff --git a/library/pk.c b/library/pk.c index 70691d6e8..fae517a85 100644 --- a/library/pk.c +++ b/library/pk.c @@ -73,7 +73,7 @@ void mbedtls_pk_free( mbedtls_pk_context *ctx ) mbedtls_zeroize( ctx, sizeof( mbedtls_pk_context ) ); } -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* * Initialize a restart context */ @@ -99,7 +99,7 @@ void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) ctx->pk_info = NULL; ctx->rs_ctx = NULL; } -#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* * Get pk_info structure from type @@ -203,7 +203,7 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len return( 0 ); } -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* * Helper to set up a restart context if needed */ @@ -225,7 +225,7 @@ static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, return( 0 ); } -#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ /* * Verify a signature (restartable) @@ -240,7 +240,7 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && ctx->pk_info->verify_rs_func != NULL ) { int ret; @@ -256,9 +256,9 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, return( ret ); } -#else +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ (void) rs_ctx; -#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ if( ctx->pk_info->verify_func == NULL ) return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); @@ -350,7 +350,7 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, pk_hashlen_helper( md_alg, &hash_len ) != 0 ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && ctx->pk_info->sign_rs_func != NULL ) { int ret; @@ -366,9 +366,9 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, return( ret ); } -#else +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ (void) rs_ctx; -#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ if( ctx->pk_info->sign_func == NULL ) return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); diff --git a/library/pk_wrap.c b/library/pk_wrap.c index 824c9d435..9ca555672 100644 --- a/library/pk_wrap.c +++ b/library/pk_wrap.c @@ -180,7 +180,7 @@ const mbedtls_pk_info_t mbedtls_rsa_info = { rsa_can_do, rsa_verify_wrap, rsa_sign_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) NULL, NULL, #endif @@ -189,7 +189,7 @@ const mbedtls_pk_info_t mbedtls_rsa_info = { rsa_check_pair_wrap, rsa_alloc_wrap, rsa_free_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) NULL, NULL, #endif @@ -410,17 +410,13 @@ const mbedtls_pk_info_t mbedtls_eckey_info = { #else /* MBEDTLS_ECDSA_C */ NULL, NULL, -#if defined(MBEDTLS_ECP_RESTARTABLE) - NULL, - NULL, -#endif #endif /* MBEDTLS_ECDSA_C */ NULL, NULL, eckey_check_pair, eckey_alloc_wrap, eckey_free_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) eckey_rs_alloc, eckey_rs_free, #endif @@ -443,7 +439,7 @@ const mbedtls_pk_info_t mbedtls_eckeydh_info = { eckeydh_can_do, NULL, NULL, -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) NULL, NULL, #endif @@ -452,7 +448,7 @@ const mbedtls_pk_info_t mbedtls_eckeydh_info = { eckey_check_pair, eckey_alloc_wrap, /* Same underlying key structure */ eckey_free_wrap, /* Same underlying key structure */ -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) NULL, NULL, #endif @@ -688,7 +684,7 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = { rsa_alt_can_do, NULL, rsa_alt_sign_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) NULL, NULL, #endif @@ -701,7 +697,7 @@ const mbedtls_pk_info_t mbedtls_rsa_alt_info = { #endif rsa_alt_alloc_wrap, rsa_alt_free_wrap, -#if defined(MBEDTLS_ECP_RESTARTABLE) +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) NULL, NULL, #endif From d55f776cb778c85cc017de4a3fbde059ad673691 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Fri, 18 Aug 2017 17:40:15 +0200 Subject: [PATCH 097/148] Skip context allocation if restart disabled --- library/pk.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/library/pk.c b/library/pk.c index fae517a85..9a6e86233 100644 --- a/library/pk.c +++ b/library/pk.c @@ -241,7 +241,10 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && ctx->pk_info->verify_rs_func != NULL ) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_enabled() && + ctx->pk_info->verify_rs_func != NULL ) { int ret; @@ -351,7 +354,10 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && ctx->pk_info->sign_rs_func != NULL ) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_enabled() && + ctx->pk_info->sign_rs_func != NULL ) { int ret; From 8b7b96bbd3ae77657c512a0addd5a8d9f2084c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 10:02:51 +0200 Subject: [PATCH 098/148] Fix typo --- include/mbedtls/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index fbfab63b0..d400dee97 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -571,7 +571,7 @@ * again later with the same arguments in order to further progress and * eventually complete the operation, see \c mbedtls_ecp_set_max_ops(). * - * This is usefull in non-threaded environments if you want to avoid blocking + * This is useful in non-threaded environments if you want to avoid blocking * for too long on ECC (hence, X509 or SSL/TLS) operations. * * Uncomment this macro to enable restartable ECC computations. From 83e923ba2b0a01215c0e230426191e82e589ca0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 10:55:41 +0200 Subject: [PATCH 099/148] Better initialisation of ver_chain Use dedicated function for consistency, and initialise flags to -1 as this is the safe value. --- library/x509_crt.c | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index a6f6a78d8..7d60a5786 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -207,6 +207,23 @@ static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, return( -1 ); } +/* + * Reset (init or clear) a verify_chain + */ +static void x509_crt_verify_chain_reset( + mbedtls_x509_crt_verify_chain *ver_chain ) +{ + size_t i; + + for( i = 0; i < MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE; i++ ) + { + ver_chain->items[i].crt = NULL; + ver_chain->items[i].flags = -1; + } + + ver_chain->len = 0; +} + /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ @@ -2258,8 +2275,9 @@ static int x509_crt_verify_chain( /* Add certificate to the verification chain */ cur = &ver_chain->items[ver_chain->len]; cur->crt = child; - flags = &cur->flags; + cur->flags = 0; ver_chain->len++; + flags = &cur->flags; /* Check time-validity (all certificates) */ if( mbedtls_x509_time_is_past( &child->valid_to ) ) @@ -2499,10 +2517,11 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, int ret; mbedtls_pk_type_t pk_type; mbedtls_x509_crt_verify_chain ver_chain; - uint32_t *ee_flags = &ver_chain.items[0].flags; + uint32_t ee_flags; *flags = 0; - memset( &ver_chain, 0, sizeof( ver_chain ) ); + ee_flags = 0; + x509_crt_verify_chain_reset( &ver_chain ); if( profile == NULL ) { @@ -2512,16 +2531,16 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, /* check name if requested */ if( cn != NULL ) - x509_crt_verify_name( crt, cn, ee_flags ); + x509_crt_verify_name( crt, cn, &ee_flags ); /* Check the type and size of the key */ pk_type = mbedtls_pk_get_type( &crt->pk ); if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) - *ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; + ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; if( x509_profile_check_key( profile, pk_type, &crt->pk ) != 0 ) - *ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; /* Check the chain */ ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, @@ -2530,6 +2549,9 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, if( ret != 0 ) goto exit; + /* Merge end-entity flags */ + ver_chain.items[0].flags |= ee_flags; + /* Build final flags, calling callback on the way if any */ ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); @@ -2663,8 +2685,7 @@ void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) ctx->child = NULL; ctx->self_cnt = 0; - memset( ctx->ver_chain.items, 0, sizeof( ctx->ver_chain.items ) ); - ctx->ver_chain.len = 0; + x509_crt_verify_chain_reset( &ctx->ver_chain ); } /* From 3627a8b2f63bafeba916eeed7408e3ff97b0f20b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 11:20:48 +0200 Subject: [PATCH 100/148] Clarify state handling in find_parent(_in)() --- library/x509_crt.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 7d60a5786..1a3eb2d96 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1992,13 +1992,20 @@ static int x509_crt_find_parent_in( int signature_is_good, fallback_sign_good; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* restore state if we have some stored */ + /* did we have something in progress? */ if( rs_ctx != NULL && rs_ctx->parent != NULL ) { + /* restore saved state */ parent = rs_ctx->parent; fallback_parent = rs_ctx->fallback_parent; fallback_sign_good = rs_ctx->fallback_sign_good; + /* clear saved state */ + rs_ctx->parent = NULL; + rs_ctx->fallback_parent = NULL; + rs_ctx->fallback_sign_good = 0; + + /* resume where we left */ goto check_signature; } #endif @@ -2070,16 +2077,6 @@ check_signature: *r_signature_is_good = fallback_sign_good; } -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL ) - { - /* reset state */ - rs_ctx->parent = NULL; - rs_ctx->fallback_parent = NULL; - rs_ctx->fallback_sign_good = 0; - } -#endif - return( 0 ); } @@ -2116,9 +2113,12 @@ static int x509_crt_find_parent( *parent_is_trusted = 1; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* restore state if we have some stored */ - if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1) + /* restore then clear saved state if we have some stored */ + if( rs_ctx != NULL && rs_ctx->parent_is_trusted != -1 ) + { *parent_is_trusted = rs_ctx->parent_is_trusted; + rs_ctx->parent_is_trusted = -1; + } #endif while( 1 ) { @@ -2155,12 +2155,6 @@ static int x509_crt_find_parent( signature_is_good = 0; } -#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) - /* reset state */ - if( rs_ctx != NULL ) - rs_ctx->parent_is_trusted = -1; -#endif - return( 0 ); } @@ -2254,7 +2248,7 @@ static int x509_crt_verify_chain( /* resume if we had an operation in progress */ if( rs_ctx != NULL && rs_ctx->child != NULL ) { - /* save state */ + /* restore saved state */ child = rs_ctx->child; self_cnt = rs_ctx->self_cnt; *ver_chain = rs_ctx->ver_chain; From a96884342928667f40ea8e27f178b701a2faea86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 11:23:59 +0200 Subject: [PATCH 101/148] Improve some comments in verify_chain() --- library/x509_crt.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 1a3eb2d96..69cec4db8 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2219,6 +2219,8 @@ static int x509_crt_check_ee_locally_trusted( * - [in] trust_ca: the trusted list R1, ..., Rp * - [in] ca_crl, profile: as in verify_with_profile() * - [out] ver_chain: the built and verified chain + * Only valid when return value is 0, may contain garbage otherwise! + * Restart note: need not be the same when calling again to resume. * - [in-out] rs_ctx: context for restarting operations * * Return value: @@ -2234,6 +2236,8 @@ static int x509_crt_verify_chain( mbedtls_x509_crt_verify_chain *ver_chain, mbedtls_x509_crt_restart_ctx *rs_ctx ) { + /* Don't initialize any of those variables here, so that the compiler can + * catch potential issues with jumping ahead when restarting */ int ret; uint32_t *flags; mbedtls_x509_crt_verify_chain_item *cur; @@ -2251,7 +2255,7 @@ static int x509_crt_verify_chain( /* restore saved state */ child = rs_ctx->child; self_cnt = rs_ctx->self_cnt; - *ver_chain = rs_ctx->ver_chain; + *ver_chain = rs_ctx->ver_chain; /* struct copy */ cur = &ver_chain->items[ver_chain->len - 1]; flags = &cur->flags; @@ -2312,7 +2316,7 @@ find_parent: /* save state */ rs_ctx->child = child; rs_ctx->self_cnt = self_cnt; - rs_ctx-> ver_chain = *ver_chain; + rs_ctx->ver_chain = *ver_chain; /* struct copy */ return( ret ); } From daf049144e84c9cb76511c61aa0b31159cfbc1c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 12:32:19 +0200 Subject: [PATCH 102/148] Rework state saving for verify_chain() Child was almost redundant as it's already saved in ver_chain, except it was multiplexed to also indicate whether an operation is in progress. This commit removes it and introduces an explicit state variable instead. This state can be useful later if we start returning IN_PROGRESS at other points than find_parent() (for example when checking CRL). Note that the state goes none -> find_parent and stays there until the context is free(), as it's only on the first call that nothing was in progress. --- include/mbedtls/x509_crt.h | 5 ++++- library/x509_crt.c | 11 ++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 3388c3b93..2f652b76d 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -183,7 +183,10 @@ typedef struct int parent_is_trusted; /* -1 if find_parent is not in progress */ /* for verify_chain() */ - mbedtls_x509_crt *child; /* non-null iff in progress */ + enum { + x509_crt_rs_none, + x509_crt_rs_find_parent, + } in_progress; /* none if no operation is in progress */ int self_cnt; mbedtls_x509_crt_verify_chain ver_chain; diff --git a/library/x509_crt.c b/library/x509_crt.c index 69cec4db8..586ec8375 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2250,14 +2250,15 @@ static int x509_crt_verify_chain( #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* resume if we had an operation in progress */ - if( rs_ctx != NULL && rs_ctx->child != NULL ) + if( rs_ctx != NULL && rs_ctx->in_progress == x509_crt_rs_find_parent ) { /* restore saved state */ - child = rs_ctx->child; - self_cnt = rs_ctx->self_cnt; *ver_chain = rs_ctx->ver_chain; /* struct copy */ + self_cnt = rs_ctx->self_cnt; + /* restore derived state */ cur = &ver_chain->items[ver_chain->len - 1]; + child = cur->crt; flags = &cur->flags; goto find_parent; @@ -2314,7 +2315,7 @@ find_parent: if( rs_ctx != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { /* save state */ - rs_ctx->child = child; + rs_ctx->in_progress = x509_crt_rs_find_parent; rs_ctx->self_cnt = self_cnt; rs_ctx->ver_chain = *ver_chain; /* struct copy */ @@ -2681,7 +2682,7 @@ void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) ctx->parent_is_trusted = -1; - ctx->child = NULL; + ctx->in_progress = x509_crt_rs_none; ctx->self_cnt = 0; x509_crt_verify_chain_reset( &ctx->ver_chain ); } From 7037e222ea661ca3b655c387fb8ff18951809f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 14:30:36 +0200 Subject: [PATCH 103/148] Improve comments and doc for ECP --- include/mbedtls/ecp.h | 19 +++++++--- library/ecp.c | 87 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 90 insertions(+), 16 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 04a557bdb..07ed110cd 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -310,9 +310,15 @@ typedef void mbedtls_ecp_restart_ctx; * MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the * function performing the computation. It is then the * caller's responsibility to either call again with the same - * arguments until it returns 0 or an error code; or to free + * parameters until it returns 0 or an error code; or to free * the restart context if the operation is to be aborted. * + * It is strictly required that all input parameters and the + * restart context be the same on successive calls for the + * same operation, but output parameters need not be the + * same; they must not be used until the function finally + * returns 0. + * * This only affects functions that accept a pointer to a * \c mbedtls_ecp_restart_ctx as an argument, and only works * if that pointer valid (in particular, not NULL). @@ -334,10 +340,13 @@ typedef void mbedtls_ecp_restart_ctx; * operations, and will do so even if max_ops is set to a * lower value. That minimum depends on the curve size, and * can be made lower by decreasing the value of - * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, with that - * parameter set to 4, the minimum amount of blocking is: - * - around 165 basic operations for P-256 - * - around 330 basic operations for P-384 + * \c MBEDTLS_ECP_WINDOW_SIZE. As an indication, here is the + * lowest effective value for various curves and values of + * that parameter (w for short): + * w=6 w=5 w=4 w=3 w=2 + * P-256 208 208 160 136 124 + * P-384 682 416 320 272 248 + * P-521 1364 832 640 544 496 * * \note This setting is currently ignored by Curve25519 */ diff --git a/library/ecp.c b/library/ecp.c index 74a19eecb..9a8f552b7 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -89,6 +89,13 @@ static unsigned long add_count, dbl_count, mul_count; #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Maximum number of "basic operations" to be done in a row. + * + * Default value 0 means that ECC operations will not yield. + * Note that regardless of the value of ecp_max_ops, always at + * least one step is performed before yielding. + * + * Setting ecp_max_ops=1 can be suitable for testing purposes + * as it will interrupt computation at all possible points. */ static unsigned ecp_max_ops = 0; @@ -1341,11 +1348,38 @@ cleanup: * modified version that provides resistance to SPA by avoiding zero * digits in the representation as in [3]. We modify the method further by * requiring that all K_i be odd, which has the small cost that our - * representation uses one more K_i, due to carries. + * representation uses one more K_i, due to carries, but saves on the size of + * the precomputed table. * - * Also, for the sake of compactness, only the seven low-order bits of x[i] - * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in - * the paper): it is set if and only if if s_i == -1; + * Summary of the comb method and its modifications: + * + * - The goal is to compute m*P for some w*d-bit integer m. + * + * - The basic comb method splits m into the w-bit integers + * x[0] .. x[d-1] where x[i] consists of the bits in m whose + * index has residue i modulo d, and computes m * P as + * S[x[0]] + 2 * S[x[1]] + .. + 2^(d-1) S[x[d-1]], where + * S[i_{w-1} .. i_0] := i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + i_0 P. + * + * - If it happens that, say, x[i+1]=0 (=> S[x[i+1]]=0), one can replace the sum by + * .. + 2^{i-1} S[x[i-1]] - 2^i S[x[i]] + 2^{i+1} S[x[i]] + 2^{i+2} S[x[i+2]] .., + * thereby successively converting it into a form where all summands + * are nonzero, at the cost of negative summands. This is the basic idea of [3]. + * + * - More generally, even if x[i+1] != 0, we can first transform the sum as + * .. - 2^i S[x[i]] + 2^{i+1} ( S[x[i]] + S[x[i+1]] ) + 2^{i+2} S[x[i+2]] .., + * and then replace S[x[i]] + S[x[i+1]] = S[x[i] ^ x[i+1]] + 2 S[x[i] & x[i+1]]. + * Performing and iterating this procedure for those x[i] that are even + * (keeping track of carry), we can transform the original sum into one of the form + * S[x'[0]] +- 2 S[x'[1]] +- .. +- 2^{d-1} S[x'[d-1]] + 2^d S[x'[d]] + * with all x'[i] odd. It is therefore only necessary to know S at odd indices, + * which is why we are only computing half of it in the first place in + * ecp_precompute_comb and accessing it with index abs(i) / 2 in ecp_select_comb. + * + * - For the sake of compactness, only the seven low-order bits of x[i] + * are used to represent its absolute value (K_i in the paper), and the msb + * of x[i] encodes the the sign (s_i in the paper): it is set if and only if + * if s_i == -1; * * Calling conventions: * - x is an array of size d + 1 @@ -1385,14 +1419,41 @@ static void ecp_comb_recode_core( unsigned char x[], size_t d, } /* - * Precompute points for the comb method + * Precompute points for the adapted comb method * - * If i = i_{w-1} ... i_1 is the binary representation of i, then - * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P + * Assumption: T must be able to hold 2^{w - 1} elements. * - * T must be able to hold 2^{w - 1} elements + * Operation: If i = i_{w-1} ... i_1 is the binary representation of i, + * sets T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P. * * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + * + * Note: Even comb values (those where P would be omitted from the + * sum defining T[i] above) are not needed in our adaption + * the the comb method. See ecp_comb_recode_core(). + * + * This function currently works in four steps: + * (1) Computation of intermediate T[i] for 2-powers values of i + * (restart state is ecp_rsm_init). + * (2) Normalization of coordinates of these T[i] + * (restart state is ecp_rsm_pre_norm_dbl). + * (3) Computation of all T[i] (restart state is ecp_rsm_pre_add). + * (4) Normalization of all T[i] (restart state is ecp_rsm_pre_norm_add) + * The final restart state is ecp_rsm_T_done. + * + * Step 1 can be interrupted but not the others; together with the final + * coordinate normalization they are the largest steps done at once, depending + * on the window size. Here are operation counts for P-256: + * + * step (2) (3) (4) + * w = 5 142 165 208 + * w = 4 136 77 160 + * w = 3 130 33 136 + * w = 2 124 11 124 + * + * So if ECC operations are blocking for too long even with a low max_ops + * value, it's useful to set MBEDTLS_ECP_WINDOW_SIZE to a lower value in order + * to minimize maximum blocking time. */ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point T[], const mbedtls_ecp_point *P, @@ -1534,6 +1595,8 @@ cleanup: /* * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + * + * See ecp_comb_recode_core() for background */ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_ecp_point T[], unsigned char t_len, @@ -1637,6 +1700,8 @@ cleanup: * As the actual scalar recoding needs an odd scalar as a starting point, * this wrapper ensures that by replacing m by N - m if necessary, and * informs the caller that the result of multiplication will be negated. + * + * See ecp_comb_recode_core() for background. */ static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, const mbedtls_mpi *m, @@ -1824,8 +1889,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* Pre-computed table: do we have it already for the base point? */ if( p_eq_g && grp->T != NULL ) { - /* second pointer to the same table - * no ownership transfer as other threads might be using T too */ + /* second pointer to the same table, will be deleted on exit */ T = grp->T; T_ok = 1; } @@ -1862,9 +1926,10 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, if( p_eq_g ) { + /* almost transfer ownership of T to the group, but keep a copy of + * the pointer to use for caling the next function more easily */ grp->T = T; grp->T_size = pre_len; - /* now have two pointers to the same table */ } } From eaf55beeadb90016fa0d6d6676844c0cca774306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 14:40:21 +0200 Subject: [PATCH 104/148] Misc documentation fixes/improvements --- include/mbedtls/ecdh.h | 6 +++++- include/mbedtls/ecdsa.h | 4 ++++ include/mbedtls/x509_crt.h | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h index 6f3fe137c..435ba00cb 100644 --- a/include/mbedtls/ecdh.h +++ b/include/mbedtls/ecdh.h @@ -40,6 +40,10 @@ typedef enum /** * \brief ECDH context structure + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. */ typedef struct { @@ -159,7 +163,7 @@ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, * ServerKeyEchange for static ECDH: import ECDH parameters * from a certificate's EC key information.) * - * \param ctx ECDH constext to set + * \param ctx ECDH context to set * \param key EC key to use * \param side Is it our key (1) or the peer's key (0) ? * diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index ce94af871..3440a84fe 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -52,6 +52,10 @@ extern "C" { /** * \brief ECDSA context structure + * + * \warning Performing multiple operations concurrently on the same + * ECDSA context is not supported; objects of this type + * should not be shared between multiple threads. */ typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 2f652b76d..683181270 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -425,7 +425,7 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, * \param flags result of the verification * \param f_vrfy verification function * \param p_vrfy verification parameter - * \param rs_ctx resart context + * \param rs_ctx restart context * * \return See \c mbedtls_crt_verify_with_profile(), or * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of From ebac5d3797504870e7997f29c5a95f21ee6c4e42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 16:23:36 +0200 Subject: [PATCH 105/148] Fix some whitespace & style issues --- library/ecdsa.c | 2 -- library/ecp.c | 71 +++++++++++++++---------------------------------- 2 files changed, 21 insertions(+), 52 deletions(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index 487bbd8e5..19d0004b5 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -268,7 +268,6 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, pk = &rs_ctx->sig->k; pr = &rs_ctx->sig->r; - /* jump to current step */ if( rs_ctx->sig->state == ecdsa_sig_mul ) goto mul; @@ -315,7 +314,6 @@ mul: } while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 ); - #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->sig != NULL ) rs_ctx->sig->state++; diff --git a/library/ecp.c b/library/ecp.c index 9a8f552b7..5217b55bd 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -85,7 +85,6 @@ static void mbedtls_zeroize( void *v, size_t n ) { static unsigned long add_count, dbl_count, mul_count; #endif - #if defined(MBEDTLS_ECP_RESTARTABLE) /* * Maximum number of "basic operations" to be done in a row. @@ -927,11 +926,10 @@ static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p return( 0 ); #if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_jac( grp, pt ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac( grp, pt ) ); #endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); /* @@ -981,10 +979,8 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, return( ecp_normalize_jac( grp, *T ) ); #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_jac_many( grp, T, t_len ) ); #endif if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) @@ -1104,10 +1100,8 @@ static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif #if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_double_jac( grp, R, P ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_jac( grp, R, P ) ); #endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); @@ -1202,10 +1196,8 @@ static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif #if defined(MBEDTLS_ECP_ADD_MIXED_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_add_mixed( grp, R, P, Q ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_add_mixed( grp, R, P, Q ) ); #endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ /* @@ -1289,10 +1281,8 @@ static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *p int count = 0; #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ) ); #endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ p_size = ( grp->pbits + 7 ) / 8; @@ -1798,7 +1788,6 @@ cleanup: return( ret ); } - /* * Pick window size based on curve size and whether we optimize for base point */ @@ -2004,10 +1993,8 @@ static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P int ret; #if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_normalize_mxz( grp, P ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_normalize_mxz( grp, P ) ); #endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); @@ -2035,10 +2022,8 @@ static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P int count = 0; #if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); #endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ p_size = ( grp->pbits + 7 ) / 8; @@ -2090,10 +2075,8 @@ static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; #if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) - if ( mbedtls_internal_ecp_grp_capable( grp ) ) - { - return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ); - } + if( mbedtls_internal_ecp_grp_capable( grp ) ) + return( mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ) ); #endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); @@ -2209,11 +2192,8 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #endif #if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) - { + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); - } - #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #if defined(MBEDTLS_ECP_RESTARTABLE) && defined(ECP_SHORTWEIERSTRASS) @@ -2243,11 +2223,8 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, cleanup: #if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable ) - { + if( is_grp_capable ) mbedtls_internal_ecp_free( grp ); - } - #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #if defined(MBEDTLS_ECP_RESTARTABLE) @@ -2378,11 +2355,8 @@ int mbedtls_ecp_muladd_restartable( mbedtls_ecp_point_init( &mP ); #if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) - { + if( ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) ) MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); - } - #endif /* MBEDTLS_ECP_INTERNAL_ALT */ #if defined(MBEDTLS_ECP_RESTARTABLE) @@ -2448,11 +2422,8 @@ norm: cleanup: #if defined(MBEDTLS_ECP_INTERNAL_ALT) - if ( is_grp_capable ) - { + if( is_grp_capable ) mbedtls_internal_ecp_free( grp ); - } - #endif /* MBEDTLS_ECP_INTERNAL_ALT */ mbedtls_ecp_point_free( &mP ); From 92cceb29bd2cab4a75311742986e637ff1f45e86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 16:27:29 +0200 Subject: [PATCH 106/148] Make some names more consistent --- library/ecp.c | 54 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 5217b55bd..365372a44 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -969,21 +969,21 @@ cleanup: * Cost: 1N(t) := 1I + (6t - 3)M + 1S */ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, - mbedtls_ecp_point *T[], size_t t_len ) + mbedtls_ecp_point *T[], size_t T_size ) { int ret; size_t i; mbedtls_mpi *c, u, Zi, ZZi; - if( t_len < 2 ) + if( T_size < 2 ) return( ecp_normalize_jac( grp, *T ) ); #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) if( mbedtls_internal_ecp_grp_capable( grp ) ) - return( mbedtls_internal_ecp_normalize_jac_many( grp, T, t_len ) ); + return( mbedtls_internal_ecp_normalize_jac_many( grp, T, T_size ) ); #endif - if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) + if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL ) return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); @@ -992,7 +992,7 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, * c[i] = Z_0 * ... * Z_i */ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); - for( i = 1; i < t_len; i++ ) + for( i = 1; i < T_size; i++ ) { MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); MOD_MUL( c[i] ); @@ -1001,9 +1001,9 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, /* * u = 1 / (Z_0 * ... * Z_n) mod P */ - MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[T_size-1], &grp->P ) ); - for( i = t_len - 1; ; i-- ) + for( i = T_size - 1; ; i-- ) { /* * Zi = 1 / Z_i mod p @@ -1043,7 +1043,7 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, cleanup: mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); - for( i = 0; i < t_len; i++ ) + for( i = 0; i < T_size; i++ ) mbedtls_mpi_free( &c[i] ); mbedtls_free( c ); @@ -1453,7 +1453,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, int ret; unsigned char i; size_t j = 0; - const unsigned char T_len = 1U << ( w - 1 ); + const unsigned char T_size = 1U << ( w - 1 ); mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; #if !defined(MBEDTLS_ECP_RESTARTABLE) @@ -1515,7 +1515,7 @@ norm_dbl: #endif j = 0; - for( i = 1; i < T_len; i <<= 1 ) + for( i = 1; i < T_size; i <<= 1 ) TT[j++] = T + i; MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); @@ -1535,9 +1535,9 @@ norm_dbl: add: #endif - MBEDTLS_ECP_BUDGET( ( T_len - 1 ) * MBEDTLS_ECP_OPS_ADD ); + MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD ); - for( i = 1; i < T_len; i <<= 1 ) + for( i = 1; i < T_size; i <<= 1 ) { j = i; while( j-- ) @@ -1558,7 +1558,7 @@ add: norm_add: #endif - for( j = 0; j + 1 < T_len; j++ ) + for( j = 0; j + 1 < T_size; j++ ) TT[j] = T + j + 1; MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV + 6 * j - 2 ); @@ -1589,7 +1589,7 @@ cleanup: * See ecp_comb_recode_core() for background */ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point T[], unsigned char t_len, + const mbedtls_ecp_point T[], unsigned char T_size, unsigned char i ) { int ret; @@ -1599,7 +1599,7 @@ static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, ii = ( i & 0x7Fu ) >> 1; /* Read the whole table to thwart cache-based timing attacks */ - for( j = 0; j < t_len; j++ ) + for( j = 0; j < T_size; j++ ) { MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); @@ -1619,7 +1619,7 @@ cleanup: * Cost: d A + d D + 1 R */ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, - const mbedtls_ecp_point T[], unsigned char t_len, + const mbedtls_ecp_point T[], unsigned char T_size, const unsigned char x[], size_t d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, @@ -1646,7 +1646,7 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R { /* Start with a non-zero point and randomize its coordinates */ i = d; - MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, T_size, x[i] ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); if( f_rng != 0 ) MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); @@ -1656,7 +1656,7 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R { MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD ); MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); - MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) ); MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); } @@ -1739,7 +1739,7 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, const mbedtls_mpi *m, const mbedtls_ecp_point *T, - unsigned char pre_len, + unsigned char T_size, unsigned char w, size_t d, int (*f_rng)(void *, unsigned char *, size_t), @@ -1767,7 +1767,7 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, { MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, &parity_trick ) ); - MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, pre_len, k, d, + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d, f_rng, p_rng, rs_ctx ) ); MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); @@ -1845,7 +1845,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, int ret; unsigned char w, p_eq_g = 0, i; size_t d; - unsigned char pre_len = 0, T_ok = 0; + unsigned char T_size = 0, T_ok = 0; mbedtls_ecp_point *T = NULL; #if !defined(MBEDTLS_ECP_RESTARTABLE) @@ -1872,7 +1872,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* Pick window size and deduce related sizes */ w = ecp_pick_window_size( grp, p_eq_g ); - pre_len = 1U << ( w - 1 ); + T_size = 1U << ( w - 1 ); d = ( grp->nbits + w - 1 ) / w; /* Pre-computed table: do we have it already for the base point? */ @@ -1900,7 +1900,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* Allocate table if we didn't have any */ if( T == NULL ) { - T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); + T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) ); if( T == NULL ) { ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; @@ -1918,13 +1918,13 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /* almost transfer ownership of T to the group, but keep a copy of * the pointer to use for caling the next function more easily */ grp->T = T; - grp->T_size = pre_len; + grp->T_size = T_size; } } /* Actual comb multiplication using precomputed points */ MBEDTLS_MPI_CHK( ecp_mul_comb_after_precomp( grp, R, m, - T, pre_len, w, d, + T, T_size, w, d, f_rng, p_rng, rs_ctx ) ); cleanup: @@ -1938,7 +1938,7 @@ cleanup: if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS && T != NULL ) { /* transfer ownership of T from local function to rsm */ - rs_ctx->rsm->T_size = pre_len; + rs_ctx->rsm->T_size = T_size; rs_ctx->rsm->T = T; T = NULL; } @@ -1947,7 +1947,7 @@ cleanup: /* did T belong to us? then let's destroy it! */ if( T != NULL ) { - for( i = 0; i < pre_len; i++ ) + for( i = 0; i < T_size; i++ ) mbedtls_ecp_point_free( &T[i] ); mbedtls_free( T ); } From 5bd38b1144420d234c4411914433ff31256e9168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 16:55:59 +0200 Subject: [PATCH 107/148] Replace memset() calls with xxx_init() calls And follow calloc() calls with xxx_init() too --- library/ecdh.c | 17 ++++++++++++++--- library/ecdsa.c | 18 ++++++++++-------- library/ecp.c | 48 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 61 insertions(+), 22 deletions(-) diff --git a/library/ecdh.c b/library/ecdh.c index cae3b290f..b8a7dbf0a 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -126,9 +126,18 @@ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, */ void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) { - memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); + mbedtls_ecp_group_init( &ctx->grp ); + mbedtls_mpi_init( &ctx->d ); + mbedtls_ecp_point_init( &ctx->Q ); + mbedtls_ecp_point_init( &ctx->Qp ); + mbedtls_mpi_init( &ctx->z ); + ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; + mbedtls_ecp_point_init( &ctx->Vi ); + mbedtls_ecp_point_init( &ctx->Vf ); + mbedtls_mpi_init( &ctx->_d ); #if defined(MBEDTLS_ECP_RESTARTABLE) + ctx->restart_enabled = 0; mbedtls_ecp_restart_init( &ctx->rs ); #endif } @@ -142,17 +151,19 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) return; mbedtls_ecp_group_free( &ctx->grp ); + mbedtls_mpi_free( &ctx->d ); mbedtls_ecp_point_free( &ctx->Q ); mbedtls_ecp_point_free( &ctx->Qp ); + mbedtls_mpi_free( &ctx->z ); mbedtls_ecp_point_free( &ctx->Vi ); mbedtls_ecp_point_free( &ctx->Vf ); - mbedtls_mpi_free( &ctx->d ); - mbedtls_mpi_free( &ctx->z ); mbedtls_mpi_free( &ctx->_d ); #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_free( &ctx->rs ); #endif + + mbedtls_ecdh_init( ctx ); } #if defined(MBEDTLS_ECP_RESTARTABLE) diff --git a/library/ecdsa.c b/library/ecdsa.c index 19d0004b5..f3b3cf26d 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -69,7 +69,9 @@ struct mbedtls_ecdsa_restart_ver */ static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx ) { - memset( ctx, 0, sizeof( *ctx ) ); + mbedtls_mpi_init( &ctx->u1 ); + mbedtls_mpi_init( &ctx->u2 ); + ctx->state = ecdsa_ver_init; } /* @@ -83,7 +85,7 @@ static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) mbedtls_mpi_free( &ctx->u1 ); mbedtls_mpi_free( &ctx->u2 ); - memset( ctx, 0, sizeof( *ctx ) ); + ecdsa_restart_ver_init( ctx ); } /* @@ -107,10 +109,11 @@ struct mbedtls_ecdsa_restart_sig */ static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx ) { - memset( ctx, 0, sizeof( *ctx ) ); - + ctx->sign_tries = 0; + ctx->key_tries = 0; mbedtls_mpi_init( &ctx->k ); mbedtls_mpi_init( &ctx->r ); + ctx->state = ecdsa_sig_init; } /* @@ -124,7 +127,7 @@ static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) mbedtls_mpi_free( &ctx->k ); mbedtls_mpi_free( &ctx->r ); - memset( ctx, 0, sizeof( *ctx ) ); + ecdsa_restart_sig_init( ctx ); } #if defined(MBEDTLS_ECDSA_DETERMINISTIC) @@ -145,9 +148,8 @@ struct mbedtls_ecdsa_restart_det */ static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx ) { - memset( ctx, 0, sizeof( *ctx ) ); - mbedtls_hmac_drbg_init( &ctx->rng_ctx ); + ctx->state = ecdsa_det_init; } /* @@ -160,7 +162,7 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) mbedtls_hmac_drbg_free( &ctx->rng_ctx ); - memset( ctx, 0, sizeof( *ctx ) ); + ecdsa_restart_det_init( ctx ); } #endif /* MBEDTLS_ECDSA_DETERMINISTIC */ diff --git a/library/ecp.c b/library/ecp.c index 365372a44..6675c475c 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -138,7 +138,11 @@ struct mbedtls_ecp_restart_mul */ static void ecp_restart_mul_init( mbedtls_ecp_restart_mul_ctx *ctx ) { - memset( ctx, 0, sizeof( mbedtls_ecp_restart_mul_ctx ) ); + mbedtls_ecp_point_init( &ctx->R ); + ctx->i = 0; + ctx->T = NULL; + ctx->T_size = 0; + ctx->state = ecp_rsm_init; } /* @@ -160,7 +164,7 @@ static void ecp_restart_mul_free( mbedtls_ecp_restart_mul_ctx *ctx ) mbedtls_free( ctx->T ); } - memset( ctx, 0, sizeof( mbedtls_ecp_restart_mul_ctx ) ); + ecp_restart_mul_init( ctx ); } /* @@ -183,7 +187,9 @@ struct mbedtls_ecp_restart_muladd */ static void ecp_restart_muladd_init( mbedtls_ecp_restart_muladd_ctx *ctx ) { - memset( ctx, 0, sizeof( *ctx ) ); + mbedtls_ecp_point_init( &ctx->mP ); + mbedtls_ecp_point_init( &ctx->R ); + ctx->state = ecp_rsma_mul1; } /* @@ -197,7 +203,7 @@ static void ecp_restart_muladd_free( mbedtls_ecp_restart_muladd_ctx *ctx ) mbedtls_ecp_point_free( &ctx->mP ); mbedtls_ecp_point_free( &ctx->R ); - memset( ctx, 0, sizeof( *ctx ) ); + ecp_restart_muladd_init( ctx ); } /* @@ -205,7 +211,10 @@ static void ecp_restart_muladd_free( mbedtls_ecp_restart_muladd_ctx *ctx ) */ void mbedtls_ecp_restart_init( mbedtls_ecp_restart_ctx *ctx ) { - memset( ctx, 0, sizeof( *ctx ) ); + ctx->ops_done = 0; + ctx->depth = 0; + ctx->rsm = NULL; + ctx->ma = NULL; } /* @@ -216,16 +225,13 @@ void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) if( ctx == NULL ) return; - ctx->ops_done = 0; - ctx->depth = 0; - ecp_restart_mul_free( ctx->rsm ); mbedtls_free( ctx->rsm ); - ctx->rsm = NULL; ecp_restart_muladd_free( ctx->ma ); mbedtls_free( ctx->ma ); - ctx->ma = NULL; + + mbedtls_ecp_restart_init( ctx ); } /* @@ -463,7 +469,21 @@ void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) if( grp == NULL ) return; - memset( grp, 0, sizeof( mbedtls_ecp_group ) ); + grp->id = 0; + mbedtls_mpi_init( &grp->P ); + mbedtls_mpi_init( &grp->A ); + mbedtls_mpi_init( &grp->B ); + mbedtls_ecp_point_init( &grp->G ); + mbedtls_mpi_init( &grp->N ); + grp->pbits = 0; + grp->nbits = 0; + grp->h = 0; + grp->modp = NULL; + grp->t_pre = NULL; + grp->t_post = NULL; + grp->t_data = NULL; + grp->T = NULL; + grp->T_size = 0; } /* @@ -986,6 +1006,9 @@ static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, if( ( c = mbedtls_calloc( T_size, sizeof( mbedtls_mpi ) ) ) == NULL ) return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + for( i = 0; i < T_size; i++ ) + mbedtls_mpi_init( &c[i] ); + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); /* @@ -1906,6 +1929,9 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; goto cleanup; } + + for( i = 0; i < T_size; i++ ) + mbedtls_ecp_point_init( &T[i] ); } /* Compute table (or finish computing it) if not done already */ From 28d162829b2a136f9e57b9b260ea2f43315fb597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 17:33:27 +0200 Subject: [PATCH 108/148] Avoid unnecessary xxx_copy() calls The call would anyway check for pointer equality and return early, but it doesn't hurt to save a function call, and also this follows more uniformly the pattern that those two lines go together: #if defined(MBEDTLS_ECP_RESTARTBLE) if( rs_ctx != NULL && ... --- library/ecdsa.c | 3 ++- library/ecp.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index f3b3cf26d..835d3de88 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -353,7 +353,8 @@ modn: while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); #if defined(MBEDTLS_ECP_RESTARTABLE) - mbedtls_mpi_copy( r, pr ); + if( rs_ctx != NULL && rs_ctx->sig != NULL ) + mbedtls_mpi_copy( r, pr ); #endif cleanup: diff --git a/library/ecp.c b/library/ecp.c index 6675c475c..a8c367a3d 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1804,7 +1804,8 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) - MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, RR ) ); #endif cleanup: From bfa1972b4fa47c9c6ce0230829109b42c4bc2ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 17:39:18 +0200 Subject: [PATCH 109/148] Remove redundant checks, save a few muls ecp_mul() already checks for this, and this check is not going away, so no need to do it twice (didn't even result in better error reporting) --- library/ecdh.c | 5 ----- library/ecdsa.c | 9 ++------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/library/ecdh.c b/library/ecdh.c index b8a7dbf0a..25a788b93 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -87,11 +87,6 @@ static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point_init( &P ); - /* - * Make sure Q is a valid pubkey before using it - */ - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, f_rng, p_rng, rs_ctx ) ); diff --git a/library/ecdsa.c b/library/ecdsa.c index 835d3de88..3fddc4e4d 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -498,13 +498,6 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, goto cleanup; } - /* - * Additional precaution: make sure Q is valid - * For ops count, group that together with step 4 - */ - ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); - MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); - /* * Step 3: derive MPI from hashed message */ @@ -513,6 +506,8 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, /* * Step 4: u1 = e / s mod n, u2 = r / s mod n */ + ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) ); From b948f7dc20a67a2a9dfd1cee78c721da10d42223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 17:58:40 +0200 Subject: [PATCH 110/148] Don't bother to free NULL subcontexts --- library/ecdsa.c | 5 ++++- library/ecp.c | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index 3fddc4e4d..73389bb94 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -172,6 +172,7 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) #define ECDSA_BUDGET( ops ) \ MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) ); +/* Call this when entering a function that needs its own sub-context */ #define ECDSA_RS_ENTER( SUB ) do { \ /* reset ops count for this call if top-level */ \ if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \ @@ -189,9 +190,11 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) } \ } while( 0 ) +/* Call this when leaving a function that needs its own sub-context */ #define ECDSA_RS_LEAVE( SUB ) do { \ /* clear our sub-context when not in progress (done or error) */ \ - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ { \ ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \ mbedtls_free( rs_ctx->SUB ); \ diff --git a/library/ecp.c b/library/ecp.c index a8c367a3d..0c9feae3f 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1989,7 +1989,8 @@ cleanup: /* clear our sub-context when not in progress (done or error) */ #if defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { ecp_restart_mul_free( rs_ctx->rsm ); mbedtls_free( rs_ctx->rsm ); @@ -2457,7 +2458,8 @@ cleanup: #if defined(MBEDTLS_ECP_RESTARTABLE) /* clear our sub-context when not in progress (done or error) */ - if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + if( rs_ctx != NULL && rs_ctx->ma != NULL && + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) { ecp_restart_muladd_free( rs_ctx->ma ); mbedtls_free( rs_ctx->ma ); From db4a8eb992f0d563a86ddf3998d8c45c619dad31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 23 Aug 2017 18:18:22 +0200 Subject: [PATCH 111/148] Use ECP_RS_ENTER/LEAVE() macros, as in ECDSA --- library/ecp.c | 115 ++++++++++++++++++++++---------------------------- 1 file changed, 51 insertions(+), 64 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 0c9feae3f..f2c7448a3 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -136,7 +136,7 @@ struct mbedtls_ecp_restart_mul /* * Init restart_mul sub-context */ -static void ecp_restart_mul_init( mbedtls_ecp_restart_mul_ctx *ctx ) +static void ecp_restart_rsm_init( mbedtls_ecp_restart_mul_ctx *ctx ) { mbedtls_ecp_point_init( &ctx->R ); ctx->i = 0; @@ -148,7 +148,7 @@ static void ecp_restart_mul_init( mbedtls_ecp_restart_mul_ctx *ctx ) /* * Free the components of a restart_mul sub-context */ -static void ecp_restart_mul_free( mbedtls_ecp_restart_mul_ctx *ctx ) +static void ecp_restart_rsm_free( mbedtls_ecp_restart_mul_ctx *ctx ) { unsigned char i; @@ -164,7 +164,7 @@ static void ecp_restart_mul_free( mbedtls_ecp_restart_mul_ctx *ctx ) mbedtls_free( ctx->T ); } - ecp_restart_mul_init( ctx ); + ecp_restart_rsm_init( ctx ); } /* @@ -185,7 +185,7 @@ struct mbedtls_ecp_restart_muladd /* * Init restart_muladd sub-context */ -static void ecp_restart_muladd_init( mbedtls_ecp_restart_muladd_ctx *ctx ) +static void ecp_restart_ma_init( mbedtls_ecp_restart_muladd_ctx *ctx ) { mbedtls_ecp_point_init( &ctx->mP ); mbedtls_ecp_point_init( &ctx->R ); @@ -195,7 +195,7 @@ static void ecp_restart_muladd_init( mbedtls_ecp_restart_muladd_ctx *ctx ) /* * Free the components of a restart_muladd sub-context */ -static void ecp_restart_muladd_free( mbedtls_ecp_restart_muladd_ctx *ctx ) +static void ecp_restart_ma_free( mbedtls_ecp_restart_muladd_ctx *ctx ) { if( ctx == NULL ) return; @@ -203,7 +203,7 @@ static void ecp_restart_muladd_free( mbedtls_ecp_restart_muladd_ctx *ctx ) mbedtls_ecp_point_free( &ctx->mP ); mbedtls_ecp_point_free( &ctx->R ); - ecp_restart_muladd_init( ctx ); + ecp_restart_ma_init( ctx ); } /* @@ -225,10 +225,10 @@ void mbedtls_ecp_restart_free( mbedtls_ecp_restart_ctx *ctx ) if( ctx == NULL ) return; - ecp_restart_mul_free( ctx->rsm ); + ecp_restart_rsm_free( ctx->rsm ); mbedtls_free( ctx->rsm ); - ecp_restart_muladd_free( ctx->ma ); + ecp_restart_ma_free( ctx->ma ); mbedtls_free( ctx->ma ); mbedtls_ecp_restart_init( ctx ); @@ -261,6 +261,44 @@ int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, return( 0 ); } +/* Call this when entering a function that needs its own sub-context */ +#define ECP_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \ + rs_ctx->ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecp_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ +} while( 0 ) + +/* Call this when leaving a function that needs its own sub-context */ +#define ECP_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecp_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->depth--; \ +} while( 0 ) + +#else /* MBEDTLS_ECP_RESTARTABLE */ + +#define ECP_RS_ENTER( sub ) (void) rs_ctx; +#define ECP_RS_LEAVE( sub ) (void) rs_ctx; + #endif /* MBEDTLS_ECP_RESTARTABLE */ #if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ @@ -1872,21 +1910,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, unsigned char T_size = 0, T_ok = 0; mbedtls_ecp_point *T = NULL; -#if !defined(MBEDTLS_ECP_RESTARTABLE) - (void) rs_ctx; -#endif - -#if defined(MBEDTLS_ECP_RESTARTABLE) - /* set up our own sub-context if needed */ - if( ecp_max_ops != 0 && rs_ctx != NULL && rs_ctx->rsm == NULL ) - { - rs_ctx->rsm = mbedtls_calloc( 1, sizeof( mbedtls_ecp_restart_mul_ctx ) ); - if( rs_ctx->rsm == NULL ) - return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); - - ecp_restart_mul_init( rs_ctx->rsm ); - } -#endif + ECP_RS_ENTER( rsm ); /* Is P the base point ? */ #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 @@ -1987,16 +2011,7 @@ cleanup: if( ret != 0 ) mbedtls_ecp_point_free( R ); - /* clear our sub-context when not in progress (done or error) */ -#if defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && rs_ctx->rsm != NULL && - ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) - { - ecp_restart_mul_free( rs_ctx->rsm ); - mbedtls_free( rs_ctx->rsm ); - rs_ctx->rsm = NULL; - } -#endif + ECP_RS_LEAVE( rsm ); return( ret ); } @@ -2373,10 +2388,6 @@ int mbedtls_ecp_muladd_restartable( char is_grp_capable = 0; #endif -#if !defined(MBEDTLS_ECP_RESTARTABLE) - (void) rs_ctx; -#endif - if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); @@ -2387,21 +2398,9 @@ int mbedtls_ecp_muladd_restartable( MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); #endif /* MBEDTLS_ECP_INTERNAL_ALT */ + ECP_RS_ENTER( ma ); + #if defined(MBEDTLS_ECP_RESTARTABLE) - /* reset ops count for this call if top-level */ - if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) - rs_ctx->ops_done = 0; - - /* set up our own sub-context if needed */ - if( ecp_max_ops != 0 && rs_ctx != NULL && rs_ctx->ma == NULL ) - { - rs_ctx->ma = mbedtls_calloc( 1, sizeof( mbedtls_ecp_restart_muladd_ctx ) ); - if( rs_ctx->ma == NULL ) - return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); - - ecp_restart_muladd_init( rs_ctx->ma ); - } - if( rs_ctx != NULL && rs_ctx->ma != NULL ) { /* redirect intermediate results to restart context */ @@ -2456,19 +2455,7 @@ cleanup: mbedtls_ecp_point_free( &mP ); -#if defined(MBEDTLS_ECP_RESTARTABLE) - /* clear our sub-context when not in progress (done or error) */ - if( rs_ctx != NULL && rs_ctx->ma != NULL && - ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) - { - ecp_restart_muladd_free( rs_ctx->ma ); - mbedtls_free( rs_ctx->ma ); - rs_ctx->ma = NULL; - } - - if( rs_ctx != NULL ) - rs_ctx->depth--; -#endif /* MBEDTLS_ECP_RESTARTABLE */ + ECP_RS_LEAVE( ma ); return( ret ); } From c9efa00871a253203be3a3fa1d618d4fd5567236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 24 Aug 2017 10:25:06 +0200 Subject: [PATCH 112/148] ECP: Use explicit state assignments Incrementing the state is error-prone as we can end up doing it too many times (loops) or not enough (skipped branches), or just make programming mistakes (eg. the state was incremented twice at the end, so it ended up with a value not in the enum...) This is the first step of the rework, the next one will rationalize where the state assignments are done. --- library/ecp.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index f2c7448a3..fc4838a0d 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1563,7 +1563,7 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { rs_ctx->rsm->i = 0; - rs_ctx->rsm->state++; + rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; } #endif @@ -1585,7 +1585,7 @@ norm_dbl: #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - rs_ctx->rsm->state++; + rs_ctx->rsm->state = ecp_rsm_pre_add; #endif /* @@ -1607,7 +1607,7 @@ add: #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - rs_ctx->rsm->state++; + rs_ctx->rsm->state = ecp_rsm_pre_norm_add; #endif /* @@ -1628,7 +1628,7 @@ norm_add: #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - rs_ctx->rsm->state++; + rs_ctx->rsm->state = ecp_rsm_T_done; #endif cleanup: @@ -1730,7 +1730,7 @@ cleanup: { if( ret == 0 ) { - rs_ctx->rsm->state++; + rs_ctx->rsm->state = ecp_rsm_final_norm; rs_ctx->rsm->i = 0; } else if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) @@ -1834,7 +1834,7 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - rs_ctx->rsm->state++; + rs_ctx->rsm->state = ecp_rsm_final_norm; #endif } @@ -2420,14 +2420,14 @@ int mbedtls_ecp_muladd_restartable( MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pmP, m, P, rs_ctx ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ma != NULL ) - rs_ctx->ma->state++; + rs_ctx->ma->state = ecp_rsma_mul2; mul2: #endif MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, pR, n, Q, rs_ctx ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ma != NULL ) - rs_ctx->ma->state++; + rs_ctx->ma->state = ecp_rsma_add; add: #endif @@ -2435,7 +2435,7 @@ add: MBEDTLS_MPI_CHK( ecp_add_mixed( grp, pR, pmP, pR ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ma != NULL ) - rs_ctx->ma->state++; + rs_ctx->ma->state = ecp_rsma_norm; norm: #endif From 4ed1dab474bbdbaaa6fb3191a533028d6442dca1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 24 Aug 2017 11:02:04 +0200 Subject: [PATCH 113/148] ECP: move state changes closer to operations Systematically assign state just before the next operation that may return, rather that just after the previous one. This makes things more local. (For example, previously precompute_comb() has to handle a state reset for mul_comb_core(), a kind of coupling that's best avoided.) Note that this change doesn't move the location of state updates relative to any potential return point, which is all that matters. --- library/ecp.c | 137 ++++++++++++++++++++++++-------------------------- 1 file changed, 66 insertions(+), 71 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index fc4838a0d..5f2c41b00 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -123,12 +123,13 @@ struct mbedtls_ecp_restart_mul size_t i; /* current index in various loops, 0 outside */ mbedtls_ecp_point *T; /* table for precomputed points */ unsigned char T_size; /* number of points in table T */ - enum { /* what's the next step ? */ - ecp_rsm_init = 0, /* just getting started */ + enum { /* what were we doing last time we returned? */ + ecp_rsm_init = 0, /* nothing so far, dummy initial state */ + ecp_rsm_pre_dbl, /* precompute 2^n multiples */ ecp_rsm_pre_norm_dbl, /* normalize precomputed 2^n multiples */ ecp_rsm_pre_add, /* precompute remaining points by adding */ ecp_rsm_pre_norm_add, /* normalize all precomputed points */ - ecp_rsm_T_done, /* call ecp_mul_comb_after_precomp() */ + ecp_rsm_comb_core, /* ecp_mul_comb_core() */ ecp_rsm_final_norm, /* do the final normalization */ } state; }; @@ -1484,13 +1485,10 @@ static void ecp_comb_recode_core( unsigned char x[], size_t d, * the the comb method. See ecp_comb_recode_core(). * * This function currently works in four steps: - * (1) Computation of intermediate T[i] for 2-powers values of i - * (restart state is ecp_rsm_init). - * (2) Normalization of coordinates of these T[i] - * (restart state is ecp_rsm_pre_norm_dbl). - * (3) Computation of all T[i] (restart state is ecp_rsm_pre_add). - * (4) Normalization of all T[i] (restart state is ecp_rsm_pre_norm_add) - * The final restart state is ecp_rsm_T_done. + * (1) [dbl] Computation of intermediate T[i] for 2-powers values of i + * (2) [norm_dbl] Normalization of coordinates of these T[i] + * (3) [add] Computation of all T[i] + * (4) [norm_add] Normalization of all T[i] * * Step 1 can be interrupted but not the others; together with the final * coordinate normalization they are the largest steps done at once, depending @@ -1524,12 +1522,14 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { - if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) - goto norm_add; - if( rs_ctx->rsm->state == ecp_rsm_pre_add ) - goto add; + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) + goto dbl; if( rs_ctx->rsm->state == ecp_rsm_pre_norm_dbl ) goto norm_dbl; + if( rs_ctx->rsm->state == ecp_rsm_pre_add ) + goto add; + if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) + goto norm_add; } #endif @@ -1537,6 +1537,18 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, * Set T[0] = P and * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) */ +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + rs_ctx->rsm->state = ecp_rsm_pre_dbl; + + /* initial state for the loop */ + rs_ctx->rsm->i = 0; + } + +dbl: +#endif + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) @@ -1559,19 +1571,14 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); } -#if defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - { - rs_ctx->rsm->i = 0; - rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; - } -#endif - /* * Normalize current elements in T. As T has holes, * use an auxiliary array of pointers to elements in T. */ #if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; + norm_dbl: #endif @@ -1583,16 +1590,14 @@ norm_dbl: MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); -#if defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - rs_ctx->rsm->state = ecp_rsm_pre_add; -#endif - /* * Compute the remaining ones using the minimal number of additions * Be careful to update T[2^l] only after using it! */ #if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_add; + add: #endif @@ -1605,17 +1610,15 @@ add: MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); } -#if defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - rs_ctx->rsm->state = ecp_rsm_pre_norm_add; -#endif - /* * Normalize final elements in T. Even though there are no holes now, * we still need the auxiliary array for homogeneity with last time. * Also, skip T[0] which is already normalised, being a copy of P. */ #if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + rs_ctx->rsm->state = ecp_rsm_pre_norm_add; + norm_add: #endif @@ -1626,17 +1629,12 @@ norm_add: MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); -#if defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - rs_ctx->rsm->state = ecp_rsm_T_done; -#endif - cleanup: #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - if( rs_ctx->rsm->state == ecp_rsm_init ) + if( rs_ctx->rsm->state == ecp_rsm_pre_dbl ) rs_ctx->rsm->i = j; } #endif @@ -1697,6 +1695,14 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R #endif #if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + rs_ctx->rsm->state != ecp_rsm_comb_core ) + { + rs_ctx->rsm->i = 0; + rs_ctx->rsm->state = ecp_rsm_comb_core; + } + + /* new 'if' instead of nested for the sake of the 'else' branch */ if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->i != 0 ) { /* restore current index (R already pointing to rs_ctx->rsm->R) */ @@ -1726,19 +1732,12 @@ cleanup: mbedtls_ecp_point_free( &Txi ); #if defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && + ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - if( ret == 0 ) - { - rs_ctx->rsm->state = ecp_rsm_final_norm; - rs_ctx->rsm->i = 0; - } - else if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) - { - /* was decreased before actually doing it */ - rs_ctx->rsm->i = i + 1; - /* no need to save R, already pointing to rs_ctx->rsm->R */ - } + /* was decreased before actually doing it */ + rs_ctx->rsm->i = i + 1; + /* no need to save R, already pointing to rs_ctx->rsm->R */ } #endif @@ -1812,32 +1811,28 @@ static int ecp_mul_comb_after_precomp( const mbedtls_ecp_group *grp, unsigned char k[COMB_MAX_D + 1]; mbedtls_ecp_point *RR = R; -#if !defined(MBEDTLS_ECP_RESTARTABLE) - (void) rs_ctx; +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( rs_ctx != NULL && rs_ctx->rsm != NULL ) + { + RR = &rs_ctx->rsm->R; + + if( rs_ctx->rsm->state == ecp_rsm_final_norm ) + goto final_norm; + } #endif + MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, + &parity_trick ) ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d, + f_rng, p_rng, rs_ctx ) ); + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); + #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - RR = &rs_ctx->rsm->R; -#endif + rs_ctx->rsm->state = ecp_rsm_final_norm; -#if defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx == NULL || rs_ctx->rsm == NULL || - rs_ctx->rsm->state < ecp_rsm_final_norm ) +final_norm: #endif - { - MBEDTLS_MPI_CHK( ecp_comb_recode_scalar( grp, m, k, d, w, - &parity_trick ) ); - MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, RR, T, T_size, k, d, - f_rng, p_rng, rs_ctx ) ); - MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, RR, parity_trick ) ); - -#if defined(MBEDTLS_ECP_RESTARTABLE) - if( rs_ctx != NULL && rs_ctx->rsm != NULL ) - rs_ctx->rsm->state = ecp_rsm_final_norm; -#endif - } - MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_INV ); MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, RR ) ); @@ -1940,7 +1935,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, rs_ctx->rsm->T = NULL; rs_ctx->rsm->T_size = 0; - if( rs_ctx->rsm->state >= ecp_rsm_T_done ) + if( rs_ctx->rsm->state >= ecp_rsm_comb_core ) T_ok = 1; } #endif From 6348181da956c97da6658f0e38b307ac0be0497d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 24 Aug 2017 11:16:01 +0200 Subject: [PATCH 114/148] Explicit state assignments in ecdsa too --- library/ecdsa.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index 73389bb94..981846bb4 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -307,9 +307,7 @@ static int ecdsa_sign_restartable( mbedtls_ecp_group *grp, #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->sig != NULL ) - { - rs_ctx->sig->state++; - } + rs_ctx->sig->state = ecdsa_sig_mul; mul: #endif @@ -321,7 +319,7 @@ mul: #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->sig != NULL ) - rs_ctx->sig->state++; + rs_ctx->sig->state = ecdsa_sig_modn; modn: #endif @@ -426,7 +424,7 @@ static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp, #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->det != NULL ) - rs_ctx->det->state++; + rs_ctx->det->state = ecdsa_det_sign; sign: #endif @@ -521,7 +519,7 @@ static int ecdsa_verify_restartable( mbedtls_ecp_group *grp, #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->ver != NULL ) - rs_ctx->ver->state++; + rs_ctx->ver->state = ecdsa_ver_muladd; muladd: #endif From 0b23f167ba288083a46deb7655e9d9c1f8821c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 24 Aug 2017 12:08:33 +0200 Subject: [PATCH 115/148] SSL: rework restart state handling As done by previous commits for ECC and ECDSA: - use explicit state assignments rather than increment - always place the state update right before the operation label This will make it easier to add restart support for other operations later if desired. SSL-specific changes: - remove useless states: when the last restartable operation on a message is complete, ssl->state is incremented already, so we don't need any additional state update: ecrs_state is only meant to complement ssl->state - rename remaining states consistently as _ - move some labels closer to the actual operation when possible (no assignment to variables used after the label between its previous and current position) --- include/mbedtls/ssl_internal.h | 20 +++++-------- library/ssl_cli.c | 54 +++++++++++++--------------------- library/ssl_tls.c | 9 ++---- 3 files changed, 30 insertions(+), 53 deletions(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 4cfe1540c..036b60a06 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -229,18 +229,14 @@ struct mbedtls_ssl_handshake_params #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) int ecrs_enabled; /*!< Handshake supports EC restart? */ mbedtls_x509_crt_restart_ctx ecrs_ctx; /*!< restart context */ - enum { - ssl_ecrs_init = 0, /*!< just getting started */ - ssl_ecrs_crt_parsed, /*!< server certificate was parsed */ - ssl_ecrs_crt_verified, /*!< server certificate was verified*/ - ssl_ecrs_ske_read, /*!< ServerKeyExchange was read */ - ssl_ecrs_ske_verified, /*!< ServerKeyExchange was verified */ - ssl_ecrs_ecdh_public_done, /*!< wrote ECDHE public share */ - ssl_ecrs_ecdh_completed, /*!< completed ECDHE key exchange */ - ssl_ecrs_keys_derived, /*!< ssl_derive_keys() done */ - ssl_ecrs_pk_sign_done, /*!< done writing CertificateVerify */ - } ecrs_state; /*!< state for restartable ECC */ - size_t ecrs_n; /*!< place for seving a length */ + enum { /* this complements ssl->state with info on intra-state operations */ + ssl_ecrs_none = 0, /*!< nothing going on (yet) */ + ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ + ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: step 1 */ + ssl_ecrs_ske_ecdh_calc_secret, /*!< ServerKeyExchange: ECDH step 2 */ + ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ + } ecrs_state; /*!< current (or last) operation */ + size_t ecrs_n; /*!< place for saving a length */ #endif #if defined(MBEDTLS_SSL_PROTO_DTLS) unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */ diff --git a/library/ssl_cli.c b/library/ssl_cli.c index d53f7b227..cf83e8fae 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2305,9 +2305,9 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled && - ssl->handshake->ecrs_state == ssl_ecrs_ske_read ) + ssl->handshake->ecrs_state == ssl_ecrs_ske_start_processing ) { - goto ske_process; + goto start_processing; } #endif @@ -2317,12 +2317,6 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl ) return( ret ); } -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ecrs_enabled ) - ssl->handshake->ecrs_state++; - -ske_process: -#endif if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) ); @@ -2354,6 +2348,12 @@ ske_process: return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_ske_start_processing; + +start_processing: +#endif p = ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ); end = ssl->in_msg + ssl->in_hslen; MBEDTLS_SSL_DEBUG_BUF( 3, "server key exchange", p, end - p ); @@ -2630,11 +2630,6 @@ ske_process: MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); return( ret ); } - -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ecrs_enabled ) - ssl->handshake->ecrs_state++; -#endif } #endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */ @@ -2901,7 +2896,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled ) { - if( ssl->handshake->ecrs_state == ssl_ecrs_ecdh_public_done ) + if( ssl->handshake->ecrs_state == ssl_ecrs_ske_ecdh_calc_secret ) goto ecdh_calc_secret; mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); @@ -2924,7 +2919,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) if( ssl->handshake->ecrs_enabled ) { ssl->handshake->ecrs_n = n; - ssl->handshake->ecrs_state++; + ssl->handshake->ecrs_state = ssl_ecrs_ske_ecdh_calc_secret; } ecdh_calc_secret: @@ -2942,11 +2937,6 @@ ecdh_calc_secret: } MBEDTLS_SSL_DEBUG_MPI( 3, "ECDH: z", &ssl->handshake->ecdh_ctx.z ); - -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ecrs_enabled ) - ssl->handshake->ecrs_state++; -#endif } else #endif /* MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED || @@ -3167,9 +3157,9 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled && - ssl->handshake->ecrs_state == ssl_ecrs_keys_derived ) + ssl->handshake->ecrs_state == ssl_ecrs_crt_vrfy_sign ) { - goto keys_derived; + goto sign; } #endif @@ -3179,12 +3169,6 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) return( ret ); } -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ecrs_enabled ) - ssl->handshake->ecrs_state++; - -keys_derived: -#endif if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || @@ -3210,8 +3194,15 @@ keys_derived: } /* - * Make an RSA signature of the handshake digests + * Make a signature of the handshake digests */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_enabled ) + ssl->handshake->ecrs_state = ssl_ecrs_crt_vrfy_sign; + +sign: +#endif + ssl->handshake->calc_verify( ssl, hash ); #if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \ @@ -3302,11 +3293,6 @@ keys_derived: return( ret ); } -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ecrs_enabled ) - ssl->handshake->ecrs_state++; -#endif - ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); ssl->out_msg[5 + offset] = (unsigned char)( n ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index f3cde7f0a..6d9420c61 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4554,7 +4554,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled && - ssl->handshake->ecrs_state == ssl_ecrs_crt_parsed ) + ssl->handshake->ecrs_state == ssl_ecrs_crt_verify ) { goto crt_verify; } @@ -4584,7 +4584,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled) - ssl->handshake->ecrs_state++; + ssl->handshake->ecrs_state = ssl_ecrs_crt_verify; crt_verify: if( ssl->handshake->ecrs_enabled) @@ -4726,11 +4726,6 @@ crt_verify: #endif /* MBEDTLS_DEBUG_C */ } -#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ssl->handshake->ecrs_enabled) - ssl->handshake->ecrs_state++; -#endif - ssl->state++; MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) ); From 11556e2846728f33f70155e58831a6079740b71b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 24 Aug 2017 13:41:19 +0200 Subject: [PATCH 116/148] Clarify initialization of T in mul_comb() Exactly one of three ways will be used, so make that clear by using an if 1 else if 2 else 3 structure. While at it, don't initialize variables at declaration, just to make extra sure they're properly initialized afterwards in all code paths. --- library/ecp.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 5f2c41b00..428dc68cf 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1885,7 +1885,7 @@ static unsigned char ecp_pick_window_size( const mbedtls_ecp_group *grp, * * This function is mainly responsible for administrative work: * - managing the restart context if enabled - * - managing the table of precomputed points (passed between the above two + * - managing the table of precomputed points (passed between the below two * functions): allocation, computation, ownership tranfer, freeing. * * It delegates the actual arithmetic work to: @@ -1900,10 +1900,10 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, mbedtls_ecp_restart_ctx *rs_ctx ) { int ret; - unsigned char w, p_eq_g = 0, i; + unsigned char w, p_eq_g, i; size_t d; - unsigned char T_size = 0, T_ok = 0; - mbedtls_ecp_point *T = NULL; + unsigned char T_size, T_ok; + mbedtls_ecp_point *T; ECP_RS_ENTER( rsm ); @@ -1925,23 +1925,21 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, T = grp->T; T_ok = 1; } - + else #if defined(MBEDTLS_ECP_RESTARTABLE) /* Pre-computed table: do we have one in progress? complete? */ - if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL && T == NULL ) + if( rs_ctx != NULL && rs_ctx->rsm != NULL && rs_ctx->rsm->T != NULL ) { /* transfer ownership of T from rsm to local function */ T = rs_ctx->rsm->T; rs_ctx->rsm->T = NULL; rs_ctx->rsm->T_size = 0; - if( rs_ctx->rsm->state >= ecp_rsm_comb_core ) - T_ok = 1; + T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; } + else #endif - /* Allocate table if we didn't have any */ - if( T == NULL ) { T = mbedtls_calloc( T_size, sizeof( mbedtls_ecp_point ) ); if( T == NULL ) @@ -1952,6 +1950,8 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, for( i = 0; i < T_size; i++ ) mbedtls_ecp_point_init( &T[i] ); + + T_ok = 0; } /* Compute table (or finish computing it) if not done already */ From 95aedfea331344b381db9c90cd11c0fcf3ce9532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 24 Aug 2017 13:47:04 +0200 Subject: [PATCH 117/148] Remove redundant test on curve type If rsm != NULL then the curve type has to be Short Weierstrass, as we don't implement restartable Montgomery now. If and when we do, then it's better to check for the subcontext only, and not for the curve type. --- library/ecp.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 428dc68cf..454820ae5 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -2234,10 +2234,9 @@ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); #endif /* MBEDTLS_ECP_INTERNAL_ALT */ -#if defined(MBEDTLS_ECP_RESTARTABLE) && defined(ECP_SHORTWEIERSTRASS) +#if defined(MBEDTLS_ECP_RESTARTABLE) /* skip argument check when restarting */ - if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS || - rs_ctx == NULL || rs_ctx->rsm == NULL ) + if( rs_ctx == NULL || rs_ctx->rsm == NULL ) #endif { /* check_privkey is free */ From fd87e354f6e1b24b1b2c5f34899e5a97754293fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 24 Aug 2017 14:21:05 +0200 Subject: [PATCH 118/148] Improve comments on parity trick --- include/mbedtls/ecp.h | 2 +- library/ecp.c | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 07ed110cd..a30e87611 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -119,7 +119,7 @@ mbedtls_ecp_point; * 1. Short Weierstrass y^2 = x^3 + A x + B mod P (SEC1 + RFC 4492) * 2. Montgomery, y^2 = x^3 + A x^2 + x mod P (Curve25519 + draft) * In both cases, a generator G for a prime-order subgroup is fixed. In the - * short weierstrass, this subgroup is actually the whole curve, and its + * Short Weierstrass case, this subgroup is actually the whole curve, and its * cardinal is denoted by N. * * In the case of Short Weierstrass curves, our code requires that N is an odd diff --git a/library/ecp.c b/library/ecp.c index 454820ae5..41bf03d31 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1751,6 +1751,9 @@ cleanup: * this wrapper ensures that by replacing m by N - m if necessary, and * informs the caller that the result of multiplication will be negated. * + * This works because we only support large prime order for Short Weierstrass + * curves, so N is always odd hence either m or N - m is. + * * See ecp_comb_recode_core() for background. */ static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, @@ -1766,7 +1769,7 @@ static int ecp_comb_recode_scalar( const mbedtls_ecp_group *grp, mbedtls_mpi_init( &M ); mbedtls_mpi_init( &mm ); - /* N is odd with all real-world curves, just make extra sure */ + /* N is always odd (see above), just make extra sure */ if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); From 46ba7f3a92203852e04d79912e008fb0d4a9c5dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 28 Aug 2017 12:20:39 +0200 Subject: [PATCH 119/148] Avoid running useless code in tests With max_ops set to 0 or a very large value, we would always be doing an extra full operation for no testing value. --- tests/suites/test_suite_ecdsa.function | 24 +++++++++----- tests/suites/test_suite_ecp.function | 46 ++++++++++++-------------- tests/suites/test_suite_pk.function | 22 +++++++----- 3 files changed, 50 insertions(+), 42 deletions(-) diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index 9205627be..5db01a6cc 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -254,10 +254,14 @@ void ecdsa_read_restart( int id, char *k_str, char *h_str, char *s_str, TEST_ASSERT( ret == MBEDTLS_ERR_ECP_VERIFY_FAILED ); sig[sig_len - 1]--; - /* do we leak memory when aborting? */ - ret = mbedtls_ecdsa_read_signature_restartable( &ctx, - hash, hash_len, sig, sig_len, &rs_ctx ); - TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + /* Do we leak memory when aborting an operation? + * This test only makes sense when we actually restart */ + if( min_restart > 0 ) + { + ret = mbedtls_ecdsa_read_signature_restartable( &ctx, + hash, hash_len, sig, sig_len, &rs_ctx ); + TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + } exit: mbedtls_ecdsa_free( &ctx ); @@ -311,10 +315,14 @@ void ecdsa_write_restart( int id, char *d_str, int md_alg, TEST_ASSERT( cnt_restart >= min_restart ); TEST_ASSERT( cnt_restart <= max_restart ); - /* do we leak memory when aborting? */ - ret = mbedtls_ecdsa_write_signature_restartable( &ctx, - md_alg, hash, hlen, sig, &slen, NULL, NULL, &rs_ctx ); - TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + /* Do we leak memory when aborting an operation? + * This test only makes sense when we actually restart */ + if( min_restart > 0 ) + { + ret = mbedtls_ecdsa_write_signature_restartable( &ctx, + md_alg, hash, hlen, sig, &slen, NULL, NULL, &rs_ctx ); + TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + } exit: mbedtls_ecdsa_restart_free( &rs_ctx ); diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 3ec7caf54..c60d0d349 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -103,13 +103,9 @@ void ecp_test_vect_restart( int id, cnt_restarts = 0; do { ret = mbedtls_ecp_mul_restartable( &grp, &R, &dA, &grp.G, NULL, NULL, &ctx ); - TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); - - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) - cnt_restarts++; - } - while( ret != 0 ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restarts ); + TEST_ASSERT( ret == 0 ); TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.X, &xA ) == 0 ); TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.Y, &yA ) == 0 ); @@ -120,22 +116,22 @@ void ecp_test_vect_restart( int id, cnt_restarts = 0; do { ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &R, NULL, NULL, &ctx ); - TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); - - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) - cnt_restarts++; - } - while( ret != 0 ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restarts ); + TEST_ASSERT( 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 not finishing an operation? */ - ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &R, NULL, NULL, &ctx ); - TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + /* Do we leak memory when aborting an operation? + * This test only makes sense when we actually restart */ + if( min_restarts > 0 ) + { + ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &R, NULL, NULL, &ctx ); + TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + } exit: mbedtls_ecp_restart_free( &ctx ); @@ -188,23 +184,23 @@ void ecp_muladd_restart( int id, char *xR_str, char *yR_str, do { ret = mbedtls_ecp_muladd_restartable( &grp, &R, &u1, &grp.G, &u2, &Q, &ctx ); - TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); - - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) - cnt_restarts++; - } - while( ret != 0 ); + } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restarts ); + TEST_ASSERT( ret == 0 ); TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.X, &xR ) == 0 ); TEST_ASSERT( mbedtls_mpi_cmp_mpi( &R.Y, &yR ) == 0 ); TEST_ASSERT( cnt_restarts >= min_restarts ); TEST_ASSERT( cnt_restarts <= max_restarts ); - /* Do we leak memory when aborting? */ - ret = mbedtls_ecp_muladd_restartable( &grp, &R, - &u1, &grp.G, &u2, &Q, &ctx ); - TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + /* Do we leak memory when aborting an operation? + * This test only makes sense when we actually restart */ + if( min_restarts > 0 ) + { + ret = mbedtls_ecp_muladd_restartable( &grp, &R, + &u1, &grp.G, &u2, &Q, &ctx ); + TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + } exit: mbedtls_ecp_restart_free( &ctx ); diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index 176b08f98..d7edb755c 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -347,16 +347,20 @@ void pk_sign_verify_restart( int pk_type, int grp_id, char *d_str, TEST_ASSERT( ret != 0 ); sig[0]--; - /* Do we leak memory when aborting? try verify then sign */ - ret = mbedtls_pk_verify_restartable( &pub, md_alg, - hash, hlen, sig, slen, &rs_ctx ); - TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); - mbedtls_pk_restart_free( &rs_ctx ); + /* Do we leak memory when aborting? try verify then sign + * This test only makes sense when we actually restart */ + if( min_restart > 0 ) + { + ret = mbedtls_pk_verify_restartable( &pub, md_alg, + hash, hlen, sig, slen, &rs_ctx ); + TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + mbedtls_pk_restart_free( &rs_ctx ); - slen = sizeof( sig ); - ret = mbedtls_pk_sign_restartable( &prv, md_alg, hash, hlen, - sig, &slen, NULL, NULL, &rs_ctx ); - TEST_ASSERT( ret == 0 || ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + slen = sizeof( sig ); + ret = mbedtls_pk_sign_restartable( &prv, md_alg, hash, hlen, + sig, &slen, NULL, NULL, &rs_ctx ); + TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); + } exit: mbedtls_pk_restart_free( &rs_ctx ); From 196d1338bab65c5321f77401e28d252eabe9704b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 28 Aug 2017 13:14:27 +0200 Subject: [PATCH 120/148] Fix uninitialised variable in some configs --- library/ecp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ecp.c b/library/ecp.c index 41bf03d31..126e50675 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1914,6 +1914,8 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, #if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); +#else + p_eq_g = 0; #endif /* Pick window size and deduce related sizes */ From bb216bd94040c848f6cd6310fb103da00161aa7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 28 Aug 2017 13:25:55 +0200 Subject: [PATCH 121/148] Fix MSVC 64-bit warnings "conversion from size_t to int, possible loss of data" --- include/mbedtls/x509_crt.h | 2 +- library/x509_crt.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 683181270..a168d7628 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -161,7 +161,7 @@ typedef struct { typedef struct { mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; - size_t len; + unsigned len; } mbedtls_x509_crt_verify_chain; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) diff --git a/library/x509_crt.c b/library/x509_crt.c index 586ec8375..b3fc6e40c 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -1983,8 +1983,8 @@ static int x509_crt_find_parent_in( mbedtls_x509_crt **r_parent, int *r_signature_is_good, int top, - int path_cnt, - int self_cnt, + unsigned path_cnt, + unsigned self_cnt, mbedtls_x509_crt_restart_ctx *rs_ctx ) { int ret; @@ -2021,7 +2021,7 @@ static int x509_crt_find_parent_in( /* +1 because stored max_pathlen is 1 higher that the actual value */ if( parent->max_pathlen > 0 && - parent->max_pathlen < 1 + path_cnt - self_cnt ) + (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) { continue; } @@ -2103,8 +2103,8 @@ static int x509_crt_find_parent( mbedtls_x509_crt **parent, int *parent_is_trusted, int *signature_is_good, - int path_cnt, - int self_cnt, + unsigned path_cnt, + unsigned self_cnt, mbedtls_x509_crt_restart_ctx *rs_ctx ) { int ret; @@ -2246,7 +2246,7 @@ static int x509_crt_verify_chain( int parent_is_trusted; int child_is_trusted; int signature_is_good; - int self_cnt; + unsigned self_cnt; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* resume if we had an operation in progress */ @@ -2445,7 +2445,7 @@ static int x509_crt_merge_flags_with_cb( void *p_vrfy ) { int ret; - size_t i; + unsigned i; uint32_t cur_flags; const mbedtls_x509_crt_verify_chain_item *cur; @@ -2455,7 +2455,7 @@ static int x509_crt_merge_flags_with_cb( cur_flags = cur->flags; if( NULL != f_vrfy ) - if( ( ret = f_vrfy( p_vrfy, cur->crt, i-1, &cur_flags ) ) != 0 ) + if( ( ret = f_vrfy( p_vrfy, cur->crt, (int) i-1, &cur_flags ) ) != 0 ) return( ret ); *flags |= cur_flags; From a4dd7839094a120e306887e7ec231fc0a2b570d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Thu, 7 Sep 2017 11:11:39 +0200 Subject: [PATCH 122/148] Fix some typos in comments --- library/ecdsa.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/ecdsa.c b/library/ecdsa.c index 981846bb4..b7c810e4e 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -53,7 +53,7 @@ #if defined(MBEDTLS_ECP_RESTARTABLE) /* - * Sub-contect for ecdsa_verify() + * Sub-context for ecdsa_verify() */ struct mbedtls_ecdsa_restart_ver { @@ -89,7 +89,7 @@ static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx ) } /* - * Sub-contect for ecdsa_sign() + * Sub-context for ecdsa_sign() */ struct mbedtls_ecdsa_restart_sig { @@ -132,7 +132,7 @@ static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) #if defined(MBEDTLS_ECDSA_DETERMINISTIC) /* - * Sub-contect for ecdsa_sign_det() + * Sub-context for ecdsa_sign_det() */ struct mbedtls_ecdsa_restart_det { From d0a66ccde3c0e7cb99d9f67aa436cf13535b2e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jun 2018 09:53:21 +0200 Subject: [PATCH 123/148] post-merge: fix ECDSA test vector testing The way we do negative tests only works if the initial test was positive. This was not immediately apparent with the set of test data at the time the code for negative testing was introduced, but it became apparent with the addition of the "0 private value" / "overlong private value" tests that happened in development while this branch was developed. --- tests/suites/test_suite_ecdsa.function | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/suites/test_suite_ecdsa.function b/tests/suites/test_suite_ecdsa.function index 4e4ee6d54..d87c98e4c 100644 --- a/tests/suites/test_suite_ecdsa.function +++ b/tests/suites/test_suite_ecdsa.function @@ -88,18 +88,18 @@ void ecdsa_prim_test_vectors( int id, char *d_str, char *xQ_str, char *yQ_str, TEST_ASSERT( mbedtls_mpi_cmp_mpi( &s, &s_check ) == 0 ); TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, &Q, &r_check, &s_check ) == 0 ); + + TEST_ASSERT( mbedtls_mpi_sub_int( &r, &r, 1 ) == 0 ); + TEST_ASSERT( mbedtls_mpi_add_int( &s, &s, 1 ) == 0 ); + + TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, + &Q, &r, &s_check ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); + TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, + &Q, &r_check, &s ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); + TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, + &grp.G, &r_check, &s_check ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); } - TEST_ASSERT( mbedtls_mpi_sub_int( &r, &r, 1 ) == 0 ); - TEST_ASSERT( mbedtls_mpi_add_int( &s, &s, 1 ) == 0 ); - - TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, - &Q, &r, &s_check ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); - TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, - &Q, &r_check, &s ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); - TEST_ASSERT( mbedtls_ecdsa_verify( &grp, hash, hlen, - &grp.G, &r_check, &s_check ) == MBEDTLS_ERR_ECP_VERIFY_FAILED ); - exit: mbedtls_ecp_group_free( &grp ); mbedtls_ecp_point_free( &Q ); From b5d668a7a7eef6ca5b1b2e3d152cf0ecf5cf8ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jun 2018 11:22:01 +0200 Subject: [PATCH 124/148] post-merge: adapt ssl-opt.sh to new error values The numerical value of the error code was changed when merging development into this branch; now adapt ssl-opt.sh to the new value. --- tests/ssl-opt.sh | 80 ++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index d90c12ede..d45be5a6f 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -4076,10 +4076,10 @@ run_test "EC restart: TLS, default" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1" \ 0 \ - -C "x509_verify_cert.*4b80" \ - -C "mbedtls_pk_verify.*4b80" \ - -C "mbedtls_ecdh_make_public.*4b80" \ - -C "mbedtls_pk_sign.*4b80" + -C "x509_verify_cert.*4b00" \ + -C "mbedtls_pk_verify.*4b00" \ + -C "mbedtls_ecdh_make_public.*4b00" \ + -C "mbedtls_pk_sign.*4b00" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=0" \ @@ -4088,10 +4088,10 @@ run_test "EC restart: TLS, max_ops=0" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=0" \ 0 \ - -C "x509_verify_cert.*4b80" \ - -C "mbedtls_pk_verify.*4b80" \ - -C "mbedtls_ecdh_make_public.*4b80" \ - -C "mbedtls_pk_sign.*4b80" + -C "x509_verify_cert.*4b00" \ + -C "mbedtls_pk_verify.*4b00" \ + -C "mbedtls_ecdh_make_public.*4b00" \ + -C "mbedtls_pk_sign.*4b00" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=65535" \ @@ -4100,10 +4100,10 @@ run_test "EC restart: TLS, max_ops=65535" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=65535" \ 0 \ - -C "x509_verify_cert.*4b80" \ - -C "mbedtls_pk_verify.*4b80" \ - -C "mbedtls_ecdh_make_public.*4b80" \ - -C "mbedtls_pk_sign.*4b80" + -C "x509_verify_cert.*4b00" \ + -C "mbedtls_pk_verify.*4b00" \ + -C "mbedtls_ecdh_make_public.*4b00" \ + -C "mbedtls_pk_sign.*4b00" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=1000" \ @@ -4112,10 +4112,10 @@ run_test "EC restart: TLS, max_ops=1000" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=1000" \ 0 \ - -c "x509_verify_cert.*4b80" \ - -c "mbedtls_pk_verify.*4b80" \ - -c "mbedtls_ecdh_make_public.*4b80" \ - -c "mbedtls_pk_sign.*4b80" + -c "x509_verify_cert.*4b00" \ + -c "mbedtls_pk_verify.*4b00" \ + -c "mbedtls_ecdh_make_public.*4b00" \ + -c "mbedtls_pk_sign.*4b00" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=1000, badsign" \ @@ -4126,10 +4126,10 @@ run_test "EC restart: TLS, max_ops=1000, badsign" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=1000" \ 1 \ - -c "x509_verify_cert.*4b80" \ - -C "mbedtls_pk_verify.*4b80" \ - -C "mbedtls_ecdh_make_public.*4b80" \ - -C "mbedtls_pk_sign.*4b80" \ + -c "x509_verify_cert.*4b00" \ + -C "mbedtls_pk_verify.*4b00" \ + -C "mbedtls_ecdh_make_public.*4b00" \ + -C "mbedtls_pk_sign.*4b00" \ -c "! The certificate is not correctly signed by the trusted CA" \ -c "! mbedtls_ssl_handshake returned" \ -c "X509 - Certificate verification failed" @@ -4143,10 +4143,10 @@ run_test "EC restart: TLS, max_ops=1000, auth_mode=optional badsign" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=1000 auth_mode=optional" \ 0 \ - -c "x509_verify_cert.*4b80" \ - -c "mbedtls_pk_verify.*4b80" \ - -c "mbedtls_ecdh_make_public.*4b80" \ - -c "mbedtls_pk_sign.*4b80" \ + -c "x509_verify_cert.*4b00" \ + -c "mbedtls_pk_verify.*4b00" \ + -c "mbedtls_ecdh_make_public.*4b00" \ + -c "mbedtls_pk_sign.*4b00" \ -c "! The certificate is not correctly signed by the trusted CA" \ -C "! mbedtls_ssl_handshake returned" \ -C "X509 - Certificate verification failed" @@ -4160,10 +4160,10 @@ run_test "EC restart: TLS, max_ops=1000, auth_mode=none badsign" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=1000 auth_mode=none" \ 0 \ - -C "x509_verify_cert.*4b80" \ - -c "mbedtls_pk_verify.*4b80" \ - -c "mbedtls_ecdh_make_public.*4b80" \ - -c "mbedtls_pk_sign.*4b80" \ + -C "x509_verify_cert.*4b00" \ + -c "mbedtls_pk_verify.*4b00" \ + -c "mbedtls_ecdh_make_public.*4b00" \ + -c "mbedtls_pk_sign.*4b00" \ -C "! The certificate is not correctly signed by the trusted CA" \ -C "! mbedtls_ssl_handshake returned" \ -C "X509 - Certificate verification failed" @@ -4175,10 +4175,10 @@ run_test "EC restart: DTLS, max_ops=1000" \ key_file=data_files/server5.key crt_file=data_files/server5.crt \ dtls=1 debug_level=1 ec_max_ops=1000" \ 0 \ - -c "x509_verify_cert.*4b80" \ - -c "mbedtls_pk_verify.*4b80" \ - -c "mbedtls_ecdh_make_public.*4b80" \ - -c "mbedtls_pk_sign.*4b80" + -c "x509_verify_cert.*4b00" \ + -c "mbedtls_pk_verify.*4b00" \ + -c "mbedtls_ecdh_make_public.*4b00" \ + -c "mbedtls_pk_sign.*4b00" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=1000 no client auth" \ @@ -4186,10 +4186,10 @@ run_test "EC restart: TLS, max_ops=1000 no client auth" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ debug_level=1 ec_max_ops=1000" \ 0 \ - -c "x509_verify_cert.*4b80" \ - -c "mbedtls_pk_verify.*4b80" \ - -c "mbedtls_ecdh_make_public.*4b80" \ - -C "mbedtls_pk_sign.*4b80" + -c "x509_verify_cert.*4b00" \ + -c "mbedtls_pk_verify.*4b00" \ + -c "mbedtls_ecdh_make_public.*4b00" \ + -C "mbedtls_pk_sign.*4b00" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=1000, ECDHE-PSK" \ @@ -4197,10 +4197,10 @@ run_test "EC restart: TLS, max_ops=1000, ECDHE-PSK" \ "$P_CLI force_ciphersuite=TLS-ECDHE-PSK-WITH-AES-128-CBC-SHA256 \ psk=abc123 debug_level=1 ec_max_ops=1000" \ 0 \ - -C "x509_verify_cert.*4b80" \ - -C "mbedtls_pk_verify.*4b80" \ - -C "mbedtls_ecdh_make_public.*4b80" \ - -C "mbedtls_pk_sign.*4b80" + -C "x509_verify_cert.*4b00" \ + -C "mbedtls_pk_verify.*4b00" \ + -C "mbedtls_ecdh_make_public.*4b00" \ + -C "mbedtls_pk_sign.*4b00" # Tests for DTLS HelloVerifyRequest From 558da9c3feee5d4376fcb9f481af18152165a467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 13 Jun 2018 12:02:12 +0200 Subject: [PATCH 125/148] Make SSL error code more generic It's undesirable to have users of the SSL layer check for an error code specific to a lower-level layer, both out of general layering principles, and also because if we later make another crypto module gain resume capabilities, we would need to change the contract again (checking for a new module-specific error code). --- include/mbedtls/error.h | 2 +- include/mbedtls/ssl.h | 1 + library/error.c | 2 ++ library/ssl_cli.c | 20 ++++++++++++++++++++ library/ssl_tls.c | 2 +- programs/ssl/ssl_client2.c | 18 +++++++++--------- 6 files changed, 34 insertions(+), 11 deletions(-) diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 22895e1c2..29c1c21a9 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -90,7 +90,7 @@ * ECP 4 10 (Started from top) * MD 5 5 * CIPHER 6 8 - * SSL 6 17 (Started from top) + * SSL 6 22 (Started from top) * SSL 7 31 * * Module dependent error code (5 bits 0x.00.-0x.F8.) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 250031a6d..def20dbec 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -120,6 +120,7 @@ #define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */ #define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */ #define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */ +#define MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS -0x6500 /**< A cryptographic operation is in progress. Try again later. */ /* * Various constants diff --git a/library/error.c b/library/error.c index a2de27563..4dc13a426 100644 --- a/library/error.c +++ b/library/error.c @@ -499,6 +499,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) ) mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "SSL - A cryptographic operation is in progress. Try again later" ); #endif /* MBEDTLS_SSL_TLS_C */ #if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 7a6ffe044..1937ec519 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2055,6 +2055,10 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, (const unsigned char **) p, end ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } @@ -2619,6 +2623,10 @@ start_processing: mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL, MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR ); MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_verify", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } } @@ -2933,6 +2941,10 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_public", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } @@ -2956,6 +2968,10 @@ ecdh_calc_secret: ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_calc_secret", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } @@ -3313,6 +3329,10 @@ sign: ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; +#endif return( ret ); } diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 8364eb868..2ebf12877 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4683,7 +4683,7 @@ crt_verify: #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) - return( ret ); + return( MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ); #endif /* diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index b11bedd46..0e3e1ed07 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -1516,7 +1516,7 @@ int main( int argc, char *argv[] ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && - ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n", -ret ); @@ -1533,7 +1533,7 @@ int main( int argc, char *argv[] ) } #if defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) continue; #endif @@ -1630,7 +1630,7 @@ int main( int argc, char *argv[] ) { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && - ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) { mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret ); @@ -1695,7 +1695,7 @@ send_request: { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && - ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) { mbedtls_printf( " failed\n ! mbedtls_ssl_write returned -0x%x\n\n", -ret ); @@ -1721,7 +1721,7 @@ send_request: ret = mbedtls_ssl_write( &ssl, buf, len ); #if defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) continue; #endif @@ -1779,7 +1779,7 @@ send_request: ret = mbedtls_ssl_read( &ssl, buf, len ); #if defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) continue; #endif @@ -1844,7 +1844,7 @@ send_request: ret = mbedtls_ssl_read( &ssl, buf, len ); #if defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) continue; #endif @@ -1911,7 +1911,7 @@ send_request: { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && - ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); @@ -2010,7 +2010,7 @@ reconnect: { if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE && - ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) { mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); From 95e2ecae95dde7772b1f0e98d572d8a7ba158ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 20 Jun 2018 10:29:47 +0200 Subject: [PATCH 126/148] Fix IAR warning The IAR compiler doesn't like it when we assign an int to an enum variable. "C:\builds\ws\mbedtls-restricted-pr\library\ecp.c",509 Error[Pe188]: enumerated type mixed with another type --- library/ecp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ecp.c b/library/ecp.c index 52d6d9c38..bbc1ff082 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -506,7 +506,7 @@ void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) if( grp == NULL ) return; - grp->id = 0; + grp->id = MBEDTLS_ECP_DP_NONE; mbedtls_mpi_init( &grp->P ); mbedtls_mpi_init( &grp->A ); mbedtls_mpi_init( &grp->B ); From 823c915e594c2bbff0b8d77fb1dceb4b3d73341d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 2 Jul 2018 12:05:49 +0200 Subject: [PATCH 127/148] Fix mis-merged ChangeLog --- ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index 1d1ec7c04..ab5a01742 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,10 @@ Features in ECP, ECDSA, PK and X509 (CRL not supported yet), and using existing functions in ECDH and SSL (currently only implemented client-side, for ECDHE-ECDSA ciphersuites with TLS 1.2, including client authentication). + += mbed TLS 2.11.0 branch released 2018-06-18 + +Features * Add additional block mode, OFB (Output Feedback), to the AES module and cipher abstraction module. * Implement the HMAC-based extract-and-expand key derivation function From 4edb9cbbc0a07a650946c0e83c7325093672c902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 2 Jul 2018 12:23:23 +0200 Subject: [PATCH 128/148] Justify some max_ops settings in test_suite_pk --- tests/suites/test_suite_pk.function | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/suites/test_suite_pk.function b/tests/suites/test_suite_pk.function index a2158360b..2cdc363bb 100644 --- a/tests/suites/test_suite_pk.function +++ b/tests/suites/test_suite_pk.function @@ -137,7 +137,8 @@ void pk_rsa_verify_test_vec( char *message_hex_string, int digest, rs_ctx = &ctx; mbedtls_pk_restart_init( rs_ctx ); - mbedtls_ecp_set_max_ops( 42 ); + // this setting would ensure restart would happen if ECC was used + mbedtls_ecp_set_max_ops( 1 ); #endif mbedtls_pk_init( &pk ); @@ -385,6 +386,9 @@ void pk_sign_verify( int type, int sign_ret, int verify_ret ) rs_ctx = &ctx; mbedtls_pk_restart_init( rs_ctx ); + /* This value is large enough that the operation will complete in one run. + * See comments at the top of ecp_test_vect_restart in + * test_suite_ecp.function for estimates of operation counts. */ mbedtls_ecp_set_max_ops( 42000 ); #endif From 78d7e8cbc78443660c1a4e4c94ac109edbddf368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 2 Jul 2018 12:33:14 +0200 Subject: [PATCH 129/148] Rename internal variable for consistency --- include/mbedtls/x509_crt.h | 2 +- library/x509_crt.c | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 1c3007d8d..d794b6630 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -178,7 +178,7 @@ typedef struct /* for find_parent_in() */ mbedtls_x509_crt *parent; /* non-null iff parent_in in progress */ mbedtls_x509_crt *fallback_parent; - int fallback_sign_good; + int fallback_signature_is_good; /* for find_parent() */ int parent_is_trusted; /* -1 if find_parent is not in progress */ diff --git a/library/x509_crt.c b/library/x509_crt.c index 4022ceee8..588b484f1 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2010,7 +2010,7 @@ static int x509_crt_find_parent_in( { int ret; mbedtls_x509_crt *parent, *fallback_parent; - int signature_is_good, fallback_sign_good; + int signature_is_good, fallback_signature_is_good; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* did we have something in progress? */ @@ -2019,12 +2019,12 @@ static int x509_crt_find_parent_in( /* restore saved state */ parent = rs_ctx->parent; fallback_parent = rs_ctx->fallback_parent; - fallback_sign_good = rs_ctx->fallback_sign_good; + fallback_signature_is_good = rs_ctx->fallback_signature_is_good; /* clear saved state */ rs_ctx->parent = NULL; rs_ctx->fallback_parent = NULL; - rs_ctx->fallback_sign_good = 0; + rs_ctx->fallback_signature_is_good = 0; /* resume where we left */ goto check_signature; @@ -2032,7 +2032,7 @@ static int x509_crt_find_parent_in( #endif fallback_parent = NULL; - fallback_sign_good = 0; + fallback_signature_is_good = 0; for( parent = candidates; parent != NULL; parent = parent->next ) { @@ -2059,7 +2059,7 @@ check_signature: /* save state */ rs_ctx->parent = parent; rs_ctx->fallback_parent = fallback_parent; - rs_ctx->fallback_sign_good = fallback_sign_good; + rs_ctx->fallback_signature_is_good = fallback_signature_is_good; return( ret ); } @@ -2078,7 +2078,7 @@ check_signature: if( fallback_parent == NULL ) { fallback_parent = parent; - fallback_sign_good = signature_is_good; + fallback_signature_is_good = signature_is_good; } continue; @@ -2095,7 +2095,7 @@ check_signature: else { *r_parent = fallback_parent; - *r_signature_is_good = fallback_sign_good; + *r_signature_is_good = fallback_signature_is_good; } return( 0 ); @@ -2704,7 +2704,7 @@ void mbedtls_x509_crt_restart_init( mbedtls_x509_crt_restart_ctx *ctx ) ctx->parent = NULL; ctx->fallback_parent = NULL; - ctx->fallback_sign_good = 0; + ctx->fallback_signature_is_good = 0; ctx->parent_is_trusted = -1; From c8c12b6007b4249e1fbc67c94bb28b3ec2dadc3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 2 Jul 2018 13:09:39 +0200 Subject: [PATCH 130/148] Add NULL pointer check for consistency Most other functions in this module have a similar check. --- library/pk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/pk.c b/library/pk.c index c793fd8e4..ba8950e8d 100644 --- a/library/pk.c +++ b/library/pk.c @@ -206,8 +206,8 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, const mbedtls_pk_info_t *info ) { - /* Don't do anything it already set up */ - if( ctx->pk_info != NULL ) + /* Don't do anything if already set up or invalid */ + if( ctx == NULL || ctx->pk_info != NULL ) return( 0 ); /* Should never happen when we're called */ From 1c1c20ed4d8357c73d53443277a901013da7d745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 12 Sep 2018 10:34:43 +0200 Subject: [PATCH 131/148] Fix some whitespace issues --- library/ssl_cli.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index fbf5166df..7b88e61e3 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2077,8 +2077,8 @@ static int ssl_parse_server_ecdh_params( mbedtls_ssl_context *ssl, { MBEDTLS_SSL_DEBUG_RET( 1, ( "mbedtls_ecdh_read_params" ), ret ); #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) - ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; + if( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) + ret = MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS; #endif return( ret ); } From 12e4a8be2ade943bc60774f6bfe9ae53da92c875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 12 Sep 2018 10:55:15 +0200 Subject: [PATCH 132/148] Improve documentation wording and formatting --- include/mbedtls/config.h | 5 +++-- include/mbedtls/ecdsa.h | 3 ++- include/mbedtls/ecp.h | 27 +++++++++++++++------------ include/mbedtls/pk.h | 4 ++-- include/mbedtls/x509_crt.h | 2 +- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 8b5ae9f57..3f248d5c4 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -683,8 +683,9 @@ * Enable "non-blocking" ECC operations that can return early and be resumed. * * This enables \c mbedtls_ecp_set_max_ops() and allows various functions - * to return \c MBEDTLS_ERR_ECP_IN_PROGRESS when needed, and then be called - * again later with the same arguments in order to further progress and + * to return #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL + * module, #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) when needed, and then be + * called again later with the same arguments in order to further progress and * eventually complete the operation, see \c mbedtls_ecp_set_max_ops(). * * This is useful in non-threaded environments if you want to avoid blocking diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index 710fdb9d6..d5f7985cd 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -98,7 +98,8 @@ typedef struct mbedtls_ecdsa_restart_det mbedtls_ecdsa_restart_det_ctx; */ typedef struct { - mbedtls_ecp_restart_ctx ecp; /*!< base context (admin+ecp info) */ + mbedtls_ecp_restart_ctx ecp; /*!< base context for ECP restart and + shared administrative info */ mbedtls_ecdsa_restart_ver_ctx *ver; /*!< ecdsa_verify() sub-context */ mbedtls_ecdsa_restart_sig_ctx *sig; /*!< ecdsa_sign() sub-context */ #if defined(MBEDTLS_ECDSA_DETERMINISTIC) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 4ac2926e7..15aee04c7 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -225,8 +225,8 @@ typedef struct * \param rs_ctx Restart context * \param ops Number of basic ops to do * - * \return 0 is doing 'ops' basic ops is still allowed, - * MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. + * \return \c 0 if doing \p ops basic ops is still allowed, + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS otherwise. */ int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, mbedtls_ecp_restart_ctx *rs_ctx, @@ -338,7 +338,7 @@ mbedtls_ecp_keypair; * \brief Set the maximum number of basic operations done in a row. * * If more operations are needed to complete a computation, - * MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the + * #MBEDTLS_ERR_ECP_IN_PROGRESS will be returned by the * function performing the computation. It is then the * caller's responsibility to either call again with the same * parameters until it returns 0 or an error code; or to free @@ -352,7 +352,7 @@ mbedtls_ecp_keypair; * * This only affects functions that accept a pointer to a * \c mbedtls_ecp_restart_ctx as an argument, and only works - * if that pointer valid (in particular, not NULL). + * if that pointer is valid (in particular, not NULL). * * \param max_ops Maximum number of basic operations done in a row. * Default: 0 (unlimited). @@ -379,15 +379,15 @@ mbedtls_ecp_keypair; * P-384 682 416 320 272 248 * P-521 1364 832 640 544 496 * - * \note This setting is currently ignored by Curve25519 + * \note This setting is currently ignored by Curve25519. */ void mbedtls_ecp_set_max_ops( unsigned max_ops ); /** * \brief Check if restart is enabled (max_ops != 0) * - * \return 0 if max_ops == 0 (restart disabled) - * 1 otherwise (restart enabled) + * \return \c 0 if \c max_ops == 0 (restart disabled) + * \return \c 1 otherwise (restart enabled) */ int mbedtls_ecp_restart_enabled( void ); #endif /* MBEDTLS_ECP_RESTARTABLE */ @@ -735,7 +735,7 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * \brief This function performs multiplication of a point by * an integer: \p R = \p m * \p P in a restartable way. * - * \c mbedtls_ecp_mul() + * \see mbedtls_ecp_mul() * * \note This function does the same as \c mbedtls_ecp_mul(), but * it can return early and restart according to the limit set @@ -749,8 +749,11 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * \param p_rng The RNG context. * \param rs_ctx The restart context. * - * \return See \c mbedtls_ecp_mul(), or - * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_ecp_mul_restartable( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, @@ -787,7 +790,7 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, /** * \brief This function performs multiplication and addition of two * points by integers: \p R = \p m * \p P + \p n * \p Q in a - * reastartable way. + * restartable way. * * \see \c mbedtls_ecp_muladd() * @@ -863,7 +866,7 @@ int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi * * \brief This function generates a private key. * * \param grp The ECP group. - * \param d The Destination MPI (secret part). + * \param d The destination MPI (secret part). * \param f_rng The RNG function. * \param p_rng The RNG parameter. * diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index 37a79cca4..3b486cfe9 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -329,7 +329,7 @@ int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, * \param rs_ctx Restart context (NULL to disable restart) * * \return See \c mbedtls_pk_verify(), or - * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, @@ -420,7 +420,7 @@ int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, * \param rs_ctx Restart context (NULL to disable restart) * * \return See \c mbedtls_pk_sign(), or - * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 494ea99d7..961db9844 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -429,7 +429,7 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, * \param rs_ctx restart context * * \return See \c mbedtls_crt_verify_with_profile(), or - * MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). */ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, From 5a481f1940d3ea846aa2578baa574a68192ff8cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 12 Sep 2018 12:33:32 +0200 Subject: [PATCH 133/148] Update error.h count for SSL --- include/mbedtls/error.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 1f1401150..6e26df9fe 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -95,7 +95,7 @@ * HKDF 5 1 (Started from top) * CIPHER 6 8 * SSL 6 23 (Started from top) - * SSL 7 31 + * SSL 7 32 * * Module dependent error code (5 bits 0x.00.-0x.F8.) */ From f0bbd7e3fd6c5ce10dbc5ab0bc4e3e11759a45ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Oct 2018 13:22:41 +0200 Subject: [PATCH 134/148] Misc documentation fixes/improvements. --- ChangeLog | 16 ++++++++++------ include/mbedtls/config.h | 14 ++++++++------ include/mbedtls/ecdh.h | 16 ++++++++-------- include/mbedtls/ecdsa.h | 14 +++++++------- include/mbedtls/ecp.h | 6 +++--- include/mbedtls/pk.h | 4 ++-- include/mbedtls/x509_crt.h | 2 +- library/error.c | 2 +- 8 files changed, 40 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9ec9d4d94..e7a2f4df6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,12 +3,16 @@ mbed TLS ChangeLog (Sorted per branch, date) = mbed TLS x.x.x branch released xxxx-xx-xx Features - * Add support for restartable ECC operations, enabled by - MBEDTLS_ECP_RESTARTABLE (disabled by default) at compile time and - mbedtls_ecp_set_max_ops() at runtime, using new xxx_restartable functions - in ECP, ECDSA, PK and X509 (CRL not supported yet), and using existing - functions in ECDH and SSL (currently only implemented client-side, for - ECDHE-ECDSA ciphersuites with TLS 1.2, including client authentication). + * Add support for temporarily suspending expensive ECC computations after + some configurable amount of operations, to be used in single-threaded + constrained systems where ECC is time consuming and blocking until + completion cannot be tolerated. This is enabled by + MBEDTLS_ECP_RESTARTABLE at compile time (disabled by default) and + configured by mbedtls_ecp_set_max_ops() at runtime. It applies to new + xxx_restartable functions in ECP, ECDSA, PK and X.509 (CRL not supported + yet), and to existing functions in ECDH and SSL (currently only + implemented client-side, for ECDHE-ECDSA ciphersuites in TLS 1.2, + including client authentication). Bugfix * Fix a bug in the update function for SSL ticket keys which previously diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 3f248d5c4..92f024a17 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -682,14 +682,16 @@ * * Enable "non-blocking" ECC operations that can return early and be resumed. * - * This enables \c mbedtls_ecp_set_max_ops() and allows various functions - * to return #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL - * module, #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) when needed, and then be - * called again later with the same arguments in order to further progress and - * eventually complete the operation, see \c mbedtls_ecp_set_max_ops(). + * This allows various functions to pause by returning + * #MBEDTLS_ERR_ECP_IN_PROGRESS (or, for functions in the SSL module, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS) and then be called later again in + * order to further progress and eventually complete their operation. This is + * controlled through mbedtls_ecp_set_max_ops() which limits the maximum + * number of ECC operations a function may perform before pausing; see + * mbedtls_ecp_set_max_ops() for more information. * * This is useful in non-threaded environments if you want to avoid blocking - * for too long on ECC (hence, X509 or SSL/TLS) operations. + * for too long on ECC (and, hence, X.509 or SSL/TLS) operations. * * Uncomment this macro to enable restartable ECC computations. */ diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h index ed3e8df42..8b75b9386 100644 --- a/include/mbedtls/ecdh.h +++ b/include/mbedtls/ecdh.h @@ -91,10 +91,10 @@ mbedtls_ecdh_context; * \param p_rng The RNG context. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX or - * \c MBEDTLS_MPI_XXX error code on failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), @@ -121,10 +121,10 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp * \param p_rng The RNG context. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX or - * \c MBEDTLS_MPI_XXX error code on failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX or + * \c MBEDTLS_MPI_XXX error code on failure. */ int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, const mbedtls_ecp_point *Q, const mbedtls_mpi *d, @@ -166,9 +166,9 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ); * \param p_rng The RNG context. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, @@ -210,9 +210,9 @@ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, * 0: The key of the peer. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. * */ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypair *key, @@ -235,9 +235,9 @@ int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, const mbedtls_ecp_keypai * \param p_rng The RNG context. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, @@ -283,9 +283,9 @@ int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, * \param p_rng The RNG context. * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX error code on failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. */ int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, unsigned char *buf, size_t blen, diff --git a/include/mbedtls/ecdsa.h b/include/mbedtls/ecdsa.h index d5f7985cd..4057828d4 100644 --- a/include/mbedtls/ecdsa.h +++ b/include/mbedtls/ecdsa.h @@ -73,7 +73,7 @@ typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; /** * \brief Internal restart context for ecdsa_verify() * - * \note Opaque struct + * \note Opaque struct, defined in ecdsa.c */ typedef struct mbedtls_ecdsa_restart_ver mbedtls_ecdsa_restart_ver_ctx; @@ -273,13 +273,13 @@ int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t * \param slen The length of the signature written. * \param f_rng The RNG function. * \param p_rng The RNG context. - * \param rs_ctx The restart context. + * \param rs_ctx The restart context (NULL disables restart). * * \return \c 0 on success. - * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or - * \c MBEDTLS_ERR_ASN1_XXX error code on failure. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. */ int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, @@ -387,16 +387,16 @@ int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, * \param hlen The size of the hash. * \param sig The signature to read and verify. * \param slen The size of \p sig. - * \param rs_ctx The restart context + * \param rs_ctx The restart context (NULL disables restart). * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid * signature in \p sig, but its length is less than \p siglen. - * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX - * error code on failure for any other reason. * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of * operations was reached: see \c mbedtls_ecp_set_max_ops(). + * \return Another \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. */ int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx, const unsigned char *hash, size_t hlen, diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 15aee04c7..d13f3ba22 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -50,7 +50,7 @@ #define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ #define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */ #define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */ -#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /**< Operation in progress, try again with the same parameters. */ +#define MBEDTLS_ERR_ECP_IN_PROGRESS -0x4B00 /**< Operation in progress, call again with the same parameters to continue. */ #ifdef __cplusplus extern "C" { @@ -747,7 +747,7 @@ int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * \param P The point to multiply. * \param f_rng The RNG function. * \param p_rng The RNG context. - * \param rs_ctx The restart context. + * \param rs_ctx The restart context (NULL disables restart). * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private @@ -804,7 +804,7 @@ int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, * \param P The point to multiply by \p m. * \param n The integer by which to multiply \p Q. * \param Q The point to be multiplied by \p n. - * \param rs_ctx The restart context. + * \param rs_ctx The restart context (NULL disables restart). * * \return \c 0 on success. * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not diff --git a/include/mbedtls/pk.h b/include/mbedtls/pk.h index 3b486cfe9..9ec33da05 100644 --- a/include/mbedtls/pk.h +++ b/include/mbedtls/pk.h @@ -127,7 +127,7 @@ typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; */ typedef struct mbedtls_pk_context { - const mbedtls_pk_info_t * pk_info; /**< Public key informations */ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ void * pk_ctx; /**< Underlying public key context */ } mbedtls_pk_context; @@ -137,7 +137,7 @@ typedef struct mbedtls_pk_context */ typedef struct { - const mbedtls_pk_info_t * pk_info; /**< Public key informations */ + const mbedtls_pk_info_t * pk_info; /**< Public key information */ void * rs_ctx; /**< Underlying restart context */ } mbedtls_pk_restart_ctx; #else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 961db9844..afeefca60 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -426,7 +426,7 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, * \param flags result of the verification * \param f_vrfy verification function * \param p_vrfy verification parameter - * \param rs_ctx restart context + * \param rs_ctx restart context (NULL to disable restart) * * \return See \c mbedtls_crt_verify_with_profile(), or * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of diff --git a/library/error.c b/library/error.c index d48ba8f79..3345481f0 100644 --- a/library/error.c +++ b/library/error.c @@ -290,7 +290,7 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen ) if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) ) mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" ); if( use_ret == -(MBEDTLS_ERR_ECP_IN_PROGRESS) ) - mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, try again with the same parameters" ); + mbedtls_snprintf( buf, buflen, "ECP - Operation in progress, call again with the same parameters to continue" ); #endif /* MBEDTLS_ECP_C */ #if defined(MBEDTLS_MD_C) From 32df91183e8b603deeb14d627f9da63a6f6ee1ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Oct 2018 13:29:21 +0200 Subject: [PATCH 135/148] Fix documentation of what functions restart when The previous comment in ecp.h that only functions that take a "restart context" argument can restart was wrong due to ECDH and SSL functions. Changing that criterion to "document says if can return IN PROGRESS". This requires updating the documentation of the SSL functions to mention this explicitly, but it's something we really ought to do anyway, a bit embarrassing that this wasn't done already - callers need to know what `MBEDTLS_ERR_SSL_xxx` error codes to special-case. Note that the documentation of the relevant functions was in a suboptimal state, so it was improved in the process - it could use some more improvement, but only the changes that helped cleanly insert the info about the IN_PROGRESS part were done here. Also, while updating the ecp.h comment, I noticed several functions in the ECDH module were wrongfully documented as restartable, which is probably a left-over from the days before `mbedtls_ecdh_enable_restart()` was introduced. Fixing that as well, to make the criterion used in ecp.h correct. --- include/mbedtls/ecdh.h | 6 -- include/mbedtls/ecp.h | 16 +++- include/mbedtls/ssl.h | 183 ++++++++++++++++++++++++++--------------- 3 files changed, 131 insertions(+), 74 deletions(-) diff --git a/include/mbedtls/ecdh.h b/include/mbedtls/ecdh.h index 8b75b9386..27f2ffc6a 100644 --- a/include/mbedtls/ecdh.h +++ b/include/mbedtls/ecdh.h @@ -91,8 +91,6 @@ mbedtls_ecdh_context; * \param p_rng The RNG context. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of - * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX or * \c MBEDTLS_MPI_XXX error code on failure. */ @@ -121,8 +119,6 @@ int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp * \param p_rng The RNG context. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of - * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX or * \c MBEDTLS_MPI_XXX error code on failure. */ @@ -210,8 +206,6 @@ int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, * 0: The key of the peer. * * \return \c 0 on success. - * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of - * operations was reached: see \c mbedtls_ecp_set_max_ops(). * \return Another \c MBEDTLS_ERR_ECP_XXX error code on failure. * */ diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index d13f3ba22..3bacf5cab 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -350,9 +350,19 @@ mbedtls_ecp_keypair; * same; they must not be used until the function finally * returns 0. * - * This only affects functions that accept a pointer to a - * \c mbedtls_ecp_restart_ctx as an argument, and only works - * if that pointer is valid (in particular, not NULL). + * This only applies to functions whose documentation + * mentions they may return #MBEDTLS_ERR_ECP_IN_PROGRESS (or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS for functions in the + * SSL module). For functions that accept a "restart context" + * argument, passing NULL disables restart and makes the + * function equivalent to the function with the same name + * with \c _restartable removed. For functions in the ECDH + * module, restart is disabled unless the function accepts + * an "ECDH context" argument and + * mbedtls_ecdh_enable_restart() was previously called on + * that context. For function in the SSL module, restart is + * only enabled for specific sides and key exchanges + * (currently only for clients and ECDHE-ECDSA). * * \param max_ops Maximum number of basic operations done in a row. * Default: 0 (unlimited). diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 0ce05a56d..942bf2c15 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2914,15 +2914,41 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session * * \param ssl SSL context * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED (see below), or - * a specific SSL error code. + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * in the handshake is incomplete but or waiting for data to + * be availaible for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED if DTLS is in use + * and the client did not demonstrate reachability yet - in + * this case you must stop using the context (see below). + * \return Another SSL error code - in this case you must stop using + * the context (see below). * - * If this function returns MBEDTLS_ERR_SSL_WANT_READ, the - * handshake is unfinished and no further data is available - * from the underlying transport. In this case, you must call - * the function again at some later stage. + * \warning If this function returns something other than + * \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. + * + * \note If DTLS is in use, then you may choose to handle + * #MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging + * purposes, as it is an expected return value rather than an + * actual error, but you still need to reset/free the context. * * \note Remarks regarding event-driven DTLS: * If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram @@ -2932,17 +2958,6 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session * in which case the datagram of the underlying transport that is * currently being processed might or might not contain further * DTLS records. - * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using - * the SSL context for reading or writing, and either free it or - * call \c mbedtls_ssl_session_reset() on it before re-using it - * for a new connection; the current connection must be closed. - * - * \note If DTLS is in use, then you may choose to handle - * MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED specially for logging - * purposes, as it is an expected return value rather than an - * actual error, but you still need to reset/free the context. */ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); @@ -2950,20 +2965,21 @@ int mbedtls_ssl_handshake( mbedtls_ssl_context *ssl ); * \brief Perform a single step of the SSL handshake * * \note The state of the context (ssl->state) will be at - * the next state after execution of this function. Do not + * the next state after this function returns \c 0. Do not * call this function if state is MBEDTLS_SSL_HANDSHAKE_OVER. * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using - * the SSL context for reading or writing, and either free it or - * call \c mbedtls_ssl_session_reset() on it before re-using it - * for a new connection; the current connection must be closed. - * * \param ssl SSL context * - * \return 0 if successful, or - * MBEDTLS_ERR_SSL_WANT_READ or MBEDTLS_ERR_SSL_WANT_WRITE, or - * a specific SSL error code. + * \return See mbedtls_ssl_handshake(). + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. */ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); @@ -2978,13 +2994,18 @@ int mbedtls_ssl_handshake_step( mbedtls_ssl_context *ssl ); * \param ssl SSL context * * \return 0 if successful, or any mbedtls_ssl_handshake() return - * value. + * value except #MBEDTLS_ERR_SSL_CLIENT_RECONNECT that can't + * happen during a renegotiation. + * + * \warning If this function returns something other than \c 0, + * #MBEDTLS_ERR_SSL_WANT_READ, #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, you must stop using + * the SSL context for reading or writing, and either free it + * or call \c mbedtls_ssl_session_reset() on it before + * re-using it for a new connection; the current connection + * must be closed. * - * \note If this function returns something other than 0 or - * MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop using - * the SSL context for reading or writing, and either free it or - * call \c mbedtls_ssl_session_reset() on it before re-using it - * for a new connection; the current connection must be closed. */ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); #endif /* MBEDTLS_SSL_RENEGOTIATION */ @@ -2996,40 +3017,54 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * \param buf buffer that will hold the data * \param len maximum number of bytes to read * - * \return One of the following: - * - 0 if the read end of the underlying transport was closed, - * - the (positive) number of bytes read, or - * - a negative error code on failure. + * \return The (positive) number of bytes read if successful. + * \return \c 0 is the read end of the underlying transport was closed + * - in this case you must stop using the context (see below). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * in the handshake is incomplete but or waiting for data to + * be availaible for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server + * side of a DTLS connection and the client is initiating a + * new commection using the same source port. See below. + * \return Another SSL error code - in this case you must stop using + * the context (see below). * - * If MBEDTLS_ERR_SSL_WANT_READ is returned, no application data - * is available from the underlying transport. In this case, - * the function needs to be called again at some later stage. + * \warning If this function returns something other than + * a positive value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CLIENT_RECONNECT, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. * - * If MBEDTLS_ERR_SSL_WANT_WRITE is returned, a write is pending - * but the underlying transport isn't available for writing. In this - * case, the function needs to be called again at some later stage. - * - * When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT * (which can only happen server-side), it means that a client * is initiating a new connection using the same source port. * You can either treat that as a connection close and wait * for the client to resend a ClientHello, or directly * continue with \c mbedtls_ssl_handshake() with the same - * context (as it has beeen reset internally). Either way, you - * should make sure this is seen by the application as a new + * context (as it has been reset internally). Either way, you + * must make sure this is seen by the application as a new * connection: application state, if any, should be reset, and * most importantly the identity of the client must be checked * again. WARNING: not validating the identity of the client * again, or not transmitting the new identity to the * application layer, would allow authentication bypass! * - * \note If this function returns something other than a positive value - * or MBEDTLS_ERR_SSL_WANT_READ/WRITE or MBEDTLS_ERR_SSL_CLIENT_RECONNECT, - * you must stop using the SSL context for reading or writing, - * and either free it or call \c mbedtls_ssl_session_reset() on it - * before re-using it for a new connection; the current connection - * must be closed. - * * \note Remarks regarding event-driven DTLS: * - If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram * from the underlying transport layer is currently being processed, @@ -3060,16 +3095,34 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * \param buf buffer holding the data * \param len how many bytes must be written * - * \return the number of bytes actually written (may be less than len), - * or MBEDTLS_ERR_SSL_WANT_WRITE or MBEDTLS_ERR_SSL_WANT_READ, - * or another negative error code. + * \return The (non-negative) number of bytes actually written if + * successfull (may be less than \p len). + * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE + * in the handshake is incomplete but or waiting for data to + * be availaible for reading from or writing to the underlying + * transport - in this case you must call this function again + * when the underlying transport is ready for the operation. + * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous + * operation is in progress (see + * mbedtls_ssl_conf_async_private_cb()) - in this case you + * must call this function again when the operation is ready. + * \return #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS if a cryptographic + * operation is in progress (see mbedtls_ecp_set_max_ops()) - + * in this case you must call this function again to complete + * the handshake when you're done attending other tasks. + * \return Another SSL error code - in this case you must stop using + * the context (see below). * - * \note If this function returns something other than 0, a positive - * value or MBEDTLS_ERR_SSL_WANT_READ/WRITE, you must stop - * using the SSL context for reading or writing, and either - * free it or call \c mbedtls_ssl_session_reset() on it before - * re-using it for a new connection; the current connection - * must be closed. + * \warning If this function returns something other than + * a non-negative value, + * #MBEDTLS_ERR_SSL_WANT_READ, + * #MBEDTLS_ERR_SSL_WANT_WRITE, + * #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS or + * #MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS, + * you must stop using the SSL context for reading or writing, + * and either free it or call \c mbedtls_ssl_session_reset() + * on it before re-using it for a new connection; the current + * connection must be closed. * * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, * it must be called later with the *same* arguments, From ee68cff813a8ee703121a1fd1e6a5baac850d664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Oct 2018 15:27:49 +0200 Subject: [PATCH 136/148] Fix or improve some comments (and whitespace) --- library/ecdh.c | 4 ++-- library/ecp.c | 52 ++++++++++++++++++++-------------------------- library/pk.c | 2 +- library/pk_wrap.c | 4 ++-- library/x509_crt.c | 1 - 5 files changed, 28 insertions(+), 35 deletions(-) diff --git a/library/ecdh.c b/library/ecdh.c index a118de534..833691280 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -200,7 +200,7 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, #endif if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, - f_rng, p_rng, rs_ctx ) ) != 0 ) + f_rng, p_rng, rs_ctx ) ) != 0 ) return( ret ); if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, blen ) ) @@ -211,7 +211,7 @@ int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, blen -= grp_len; if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, ctx->point_format, - &pt_len, buf, blen ) ) != 0 ) + &pt_len, buf, blen ) ) != 0 ) return( ret ); *olen = grp_len + pt_len; diff --git a/library/ecp.c b/library/ecp.c index b2ee5235a..94b42b97c 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1428,7 +1428,7 @@ cleanup: * * - For the sake of compactness, only the seven low-order bits of x[i] * are used to represent its absolute value (K_i in the paper), and the msb - * of x[i] encodes the the sign (s_i in the paper): it is set if and only if + * of x[i] encodes the sign (s_i in the paper): it is set if and only if * if s_i == -1; * * Calling conventions: @@ -1480,10 +1480,10 @@ static void ecp_comb_recode_core( unsigned char x[], size_t d, * * Note: Even comb values (those where P would be omitted from the * sum defining T[i] above) are not needed in our adaption - * the the comb method. See ecp_comb_recode_core(). + * the comb method. See ecp_comb_recode_core(). * * This function currently works in four steps: - * (1) [dbl] Computation of intermediate T[i] for 2-powers values of i + * (1) [dbl] Computation of intermediate T[i] for 2-power values of i * (2) [norm_dbl] Normalization of coordinates of these T[i] * (3) [add] Computation of all T[i] * (4) [norm_add] Normalization of all T[i] @@ -1513,10 +1513,6 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, const unsigned char T_size = 1U << ( w - 1 ); mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; -#if !defined(MBEDTLS_ECP_RESTARTABLE) - (void) rs_ctx; -#endif - #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { @@ -1529,12 +1525,10 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, if( rs_ctx->rsm->state == ecp_rsm_pre_norm_add ) goto norm_add; } +#else + (void) rs_ctx; #endif - /* - * Set T[0] = P and - * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) - */ #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) { @@ -1546,7 +1540,10 @@ static int ecp_precompute_comb( const mbedtls_ecp_group *grp, dbl: #endif - + /* + * Set T[0] = P and + * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) + */ MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); #if defined(MBEDTLS_ECP_RESTARTABLE) @@ -1569,17 +1566,16 @@ dbl: MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); } - /* - * Normalize current elements in T. As T has holes, - * use an auxiliary array of pointers to elements in T. - */ #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) rs_ctx->rsm->state = ecp_rsm_pre_norm_dbl; norm_dbl: #endif - + /* + * Normalize current elements in T. As T has holes, + * use an auxiliary array of pointers to elements in T. + */ j = 0; for( i = 1; i < T_size; i <<= 1 ) TT[j++] = T + i; @@ -1588,17 +1584,16 @@ norm_dbl: MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, j ) ); - /* - * Compute the remaining ones using the minimal number of additions - * Be careful to update T[2^l] only after using it! - */ #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) rs_ctx->rsm->state = ecp_rsm_pre_add; add: #endif - + /* + * Compute the remaining ones using the minimal number of additions + * Be careful to update T[2^l] only after using it! + */ MBEDTLS_ECP_BUDGET( ( T_size - 1 ) * MBEDTLS_ECP_OPS_ADD ); for( i = 1; i < T_size; i <<= 1 ) @@ -1608,18 +1603,17 @@ add: MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); } - /* - * Normalize final elements in T. Even though there are no holes now, - * we still need the auxiliary array for homogeneity with last time. - * Also, skip T[0] which is already normalised, being a copy of P. - */ #if defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && rs_ctx->rsm != NULL ) rs_ctx->rsm->state = ecp_rsm_pre_norm_add; norm_add: #endif - + /* + * Normalize final elements in T. Even though there are no holes now, + * we still need the auxiliary array for homogeneity with last time. + * Also, skip T[0] which is already normalised, being a copy of P. + */ for( j = 0; j + 1 < T_size; j++ ) TT[j] = T + j + 1; @@ -1965,7 +1959,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, if( p_eq_g ) { /* almost transfer ownership of T to the group, but keep a copy of - * the pointer to use for caling the next function more easily */ + * the pointer to use for calling the next function more easily */ grp->T = T; grp->T_size = T_size; } diff --git a/library/pk.c b/library/pk.c index ba8950e8d..ce8dbb5bb 100644 --- a/library/pk.c +++ b/library/pk.c @@ -204,7 +204,7 @@ static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len * Helper to set up a restart context if needed */ static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, - const mbedtls_pk_info_t *info ) + const mbedtls_pk_info_t *info ) { /* Don't do anything if already set up or invalid */ if( ctx == NULL || ctx->pk_info != NULL ) diff --git a/library/pk_wrap.c b/library/pk_wrap.c index cb08ebac3..87806be33 100644 --- a/library/pk_wrap.c +++ b/library/pk_wrap.c @@ -337,7 +337,7 @@ static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, if( rs == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - /* set up our own sub-context if needed */ + /* set up our own sub-context if needed (that is, on first run) */ if( rs->ecdsa_ctx.grp.pbits == 0 ) MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); @@ -362,7 +362,7 @@ static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, if( rs == NULL ) return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - /* set up our own sub-context if needed */ + /* set up our own sub-context if needed (that is, on first run) */ if( rs->ecdsa_ctx.grp.pbits == 0 ) MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); diff --git a/library/x509_crt.c b/library/x509_crt.c index 5d9c6230f..5f9b74f71 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2727,7 +2727,6 @@ void mbedtls_x509_crt_restart_free( mbedtls_x509_crt_restart_ctx *ctx ) return; mbedtls_pk_restart_free( &ctx->pk ); - mbedtls_x509_crt_restart_init( ctx ); } #endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ From 25781f90da956adaa4e0903850da4fc6ad51fa4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 15 Oct 2018 15:28:16 +0200 Subject: [PATCH 137/148] Fix missing check in example client And a mis-indented check as well. --- programs/ssl/ssl_client2.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 146bdfbeb..15c778d31 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -1570,8 +1570,8 @@ int main( int argc, char *argv[] ) } #if defined(MBEDTLS_ECP_RESTARTABLE) - if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) - continue; + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; #endif /* For event-driven IO, wait for socket to become available */ @@ -1674,6 +1674,11 @@ int main( int argc, char *argv[] ) goto exit; } +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + /* For event-driven IO, wait for socket to become available */ if( opt.event == 1 /* level triggered IO */ ) { From c37423fa7628dd39d77090fb1fea7cde2408bc1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Oct 2018 10:28:17 +0200 Subject: [PATCH 138/148] Fix misleading sub-state name and comments The enum constant had 'ske' in its name while this was a sub-state of the "write client key exchange" state; corresponding issue in the comment. --- include/mbedtls/ssl_internal.h | 4 ++-- library/ssl_cli.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index c09fd7007..97abb9f90 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -301,8 +301,8 @@ struct mbedtls_ssl_handshake_params enum { /* this complements ssl->state with info on intra-state operations */ ssl_ecrs_none = 0, /*!< nothing going on (yet) */ ssl_ecrs_crt_verify, /*!< Certificate: crt_verify() */ - ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: step 1 */ - ssl_ecrs_ske_ecdh_calc_secret, /*!< ServerKeyExchange: ECDH step 2 */ + ssl_ecrs_ske_start_processing, /*!< ServerKeyExchange: pk_verify() */ + ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */ ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */ } ecrs_state; /*!< current (or last) operation */ size_t ecrs_n; /*!< place for saving a length */ diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 7b88e61e3..5720a4b88 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -2946,7 +2946,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) if( ssl->handshake->ecrs_enabled ) { - if( ssl->handshake->ecrs_state == ssl_ecrs_ske_ecdh_calc_secret ) + if( ssl->handshake->ecrs_state == ssl_ecrs_cke_ecdh_calc_secret ) goto ecdh_calc_secret; mbedtls_ecdh_enable_restart( &ssl->handshake->ecdh_ctx ); @@ -2973,7 +2973,7 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl ) if( ssl->handshake->ecrs_enabled ) { ssl->handshake->ecrs_n = n; - ssl->handshake->ecrs_state = ssl_ecrs_ske_ecdh_calc_secret; + ssl->handshake->ecrs_state = ssl_ecrs_cke_ecdh_calc_secret; } ecdh_calc_secret: From d8b73f2312a2b5bff26210f4de82c0de573d8d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Oct 2018 10:34:13 +0200 Subject: [PATCH 139/148] Remove unnecessary calls to init() from free() Our API makes no guarantee that you can use a context after free()ing it without re-init()ing it first, so better not give the wrong impression that we do, while it's not policy and the rest of the code might not allow it. --- library/ecdh.c | 2 -- library/ecdsa.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/library/ecdh.c b/library/ecdh.c index 833691280..fb46845c9 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -161,8 +161,6 @@ void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) #if defined(MBEDTLS_ECP_RESTARTABLE) mbedtls_ecp_restart_free( &ctx->rs ); #endif - - mbedtls_ecdh_init( ctx ); } #if defined(MBEDTLS_ECP_RESTARTABLE) diff --git a/library/ecdsa.c b/library/ecdsa.c index 663433c90..9e35da1f7 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -126,8 +126,6 @@ static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx ) mbedtls_mpi_free( &ctx->k ); mbedtls_mpi_free( &ctx->r ); - - ecdsa_restart_sig_init( ctx ); } #if defined(MBEDTLS_ECDSA_DETERMINISTIC) From c0edc96704c36c68a57da05f0cd20cf49376a000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Oct 2018 10:38:19 +0200 Subject: [PATCH 140/148] Add comment on internal function API --- library/ecdh.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/ecdh.c b/library/ecdh.c index fb46845c9..eaad62c99 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -41,6 +41,10 @@ #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) /* * Generate public key (restartable version) + * + * Note: this internal function relies on its caller preserving the value of + * the output parameter 'd' accross continuation calls. This would not be + * acceptable for a public function but is OK here as we control call sites. */ static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, From b843b15a02aa5eb4c466422193b4a2df44859265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Oct 2018 10:41:31 +0200 Subject: [PATCH 141/148] Fix function name to fit conventions --- include/mbedtls/ecp.h | 2 +- library/ecdsa.c | 2 +- library/ecp.c | 4 ++-- library/pk.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h index 3bacf5cab..448549cfc 100644 --- a/include/mbedtls/ecp.h +++ b/include/mbedtls/ecp.h @@ -399,7 +399,7 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ); * \return \c 0 if \c max_ops == 0 (restart disabled) * \return \c 1 otherwise (restart enabled) */ -int mbedtls_ecp_restart_enabled( void ); +int mbedtls_ecp_restart_is_enabled( void ); #endif /* MBEDTLS_ECP_RESTARTABLE */ /** diff --git a/library/ecdsa.c b/library/ecdsa.c index 9e35da1f7..abac015ce 100644 --- a/library/ecdsa.c +++ b/library/ecdsa.c @@ -177,7 +177,7 @@ static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx ) rs_ctx->ecp.ops_done = 0; \ \ /* set up our own sub-context if needed */ \ - if( mbedtls_ecp_restart_enabled() && \ + if( mbedtls_ecp_restart_is_enabled() && \ rs_ctx != NULL && rs_ctx->SUB == NULL ) \ { \ rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ diff --git a/library/ecp.c b/library/ecp.c index 94b42b97c..df85ca4a5 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -106,7 +106,7 @@ void mbedtls_ecp_set_max_ops( unsigned max_ops ) /* * Check if restart is enabled */ -int mbedtls_ecp_restart_enabled( void ) +int mbedtls_ecp_restart_is_enabled( void ) { return( ecp_max_ops != 0 ); } @@ -266,7 +266,7 @@ int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, rs_ctx->ops_done = 0; \ \ /* set up our own sub-context if needed */ \ - if( mbedtls_ecp_restart_enabled() && \ + if( mbedtls_ecp_restart_is_enabled() && \ rs_ctx != NULL && rs_ctx->SUB == NULL ) \ { \ rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ diff --git a/library/pk.c b/library/pk.c index ce8dbb5bb..e0e8dbad2 100644 --- a/library/pk.c +++ b/library/pk.c @@ -239,7 +239,7 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* optimization: use non-restartable version if restart disabled */ if( rs_ctx != NULL && - mbedtls_ecp_restart_enabled() && + mbedtls_ecp_restart_is_enabled() && ctx->pk_info->verify_rs_func != NULL ) { int ret; @@ -352,7 +352,7 @@ int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* optimization: use non-restartable version if restart disabled */ if( rs_ctx != NULL && - mbedtls_ecp_restart_enabled() && + mbedtls_ecp_restart_is_enabled() && ctx->pk_info->sign_rs_func != NULL ) { int ret; From a58e011ac06b1bc05df613345fdebc47c993cd6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Oct 2018 10:42:47 +0200 Subject: [PATCH 142/148] Fix alignment in a macro definition --- library/ecp.c | 54 +++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index df85ca4a5..55d7eb88d 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -260,36 +260,36 @@ int mbedtls_ecp_check_budget( const mbedtls_ecp_group *grp, } /* Call this when entering a function that needs its own sub-context */ -#define ECP_RS_ENTER( SUB ) do { \ - /* reset ops count for this call if top-level */ \ - if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \ - rs_ctx->ops_done = 0; \ - \ - /* set up our own sub-context if needed */ \ - if( mbedtls_ecp_restart_is_enabled() && \ - rs_ctx != NULL && rs_ctx->SUB == NULL ) \ - { \ - rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ - if( rs_ctx->SUB == NULL ) \ - return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ - \ - ecp_restart_## SUB ##_init( rs_ctx->SUB ); \ - } \ +#define ECP_RS_ENTER( SUB ) do { \ + /* reset ops count for this call if top-level */ \ + if( rs_ctx != NULL && rs_ctx->depth++ == 0 ) \ + rs_ctx->ops_done = 0; \ + \ + /* set up our own sub-context if needed */ \ + if( mbedtls_ecp_restart_is_enabled() && \ + rs_ctx != NULL && rs_ctx->SUB == NULL ) \ + { \ + rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \ + if( rs_ctx->SUB == NULL ) \ + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \ + \ + ecp_restart_## SUB ##_init( rs_ctx->SUB ); \ + } \ } while( 0 ) /* Call this when leaving a function that needs its own sub-context */ -#define ECP_RS_LEAVE( SUB ) do { \ - /* clear our sub-context when not in progress (done or error) */ \ - if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ - ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ - { \ - ecp_restart_## SUB ##_free( rs_ctx->SUB ); \ - mbedtls_free( rs_ctx->SUB ); \ - rs_ctx->SUB = NULL; \ - } \ - \ - if( rs_ctx != NULL ) \ - rs_ctx->depth--; \ +#define ECP_RS_LEAVE( SUB ) do { \ + /* clear our sub-context when not in progress (done or error) */ \ + if( rs_ctx != NULL && rs_ctx->SUB != NULL && \ + ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \ + { \ + ecp_restart_## SUB ##_free( rs_ctx->SUB ); \ + mbedtls_free( rs_ctx->SUB ); \ + rs_ctx->SUB = NULL; \ + } \ + \ + if( rs_ctx != NULL ) \ + rs_ctx->depth--; \ } while( 0 ) #else /* MBEDTLS_ECP_RESTARTABLE */ From 90f31b71a866b7813e0798b5424ba372eac7d803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Oct 2018 10:45:24 +0200 Subject: [PATCH 143/148] Improve readability by moving counter decrement Avoid the slightly awkward rs_ctx-> i = i + 1 --- library/ecp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/ecp.c b/library/ecp.c index 55d7eb88d..66ad12ef9 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1711,9 +1711,11 @@ static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); } - while( i-- != 0 ) + while( i != 0 ) { MBEDTLS_ECP_BUDGET( MBEDTLS_ECP_OPS_DBL + MBEDTLS_ECP_OPS_ADD ); + --i; + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, T_size, x[i] ) ); MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); @@ -1727,8 +1729,7 @@ cleanup: if( rs_ctx != NULL && rs_ctx->rsm != NULL && ret == MBEDTLS_ERR_ECP_IN_PROGRESS ) { - /* was decreased before actually doing it */ - rs_ctx->rsm->i = i + 1; + rs_ctx->rsm->i = i; /* no need to save R, already pointing to rs_ctx->rsm->R */ } #endif From 7a28e99fa09471689995d766d04e05a84668fc02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Oct 2018 11:22:45 +0200 Subject: [PATCH 144/148] Expand test to ensure no assumption on output The functions don't require the caller to preserve the content of the output parameter - let's ensure that they don't assume that. --- tests/suites/test_suite_ecp.function | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function index 65736f365..65c487ef8 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -2,6 +2,10 @@ #include "mbedtls/ecp.h" #define ECP_PF_UNKNOWN -1 + +#define ECP_PT_RESET( x ) \ + mbedtls_ecp_point_free( x ); \ + mbedtls_ecp_point_init( x ); /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -78,13 +82,14 @@ void ecp_test_vect_restart( int id, */ mbedtls_ecp_restart_ctx ctx; mbedtls_ecp_group grp; - mbedtls_ecp_point R; + mbedtls_ecp_point R, P; mbedtls_mpi dA, xA, yA, dB, xZ, yZ; int cnt_restarts; int ret; mbedtls_ecp_restart_init( &ctx ); - mbedtls_ecp_group_init( &grp ); mbedtls_ecp_point_init( &R ); + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &R ); mbedtls_ecp_point_init( &P ); mbedtls_mpi_init( &dA ); mbedtls_mpi_init( &xA ); mbedtls_mpi_init( &yA ); mbedtls_mpi_init( &dB ); mbedtls_mpi_init( &xZ ); mbedtls_mpi_init( &yZ ); @@ -103,6 +108,7 @@ void ecp_test_vect_restart( int id, /* Base point case */ cnt_restarts = 0; do { + ECP_PT_RESET( &R ); ret = mbedtls_ecp_mul_restartable( &grp, &R, &dA, &grp.G, NULL, NULL, &ctx ); } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restarts ); @@ -114,9 +120,11 @@ void ecp_test_vect_restart( int id, TEST_ASSERT( cnt_restarts <= max_restarts ); /* Non-base point case */ + mbedtls_ecp_copy( &P, &R ); cnt_restarts = 0; do { - ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &R, NULL, NULL, &ctx ); + ECP_PT_RESET( &R ); + ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &P, NULL, NULL, &ctx ); } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restarts ); TEST_ASSERT( ret == 0 ); @@ -130,13 +138,14 @@ void ecp_test_vect_restart( int id, * This test only makes sense when we actually restart */ if( min_restarts > 0 ) { - ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &R, NULL, NULL, &ctx ); + ret = mbedtls_ecp_mul_restartable( &grp, &R, &dB, &P, NULL, NULL, &ctx ); TEST_ASSERT( ret == MBEDTLS_ERR_ECP_IN_PROGRESS ); } exit: mbedtls_ecp_restart_free( &ctx ); - mbedtls_ecp_group_free( &grp ); mbedtls_ecp_point_free( &R ); + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); mbedtls_ecp_point_free( &P ); mbedtls_mpi_free( &dA ); mbedtls_mpi_free( &xA ); mbedtls_mpi_free( &yA ); mbedtls_mpi_free( &dB ); mbedtls_mpi_free( &xZ ); mbedtls_mpi_free( &yZ ); } @@ -183,6 +192,7 @@ void ecp_muladd_restart( int id, char *xR_str, char *yR_str, cnt_restarts = 0; do { + ECP_PT_RESET( &R ); ret = mbedtls_ecp_muladd_restartable( &grp, &R, &u1, &grp.G, &u2, &Q, &ctx ); } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restarts ); From a5a3e40c4eadc4dc52ac9f2eaf0d81880fb0761b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Oct 2018 11:27:23 +0200 Subject: [PATCH 145/148] Fix missing dereference. Went unnoticed because it was only on a defensive code path, in an internal function, so not exercised. --- library/x509_crt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 5f9b74f71..25aaff3b0 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2182,8 +2182,8 @@ static int x509_crt_find_parent( /* extra precaution against mistakes in the caller */ if( parent == NULL ) { - parent_is_trusted = 0; - signature_is_good = 0; + *parent_is_trusted = 0; + *signature_is_good = 0; } return( 0 ); From b25cb603bbb68f225a3fc5a25c22adb81eaf6c34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 16 Oct 2018 11:48:09 +0200 Subject: [PATCH 146/148] Add a comment to clarify code flow --- library/ecp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/library/ecp.c b/library/ecp.c index 66ad12ef9..dff5f9004 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1933,6 +1933,7 @@ static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, rs_ctx->rsm->T = NULL; rs_ctx->rsm->T_size = 0; + /* This effectively jumps to the call to mul_comb_after_precomp() */ T_ok = rs_ctx->rsm->state >= ecp_rsm_comb_core; } else From ca29fdf569a43a0302895fd6f8b6443f1cbba581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 22 Oct 2018 09:56:53 +0200 Subject: [PATCH 147/148] Fix some typos in documentation and comments --- include/mbedtls/ssl.h | 20 ++++++++++---------- library/ecdh.c | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 942bf2c15..163ca3871 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2917,7 +2917,7 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE * in the handshake is incomplete but or waiting for data to - * be availaible for reading from or writing to the underlying + * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous @@ -2951,7 +2951,7 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session * actual error, but you still need to reset/free the context. * * \note Remarks regarding event-driven DTLS: - * If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram + * If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram * from the underlying transport layer is currently being processed, * and it is safe to idle until the timer or the underlying transport * signal a new event. This is not true for a successful handshake, @@ -3022,7 +3022,7 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * - in this case you must stop using the context (see below). * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE * in the handshake is incomplete but or waiting for data to - * be availaible for reading from or writing to the underlying + * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous @@ -3035,7 +3035,7 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * the handshake when you're done attending other tasks. * \return #MBEDTLS_ERR_SSL_CLIENT_RECONNECT if we're at the server * side of a DTLS connection and the client is initiating a - * new commection using the same source port. See below. + * new connection using the same source port. See below. * \return Another SSL error code - in this case you must stop using * the context (see below). * @@ -3051,7 +3051,7 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * on it before re-using it for a new connection; the current * connection must be closed. * - * \note When this function return MBEDTLS_ERR_SSL_CLIENT_RECONNECT + * \note When this function returns #MBEDTLS_ERR_SSL_CLIENT_RECONNECT * (which can only happen server-side), it means that a client * is initiating a new connection using the same source port. * You can either treat that as a connection close and wait @@ -3066,7 +3066,7 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * application layer, would allow authentication bypass! * * \note Remarks regarding event-driven DTLS: - * - If the function returns MBEDTLS_ERR_SSL_WANT_READ, no datagram + * - If the function returns #MBEDTLS_ERR_SSL_WANT_READ, no datagram * from the underlying transport layer is currently being processed, * and it is safe to idle until the timer or the underlying transport * signal a new event. @@ -3096,10 +3096,10 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * \param len how many bytes must be written * * \return The (non-negative) number of bytes actually written if - * successfull (may be less than \p len). + * successful (may be less than \p len). * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE * in the handshake is incomplete but or waiting for data to - * be availaible for reading from or writing to the underlying + * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. * \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if an asynchronous @@ -3124,10 +3124,10 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * on it before re-using it for a new connection; the current * connection must be closed. * - * \note When this function returns MBEDTLS_ERR_SSL_WANT_WRITE/READ, + * \note When this function returns #MBEDTLS_ERR_SSL_WANT_WRITE/READ, * it must be called later with the *same* arguments, * until it returns a value greater that or equal to 0. When - * the function returns MBEDTLS_ERR_SSL_WANT_WRITE there may be + * the function returns #MBEDTLS_ERR_SSL_WANT_WRITE there may be * some partial data in the output buffer, however this is not * yet sent. * diff --git a/library/ecdh.c b/library/ecdh.c index eaad62c99..80e967641 100644 --- a/library/ecdh.c +++ b/library/ecdh.c @@ -43,7 +43,7 @@ * Generate public key (restartable version) * * Note: this internal function relies on its caller preserving the value of - * the output parameter 'd' accross continuation calls. This would not be + * the output parameter 'd' across continuation calls. This would not be * acceptable for a public function but is OK here as we control call sites. */ static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, From a966fdea72678e38beb06c1160768afa6362e295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 23 Oct 2018 10:41:11 +0200 Subject: [PATCH 148/148] Fix some documentation typos and improve a comment --- include/mbedtls/ssl.h | 8 ++++---- library/ecp.c | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 163ca3871..e8f664a78 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2916,7 +2916,7 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session * * \return \c 0 if successful. * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE - * in the handshake is incomplete but or waiting for data to + * if the handshake is incomplete and waiting for data to * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. @@ -3018,10 +3018,10 @@ int mbedtls_ssl_renegotiate( mbedtls_ssl_context *ssl ); * \param len maximum number of bytes to read * * \return The (positive) number of bytes read if successful. - * \return \c 0 is the read end of the underlying transport was closed + * \return \c 0 if the read end of the underlying transport was closed * - in this case you must stop using the context (see below). * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE - * in the handshake is incomplete but or waiting for data to + * if the handshake is incomplete and waiting for data to * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. @@ -3098,7 +3098,7 @@ int mbedtls_ssl_read( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len ) * \return The (non-negative) number of bytes actually written if * successful (may be less than \p len). * \return #MBEDTLS_ERR_SSL_WANT_READ or #MBEDTLS_ERR_SSL_WANT_WRITE - * in the handshake is incomplete but or waiting for data to + * if the handshake is incomplete and waiting for data to * be available for reading from or writing to the underlying * transport - in this case you must call this function again * when the underlying transport is ready for the operation. diff --git a/library/ecp.c b/library/ecp.c index dff5f9004..b193ad4f8 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -1610,9 +1610,9 @@ add: norm_add: #endif /* - * Normalize final elements in T. Even though there are no holes now, - * we still need the auxiliary array for homogeneity with last time. - * Also, skip T[0] which is already normalised, being a copy of P. + * Normalize final elements in T. Even though there are no holes now, we + * still need the auxiliary array for homogeneity with the previous + * call. Also, skip T[0] which is already normalised, being a copy of P. */ for( j = 0; j + 1 < T_size; j++ ) TT[j] = T + j + 1;