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 */