Make muladd_restartable() actually restartable
diff --git a/library/ecp.c b/library/ecp.c
index 4933460..f520b9c 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -153,7 +153,14 @@
  */
 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 @@
     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 @@
     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 @@
 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 @@
     }
     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 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 @@
     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 @@
 
         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 @@
     }
 
 #endif /* MBEDTLS_ECP_INTERNAL_ALT */
+
     mbedtls_ecp_point_free( &mP );
 
 #if defined(MBEDTLS_ECP_EARLY_RETURN)
@@ -2351,7 +2409,6 @@
         rs_ctx->ma = NULL;
     }
 
-
     if( rs_ctx != NULL )
         rs_ctx->depth--;
 #endif /* MBEDTLS_ECP_EARLY_RETURN */