Merged EC key generation support
diff --git a/ChangeLog b/ChangeLog
index 9419df2..b1cbb00 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,9 @@
PolarSSL ChangeLog (Sorted per branch, date)
= PolarSSL 1.3 branch
+Features
+ * EC key generation support in gen_key app
+
Changes
* gen_prime() speedup
* Speedup of ECP multiplication operation
diff --git a/include/polarssl/ecp.h b/include/polarssl/ecp.h
index 33c09fc..c0f5079 100644
--- a/include/polarssl/ecp.h
+++ b/include/polarssl/ecp.h
@@ -205,6 +205,15 @@
const ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id );
/**
+ * \brief Get curve information from a human-readable name
+ *
+ * \param name The name
+ *
+ * \return The associated curve information or NULL
+ */
+const ecp_curve_info *ecp_curve_info_from_name( const char *name );
+
+/**
* \brief Initialize a point (as zero)
*/
void ecp_point_init( ecp_point *pt );
@@ -536,6 +545,20 @@
void *p_rng );
/**
+ * \brief Generate a keypair
+ *
+ * \param grp_id ECP group identifier
+ * \param key Destination keypair
+ * \param f_rng RNG function
+ * \param p_rng RNG parameter
+ *
+ * \return 0 if successful,
+ * or a POLARSSL_ERR_ECP_XXX or POLARSSL_MPI_XXX error code
+ */
+int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
+
+/**
* \brief Checkup routine
*
* \return 0 if successful, or 1 if the test failed
diff --git a/library/ecp.c b/library/ecp.c
index 0c66d35..ef38d19 100644
--- a/library/ecp.c
+++ b/library/ecp.c
@@ -58,6 +58,11 @@
#include <limits.h>
#include <stdlib.h>
+#if defined(_MSC_VER) && !defined strcasecmp && !defined(EFIX64) && \
+ !defined(EFI32)
+#define strcasecmp _stricmp
+#endif
+
#if defined(_MSC_VER) && !defined(inline)
#define inline _inline
#else
@@ -84,13 +89,13 @@
const ecp_curve_info ecp_supported_curves[] =
{
#if defined(POLARSSL_ECP_DP_BP512R1_ENABLED)
- { POLARSSL_ECP_DP_BP512R1, 28, 512, "brainpool512r1" },
+ { POLARSSL_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" },
#endif
#if defined(POLARSSL_ECP_DP_BP384R1_ENABLED)
- { POLARSSL_ECP_DP_BP384R1, 27, 384, "brainpool384r1" },
+ { POLARSSL_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" },
#endif
#if defined(POLARSSL_ECP_DP_BP256R1_ENABLED)
- { POLARSSL_ECP_DP_BP256R1, 26, 256, "brainpool256r1" },
+ { POLARSSL_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" },
#endif
#if defined(POLARSSL_ECP_DP_SECP521R1_ENABLED)
{ POLARSSL_ECP_DP_SECP521R1, 25, 521, "secp521r1" },
@@ -155,6 +160,24 @@
}
/*
+ * Get the curve info from the name
+ */
+const ecp_curve_info *ecp_curve_info_from_name( const char *name )
+{
+ const ecp_curve_info *curve_info;
+
+ for( curve_info = ecp_curve_list();
+ curve_info->grp_id != POLARSSL_ECP_DP_NONE;
+ curve_info++ )
+ {
+ if( strcasecmp( curve_info->name, name ) == 0 )
+ return( curve_info );
+ }
+
+ return( NULL );
+}
+
+/*
* Initialize (the components of) a point
*/
void ecp_point_init( ecp_point *pt )
@@ -1669,6 +1692,20 @@
return( ecp_mul( grp, Q, d, &grp->G, f_rng, p_rng ) );
}
+/*
+ * Generate a keypair, prettier wrapper
+ */
+int ecp_gen_key( ecp_group_id grp_id, ecp_keypair *key,
+ int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
+{
+ int ret;
+
+ if( ( ret = ecp_use_known_dp( &key->grp, grp_id ) ) != 0 )
+ return( ret );
+
+ return( ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) );
+}
+
#if defined(POLARSSL_ECP_NIST_OPTIM)
/*
* Fast reduction modulo the primes used by the NIST curves.
diff --git a/programs/.gitignore b/programs/.gitignore
index 003369b..50f1521 100644
--- a/programs/.gitignore
+++ b/programs/.gitignore
@@ -47,3 +47,6 @@
x509/crl_app
x509/cert_write
x509/req_app
+
+# generated files
+pkey/keyfile.key
diff --git a/programs/pkey/gen_key.c b/programs/pkey/gen_key.c
index 19f46a4..e7dab24 100644
--- a/programs/pkey/gen_key.c
+++ b/programs/pkey/gen_key.c
@@ -51,13 +51,12 @@
}
#else
-#define TYPE_RSA 0
-
#define FORMAT_PEM 0
#define FORMAT_DER 1
-#define DFL_TYPE TYPE_RSA
+#define DFL_TYPE POLARSSL_PK_RSA
#define DFL_RSA_KEYSIZE 4096
+#define DFL_EC_CURVE ecp_curve_list()->grp_id
#define DFL_FILENAME "keyfile.key"
#define DFL_FORMAT FORMAT_PEM
@@ -68,6 +67,7 @@
{
int type; /* the type of key to generate */
int rsa_keysize; /* length of key in bits */
+ int ec_curve; /* curve identifier for EC keys */
const char *filename; /* filename of the key file */
int format; /* the output format to use */
} opt;
@@ -109,11 +109,12 @@
}
#define USAGE \
- "\n usage: gen_key param=<>...\n" \
+ "\n usage: gen_key param=<>...\n" \
"\n acceptable parameters:\n" \
- " type=rsa default: rsa\n" \
- " rsa_keysize=%%d default: 4096\n" \
- " filename=%%s default: keyfile.key\n" \
+ " type=rsa|ec default: rsa\n" \
+ " rsa_keysize=%%d default: 4096\n" \
+ " ec_curve=%%s see below\n" \
+ " filename=%%s default: keyfile.key\n" \
" format=pem|der default: pem\n" \
"\n"
@@ -127,6 +128,9 @@
entropy_context entropy;
ctr_drbg_context ctr_drbg;
const char *pers = "gen_key";
+#if defined(POLARSSL_ECP_C)
+ const ecp_curve_info *curve_info;
+#endif
/*
* Set to sane values
@@ -139,11 +143,19 @@
usage:
ret = 1;
printf( USAGE );
+#if defined(POLARSSL_ECP_C)
+ printf( " availabled ec_curve values:\n" );
+ curve_info = ecp_curve_list();
+ printf( " %s (default)\n", curve_info->name );
+ while( ( ++curve_info )->name != NULL )
+ printf( " %s\n", curve_info->name );
+#endif
goto exit;
}
opt.type = DFL_TYPE;
opt.rsa_keysize = DFL_RSA_KEYSIZE;
+ opt.ec_curve = DFL_EC_CURVE;
opt.filename = DFL_FILENAME;
opt.format = DFL_FORMAT;
@@ -157,7 +169,9 @@
if( strcmp( p, "type" ) == 0 )
{
if( strcmp( q, "rsa" ) == 0 )
- opt.type = TYPE_RSA;
+ opt.type = POLARSSL_PK_RSA;
+ if( strcmp( q, "ec" ) == 0 )
+ opt.type = POLARSSL_PK_ECKEY;
else
goto usage;
}
@@ -176,6 +190,12 @@
if( opt.rsa_keysize < 1024 || opt.rsa_keysize > 8192 )
goto usage;
}
+ else if( strcmp( p, "ec_curve" ) == 0 )
+ {
+ if( ( curve_info = ecp_curve_info_from_name( q ) ) == NULL )
+ goto usage;
+ opt.ec_curve = curve_info->grp_id;
+ }
else if( strcmp( p, "filename" ) == 0 )
opt.filename = q;
else
@@ -200,10 +220,15 @@
printf( "\n . Generating the private key ..." );
fflush( stdout );
-#if defined(POLARSSL_RSA_C) && defined(POLARSSL_GENPRIME)
- if( opt.type == TYPE_RSA )
+ if( ( ret = pk_init_ctx( &key, pk_info_from_type( opt.type ) ) ) != 0 )
{
- pk_init_ctx( &key, pk_info_from_type( POLARSSL_PK_RSA ) );
+ printf( " failed\n ! pk_init_ctx returned -0x%04x", -ret );
+ goto exit;
+ }
+
+#if defined(POLARSSL_RSA_C) && defined(POLARSSL_GENPRIME)
+ if( opt.type == POLARSSL_PK_RSA )
+ {
ret = rsa_gen_key( pk_rsa( key ), ctr_drbg_random, &ctr_drbg,
opt.rsa_keysize, 65537 );
if( ret != 0 )
@@ -211,20 +236,31 @@
printf( " failed\n ! rsa_gen_key returned -0x%04x", -ret );
goto exit;
}
-
- printf( " ok\n" );
}
else
#endif /* POLARSSL_RSA_C */
+#if defined(POLARSSL_ECP_C)
+ if( opt.type == POLARSSL_PK_ECKEY )
{
- printf( " failed\n ! key type not supported in library" );
+ ret = ecp_gen_key( opt.ec_curve, pk_ec( key ),
+ ctr_drbg_random, &ctr_drbg );
+ if( ret != 0 )
+ {
+ printf( " failed\n ! rsa_gen_key returned -0x%04x", -ret );
+ goto exit;
+ }
+ }
+ else
+#endif /* POLARSSL_ECP_C */
+ {
+ printf( " failed\n ! key type not supported\n" );
goto exit;
}
/*
* 1.2 Print the key
*/
- printf( " . Key information ...\n" );
+ printf( " ok\n . Key information:\n" );
#if defined(POLARSSL_RSA_C)
if( pk_get_type( &key ) == POLARSSL_PK_RSA )
@@ -245,14 +281,15 @@
if( pk_get_type( &key ) == POLARSSL_PK_ECKEY )
{
ecp_keypair *ecp = pk_ec( key );
- mpi_write_file( "Q(X): ", &ecp->Q.X, 16, NULL );
- mpi_write_file( "Q(Y): ", &ecp->Q.Y, 16, NULL );
- mpi_write_file( "Q(Z): ", &ecp->Q.Z, 16, NULL );
- mpi_write_file( "D : ", &ecp->d , 16, NULL );
+ printf( "curve: %s\n",
+ ecp_curve_info_from_grp_id( ecp->grp.id )->name );
+ mpi_write_file( "X_Q: ", &ecp->Q.X, 16, NULL );
+ mpi_write_file( "Y_Q: ", &ecp->Q.Y, 16, NULL );
+ mpi_write_file( "D: ", &ecp->d , 16, NULL );
}
else
#endif
- printf("key type not supported yet\n");
+ printf(" ! key type not supported\n");
write_private_key( &key, opt.filename );
diff --git a/tests/suites/test_suite_ecp.data b/tests/suites/test_suite_ecp.data
index 8dafc39..17ad8aa 100644
--- a/tests/suites/test_suite_ecp.data
+++ b/tests/suites/test_suite_ecp.data
@@ -1,3 +1,35 @@
+ECP curve info #1
+depends_on:POLARSSL_ECP_DP_BP512R1_ENABLED
+ecp_curve_info:POLARSSL_ECP_DP_BP512R1:28:512:"brainpoolP512r1"
+
+ECP curve info #2
+depends_on:POLARSSL_ECP_DP_BP384R1_ENABLED
+ecp_curve_info:POLARSSL_ECP_DP_BP384R1:27:384:"brainpoolP384r1"
+
+ECP curve info #3
+depends_on:POLARSSL_ECP_DP_BP256R1_ENABLED
+ecp_curve_info:POLARSSL_ECP_DP_BP256R1:26:256:"brainpoolP256r1"
+
+ECP curve info #4
+depends_on:POLARSSL_ECP_DP_SECP521R1_ENABLED
+ecp_curve_info:POLARSSL_ECP_DP_SECP521R1:25:521:"secp521r1"
+
+ECP curve info #5
+depends_on:POLARSSL_ECP_DP_SECP384R1_ENABLED
+ecp_curve_info:POLARSSL_ECP_DP_SECP384R1:24:384:"secp384r1"
+
+ECP curve info #6
+depends_on:POLARSSL_ECP_DP_SECP256R1_ENABLED
+ecp_curve_info:POLARSSL_ECP_DP_SECP256R1:23:256:"secp256r1"
+
+ECP curve info #7
+depends_on:POLARSSL_ECP_DP_SECP224R1_ENABLED
+ecp_curve_info:POLARSSL_ECP_DP_SECP224R1:21:224:"secp224r1"
+
+ECP curve info #8
+depends_on:POLARSSL_ECP_DP_SECP192R1_ENABLED
+ecp_curve_info:POLARSSL_ECP_DP_SECP192R1:19:192:"secp192r1"
+
ECP small addition #1
ecp_small_add:1:"":"":1:"":"":1:0:0
@@ -247,6 +279,10 @@
depends_on:POLARSSL_ECP_DP_SECP192R1_ENABLED
ecp_gen_keypair:POLARSSL_ECP_DP_SECP192R1
+ECP gen keypair wrapper
+depends_on:POLARSSL_ECP_DP_SECP192R1_ENABLED
+ecp_gen_key:POLARSSL_ECP_DP_SECP192R1
+
ECP mod p192 small (more than 192 bits, less limbs than 2 * 192 bits)
depends_on:POLARSSL_ECP_DP_SECP192R1_ENABLED
ecp_fast_mod:POLARSSL_ECP_DP_SECP192R1:"0100000000000103010000000000010201000000000001010100000000000100"
diff --git a/tests/suites/test_suite_ecp.function b/tests/suites/test_suite_ecp.function
index 8cc5aba..cb93e85 100644
--- a/tests/suites/test_suite_ecp.function
+++ b/tests/suites/test_suite_ecp.function
@@ -10,6 +10,22 @@
*/
/* BEGIN_CASE */
+void ecp_curve_info( int id, int tls_id, int size, char *name )
+{
+ const ecp_curve_info *by_id, *by_tls, *by_name;
+
+ TEST_ASSERT( ( by_id = ecp_curve_info_from_grp_id( id ) ) != NULL );
+ TEST_ASSERT( ( by_tls = ecp_curve_info_from_tls_id( tls_id ) ) != NULL );
+ TEST_ASSERT( ( by_name = ecp_curve_info_from_name( name ) ) != NULL );
+
+ TEST_ASSERT( by_id == by_tls );
+ TEST_ASSERT( by_id == by_name );
+
+ TEST_ASSERT( by_id->size == size );
+}
+/* END_CASE */
+
+/* BEGIN_CASE */
void ecp_small_add( int a_zero, char *x_a, char *y_a, int b_zero, char *x_b,
char *y_b, int c_zero, int x_c, int y_c )
{
@@ -522,6 +538,24 @@
}
/* END_CASE */
+/* BEGIN_CASE */
+void ecp_gen_key( int id )
+{
+ ecp_keypair key;
+ rnd_pseudo_info rnd_info;
+
+ ecp_keypair_init( &key );
+ memset( &rnd_info, 0x00, sizeof( rnd_pseudo_info ) );
+
+ TEST_ASSERT( ecp_gen_key( id, &key, &rnd_pseudo_rand, &rnd_info ) == 0 );
+
+ TEST_ASSERT( ecp_check_pubkey( &key.grp, &key.Q ) == 0 );
+ TEST_ASSERT( ecp_check_privkey( &key.grp, &key.d ) == 0 );
+
+ ecp_keypair_free( &key );
+}
+/* END_CASE */
+
/* BEGIN_CASE depends_on:POLARSSL_SELF_TEST */
void ecp_selftest()
{