--- httpd-2.4.2/modules/ssl/mod_ssl.c 2011-12-30 11:42:16.000000000 +0100 +++ httpd-2.4.2/modules/ssl/mod_ssl.c 2012-04-30 17:18:21.648996033 +0200 @@ -88,6 +88,9 @@ SSL_CMD_SRV(CertificateKeyFile, TAKE1, "SSL Server Private Key file " "('/path/to/file' - PEM or DER encoded)") + SSL_CMD_SRV(DHParametersFile, TAKE1, + "SSL Server Diffie-Hellman parameters file " + "(`/path/to/file' - PEM or DER encoded)") SSL_CMD_SRV(CertificateChainFile, TAKE1, "SSL Server CA Certificate Chain file " "('/path/to/file' - PEM encoded)") --- httpd-2.4.2/modules/ssl/ssl_engine_config.c 2011-12-24 08:34:07.000000000 +0100 +++ httpd-2.4.2/modules/ssl/ssl_engine_config.c 2012-04-30 17:23:20.940135394 +0200 @@ -67,6 +67,7 @@ mc->tVHostKeys = apr_hash_make(pool); mc->tPrivateKey = apr_hash_make(pool); mc->tPublicCert = apr_hash_make(pool); + mc->tDHParams = apr_hash_make(pool); #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) mc->szCryptoDevice = NULL; #endif @@ -182,6 +183,9 @@ /* mctx->pks->... certs/keys are set during module init */ + mctx->pks->dhparams_file = NULL; + mctx->pks->dhparams = NULL; + #ifdef HAVE_TLS_SESSION_TICKETS mctx->ticket_key = apr_pcalloc(p, sizeof(*mctx->ticket_key)); #endif @@ -299,6 +303,7 @@ cfgMergeString(pks->ca_name_path); cfgMergeString(pks->ca_name_file); + cfgMergeString(pks->dhparams_file); #ifdef HAVE_TLS_SESSION_TICKETS cfgMergeString(ticket_key->file_path); @@ -760,6 +765,22 @@ return NULL; } + +const char *ssl_cmd_SSLDHParametersFile(cmd_parms *cmd, + void *dcfg, + const char *arg) +{ + SSLSrvConfigRec *sc = mySrvConfig(cmd->server); + const char *err; + + if ((err = ssl_cmd_check_file(cmd, &arg))) { + return err; + } + + sc->server->pks->dhparams_file = arg; + + return NULL; +} const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *cmd, void *dcfg, --- httpd-2.4.2/modules/ssl/ssl_engine_init.c 2012-04-03 14:37:57.000000000 +0200 +++ httpd-2.4.2/modules/ssl/ssl_engine_init.c 2012-04-30 17:59:21.143665396 +0200 @@ -950,6 +950,42 @@ } } +static int ssl_server_import_dhparams(server_rec *s, + modssl_ctx_t *mctx, + const char *id) +{ + SSLModConfigRec *mc = myModConfig(s); + ssl_asn1_t *asn1; + MODSSL_D2I_DHparams_CONST unsigned char *ptr; + DH *dhparams = NULL; + + if (!(asn1 = ssl_asn1_table_get(mc->tDHParams, id))) { + return FALSE; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "Configuring server Diffie-Hellman parameters"); + + ptr = asn1->cpData; + if (!(dhparams = d2i_DHparams(NULL, &ptr, asn1->nData))) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Unable to import server Diffie-Hellman parameters"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + ssl_die(); + } + + if (SSL_CTX_set_tmp_dh(mctx->ssl_ctx, dhparams) <= 0) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Unable to configure server Diffie-Hellman parameters"); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + ssl_die(); + } + + mctx->pks->dhparams = dhparams; + + return TRUE; +} + static int ssl_server_import_cert(server_rec *s, modssl_ctx_t *mctx, const char *id, @@ -1157,7 +1193,7 @@ apr_pool_t *ptemp, modssl_ctx_t *mctx) { - const char *rsa_id, *dsa_id; + const char *rsa_id, *dsa_id, *dh_id; #ifndef OPENSSL_NO_EC const char *ecc_id; #endif @@ -1170,12 +1206,14 @@ rsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_RSA); dsa_id = ssl_asn1_table_keyfmt(ptemp, vhost_id, SSL_AIDX_DSA); + dh_id = apr_pstrcat(ptemp, vhost_id, ":", "DH", NULL); #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); + (void)ssl_server_import_dhparams(s, mctx, dh_id); #ifndef OPENSSL_NO_EC have_ecc = ssl_server_import_cert(s, mctx, ecc_id, SSL_AIDX_ECC); #endif @@ -1711,6 +1749,7 @@ MODSSL_CFG_ITEM_FREE(EVP_PKEY_free, mctx->pks->keys[i]); } + MODSSL_CFG_ITEM_FREE(DH_free, mctx->pks->dhparams); } apr_status_t ssl_init_ModuleKill(void *data) --- httpd-2.4.2/modules/ssl/ssl_engine_pphrase.c 2011-12-18 19:02:21.000000000 +0100 +++ httpd-2.4.2/modules/ssl/ssl_engine_pphrase.c 2012-04-30 18:10:18.507346301 +0200 @@ -147,6 +147,7 @@ unsigned char *ucp; long int length; X509 *pX509Cert; + DH *pDHParams; BOOL bReadable; apr_array_header_t *aPassPhrase; int nPassPhrase; @@ -162,6 +163,7 @@ char *an; apr_time_t pkey_mtime = 0; apr_status_t rv; + const char *dhid; /* * Start with a fresh pass phrase array */ @@ -550,6 +552,43 @@ */ EVP_PKEY_free(pPrivateKey); } + /* + * Read in Diffie-Hellman parameters file if such a file is + * specified. + */ + if (sc->server->pks->dhparams_file) { + apr_cpystrn(szPath, sc->server->pks->dhparams_file, sizeof(szPath)); + if ((rv = exists_and_readable(szPath, p, NULL)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "Init: Can't open server Diffie-Hellman parameters file %s", + szPath); + ssl_die(); + } + if ((pDHParams = SSL_read_DHparams(szPath, NULL, NULL)) == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Init: Unable to read server Diffie-Hellman parameters from file %s", szPath); + ssl_log_ssl_error(SSLLOG_MARK, APLOG_ERR, s); + ssl_die(); + } + + /* + * Insert the DH params into global module configuration + * to let it survive the processing between the 1st Apache + * API init round (where we operate here) and the 2nd + * Apache init round (where it will be actually used to + * configure mod_ssl's per-server configuration + * structures). + */ + dhid = asn1_table_vhost_key(mc, p, cpVHostID, "DH"); + length = i2d_DHparams(pDHParams, NULL); + ucp = ssl_asn1_table_set(mc->tDHParams, dhid, length); + (void)i2d_DHparams(pDHParams, &ucp); /* 2nd arg increments */ + + /* + * Free the DH structure + */ + DH_free(pDHParams); + } } /* --- httpd-2.4.2/modules/ssl/ssl_private.h 2012-04-03 14:37:57.000000000 +0200 +++ httpd-2.4.2/modules/ssl/ssl_private.h 2012-04-30 17:37:17.636094136 +0200 @@ -121,10 +121,12 @@ #define MODSSL_D2I_ASN1_type_bytes_CONST const #define MODSSL_D2I_PrivateKey_CONST const #define MODSSL_D2I_X509_CONST const +#define MODSSL_D2I_DHparams_CONST const #else #define MODSSL_D2I_ASN1_type_bytes_CONST #define MODSSL_D2I_PrivateKey_CONST #define MODSSL_D2I_X509_CONST +#define MODSSL_D2I_DHparams_CONST #endif #if OPENSSL_VERSION_NUMBER >= 0x00908080 && !defined(OPENSSL_NO_OCSP) \ @@ -526,6 +528,7 @@ * example the string "vhost.example.com:443:RSA". */ apr_hash_t *tPublicCert; apr_hash_t *tPrivateKey; + apr_hash_t *tDHParams; #if defined(HAVE_OPENSSL_ENGINE_H) && defined(HAVE_ENGINE_INIT) const char *szCryptoDevice; @@ -552,11 +555,13 @@ * unordered lists. */ const char *cert_files[SSL_AIDX_MAX]; const char *key_files[SSL_AIDX_MAX]; + const char *dhparams_file; /* Loaded certs and keys; these arrays ARE indexed by the * algorithm type, i.e. keys[SSL_AIDX_RSA] maps to the RSA * private key. */ X509 *certs[SSL_AIDX_MAX]; EVP_PKEY *keys[SSL_AIDX_MAX]; + DH *dhparams; /** Certificates which specify the set of CA names which should be * sent in the CertificateRequest message: */ @@ -711,6 +716,7 @@ const char *ssl_cmd_SSLRandomSeed(cmd_parms *, void *, const char *, const char *, const char *); const char *ssl_cmd_SSLEngine(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCipherSuite(cmd_parms *, void *, const char *); +const char *ssl_cmd_SSLDHParametersFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateKeyFile(cmd_parms *, void *, const char *); const char *ssl_cmd_SSLCertificateChainFile(cmd_parms *, void *, const char *); --- httpd-2.4.2/modules/ssl/ssl_util_ssl.c 2012-02-28 13:07:31.000000000 +0100 +++ httpd-2.4.2/modules/ssl/ssl_util_ssl.c 2012-04-30 18:04:06.494472218 +0200 @@ -156,6 +156,47 @@ return rc; } +DH *SSL_read_DHparams(char* filename, DH **DHparams, void *cb) +{ + DH *rc; + BIO *bioS; + BIO *bioF; + + /* 1. try PEM (= DER+Base64+headers) */ + if ((bioS=BIO_new_file(filename, "r")) == NULL) + return NULL; + rc = PEM_read_bio_DHparams(bioS, DHparams, cb, NULL); + BIO_free(bioS); + + if (rc == NULL) { + /* 2. try DER+Base64 */ + if ((bioS=BIO_new_file(filename, "r")) == NULL) + return NULL; + + if ((bioF = BIO_new(BIO_f_base64())) == NULL) { + BIO_free(bioS); + return NULL; + } + bioS = BIO_push(bioF, bioS); + rc = d2i_DHparams_bio(bioS, NULL); + BIO_free_all(bioS); + + if (rc == NULL) { + /* 3. try plain DER */ + if ((bioS=BIO_new_file(filename, "r")) == NULL) + return NULL; + rc = d2i_DHparams_bio(bioS, NULL); + BIO_free(bioS); + } + } + if (rc != NULL && DHparams != NULL) { + if (*DHparams != NULL) + DH_free(*DHparams); + *DHparams = rc; + } + return rc; +} + /* _________________________________________________________________ ** ** Smart shutdown --- httpd-2.4.2/modules/ssl/ssl_util_ssl.h 2012-01-08 11:12:18.000000000 +0100 +++ httpd-2.4.2/modules/ssl/ssl_util_ssl.h 2012-04-30 18:04:13.342635578 +0200 @@ -62,6 +62,7 @@ void SSL_set_app_data2(SSL *, void *); X509 *SSL_read_X509(char *, X509 **, pem_password_cb *); EVP_PKEY *SSL_read_PrivateKey(char *, EVP_PKEY **, pem_password_cb *, void *); +DH *SSL_read_DHparams(char* filename, DH **DHparams, void *cb); int SSL_smart_shutdown(SSL *ssl); BOOL SSL_X509_isSGC(X509 *); BOOL SSL_X509_getBC(X509 *, int *, int *);