Add test for ECP group metadata

Test cases added to check curve parameters and information for each
curve supported. Expected parameters are taken from references: SEC 2
for NIST, RFC 5639 for Brainpool, and RFC 7748 for curve25519/curve448.

Signed-off-by: Werner Lewis <werner.lewis@arm.com>
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 0f3e913..896f649 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -1,5 +1,7 @@
 /* BEGIN_HEADER */
 #include "mbedtls/ecp.h"
+#include "mbedtls/ecdsa.h"
+#include "mbedtls/ecdh.h"
 
 #include "ecp_invasive.h"
 
@@ -1100,6 +1102,110 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE depends_on:MBEDTLS_ECDH_C:MBEDTLS_ECDSA_C */
+void mbedtls_ecp_group_metadata( int id, int bit_size, int crv_type,
+                                 char* P, char* A, char* B,
+                                 char* G_x, char* G_y, char* N,
+                                 int tls_id )
+{
+    mbedtls_ecp_group grp, grp_read, grp_cpy;
+    const mbedtls_ecp_group_id *g_id;
+    const mbedtls_ecp_curve_info *crv, *crv_tls_id, *crv_name;
+
+    mbedtls_mpi exp_P, exp_A, exp_B, exp_G_x, exp_G_y, exp_N;
+
+    unsigned char buf[3], ecparameters[3] = { 3, 0, tls_id };
+    const unsigned char *vbuf = buf;
+    size_t olen;
+
+    mbedtls_ecp_group_init( &grp );
+    mbedtls_ecp_group_init( &grp_read );
+    mbedtls_ecp_group_init( &grp_cpy );
+
+    mbedtls_mpi_init( &exp_P );
+    mbedtls_mpi_init( &exp_A );
+    mbedtls_mpi_init( &exp_B );
+    mbedtls_mpi_init( &exp_G_x );
+    mbedtls_mpi_init( &exp_G_y );
+    mbedtls_mpi_init( &exp_N );
+
+    // Read expected parameters
+    TEST_EQUAL( mbedtls_test_read_mpi( &exp_P, P ), 0 );
+    TEST_EQUAL( mbedtls_test_read_mpi( &exp_A, A ), 0 );
+    TEST_EQUAL( mbedtls_test_read_mpi( &exp_G_x, G_x ), 0 );
+    TEST_EQUAL( mbedtls_test_read_mpi( &exp_N, N ), 0 );
+    TEST_EQUAL( mbedtls_test_read_mpi( &exp_B, B ), 0 );
+    TEST_EQUAL( mbedtls_test_read_mpi( &exp_G_y, G_y ), 0 );
+
+    // Load group
+    TEST_EQUAL( mbedtls_ecp_group_load( &grp, id ), 0 );
+
+    // Compare group with expected parameters
+    // A is NULL for SECPxxxR1 curves
+    // B and G_y are NULL for curve25519 and curve448
+    TEST_EQUAL( mbedtls_mpi_cmp_mpi( &exp_P, &grp.P ), 0 );
+    if( *A != 0 )
+        TEST_EQUAL( mbedtls_mpi_cmp_mpi( &exp_A, &grp.A ), 0 );
+    if( *B != 0 )
+        TEST_EQUAL( mbedtls_mpi_cmp_mpi( &exp_B, &grp.B ), 0 );
+    TEST_EQUAL( mbedtls_mpi_cmp_mpi( &exp_G_x, &grp.G.X ), 0 );
+    if( *G_y != 0 )
+        TEST_EQUAL( mbedtls_mpi_cmp_mpi( &exp_G_y, &grp.G.Y ), 0 );
+    TEST_EQUAL( mbedtls_mpi_cmp_mpi( &exp_N, &grp.N ), 0 );
+
+    // Load curve info and compare with known values
+    crv = mbedtls_ecp_curve_info_from_grp_id( id );
+    TEST_EQUAL( crv->grp_id, id );
+    TEST_EQUAL( crv->bit_size, bit_size );
+    TEST_EQUAL( crv->tls_id, tls_id );
+
+    // Load curve from TLS ID and name, and compare IDs
+    crv_tls_id = mbedtls_ecp_curve_info_from_tls_id( crv->tls_id );
+    crv_name = mbedtls_ecp_curve_info_from_name( crv->name );
+    TEST_EQUAL( crv_tls_id->grp_id, id );
+    TEST_EQUAL( crv_name->grp_id, id );
+
+    // Validate write_group against test data, read result
+    TEST_EQUAL( mbedtls_ecp_tls_write_group( &grp, &olen,
+                                             buf, sizeof( buf ) ),
+                0 );
+    TEST_EQUAL( mbedtls_test_hexcmp( buf, ecparameters, olen,
+                                     sizeof( ecparameters ) ),
+                0 );
+    TEST_EQUAL( mbedtls_ecp_tls_read_group( &grp_read, &vbuf, olen ),
+                0 );
+    TEST_EQUAL( grp_read.id, id );
+
+    // Check curve type, and if it can be used for ECDH/ECDSA
+    TEST_EQUAL( mbedtls_ecp_get_type( &grp ), crv_type );
+    TEST_EQUAL( mbedtls_ecdh_can_do( id ), 1 );
+    TEST_EQUAL( mbedtls_ecdsa_can_do( id ),
+                crv_type == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS );
+
+    // Copy group and compare with original
+    TEST_EQUAL( mbedtls_ecp_group_copy( &grp_cpy, &grp ), 0 );
+    TEST_EQUAL( mbedtls_ecp_group_cmp( &grp, &grp_cpy ), 0 );
+
+    // Check curve is in curve list and group ID list
+    for( crv = mbedtls_ecp_curve_list(  );
+          crv->grp_id != MBEDTLS_ECP_DP_NONE &&
+          crv->grp_id != (unsigned) id;
+          crv++ );
+    TEST_EQUAL( crv->grp_id, id );
+    for( g_id = mbedtls_ecp_grp_id_list(  );
+         *g_id != MBEDTLS_ECP_DP_NONE && *g_id != (unsigned) id;
+         g_id++ );
+    TEST_EQUAL( *g_id, (unsigned) id );
+
+exit:
+    mbedtls_ecp_group_free( &grp ); mbedtls_ecp_group_free( &grp_cpy );
+    mbedtls_ecp_group_free( &grp_read );
+    mbedtls_mpi_free( &exp_P ); mbedtls_mpi_free( &exp_A );
+    mbedtls_mpi_free( &exp_B ); mbedtls_mpi_free( &exp_G_x );
+    mbedtls_mpi_free( &exp_G_y ); mbedtls_mpi_free( &exp_N );
+}
+/* END_CASE */
+
 /* BEGIN_CASE */
 void mbedtls_ecp_check_privkey( int id, char * key_hex, int ret )
 {