Merge r1526168, r1527291, r1527294, r1527295, r1527926 from trunk:

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


Follow-up fixes for r1526168:

- drop SSL_TMP_KEY_* constants from ssl_private.h, too

- make sure we also disable aNULL, eNULL and EXP ciphers
  for per-directory SSLCipherSuite directives

- apply the same treatment to SSLProxyCipherSuite


Increase minimum required OpenSSL version to 0.9.8a (in preparation
for the next mod_ssl commit, which will rely on the get_rfcX_prime_Y
functions added in that release):

- remove obsolete #defines / macros

- in ssl_private.h, regroup definitions based on whether
  they depend on TLS extension support or not

- for ECC and SRP support, set HAVE_X and change the rather awkward
  #ifndef OPENSSL_NO_X lines accordingly

For the discussion prior to taking this step, see
https://mail-archives.apache.org/mod_mbox/httpd-dev/201309.mbox/%3C524275C7.9060408%40velox.ch%3E


Improve ephemeral key handling (companion to r1526168):

- allow to configure custom DHE or ECDHE parameters via the
  SSLCertificateFile directive, and adapt its documentation
  accordingly (addresses PR 49559)

- add standardized DH parameters from RFCs 2409 and 3526,
  use them based on the length of the certificate's RSA/DSA key,
  and add a FAQ entry for clients which limit DH support
  to 1024 bits (such as Java 7 and earlier)

- move ssl_dh_GetParamFromFile() from ssl_engine_dh.c to
  ssl_util_ssl.c, and add ssl_ec_GetParamFromFile()

- drop ssl_engine_dh.c from mod_ssl

For the standardized DH parameters, OpenSSL version 0.9.8a
or later is required, which was therefore made a new minimum
requirement in r1527294.


PR 55616 (add missing APLOGNO), part 2
Submitted by: kbrand
Reviewed/backported by: jim


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1542327 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Jim Jagielski
2013-11-15 17:06:18 +00:00
parent 42b70184f6
commit 507e66cc67
19 changed files with 320 additions and 721 deletions

View File

@ -35,7 +35,7 @@
** _________________________________________________________________
*/
#ifndef OPENSSL_NO_EC
#ifdef HAVE_ECC
#define KEYTYPES "RSA, DSA or ECC"
#else
#define KEYTYPES "RSA or DSA"
@ -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
*/
@ -481,7 +303,7 @@ static void ssl_init_server_check(server_rec *s,
*/
if (mctx->pks->certs[SSL_AIDX_RSA] ||
mctx->pks->certs[SSL_AIDX_DSA]
#ifndef OPENSSL_NO_EC
#ifdef HAVE_ECC
|| mctx->pks->certs[SSL_AIDX_ECC]
#endif
)
@ -493,7 +315,7 @@ static void ssl_init_server_check(server_rec *s,
}
}
#ifndef OPENSSL_NO_TLSEXT
#ifdef HAVE_TLSEXT
static void ssl_init_ctx_tls_extensions(server_rec *s,
apr_pool_t *p,
apr_pool_t *ptemp,
@ -527,7 +349,7 @@ static void ssl_init_ctx_tls_extensions(server_rec *s,
}
#endif
#ifndef OPENSSL_NO_SRP
#ifdef HAVE_SRP
/*
* TLS-SRP support
*/
@ -660,7 +482,7 @@ static void ssl_init_ctx_protocol(server_rec *s,
#ifdef SSL_OP_NO_COMPRESSION
/* OpenSSL >= 1.0 only */
SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
#elif OPENSSL_VERSION_NUMBER >= 0x00908000L
#else
sk_SSL_COMP_zero(SSL_COMP_get_compression_methods());
#endif
}
@ -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);
#ifdef HAVE_ECC
SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE);
#endif
#ifdef SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
/*
@ -718,11 +543,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);
}
@ -818,14 +639,16 @@ 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,
* see also ssl_engine_config.c:ssl_cmd_SSLCipherSuite().
* OpenSSL's SSL_DEFAULT_CIPHER_LIST already includes !aNULL:!eNULL,
* so only prepend !EXP in this case.
*/
if (!suite) {
return;
}
suite = mctx->auth.cipher_suite ? mctx->auth.cipher_suite :
apr_pstrcat(ptemp, "!EXP:", SSL_DEFAULT_CIPHER_LIST, NULL);
ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, s,
"Configuring permitted SSL ciphers [%s]",
@ -988,7 +811,7 @@ static void ssl_init_ctx(server_rec *s,
if (mctx->pks) {
/* XXX: proxy support? */
ssl_init_ctx_cert_chain(s, p, ptemp, mctx);
#ifndef OPENSSL_NO_TLSEXT
#ifdef HAVE_TLSEXT
ssl_init_ctx_tls_extensions(s, p, ptemp, mctx);
#endif
}
@ -1001,7 +824,7 @@ static int ssl_server_import_cert(server_rec *s,
{
SSLModConfigRec *mc = myModConfig(s);
ssl_asn1_t *asn1;
MODSSL_D2I_X509_CONST unsigned char *ptr;
const unsigned char *ptr;
const char *type = ssl_asn1_keystr(idx);
X509 *cert;
@ -1048,12 +871,12 @@ static int ssl_server_import_key(server_rec *s,
{
SSLModConfigRec *mc = myModConfig(s);
ssl_asn1_t *asn1;
MODSSL_D2I_PrivateKey_CONST unsigned char *ptr;
const unsigned char *ptr;
const char *type = ssl_asn1_keystr(idx);
int pkey_type;
EVP_PKEY *pkey;
#ifndef OPENSSL_NO_EC
#ifdef HAVE_ECC
if (idx == SSL_AIDX_ECC)
pkey_type = EVP_PKEY_EC;
else
@ -1157,30 +980,34 @@ static void ssl_init_server_certs(server_rec *s,
modssl_ctx_t *mctx)
{
const char *rsa_id, *dsa_id;
#ifndef OPENSSL_NO_EC
#ifdef HAVE_ECC
const char *ecc_id;
EC_GROUP *ecparams;
int nid;
EC_KEY *eckey;
#endif
const char *vhost_id = mctx->sc->vhost_id;
int i;
int have_rsa, have_dsa;
#ifndef OPENSSL_NO_EC
DH *dhparams;
#ifdef HAVE_ECC
int have_ecc;
#endif
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
#ifdef HAVE_ECC
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
#ifdef HAVE_ECC
have_ecc = ssl_server_import_cert(s, mctx, ecc_id, SSL_AIDX_ECC);
#endif
if (!(have_rsa || have_dsa
#ifndef OPENSSL_NO_EC
#ifdef HAVE_ECC
|| have_ecc
#endif
)) {
@ -1196,12 +1023,12 @@ 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);
#ifndef OPENSSL_NO_EC
#ifdef HAVE_ECC
have_ecc = ssl_server_import_key(s, mctx, ecc_id, SSL_AIDX_ECC);
#endif
if (!(have_rsa || have_dsa
#ifndef OPENSSL_NO_EC
#ifdef HAVE_ECC
|| have_ecc
#endif
)) {
@ -1209,6 +1036,40 @@ static void ssl_init_server_certs(server_rec *s,
"Oops, no " KEYTYPES " server private key found?!");
ssl_die(s);
}
/*
* Try to read DH parameters from the (first) SSLCertificateFile
*/
if ((mctx->pks->cert_files[0] != NULL) &&
(dhparams = ssl_dh_GetParamFromFile(mctx->pks->cert_files[0]))) {
SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02540)
"Custom DH parameters (%d bits) for %s loaded from %s",
BN_num_bits(dhparams->p), vhost_id,
mctx->pks->cert_files[0]);
}
#ifdef HAVE_ECC
/*
* Similarly, try to read the ECDH curve name from SSLCertificateFile...
*/
if ((mctx->pks->cert_files[0] != NULL) &&
(ecparams = ssl_ec_GetParamFromFile(mctx->pks->cert_files[0])) &&
(nid = EC_GROUP_get_curve_name(ecparams)) &&
(eckey = EC_KEY_new_by_curve_name(nid))) {
SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx, eckey);
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(02541)
"ECDH curve %s for %s specified in %s",
OBJ_nid2sn(nid), vhost_id, mctx->pks->cert_files[0]);
}
/*
* ...otherwise, configure NIST P-256 (required to enable ECDHE)
*/
else {
SSL_CTX_set_tmp_ecdh(mctx->ssl_ctx,
EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
}
#endif
}
#ifdef HAVE_TLS_SESSION_TICKETS
@ -1516,7 +1377,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p)
klen = strlen(key);
if ((ps = (server_rec *)apr_hash_get(table, key, klen))) {
#ifdef OPENSSL_NO_TLSEXT
#ifndef HAVE_TLSEXT
int level = APLOG_WARNING;
const char *problem = "conflict";
#else
@ -1540,7 +1401,7 @@ void ssl_init_CheckServers(server_rec *base_server, apr_pool_t *p)
}
if (conflict) {
#ifdef OPENSSL_NO_TLSEXT
#ifndef HAVE_TLSEXT
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, base_server, APLOGNO(01917)
"Init: You should not use name-based "
"virtual hosts in conjunction with SSL!!");
@ -1689,7 +1550,7 @@ static void ssl_init_ctx_cleanup(modssl_ctx_t *mctx)
{
MODSSL_CFG_ITEM_FREE(SSL_CTX_free, mctx->ssl_ctx);
#ifndef OPENSSL_NO_SRP
#ifdef HAVE_SRP
if (mctx->srp_vbase != NULL) {
SRP_VBASE_free(mctx->srp_vbase);
mctx->srp_vbase = NULL;
@ -1744,11 +1605,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