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 */


Reply via email to