Hi Janjust, I've finally had the time to take a look at this patch with a colleague who is more familiar with the subject at hand :).
Hope this helps. Please see my comments inline. Adriaan On 02/07/2012 04:13 PM, Jan Just Keijser wrote: > Added support for Elliptic curves (ECDSA) + SHA2 family signed > certificates. > --- > init.c | 7 ++++ > options.c | 15 ++++++++++ > options.h | 6 ++++ > ssl.c | 3 ++ > ssl_backend.h | 10 ++++++ > ssl_openssl.c | 84 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ssl_polarssl.c | 9 ++++++ > 7 files changed, 134 insertions(+), 0 deletions(-) > > diff --git a/init.c b/init.c > index 525f441..51b0d64 100644 > --- a/init.c > +++ b/init.c > @@ -895,6 +895,9 @@ print_openssl_info (const struct options *options) > if (options->show_ciphers || options->show_digests || options->show_engines > #ifdef USE_SSL > || options->show_tls_ciphers > +#ifdef USE_SSL_EC > +|| options->show_curves > +#endif > #endif > ) > { > @@ -907,6 +910,10 @@ print_openssl_info (const struct options *options) > #ifdef USE_SSL > if (options->show_tls_ciphers) > show_available_tls_ciphers (); > +#ifdef USE_SSL_EC > + if (options->show_curves) > + show_available_curves (); > +#endif > #endif > return true; > } > diff --git a/options.c b/options.c > index 6b8ae22..ce23dbc 100644 > --- a/options.c > +++ b/options.c > @@ -836,6 +836,9 @@ init_options (struct options *o, const bool init_gc) > #ifdef ENABLE_X509ALTUSERNAME > o->x509_username_field = X509_USERNAME_FIELD_DEFAULT; > #endif > +#ifdef USE_SSL_EC > + o->curve_name = NULL; > +#endif > #endif /* USE_SSL */ > #endif /* USE_CRYPTO */ > #ifdef ENABLE_PKCS11 > @@ -6368,6 +6371,18 @@ add_option (struct options *options, > VERIFY_PERMISSION (OPT_P_GENERAL); > options->show_tls_ciphers = true; > } > +#ifdef USE_SSL_EC > + else if (streq (p[0], "show-curves")) > + { > + VERIFY_PERMISSION (OPT_P_GENERAL); > + options->show_curves = true; > + } > + else if (streq (p[0], "ecdh") && p[1]) > + { > + VERIFY_PERMISSION (OPT_P_CRYPTO); > + options->curve_name= p[1]; > + } > +#endif > else if (streq (p[0], "tls-server")) > { > VERIFY_PERMISSION (OPT_P_GENERAL); > diff --git a/options.h b/options.h > index 831d4f6..81e0757 100644 > --- a/options.h > +++ b/options.h > @@ -200,6 +200,9 @@ struct options > bool show_engines; > #ifdef USE_SSL > bool show_tls_ciphers; > +#ifdef USE_SSL_EC > + bool show_curves; > +#endif > #endif > bool genkey; > #endif > @@ -533,6 +536,9 @@ struct options > const char *priv_key_file; > const char *pkcs12_file; > const char *cipher_list; > +#ifdef USE_SSL_EC > + const char *curve_name; > +#endif > const char *tls_verify; > const char *tls_export_cert; > const char *tls_remote; > diff --git a/ssl.c b/ssl.c > index c26756e..54efe2f 100644 > --- a/ssl.c > +++ b/ssl.c > @@ -308,6 +308,9 @@ init_ssl (const struct options *options, struct > tls_root_ctx *new_ctx) > { > tls_ctx_server_new(new_ctx); > tls_ctx_load_dh_params(new_ctx, options->dh_file, > options->dh_file_inline); > +#ifdef USE_SSL_EC > + tls_ctx_load_ecdh_params(new_ctx, options->curve_name); > +#endif > } > else /* if client */ > { > diff --git a/ssl_backend.h b/ssl_backend.h > index 243c9e3..ebf9f36 100644 > --- a/ssl_backend.h > +++ b/ssl_backend.h > @@ -145,6 +145,16 @@ void tls_ctx_load_dh_params(struct tls_root_ctx *ctx, > const char *dh_file > ); > > /** > + * Load Elliptic Curve Parameters, and load them into the library-specific > + * TLS context. > + * > + * @param ctx TLS context to use > + * @param curve_name The name of the elliptic curve to load. > + */ > +void tls_ctx_load_ecdh_params(struct tls_root_ctx *ctx, const char > *curve_name > + ); > + > +/** > * Load PKCS #12 file for key, cert and (optionally) CA certs, and add to > * library-specific TLS context. > * > diff --git a/ssl_openssl.c b/ssl_openssl.c > index b95944c..912dd8f 100644 > --- a/ssl_openssl.c > +++ b/ssl_openssl.c > @@ -50,6 +50,9 @@ > #include <openssl/pkcs12.h> > #include <openssl/x509.h> > #include <openssl/crypto.h> > +#ifdef USE_SSL_EC > +#include <openssl/ec.h> > +#endif > > /* > * Allocate space in SSL objects in which to store a struct tls_session > @@ -238,6 +241,46 @@ tls_ctx_load_dh_params (struct tls_root_ctx *ctx, const > char *dh_file > DH_free (dh); > } > > +void > +tls_ctx_load_ecdh_params (struct tls_root_ctx *ctx, const char *curve_name > + ) > +{ > +#ifdef USE_SSL_EC > + if (curve_name != NULL) > + { > + int nid; > + EC_KEY *ecdh = NULL; > + > + nid = OBJ_sn2nid(curve_name); > + > + if (nid == 0) > + msg(M_SSLERR, "unknown curve name (%s)", curve_name); > + else > + { > + ecdh = EC_KEY_new_by_curve_name(nid); > + if (ecdh == NULL) > + msg (M_SSLERR, "Unable to create curve (%s)", curve_name); > + else > + { > + const char *sname; > + > + if (!SSL_CTX_set_tmp_ecdh(ctx->ctx, ecdh)) > + msg (M_SSLERR, "SSL_CTX_set_tmp_ecdh: cannot add curve"); > + What is happening here exactly? Is the same key being reused for every connection, or is it magically regenerated by OpenSSL on every connection? > + /* Translate NID back to name , just for kicks */ > + sname = OBJ_nid2sn(nid); > + if (sname == NULL) sname = "(Unknown)"; > + msg (D_TLS_DEBUG_LOW, "ECDH curve %s added", sname); > + > + EC_KEY_free(ecdh); > + } > + } > + } > +#else > + msg(M_SSLERR, "Elliptic Curves not supported by this version of OpenSSL"); > +#endif > +} > + > int > tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, > #if ENABLE_INLINE_FILES > @@ -1273,6 +1316,47 @@ show_available_tls_ciphers () > SSL_CTX_free (ctx); > } > > +/* > + * * Show the Elliptic curves that are available for us to use > + * * in the OpenSSL library. > + * */ > +#ifdef USE_SSL_EC > +void > +show_available_curves() > +{ > + EC_builtin_curve *curves = NULL; > + size_t crv_len = 0; > + size_t n = 0; > + > + crv_len = EC_get_builtin_curves(NULL, 0); > + > + curves = OPENSSL_malloc((int)(sizeof(EC_builtin_curve) * crv_len)); > + > + if (curves == NULL) > + msg (M_SSLERR, "Cannot create EC_builtin_curve object"); > + else > + { > + if (EC_get_builtin_curves(curves, crv_len)) > + { > + printf ("Available Elliptic curves:\n"); > + for (n = 0; n < crv_len; n++) > + { > + const char *sname; > + sname = OBJ_nid2sn(curves[n].nid); > + if (sname == NULL) sname = ""; > + > + printf("%s\n", sname); > + } > + } > + else > + { > + msg (M_SSLERR, "Cannot get list of builtin curves"); > + } > + OPENSSL_free(curves); > + } > +} > +#endif > + > void > get_highest_preference_tls_cipher (char *buf, int size) > { > diff --git a/ssl_polarssl.c b/ssl_polarssl.c > index c50cf0a..a7a6d61 100644 > --- a/ssl_polarssl.c > +++ b/ssl_polarssl.c > @@ -218,6 +218,15 @@ else > (counter_type) 8 * mpi_size(&ctx->dhm_ctx->P)); > } > > +#ifdef USE_SSL_EC > +void > +tls_ctx_load_ecdh_params (struct tls_root_ctx *ctx, const char *curve_name > + ) > +{ > + msg(M_WARN, "Elliptic Curves not yet supported by PolarSSL"); > +} > +#endif > + > int > tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, > #if ENABLE_INLINE_FILES Codewise I don't have many comments. I do have a few questions surrounding the use of OpenSSL: - How are curves for ECDSA set? - Is the default curve used, or is the same curve reused? - I don't quite understand how setting an ECDH curve relates to the ECDSA signature size. Is this an OpenSSL specific issue? These are partially based on a lack of knowledge of the OpenSSL implementation, so forgive me for any newbie questions there. Finally one more comment: to be accepted into the main branch, this needs manpage and command line documentation.