Add ecjpake_zpk_read()

Not really tested yet
diff --git a/include/mbedtls/ecp.h b/include/mbedtls/ecp.h
index e827040..5246c78 100644
--- a/include/mbedtls/ecp.h
+++ b/include/mbedtls/ecp.h
@@ -347,6 +347,21 @@
 int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt );
 
 /**
+ * \brief           Compare two points
+ *
+ * \note            This assumes the points are normalized. Otherwise,
+ *                  they may compare as "not equal" even if they are.
+ *
+ * \param P         First point to compare
+ * \param Q         Second point to compare
+ *
+ * \return          0 if the points are equal,
+ *                  MBEDTLS_ERR_ECP_BAD_INPUT_DATA otherwise
+ */
+int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
+                           const mbedtls_ecp_point *Q );
+
+/**
  * \brief           Import a non-zero point from two ASCII strings
  *
  * \param P         Destination point
diff --git a/library/ecjpake.c b/library/ecjpake.c
index 3046154..328204c 100644
--- a/library/ecjpake.c
+++ b/library/ecjpake.c
@@ -121,7 +121,7 @@
 /*
  * Generate ZKP (7.4.2.3.2) and write it as ECSchnorrZKP (7.4.2.2.2)
  */
-static int ecjpake_write_zkp( const mbedtls_md_info_t *md_info,
+static int ecjpake_zkp_write( const mbedtls_md_info_t *md_info,
                               const mbedtls_ecp_group *grp,
                               const mbedtls_ecp_point *G,
                               const mbedtls_mpi *x,
@@ -174,6 +174,69 @@
     return( ret );
 }
 
+/*
+ * Parse a ECShnorrZKP (7.4.2.2.2) and verify it (7.4.2.3.3)
+ */
+static int ecjpake_zkp_read( const mbedtls_md_info_t *md_info,
+                             const mbedtls_ecp_group *grp,
+                             const mbedtls_ecp_point *G,
+                             const mbedtls_ecp_point *X,
+                             const char *id,
+                             unsigned char **p,
+                             const unsigned char *end )
+{
+    int ret;
+    mbedtls_ecp_point V, VV;
+    mbedtls_mpi r, h;
+    size_t r_len;
+
+    mbedtls_ecp_point_init( &V );
+    mbedtls_ecp_point_init( &VV );
+    mbedtls_mpi_init( &r );
+    mbedtls_mpi_init( &h );
+
+    /*
+     * struct {
+     *     ECPoint V;
+     *     opaque r<1..2^8-1>;
+     * } ECSchnorrZKP;
+     */
+    if( end < *p )
+        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+
+    MBEDTLS_MPI_CHK( mbedtls_ecp_tls_read_point( grp, &V,
+                     (const unsigned char **) p, end - *p ) );
+
+    if( end < *p || (size_t)( end - *p ) < 1 )
+        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+
+    r_len = *(*p)++;
+    if( end < *p || (size_t)( end - *p ) < r_len )
+        return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+
+    MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &r, *p, r_len ) );
+    *p += r_len;
+
+    /*
+     * Verification
+     */
+    MBEDTLS_MPI_CHK( ecjpake_hash( md_info, grp, G, &V, X, id, &h ) );
+    MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( (mbedtls_ecp_group *) grp,
+                     &VV, &h, X, &r, G ) );
+
+    if( mbedtls_ecp_point_cmp( &VV, &V ) != 0 )
+        return( MBEDTLS_ERR_ECP_VERIFY_FAILED );
+
+cleanup:
+    mbedtls_ecp_point_free( &V );
+    mbedtls_ecp_point_free( &VV );
+    mbedtls_mpi_free( &r );
+    mbedtls_mpi_free( &h );
+
+    return( ret );
+}
+
+
 #if defined(MBEDTLS_SELF_TEST)
 
 #if defined(MBEDTLS_PLATFORM_C)
@@ -293,16 +356,20 @@
         mbedtls_printf( "passed\n" );
 
     if( verbose != 0 )
-        mbedtls_printf( "  ECJPAKE test #2 (zkp, WIP): " );
+        mbedtls_printf( "  ECJPAKE test #2 (zkp write/read): " );
 
     MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair_base( &grp, &G, &x, &X,
                                                    ecjpake_lgc, NULL ) );
 
     p = buf;
-    MBEDTLS_MPI_CHK( ecjpake_write_zkp( md_info, &grp, &G, &x, &X, "client",
+    MBEDTLS_MPI_CHK( ecjpake_zkp_write( md_info, &grp, &G, &x, &X, "client",
                                         &p, buf + sizeof( buf ),
                                         ecjpake_lgc, NULL ) );
 
+    p = buf;
+    MBEDTLS_MPI_CHK( ecjpake_zkp_read( md_info, &grp, &G, &X, "client",
+                                       &p, buf + sizeof( buf ) ) );
+
     if( verbose != 0 )
         mbedtls_printf( "passed\n" );
 
diff --git a/library/ecp.c b/library/ecp.c
index b21e69d..54f51ab 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -403,6 +403,22 @@
 }
 
 /*
+ * Compare two points lazyly
+ */
+int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P,
+                           const mbedtls_ecp_point *Q )
+{
+    if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 &&
+        mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 &&
+        mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 )
+    {
+        return( 0 );
+    }
+
+    return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
+}
+
+/*
  * Import a non-zero point from ASCII strings
  */
 int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix,