|
|
41a6c3 |
diff --git a/modules/ssl/ssl_engine_init.c b/modules/ssl/ssl_engine_init.c
|
|
|
41a6c3 |
index 46769e9..0275452 100644
|
|
|
41a6c3 |
--- a/modules/ssl/ssl_engine_init.c
|
|
|
41a6c3 |
+++ b/modules/ssl/ssl_engine_init.c
|
|
|
41a6c3 |
@@ -41,6 +41,79 @@
|
|
|
41a6c3 |
#define KEYTYPES "RSA or DSA"
|
|
|
41a6c3 |
#endif
|
|
|
41a6c3 |
|
|
|
41a6c3 |
+/*
|
|
|
41a6c3 |
+ * Grab well-defined DH parameters from OpenSSL, see the get_rfc*
|
|
|
41a6c3 |
+ * functions in <openssl/bn.h> for all available primes.
|
|
|
41a6c3 |
+ */
|
|
|
41a6c3 |
+static DH *make_dh_params(BIGNUM *(*prime)(BIGNUM *), const char *gen)
|
|
|
41a6c3 |
+{
|
|
|
41a6c3 |
+ DH *dh = DH_new();
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
+ if (!dh) {
|
|
|
41a6c3 |
+ return NULL;
|
|
|
41a6c3 |
+ }
|
|
|
41a6c3 |
+ dh->p = prime(NULL);
|
|
|
41a6c3 |
+ BN_dec2bn(&dh->g, gen);
|
|
|
41a6c3 |
+ if (!dh->p || !dh->g) {
|
|
|
41a6c3 |
+ DH_free(dh);
|
|
|
41a6c3 |
+ return NULL;
|
|
|
41a6c3 |
+ }
|
|
|
41a6c3 |
+ return dh;
|
|
|
41a6c3 |
+}
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
+/* Storage and initialization for DH parameters. */
|
|
|
41a6c3 |
+static struct dhparam {
|
|
|
41a6c3 |
+ BIGNUM *(*const prime)(BIGNUM *); /* function to generate... */
|
|
|
41a6c3 |
+ DH *dh; /* ...this, used for keys.... */
|
|
|
41a6c3 |
+ const unsigned int min; /* ...of length >= this. */
|
|
|
41a6c3 |
+} dhparams[] = {
|
|
|
41a6c3 |
+ { get_rfc3526_prime_8192, NULL, 6145 },
|
|
|
41a6c3 |
+ { get_rfc3526_prime_6144, NULL, 4097 },
|
|
|
41a6c3 |
+ { get_rfc3526_prime_4096, NULL, 3073 },
|
|
|
41a6c3 |
+ { get_rfc3526_prime_3072, NULL, 2049 },
|
|
|
41a6c3 |
+ { get_rfc3526_prime_2048, NULL, 1025 },
|
|
|
41a6c3 |
+ { get_rfc2409_prime_1024, NULL, 0 }
|
|
|
41a6c3 |
+};
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
+static void init_dh_params(void)
|
|
|
41a6c3 |
+{
|
|
|
41a6c3 |
+ unsigned n;
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
+ for (n = 0; n < sizeof(dhparams)/sizeof(dhparams[0]); n++)
|
|
|
41a6c3 |
+ dhparams[n].dh = make_dh_params(dhparams[n].prime, "2");
|
|
|
41a6c3 |
+}
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
+static void free_dh_params(void)
|
|
|
41a6c3 |
+{
|
|
|
41a6c3 |
+ unsigned n;
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
+ /* DH_free() is a noop for a NULL parameter, so these are harmless
|
|
|
41a6c3 |
+ * in the (unexpected) case where these variables are already
|
|
|
41a6c3 |
+ * NULL. */
|
|
|
41a6c3 |
+ for (n = 0; n < sizeof(dhparams)/sizeof(dhparams[0]); n++) {
|
|
|
41a6c3 |
+ DH_free(dhparams[n].dh);
|
|
|
41a6c3 |
+ dhparams[n].dh = NULL;
|
|
|
41a6c3 |
+ }
|
|
|
41a6c3 |
+}
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
+/* Hand out the same DH structure though once generated as we leak
|
|
|
41a6c3 |
+ * memory otherwise and freeing the structure up after use would be
|
|
|
41a6c3 |
+ * hard to track and in fact is not needed at all as it is safe to
|
|
|
41a6c3 |
+ * use the same parameters over and over again security wise (in
|
|
|
41a6c3 |
+ * contrast to the keys itself) and code safe as the returned structure
|
|
|
41a6c3 |
+ * is duplicated by OpenSSL anyway. Hence no modification happens
|
|
|
41a6c3 |
+ * to our copy. */
|
|
|
41a6c3 |
+DH *modssl_get_dh_params(unsigned keylen)
|
|
|
41a6c3 |
+{
|
|
|
41a6c3 |
+ unsigned n;
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
+ for (n = 0; n < sizeof(dhparams)/sizeof(dhparams[0]); n++)
|
|
|
41a6c3 |
+ if (keylen >= dhparams[n].min)
|
|
|
41a6c3 |
+ return dhparams[n].dh;
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
+ return NULL; /* impossible to reach. */
|
|
|
41a6c3 |
+}
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
static void ssl_add_version_components(apr_pool_t *p,
|
|
|
41a6c3 |
server_rec *s)
|
|
|
41a6c3 |
{
|
|
|
41a6c3 |
@@ -244,6 +317,8 @@ int ssl_init_Module(apr_pool_t *p, apr_pool_t *plog,
|
|
|
41a6c3 |
|
|
|
41a6c3 |
SSL_init_app_data2_idx(); /* for SSL_get_app_data2() at request time */
|
|
|
41a6c3 |
|
|
|
41a6c3 |
+ init_dh_params();
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
return OK;
|
|
|
41a6c3 |
}
|
|
|
41a6c3 |
|
|
|
41a6c3 |
@@ -1623,6 +1698,8 @@ apr_status_t ssl_init_ModuleKill(void *data)
|
|
|
41a6c3 |
ssl_init_ctx_cleanup_server(sc->server);
|
|
|
41a6c3 |
}
|
|
|
41a6c3 |
|
|
|
41a6c3 |
+ free_dh_params();
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
return APR_SUCCESS;
|
|
|
41a6c3 |
}
|
|
|
41a6c3 |
|
|
|
41a6c3 |
diff --git a/modules/ssl/ssl_engine_kernel.c b/modules/ssl/ssl_engine_kernel.c
|
|
|
41a6c3 |
index 2d6d59e..1ecbccd 100644
|
|
|
41a6c3 |
--- a/modules/ssl/ssl_engine_kernel.c
|
|
|
41a6c3 |
+++ b/modules/ssl/ssl_engine_kernel.c
|
|
|
41a6c3 |
@@ -1287,34 +1287,6 @@ const authz_provider ssl_authz_provider_verify_client =
|
|
|
41a6c3 |
*/
|
|
|
41a6c3 |
|
|
|
41a6c3 |
/*
|
|
|
41a6c3 |
- * Grab well-defined DH parameters from OpenSSL, see <openssl/bn.h>
|
|
|
41a6c3 |
- * (get_rfc*) for all available primes.
|
|
|
41a6c3 |
- */
|
|
|
41a6c3 |
-#define make_get_dh(rfc,size,gen) \
|
|
|
41a6c3 |
-static DH *get_dh##size(void) \
|
|
|
41a6c3 |
-{ \
|
|
|
41a6c3 |
- DH *dh; \
|
|
|
41a6c3 |
- if (!(dh = DH_new())) { \
|
|
|
41a6c3 |
- return NULL; \
|
|
|
41a6c3 |
- } \
|
|
|
41a6c3 |
- dh->p = get_##rfc##_prime_##size(NULL); \
|
|
|
41a6c3 |
- BN_dec2bn(&dh->g, #gen); \
|
|
|
41a6c3 |
- if (!dh->p || !dh->g) { \
|
|
|
41a6c3 |
- DH_free(dh); \
|
|
|
41a6c3 |
- return NULL; \
|
|
|
41a6c3 |
- } \
|
|
|
41a6c3 |
- return dh; \
|
|
|
41a6c3 |
-}
|
|
|
41a6c3 |
-
|
|
|
41a6c3 |
-/*
|
|
|
41a6c3 |
- * Prepare DH parameters from 1024 to 4096 bits, in 1024-bit increments
|
|
|
41a6c3 |
- */
|
|
|
41a6c3 |
-make_get_dh(rfc2409, 1024, 2)
|
|
|
41a6c3 |
-make_get_dh(rfc3526, 2048, 2)
|
|
|
41a6c3 |
-make_get_dh(rfc3526, 3072, 2)
|
|
|
41a6c3 |
-make_get_dh(rfc3526, 4096, 2)
|
|
|
41a6c3 |
-
|
|
|
41a6c3 |
-/*
|
|
|
41a6c3 |
* Hand out standard DH parameters, based on the authentication strength
|
|
|
41a6c3 |
*/
|
|
|
41a6c3 |
DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen)
|
|
|
41a6c3 |
@@ -1342,14 +1314,7 @@ DH *ssl_callback_TmpDH(SSL *ssl, int export, int keylen)
|
|
|
41a6c3 |
ap_log_cerror(APLOG_MARK, APLOG_TRACE2, 0, c,
|
|
|
41a6c3 |
"handing out built-in DH parameters for %d-bit authenticated connection", keylen);
|
|
|
41a6c3 |
|
|
|
41a6c3 |
- if (keylen >= 4096)
|
|
|
41a6c3 |
- return get_dh4096();
|
|
|
41a6c3 |
- else if (keylen >= 3072)
|
|
|
41a6c3 |
- return get_dh3072();
|
|
|
41a6c3 |
- else if (keylen >= 2048)
|
|
|
41a6c3 |
- return get_dh2048();
|
|
|
41a6c3 |
- else
|
|
|
41a6c3 |
- return get_dh1024();
|
|
|
41a6c3 |
+ return modssl_get_dh_params(keylen);
|
|
|
41a6c3 |
}
|
|
|
41a6c3 |
|
|
|
41a6c3 |
/*
|
|
|
41a6c3 |
diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h
|
|
|
41a6c3 |
index 744af9e..f47ed47 100644
|
|
|
41a6c3 |
--- a/modules/ssl/ssl_private.h
|
|
|
41a6c3 |
+++ b/modules/ssl/ssl_private.h
|
|
|
41a6c3 |
@@ -990,6 +990,11 @@ OCSP_RESPONSE *modssl_dispatch_ocsp_request(const apr_uri_t *uri,
|
|
|
41a6c3 |
conn_rec *c, apr_pool_t *p);
|
|
|
41a6c3 |
#endif
|
|
|
41a6c3 |
|
|
|
41a6c3 |
+/* Retrieve DH parameters for given key length. Return value should
|
|
|
41a6c3 |
+ * be treated as unmutable, since it is stored in process-global
|
|
|
41a6c3 |
+ * memory. */
|
|
|
41a6c3 |
+DH *modssl_get_dh_params(unsigned keylen);
|
|
|
41a6c3 |
+
|
|
|
41a6c3 |
#endif /* SSL_PRIVATE_H */
|
|
|
41a6c3 |
/** @} */
|
|
|
41a6c3 |
|