From: Kaspar Brand Date: Wed, 25 Sep 2013 12:52:35 +0000 (+0000) Subject: Streamline ephemeral key handling: X-Git-Tag: 2.5.0-alpha~5016 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a6a324f9bb472a3bed200366b6ac9afbcfd803f3;p=apache Streamline ephemeral key handling: - drop support for ephemeral RSA keys (only allowed/needed for export ciphers) - drop pTmpKeys from the per-process SSLModConfigRec, and remove the temp key generation at startup (unnecessary for DHE/ECDHE) - unconditionally disable null and export-grade ciphers by always prepending "!aNULL:!eNULL:!EXP:" to any cipher suite string - do not configure per-connection SSL_tmp_*_callbacks, as it is sufficient to set them for the SSL_CTX - set default curve for ECDHE at startup, obviating the need for a per-handshake callback, for the time being (and also configure SSL_OP_SINGLE_ECDH_USE, previously left out) For additional background, see https://mail-archives.apache.org/mod_mbox/httpd-dev/201309.mbox/%3C52358ED1.2070704@velox.ch%3E git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1526168 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 9ffc873331..4585487814 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,10 @@ -*- coding: utf-8 -*- Changes with Apache 2.5.0 + *) mod_ssl: drop support for export-grade ciphers with ephemeral RSA + keys, and unconditionally disable aNULL, eNULL and EXP ciphers + (not overridable via SSLCipherSuite). [Kaspar Brand] + *) Suppress formatting of startup messages written to the console when ErrorLogFormat is used. [Jeff Trawick] diff --git a/docs/manual/mod/mod_ssl.xml b/docs/manual/mod/mod_ssl.xml index d4b26f3b80..62d1c3d644 100644 --- a/docs/manual/mod/mod_ssl.xml +++ b/docs/manual/mod/mod_ssl.xml @@ -728,6 +728,15 @@ prefixes are:

  • -: remove cipher from list (can be added later again)
  • !: kill cipher from list completely (can not be added later again)
  • + + +<code>aNULL</code>, <code>eNULL</code> and <code>EXP</code> +ciphers are always disabled +

    Beginning with version 2.5.0-dev as of 2013-09-25, null and export-grade +ciphers are always disabled, as mod_ssl unconditionally prepends any supplied +cipher suite string with !aNULL:!eNULL:!EXP: at initialization.

    +
    +

    A simpler way to look at all of this is to use the ``openssl ciphers -v'' command which provides a nice way to successively create the correct cipher-spec string. The default cipher-spec string diff --git a/modules/ssl/mod_ssl.c b/modules/ssl/mod_ssl.c index 33556d69a0..881c443311 100644 --- a/modules/ssl/mod_ssl.c +++ b/modules/ssl/mod_ssl.c @@ -521,15 +521,6 @@ int ssl_init_ssl_connection(conn_rec *c, request_rec *r) sslconn->ssl = ssl; - /* - * Configure callbacks for SSL connection - */ - 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); ssl_io_filter_init(c, r, ssl); diff --git a/modules/ssl/ssl_engine_config.c b/modules/ssl/ssl_engine_config.c index 5b973c783b..e6e4d9b76e 100644 --- a/modules/ssl/ssl_engine_config.c +++ b/modules/ssl/ssl_engine_config.c @@ -75,8 +75,6 @@ SSLModConfigRec *ssl_config_global_create(server_rec *s) mc->stapling_mutex = NULL; #endif - memset(mc->pTmpKeys, 0, sizeof(mc->pTmpKeys)); - apr_pool_userdata_set(mc, SSL_MOD_CONFIG_KEY, apr_pool_cleanup_null, pool); diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c index 8a37b1e111..025be3c71e 100644 --- a/modules/ssl/ssl_engine_init.c +++ b/modules/ssl/ssl_engine_init.c @@ -56,180 +56,6 @@ static void ssl_add_version_components(apr_pool_t *p, modver, AP_SERVER_BASEVERSION, incver); } - -/* - * Handle the Temporary RSA Keys and DH Params - */ - -#define MODSSL_TMP_KEY_FREE(mc, type, idx) \ - if (mc->pTmpKeys[idx]) { \ - type##_free((type *)mc->pTmpKeys[idx]); \ - mc->pTmpKeys[idx] = NULL; \ - } - -#define MODSSL_TMP_KEYS_FREE(mc, type) \ - MODSSL_TMP_KEY_FREE(mc, type, SSL_TMP_KEY_##type##_512); \ - MODSSL_TMP_KEY_FREE(mc, type, SSL_TMP_KEY_##type##_1024) - -static void ssl_tmp_keys_free(server_rec *s) -{ - SSLModConfigRec *mc = myModConfig(s); - - MODSSL_TMP_KEYS_FREE(mc, RSA); - MODSSL_TMP_KEYS_FREE(mc, DH); -#ifndef OPENSSL_NO_EC - MODSSL_TMP_KEY_FREE(mc, EC_KEY, SSL_TMP_KEY_EC_256); -#endif -} - -static int ssl_tmp_key_init_rsa(server_rec *s, - int bits, int idx) -{ - SSLModConfigRec *mc = myModConfig(s); - -#ifdef HAVE_FIPS - - if (FIPS_mode() && bits < 1024) { - mc->pTmpKeys[idx] = NULL; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01877) - "Init: Skipping generating temporary " - "%d bit RSA private key in FIPS mode", bits); - return OK; - } - -#endif -#ifdef HAVE_GENERATE_EX - { - RSA *tkey; - BIGNUM *bn_f4; - if (!(tkey = RSA_new()) - || !(bn_f4 = BN_new()) - || !BN_set_word(bn_f4, RSA_F4) - || !RSA_generate_key_ex(tkey, bits, bn_f4, NULL)) - { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01878) - "Init: Failed to generate temporary " - "%d bit RSA private key", bits); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); - return !OK; - } - BN_free(bn_f4); - mc->pTmpKeys[idx] = tkey; - } -#else - if (!(mc->pTmpKeys[idx] = - RSA_generate_key(bits, RSA_F4, NULL, NULL))) - { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01879) - "Init: Failed to generate temporary " - "%d bit RSA private key", bits); - ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); - return !OK; - } -#endif - - return OK; -} - -static int ssl_tmp_key_init_dh(server_rec *s, - int bits, int idx) -{ - SSLModConfigRec *mc = myModConfig(s); - -#ifdef HAVE_FIPS - - if (FIPS_mode() && bits < 1024) { - mc->pTmpKeys[idx] = NULL; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01880) - "Init: Skipping generating temporary " - "%d bit DH parameters in FIPS mode", bits); - return OK; - } - -#endif - - if (!(mc->pTmpKeys[idx] = - ssl_dh_GetTmpParam(bits))) - { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(01881) - "Init: Failed to generate temporary " - "%d bit DH parameters", bits); - return !OK; - } - - return OK; -} - -#ifndef OPENSSL_NO_EC -static int ssl_tmp_key_init_ec(server_rec *s, - int bits, int idx) -{ - SSLModConfigRec *mc = myModConfig(s); - EC_KEY *ecdh = NULL; - - /* XXX: Are there any FIPS constraints we should enforce? */ - - if (bits != 256) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02298) - "Init: Failed to generate temporary " - "%d bit EC parameters, only 256 bits supported", bits); - return !OK; - } - - if ((ecdh = EC_KEY_new()) == NULL || - EC_KEY_set_group(ecdh, EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) != 1) - { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, APLOGNO(02299) - "Init: Failed to generate temporary " - "%d bit EC parameters", bits); - return !OK; - } - - mc->pTmpKeys[idx] = ecdh; - return OK; -} - -#define MODSSL_TMP_KEY_INIT_EC(s, bits) \ - ssl_tmp_key_init_ec(s, bits, SSL_TMP_KEY_EC_##bits) - -#endif - -#define MODSSL_TMP_KEY_INIT_RSA(s, bits) \ - ssl_tmp_key_init_rsa(s, bits, SSL_TMP_KEY_RSA_##bits) - -#define MODSSL_TMP_KEY_INIT_DH(s, bits) \ - ssl_tmp_key_init_dh(s, bits, SSL_TMP_KEY_DH_##bits) - -static int ssl_tmp_keys_init(server_rec *s) -{ - ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, - "Init: Generating temporary RSA private keys (512/1024 bits)"); - - if (MODSSL_TMP_KEY_INIT_RSA(s, 512) || - MODSSL_TMP_KEY_INIT_RSA(s, 1024)) { - return !OK; - } - - ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, - "Init: Generating temporary DH parameters (512/1024 bits)"); - - if (MODSSL_TMP_KEY_INIT_DH(s, 512) || - MODSSL_TMP_KEY_INIT_DH(s, 1024)) { - return !OK; - } - -#ifndef OPENSSL_NO_EC - ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, - "Init: Generating temporary EC parameters (256 bits)"); - - if (MODSSL_TMP_KEY_INIT_EC(s, 256)) { - return !OK; - } -#endif - - return OK; -} - /* * Per-module initialization */ @@ -367,10 +193,6 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog, */ ssl_pphrase_Handle(base_server, ptemp); - if (ssl_tmp_keys_init(base_server)) { - return !OK; - } - /* * initialize the mutex handling */ @@ -678,6 +500,9 @@ static void ssl_init_ctx_protocol(server_rec *s, * Configure additional context ingredients */ SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); +#ifndef OPENSSL_NO_EC + SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); +#endif #ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION /* @@ -738,11 +563,7 @@ static void ssl_init_ctx_callbacks(server_rec *s, { SSL_CTX *ctx = mctx->ssl_ctx; - 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); @@ -843,14 +664,15 @@ static void ssl_init_ctx_cipher_suite(server_rec *s, modssl_ctx_t *mctx) { SSL_CTX *ctx = mctx->ssl_ctx; - const char *suite = mctx->auth.cipher_suite; + const char *suite; /* - * Configure SSL Cipher Suite + * Configure SSL Cipher Suite. Always disable NULL and export ciphers, + * no matter what SSLCipherSuite directive is appearing in the config. */ - if (!suite) { - return; - } + suite = apr_pstrcat(ptemp, "!aNULL:!eNULL:!EXP:", mctx->auth.cipher_suite ? + mctx->auth.cipher_suite : SSL_DEFAULT_CIPHER_LIST, + NULL); ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s, "Configuring permitted SSL ciphers [%s]", @@ -1234,6 +1056,12 @@ static void ssl_init_server_certs(server_rec *s, "Oops, no " KEYTYPES " server private key found?!"); ssl_die(s); } + +#ifndef OPENSSL_NO_EC + /* Enable ECDHE by configuring a default curve */ + SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, + EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); +#endif } #ifdef HAVE_TLS_SESSION_TICKETS @@ -1769,11 +1597,6 @@ apr_status_t ssl_init_ModuleKill(void *data) */ ssl_scache_kill(base_server); - /* - * Destroy the temporary keys and params - */ - ssl_tmp_keys_free(base_server); - /* * Free the non-pool allocated structures * in the per-server configurations diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c index 28cc19a4d4..12d73d5924 100644 --- a/modules/ssl/ssl_engine_kernel.c +++ b/modules/ssl/ssl_engine_kernel.c @@ -1299,118 +1299,18 @@ const authz_provider ssl_authz_provider_verify_client = ** _________________________________________________________________ */ -/* - * Handle out temporary RSA private keys on demand - * - * The background of this as the TLSv1 standard explains it: - * - * | D.1. Temporary RSA keys - * | - * | US Export restrictions limit RSA keys used for encryption to 512 - * | bits, but do not place any limit on lengths of RSA keys used for - * | signing operations. Certificates often need to be larger than 512 - * | bits, since 512-bit RSA keys are not secure enough for high-value - * | transactions or for applications requiring long-term security. Some - * | certificates are also designated signing-only, in which case they - * | cannot be used for key exchange. - * | - * | When the public key in the certificate cannot be used for encryption, - * | the server signs a temporary RSA key, which is then exchanged. In - * | exportable applications, the temporary RSA key should be the maximum - * | allowable length (i.e., 512 bits). Because 512-bit RSA keys are - * | relatively insecure, they should be changed often. For typical - * | electronic commerce applications, it is suggested that keys be - * | changed daily or every 500 transactions, and more often if possible. - * | Note that while it is acceptable to use the same temporary key for - * | multiple transactions, it must be signed each time it is used. - * | - * | RSA key generation is a time-consuming process. In many cases, a - * | low-priority process can be assigned the task of key generation. - * | Whenever a new key is completed, the existing temporary key can be - * | replaced with the new one. - * - * XXX: base on comment above, if thread support is enabled, - * we should spawn a low-priority thread to generate new keys - * on the fly. - * - * So we generated 512 and 1024 bit temporary keys on startup - * which we now just hand out on demand.... - */ - -RSA *ssl_callback_TmpRSA(SSL *ssl, int export, int keylen) -{ - conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); - SSLModConfigRec *mc = myModConfigFromConn(c); - int idx; - - ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, - "handing out temporary %d bit RSA key", keylen); - - /* doesn't matter if export flag is on, - * we won't be asked for keylen > 512 in that case. - * if we are asked for a keylen > 1024, it is too expensive - * to generate on the fly. - * XXX: any reason not to generate 2048 bit keys at startup? - */ - - switch (keylen) { - case 512: - idx = SSL_TMP_KEY_RSA_512; - break; - - case 1024: - default: - idx = SSL_TMP_KEY_RSA_1024; - } - - return (RSA *)mc->pTmpKeys[idx]; -} - /* * Hand out the already generated DH parameters... */ DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen) { conn_rec *c = (conn_rec *)SSL_get_app_data(ssl); - SSLModConfigRec *mc = myModConfigFromConn(c); - int idx; - - ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, - "handing out temporary %d bit DH key", keylen); - - switch (keylen) { - case 512: - idx = SSL_TMP_KEY_DH_512; - break; - - case 1024: - default: - idx = SSL_TMP_KEY_DH_1024; - } - - 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 = myModConfigFromConn(c); - int idx; - /* XXX Uses 256-bit key for now. TODO: support other sizes. */ ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c, - "handing out temporary 256 bit ECC key"); - - switch (keylen) { - case 256: - default: - idx = SSL_TMP_KEY_EC_256; - } + "handing out parameters for temporary %d bit DH key", keylen); - return (EC_KEY *)mc->pTmpKeys[idx]; + return ssl_dh_GetTmpParam(keylen); } -#endif /* * This OpenSSL callback function is called when OpenSSL diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index ef7e8e3d87..ef14f7ad5a 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -549,7 +549,6 @@ typedef struct { apr_global_mutex_t *pMutex; apr_array_header_t *aRandSeed; apr_hash_t *tVHostKeys; - void *pTmpKeys[SSL_TMP_KEY_MAX]; /* Two hash tables of pointers to ssl_asn1_t structures. The * structures are used to store certificates and private keys @@ -849,11 +848,7 @@ extern const authz_provider ssl_authz_provider_require_ssl; extern const authz_provider ssl_authz_provider_verify_client; /** 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 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, X509 **x509, EVP_PKEY **pkey);