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.
diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h
index 756360b..20e4436 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 @@
     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 a2b9f8c..8d7bc45 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -2861,6 +2861,11 @@
          */
         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 @@
 
         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 @@
         }
 
         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 280fc63..05e8822 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -3441,6 +3441,48 @@
             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" \