diff --git a/ChangeLog b/ChangeLog index 9419df268..b1cbb0019 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 33c09fcf2..c0f50791d 100644 --- a/include/polarssl/ecp.h +++ b/include/polarssl/ecp.h @@ -204,6 +204,15 @@ const ecp_curve_info *ecp_curve_info_from_grp_id( ecp_group_id grp_id ); */ 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) */ @@ -535,6 +544,20 @@ int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q, int (*f_rng)(void *, unsigned char *, size_t), 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 * diff --git a/library/ecp.c b/library/ecp.c index 0c66d352d..ef38d19d7 100644 --- a/library/ecp.c +++ b/library/ecp.c @@ -58,6 +58,11 @@ #include #include +#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 @@ unsigned long add_count, dbl_count, mul_count; 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" }, @@ -154,6 +159,24 @@ const ecp_curve_info *ecp_curve_info_from_tls_id( uint16_t tls_id ) return( NULL ); } +/* + * 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 */ @@ -1669,6 +1692,20 @@ int ecp_gen_keypair( ecp_group *grp, mpi *d, ecp_point *Q, 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 003369b09..50f152124 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -47,3 +47,6 @@ x509/cert_req 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 19f46a400..e7dab2468 100644 --- a/programs/pkey/gen_key.c +++ b/programs/pkey/gen_key.c @@ -51,13 +51,12 @@ int main( int argc, char *argv[] ) } #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 @@ struct options { 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 @@ static int write_private_key( pk_context *key, const char *output_file ) } #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 @@ int main( int argc, char *argv[] ) 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 @@ int main( int argc, char *argv[] ) 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 @@ int main( int argc, char *argv[] ) 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 @@ int main( int argc, char *argv[] ) 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 @@ int main( int argc, char *argv[] ) 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 ) + { + 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 ) { - pk_init_ctx( &key, pk_info_from_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 @@ int main( int argc, char *argv[] ) 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 @@ int main( int argc, char *argv[] ) 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 8dafc39bd..17ad8aa10 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 @@ ECP gen keypair 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 8cc5abac3..cb93e850a 100644 --- a/tests/suites/test_suite_ecp.function +++ b/tests/suites/test_suite_ecp.function @@ -9,6 +9,22 @@ * END_DEPENDENCIES */ +/* 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 @@ void ecp_gen_keypair( int id ) } /* 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() {