The following is a patch that adds OpenSSL engine support to HAProxy.
This is necessary for those running load balancers and wish to offload
the SSL to any hardware devices. I've tested it with the OpenSSL padlock
engine, but it should handle any engine (such as the aesni engine on
recent Intel CPUs) as it's simply given as a string argument to OpenSSL.
This has been adapted from Stud's engine support.
- Ian Scott
diff -uprN haproxy-1.5-dev17/doc/configuration.txt
haproxy-1.5-dev17-new/doc/configuration.txt
--- haproxy-1.5-dev17/doc/configuration.txt 2012-12-28
06:04:05.000000000 -0800
+++ haproxy-1.5-dev17-new/doc/configuration.txt 2013-01-04
17:21:30.159915112 -0800
@@ -7017,6 +7017,11 @@ ecdhe <named curve>
the named curve (RFC 4492) used to generate ECDH ephemeral keys and
makes
ECDHE cipher suites usable.
+engine <engine>
+ This setting is only available when support for OpenSSL was built in.
It sets
+ the OpenSSL engine to use, such as "aesni" for Intel AES New
Instructions or
+ "padlock" for VIA Padlock.
+
ca-file <cafile>
This setting is only available when support for OpenSSL was built in. It
designates a PEM file from which to load CA certificates used to verify
diff -uprN haproxy-1.5-dev17/include/types/listener.h
haproxy-1.5-dev17-new/include/types/listener.h
--- haproxy-1.5-dev17/include/types/listener.h 2012-12-28
06:04:05.000000000 -0800
+++ haproxy-1.5-dev17-new/include/types/listener.h 2013-01-04
17:14:56.435925020 -0800
@@ -122,6 +122,7 @@ struct bind_conf {
char *ciphers; /* cipher suite to use if non-null */
char *crl_file; /* CRLfile to use on verify */
char *ecdhe; /* named curve to use for ECDHE */
+ char *engine; /* OpenSSL engine to use */
int ssl_options; /* ssl options */
int verify; /* verify method (set of SSL_VERIFY_*
flags) */
SSL_CTX *default_ctx; /* SSL context of first/default
certificate */
diff -uprN haproxy-1.5-dev17/src/cfgparse.c
haproxy-1.5-dev17-new/src/cfgparse.c
--- haproxy-1.5-dev17/src/cfgparse.c 2012-12-28 06:04:05.000000000 -0800
+++ haproxy-1.5-dev17-new/src/cfgparse.c 2013-01-04
17:14:16.503925943 -0800
@@ -6758,6 +6758,7 @@ out_uri_auth_compat:
free(bind_conf->ca_file);
free(bind_conf->ciphers);
free(bind_conf->ecdhe);
+ free(bind_conf->engine);
free(bind_conf->crl_file);
#endif /* USE_OPENSSL */
}
diff -uprN haproxy-1.5-dev17/src/haproxy.c
haproxy-1.5-dev17-new/src/haproxy.c
--- haproxy-1.5-dev17/src/haproxy.c 2012-12-28 06:04:05.000000000 -0800
+++ haproxy-1.5-dev17-new/src/haproxy.c 2013-01-04 17:14:38.091934608
-0800
@@ -1083,6 +1083,7 @@ void deinit(void)
free(bind_conf->ca_file);
free(bind_conf->ciphers);
free(bind_conf->ecdhe);
+ free(bind_conf->engine);
free(bind_conf->crl_file);
#endif /* USE_OPENSSL */
free(bind_conf->file);
diff -uprN haproxy-1.5-dev17/src/ssl_sock.c
haproxy-1.5-dev17-new/src/ssl_sock.c
--- haproxy-1.5-dev17/src/ssl_sock.c 2012-12-28 06:04:05.000000000 -0800
+++ haproxy-1.5-dev17-new/src/ssl_sock.c 2013-01-04
17:38:38.595890893 -0800
@@ -43,6 +43,11 @@
#include <openssl/x509v3.h>
#include <openssl/x509.h>
#include <openssl/err.h>
+#ifdef OPENSSL_NO_ENGINE
+static void ENGINE_cleanup(void) {};
+#else
+#include <openssl/engine.h>
+#endif
#include <common/buffer.h>
#include <common/compat.h>
@@ -572,6 +577,20 @@ int ssl_sock_prepare_ctx(struct bind_con
if (global.tune.ssllifetime)
SSL_CTX_set_timeout(ctx, global.tune.ssllifetime);
+ if (bind_conf->engine) {
+ ENGINE *engine = NULL;
+ ENGINE_load_builtin_engines();
+ if ((engine = ENGINE_by_id(bind_conf->engine)) == NULL ||
+ !ENGINE_init(engine) ||
+ !ENGINE_set_default(engine, ENGINE_METHOD_ALL)) {
+ Alert("Proxy '%s': unable to set SSL engine to '%s' for
bind '%s' at [%s:%d].\n",
+ curproxy->id, bind_conf->engine, bind_conf->arg,
bind_conf->file, bind_conf->line);
+ cfgerr++;
+ }
+ ENGINE_finish(engine);
+ ENGINE_free(engine);
+ }
+
shared_context_set_cache(ctx);
if (bind_conf->ciphers &&
!SSL_CTX_set_cipher_list(ctx, bind_conf->ciphers)) {
@@ -792,6 +811,10 @@ void ssl_sock_free_all_ctx(struct bind_c
node = back;
}
+ if (bind_conf->engine) {
+ ENGINE_cleanup();
+ }
+
bind_conf->default_ctx = NULL;
}
@@ -2390,6 +2413,30 @@ static int bind_parse_ecdhe(char **args,
#endif
}
+/* parse the "engine" bind keyword keywords */
+static int bind_parse_engine(char **args, int cur_arg, struct proxy
*px, struct bind_conf *conf, char **err)
+{
+#if OPENSSL_VERSION_NUMBER < 0x0090700fL
+ if (err)
+ memprintf(err, "'%s' : library does not support engines (too
old)", args[cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+#elif defined(OPENSSL_NO_ENGINE)
+ if (err)
+ memprintf(err, "'%s' : library does not support engines
(disabled via OPENSSL_NO_ENGINE)", args[cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+#else
+ if (!*args[cur_arg + 1]) {
+ if (err)
+ memprintf(err, "'%s' : missing named engine", args[cur_arg]);
+ return ERR_ALERT | ERR_FATAL;
+ }
+
+ conf->engine = strdup(args[cur_arg + 1]);
+
+ return 0;
+#endif
+}
+
/* parse the "crt_ignerr" and "ca_ignerr" bind keywords */
static int bind_parse_ignore_err(char **args, int cur_arg, struct
proxy *px, struct bind_conf *conf, char **err)
{
@@ -2878,6 +2925,7 @@ static struct bind_kw_list bind_kws = {
{ "crt", bind_parse_crt, 1 }, /* load
SSL certificates from this location */
{ "crt-ignore-err", bind_parse_ignore_err, 1 }, /* set
error IDs to ingore on verify depth == 0 */
{ "ecdhe", bind_parse_ecdhe, 1 }, /*
defines named curve for elliptic curve Diffie-Hellman */
+ { "engine", bind_parse_engine, 1 }, /* sets
OpenSSL engine to use */
{ "force-sslv3", bind_parse_force_sslv3, 0 }, /*
force SSLv3 */
{ "force-tlsv10", bind_parse_force_tlsv10, 0 }, /*
force TLSv10 */
{ "force-tlsv11", bind_parse_force_tlsv11, 0 }, /*
force TLSv11 */