diff options
-rw-r--r-- | CHANGES | 3 | ||||
-rw-r--r-- | docs/conf/extra/httpd-ssl.conf.in | 9 | ||||
-rw-r--r-- | modules/ssl/mod_ssl.c | 3 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_init.c | 51 | ||||
-rw-r--r-- | modules/ssl/ssl_engine_kernel.c | 27 | ||||
-rw-r--r-- | modules/ssl/ssl_private.h | 13 | ||||
-rw-r--r-- | modules/ssl/ssl_toolkit_compat.h | 5 | ||||
-rw-r--r-- | modules/ssl/ssl_util.c | 14 |
8 files changed, 119 insertions, 6 deletions
@@ -9,6 +9,9 @@ Changes with Apache 2.3.3 *) SECURITY: CVE-2009-3094 (cve.mitre.org) mod_proxy_ftp: NULL pointer dereference on error paths. [Stefan Fritsch <sf fritsch.de>, Joe Orton] + + *) mod_ssl: enable support for ECC keys and ECDH ciphers. Tested against + OpenSSL 1.0.0b3. [Vipul Gupta vipul.gupta sun.com, Sander Temme] *) mod_dav_fs: Include uri when logging a PUT error due to connection abort. PR 38149. [Stefan Fritsch] diff --git a/docs/conf/extra/httpd-ssl.conf.in b/docs/conf/extra/httpd-ssl.conf.in index 4ce8426365..809ab827d4 100644 --- a/docs/conf/extra/httpd-ssl.conf.in +++ b/docs/conf/extra/httpd-ssl.conf.in @@ -81,6 +81,9 @@ SSLEngine on # SSL Cipher Suite: # List the ciphers that the client is permitted to negotiate. # See the mod_ssl documentation for a complete list. +# Recent OpenSSL snapshots include Elliptic Curve Cryptograhpy (ECC) +# cipher suites (see RFC 4492) as part of "ALL". Edit this line +# if you need to disable any of those ciphers. SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL # Server Certificate: @@ -90,16 +93,22 @@ SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL # in mind that if you have both an RSA and a DSA certificate you # can configure both in parallel (to also allow the use of DSA # ciphers, etc.) +# Some ECC cipher suites (http://www.ietf.org/rfc/rfc4492.txt) +# require an ECC certificate which can also be configured in +# parallel. SSLCertificateFile "@exp_sysconfdir@/server.crt" #SSLCertificateFile "@exp_sysconfdir@/server-dsa.crt" +#SSLCertificateFile "@exp_sysconfdir@/server-ecc.crt" # Server Private Key: # If the key is not combined with the certificate, use this # directive to point at the key file. Keep in mind that if # you've both a RSA and a DSA private key you can configure # both in parallel (to also allow the use of DSA ciphers, etc.) +# ECC keys, when in use, can also be configured in parallel SSLCertificateKeyFile "@exp_sysconfdir@/server.key" #SSLCertificateKeyFile "@exp_sysconfdir@/server-dsa.key" +#SSLCertificateKeyFile "@exp_sysconfdir@/server-ecc.key" # Server Certificate Chain: # Point SSLCertificateChainFile at a file containing the diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index 14a2fd683b..af79b37710 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -440,6 +440,9 @@ int ssl_init_ssl_connection(conn_rec *c, request_rec *r) */ SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA); SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH); +#ifndef OPENSSL_NO_EC + SSL_set_tmp_ecdh_callback(ssl, ssl_callback_TmpECDH); +#endif SSL_set_verify_result(ssl, X509_V_OK); diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index e4e9bb45e9..3b7b019567 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -356,7 +356,11 @@ static void ssl_init_server_check(server_rec *s, * Check for problematic re-initializations */ if (mctx->pks->certs[SSL_AIDX_RSA] || - mctx->pks->certs[SSL_AIDX_DSA]) + mctx->pks->certs[SSL_AIDX_DSA] +#ifndef OPENSSL_NO_EC + || mctx->pks->certs[SSL_AIDX_ECC] +#endif + ) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "Illegal attempt to re-initialise SSL for server " @@ -519,6 +523,9 @@ static void ssl_init_ctx_callbacks(server_rec *s, SSL_CTX_set_tmp_rsa_callback(ctx, ssl_callback_TmpRSA); SSL_CTX_set_tmp_dh_callback(ctx, ssl_callback_TmpDH); +#ifndef OPENSSL_NO_EC + SSL_CTX_set_tmp_ecdh_callback(ctx,ssl_callback_TmpECDH); +#endif SSL_CTX_set_info_callback(ctx, ssl_callback_Info); } @@ -810,9 +817,16 @@ static int ssl_server_import_key(server_rec *s, ssl_asn1_t *asn1; MODSSL_D2I_PrivateKey_CONST unsigned char *ptr; const char *type = ssl_asn1_keystr(idx); - int pkey_type = (idx == SSL_AIDX_RSA) ? EVP_PKEY_RSA : EVP_PKEY_DSA; + int pkey_type; EVP_PKEY *pkey; +#ifndef OPENSSL_NO_EC + if (idx == SSL_AIDX_ECC) + pkey_type = EVP_PKEY_EC; + else +#endif /* SSL_LIBRARY_VERSION */ + pkey_type = (idx == SSL_AIDX_RSA) ? EVP_PKEY_RSA : EVP_PKEY_DSA; + if (!(asn1 = ssl_asn1_table_get(mc->tPrivateKey, id))) { return FALSE; } @@ -922,20 +936,34 @@ static void ssl_init_server_certs(server_rec *s, apr_pool_t *ptemp, modssl_ctx_t *mctx) { - const char *rsa_id, *dsa_id; + const char *rsa_id, *dsa_id, *ecc_id; const char *vhost_id = mctx->sc->vhost_id; int i; - int have_rsa, have_dsa; + int have_rsa, have_dsa, have_ecc; rsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_RSA); dsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_DSA); +#ifndef OPENSSL_NO_EC + ecc_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_ECC); +#endif have_rsa = ssl_server_import_cert(s, mctx, rsa_id, SSL_AIDX_RSA); have_dsa = ssl_server_import_cert(s, mctx, dsa_id, SSL_AIDX_DSA); +#ifndef OPENSSL_NO_EC + have_ecc = ssl_server_import_cert(s, mctx, ecc_id, SSL_AIDX_ECC); +#endif - if (!(have_rsa || have_dsa)) { + if (!(have_rsa || have_dsa +#ifndef OPENSSL_NO_EC + || have_ecc +#endif +)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +#ifndef OPENSSL_NO_EC + "Oops, no RSA, DSA or ECC server certificate found " +#else "Oops, no RSA or DSA server certificate found " +#endif "for '%s:%d'?!", s->server_hostname, s->port); ssl_die(); } @@ -946,10 +974,21 @@ static void ssl_init_server_certs(server_rec *s, have_rsa = ssl_server_import_key(s, mctx, rsa_id, SSL_AIDX_RSA); have_dsa = ssl_server_import_key(s, mctx, dsa_id, SSL_AIDX_DSA); +#if SSL_LIBRARY_VERSION >= 0x00908000 + have_ecc = ssl_server_import_key(s, mctx, ecc_id, SSL_AIDX_ECC); +#endif - if (!(have_rsa || have_dsa)) { + if (!(have_rsa || have_dsa +#if SSL_LIBRARY_VERSION >= 0x00908000 + || have_ecc +#endif + )) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, +#if SSL_LIBRARY_VERSION >= 0x00908000 + "Oops, no RSA, DSA or ECC server private key found?!"); +#else "Oops, no RSA or DSA server private key found?!"); +#endif ssl_die(); } } diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index 52bc0a8f54..1249bd1505 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -1244,6 +1244,33 @@ DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen) return (DH *)mc->pTmpKeys[idx]; } +#ifndef OPENSSL_NO_EC +EC_KEY *ssl_callback_TmpECDH(SSL *ssl, int export, int keylen) +{ + conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); + SSLModConfigRec *mc = myModConfig(c->base_server); + int idx; + static EC_KEY *ecdh = NULL; + static init = 0; + + /* XXX Uses 256-bit key for now. TODO: support other sizes. */ + ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, + "handing out temporary 256 bit ECC key"); + + if (init == 0) { + ecdh = EC_KEY_new(); + if (ecdh != NULL) { + /* ecdh->group = EC_GROUP_new_by_nid(NID_secp160r2); */ + EC_KEY_set_group(ecdh, + EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); + } + init = 1; + } + + return ecdh; +} +#endif + /* * This OpenSSL callback function is called when OpenSSL * does client authentication and verifies the certificate chain. diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index b3b053fc0f..cf9b9278e5 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -172,11 +172,21 @@ typedef int ssl_algo_t; #define SSL_ALGO_UNKNOWN (0) #define SSL_ALGO_RSA (1<<0) #define SSL_ALGO_DSA (1<<1) +#ifndef OPENSSL_NO_EC +#define SSL_ALGO_ECC (1<<2) +#define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA|SSL_ALGO_ECC) +#else #define SSL_ALGO_ALL (SSL_ALGO_RSA|SSL_ALGO_DSA) +#endif /* SSL_LIBRARY_VERSION */ #define SSL_AIDX_RSA (0) #define SSL_AIDX_DSA (1) +#ifndef OPENSSL_NO_EC +#define SSL_AIDX_ECC (2) +#define SSL_AIDX_MAX (3) +#else #define SSL_AIDX_MAX (2) +#endif /* SSL_LIBRARY_VERSION */ /** @@ -626,6 +636,9 @@ void ssl_hook_ConfigTest(apr_pool_t *pconf, server_rec *s); /** OpenSSL callbacks */ RSA *ssl_callback_TmpRSA(SSL *, int, int); DH *ssl_callback_TmpDH(SSL *, int, int); +#ifndef OPENSSL_NO_EC +EC_KEY *ssl_callback_TmpECDH(SSL *, int, int); +#endif /* SSL_LIBRARY_VERSION */ int ssl_callback_SSLVerify(int, X509_STORE_CTX *); int ssl_callback_SSLVerify_CRL(int, X509_STORE_CTX *, conn_rec *); int ssl_callback_proxy_cert(SSL *ssl, MODSSL_CLIENT_CERT_CB_ARG_TYPE **x509, EVP_PKEY **pkey); diff --git a/modules/ssl/ssl_toolkit_compat.h b/modules/ssl/ssl_toolkit_compat.h index 86a62e8c08..ec0ec856ea 100644 --- a/modules/ssl/ssl_toolkit_compat.h +++ b/modules/ssl/ssl_toolkit_compat.h @@ -48,6 +48,11 @@ #include <openssl/ocsp.h> #endif +/* ECC support came along in OpenSSL 1.0.0 */ +#if (OPENSSL_VERSION_NUMBER < 0x10000000) +#define OPENSSL_NO_EC +#endif + /** Avoid tripping over an engine build installed globally and detected * when the user points at an explicit non-engine flavor of OpenSSL */ diff --git a/modules/ssl/ssl_util.c b/modules/ssl/ssl_util.c index 27c035144f..bdd5a88f18 100644 --- a/modules/ssl/ssl_util.c +++ b/modules/ssl/ssl_util.c @@ -150,6 +150,11 @@ ssl_algo_t ssl_util_algotypeof(X509 *pCert, EVP_PKEY *pKey) case EVP_PKEY_DSA: t = SSL_ALGO_DSA; break; +#ifndef OPENSSL_NO_EC + case EVP_PKEY_EC: + t = SSL_ALGO_ECC; + break; +#endif default: break; } @@ -174,6 +179,11 @@ char *ssl_util_algotypestr(ssl_algo_t t) case SSL_ALGO_DSA: cp = "DSA"; break; +#ifndef OPENSSL_NO_EC + case SSL_ALGO_ECC: + cp = "ECC"; + break; +#endif default: break; } @@ -245,7 +255,11 @@ void ssl_asn1_table_unset(apr_hash_t *table, apr_hash_set(table, key, klen, NULL); } +#ifndef OPENSSL_NO_EC +static const char *ssl_asn1_key_types[] = {"RSA", "DSA", "ECC"}; +#else static const char *ssl_asn1_key_types[] = {"RSA", "DSA"}; +#endif const char *ssl_asn1_keystr(int keytype) { |