6db227d7c9
Use haproxy-config package to package script and service file for haproxy package. Create patches sub-folder and move patches file from haproxy/haproxy folder to this sub-folder. Refactor haproxy-service-file.patch & haproxy-spec-add-init-script.patch as we use haproxy-config to package related files. Merged meta_add_support_for_tpm.patch & spec-add-haproxy-env-var-patch.patch to spec-include-TiS-changes.patch (renamed from spec-include-TiS-config.patch) as they just includes adding source code patches. Deployment test and ping test between VMs pass config and script files check pass. Story: 2003768 Task: 27584 Depends-on: https://review.openstack.org/#/c/614709/ Change-Id: I08fd8aa662533f4ce379f352ba9bab7616c905f5 Signed-off-by: zhipengl <zhipengs.liu@intel.com>
320 lines
9.7 KiB
Diff
320 lines
9.7 KiB
Diff
From a2a25214f6f4913b774bdd6c0b80d3ea424d3a1b Mon Sep 17 00:00:00 2001
|
|
From: Kam Nasim <kam.nasim@windriver.com>
|
|
Date: Wed, 22 Mar 2017 12:07:24 -0400
|
|
Subject: [PATCH] haproxy tpm support
|
|
|
|
---
|
|
include/types/global.h | 13 +++++
|
|
src/cfgparse.c | 28 ++++++++++
|
|
src/haproxy.c | 26 ++++++++-
|
|
src/ssl_sock.c | 147 +++++++++++++++++++++++++++++++++++++++++++------
|
|
4 files changed, 197 insertions(+), 17 deletions(-)
|
|
|
|
diff --git a/include/types/global.h b/include/types/global.h
|
|
index f1525ae..2e9c077 100644
|
|
--- a/include/types/global.h
|
|
+++ b/include/types/global.h
|
|
@@ -30,6 +30,10 @@
|
|
#include <types/proxy.h>
|
|
#include <types/task.h>
|
|
|
|
+#ifdef USE_OPENSSL
|
|
+#include <openssl/engine.h>
|
|
+#endif
|
|
+
|
|
#ifndef UNIX_MAX_PATH
|
|
#define UNIX_MAX_PATH 108
|
|
#endif
|
|
@@ -71,6 +75,14 @@ enum {
|
|
SSL_SERVER_VERIFY_REQUIRED = 1,
|
|
};
|
|
|
|
+// WRS: Define a new TPM configuration structure
|
|
+struct tpm_conf {
|
|
+ char *tpm_object;
|
|
+ char *tpm_engine;
|
|
+ EVP_PKEY *tpm_key;
|
|
+ ENGINE *tpm_engine_ref;
|
|
+};
|
|
+
|
|
/* FIXME : this will have to be redefined correctly */
|
|
struct global {
|
|
#ifdef USE_OPENSSL
|
|
@@ -87,6 +99,7 @@ struct global {
|
|
char *connect_default_ciphers;
|
|
int listen_default_ssloptions;
|
|
int connect_default_ssloptions;
|
|
+ struct tpm_conf tpm; // tpm configuration
|
|
#endif
|
|
unsigned int ssl_server_verify; /* default verify mode on servers side */
|
|
struct freq_ctr conn_per_sec;
|
|
diff --git a/src/cfgparse.c b/src/cfgparse.c
|
|
index 6a7f80c..3bc6e79 100644
|
|
--- a/src/cfgparse.c
|
|
+++ b/src/cfgparse.c
|
|
@@ -1541,6 +1541,34 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
|
|
goto out;
|
|
#endif
|
|
}
|
|
+ else if (!strcmp(args[0], "tpm-object")) {
|
|
+ if (global.tpm.tpm_object) {
|
|
+ free(global.tpm.tpm_object);
|
|
+ }
|
|
+#ifdef USE_OPENSSL
|
|
+ if (*(args[1]) && (access(args[1], F_OK) != -1)) {
|
|
+ global.tpm.tpm_object = strdup(args[1]);
|
|
+ }
|
|
+#else
|
|
+ Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
|
|
+ err_code |= ERR_ALERT | ERR_FATAL;
|
|
+ goto out;
|
|
+#endif
|
|
+ }
|
|
+ else if (!strcmp(args[0], "tpm-engine")) {
|
|
+ if (global.tpm.tpm_engine) {
|
|
+ free(global.tpm.tpm_engine);
|
|
+ }
|
|
+#ifdef USE_OPENSSL
|
|
+ if (*(args[1]) && (access(args[1], F_OK) != -1)) {
|
|
+ global.tpm.tpm_engine = strdup(args[1]);
|
|
+ }
|
|
+#else
|
|
+ Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
|
|
+ err_code |= ERR_ALERT | ERR_FATAL;
|
|
+ goto out;
|
|
+#endif
|
|
+ }
|
|
else {
|
|
struct cfg_kw_list *kwl;
|
|
int index;
|
|
diff --git a/src/haproxy.c b/src/haproxy.c
|
|
index 862697d..2a1a0dc 100644
|
|
--- a/src/haproxy.c
|
|
+++ b/src/haproxy.c
|
|
@@ -959,6 +959,24 @@ static void deinit_stick_rules(struct list *rules)
|
|
}
|
|
}
|
|
|
|
+static void deinit_tpm_engine()
|
|
+{
|
|
+ /*
|
|
+ * if the tpm engine is present then
|
|
+ * deinit it, this is needed to
|
|
+ * flush the TPM key handle from TPM memory
|
|
+ */
|
|
+ if (global.tpm.tpm_engine_ref) {
|
|
+ ENGINE_finish(global.tpm.tpm_engine_ref);
|
|
+ }
|
|
+
|
|
+ if (global.tpm.tpm_key) {
|
|
+ EVP_PKEY_free(global.tpm.tpm_key);
|
|
+ }
|
|
+ free(global.tpm.tpm_engine); global.tpm.tpm_engine = NULL;
|
|
+ free(global.tpm.tpm_object); global.tpm.tpm_object = NULL;
|
|
+}
|
|
+
|
|
void deinit(void)
|
|
{
|
|
struct proxy *p = proxy, *p0;
|
|
@@ -1218,7 +1236,13 @@ void deinit(void)
|
|
|
|
free(uap);
|
|
}
|
|
-
|
|
+
|
|
+ /* if HAProxy was in TPM mode then deinit
|
|
+ * that configuration as well.
|
|
+ */
|
|
+ if (global.tpm.tpm_object && global.tpm.tpm_object != '\0')
|
|
+ deinit_tpm_engine();
|
|
+
|
|
userlist_free(userlist);
|
|
|
|
protocol_unbind_all();
|
|
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
|
|
index ead4c7b..4e16026 100644
|
|
--- a/src/ssl_sock.c
|
|
+++ b/src/ssl_sock.c
|
|
@@ -50,6 +50,7 @@
|
|
#ifndef OPENSSL_NO_DH
|
|
#include <openssl/dh.h>
|
|
#endif
|
|
+#include <openssl/engine.h>
|
|
|
|
#include <common/buffer.h>
|
|
#include <common/compat.h>
|
|
@@ -1115,6 +1116,80 @@ end:
|
|
return ret;
|
|
}
|
|
|
|
+/*
|
|
+ * initialize the TPM engine and load the
|
|
+ * TPM object as private key within the Engine.
|
|
+ * Only do this for the first bind since TPM can
|
|
+ * only load 3-4 contexes before it runs out of memory
|
|
+ */
|
|
+static int ssl_sock_load_tpm_key(SSL_CTX *ctx, char **err) {
|
|
+ if (!global.tpm.tpm_object || global.tpm.tpm_object[0] == '\0') {
|
|
+ /* not in TPM mode */
|
|
+ return -1;
|
|
+ }
|
|
+ if (!global.tpm.tpm_key) {
|
|
+ Warning ("Could not find tpm_key; initializing engine\n");
|
|
+ /* no key present; load the dynamic TPM engine */
|
|
+ if (global.tpm.tpm_engine && global.tpm.tpm_engine[0]) {
|
|
+ ENGINE_load_dynamic();
|
|
+ ENGINE *engine = ENGINE_by_id("dynamic");
|
|
+ if (!engine) {
|
|
+ memprintf(err, "%s Unable to load the dynamic engine "
|
|
+ "(needed for loading custom TPM engine)\n",
|
|
+ err && *err ? *err : "");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ ENGINE_ctrl_cmd_string(engine, "SO_PATH", global.tpm.tpm_engine, 0);
|
|
+ ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0);
|
|
+ /* stow away for ENGINE cleanup */
|
|
+ global.tpm.tpm_engine_ref = engine;
|
|
+
|
|
+ if (ENGINE_init(engine) != 1) {
|
|
+ const char *error_str = ERR_error_string(ERR_get_error(), NULL);
|
|
+ memprintf(err, "%s Unable to init the TPM engine (%s). Err: %s\n",
|
|
+ err && *err ? *err : "",
|
|
+ global.tpm.tpm_engine, error_str);
|
|
+ goto tpm_err;
|
|
+ }
|
|
+ EVP_PKEY *pkey = ENGINE_load_private_key(engine,
|
|
+ global.tpm.tpm_object,
|
|
+ NULL, NULL);
|
|
+ if (!pkey) {
|
|
+ const char *error_str = ERR_error_string(ERR_get_error(), NULL);
|
|
+ memprintf(err, "%s Unable to load TPM object (%s). Err: %s\n",
|
|
+ err && *err ? *err : "",
|
|
+ global.tpm.tpm_object, error_str);
|
|
+ goto tpm_err;
|
|
+ }
|
|
+ global.tpm.tpm_key = pkey;
|
|
+ }
|
|
+ else { /* no TPM engine found */
|
|
+ memprintf(err, "%s TPM engine option not set when TPM mode expected\n",
|
|
+ err && *err ? *err : "");
|
|
+ goto tpm_err;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (SSL_CTX_use_PrivateKey(ctx, global.tpm.tpm_key) <= 0){
|
|
+ const char *error_str = ERR_error_string(ERR_get_error(),
|
|
+ NULL);
|
|
+ memprintf(err, "%s Invalid private key provided from TPM engine(%s). Err: %s\n",
|
|
+ err && *err ? *err : "",
|
|
+ global.tpm.tpm_object, error_str);
|
|
+ goto tpm_err;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+
|
|
+tpm_err:
|
|
+ ENGINE_finish(global.tpm.tpm_engine_ref);
|
|
+ global.tpm.tpm_engine_ref = NULL;
|
|
+ EVP_PKEY_free(global.tpm.tpm_key);
|
|
+ global.tpm.tpm_key = NULL;
|
|
+ return 1;
|
|
+}
|
|
+
|
|
static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf, struct proxy *curproxy, char **sni_filter, int fcount, char **err)
|
|
{
|
|
int ret;
|
|
@@ -1127,26 +1202,54 @@ static int ssl_sock_load_cert_file(const char *path, struct bind_conf *bind_conf
|
|
return 1;
|
|
}
|
|
|
|
- if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
|
|
- memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
|
|
- err && *err ? *err : "", path);
|
|
- SSL_CTX_free(ctx);
|
|
- return 1;
|
|
+ /* NOTE (knasim-wrs): US93721: TPM support
|
|
+ * This SSL context applies to SSL frontends only.
|
|
+ * If the TPM option is set then the Private key
|
|
+ * is stored in TPM.
|
|
+ *
|
|
+ * Launch the OpenSSL TPM engine and load the TPM
|
|
+ * Private Key. The Public key will still be located
|
|
+ * at the provided path and needs to be loaded as
|
|
+ * per usual.
|
|
+ */
|
|
+ if (global.tpm.tpm_object) {
|
|
+ ret = ssl_sock_load_tpm_key(ctx, err);
|
|
+ if (ret > 0) {
|
|
+ /* tpm configuration failed */
|
|
+ SSL_CTX_free(ctx);
|
|
+ return 1;
|
|
+ }
|
|
}
|
|
-
|
|
- ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
|
|
- if (ret <= 0) {
|
|
- memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
|
|
- err && *err ? *err : "", path);
|
|
- if (ret < 0) /* serious error, must do that ourselves */
|
|
+ else { /* non TPM mode */
|
|
+ if (SSL_CTX_use_PrivateKey_file(ctx, path, SSL_FILETYPE_PEM) <= 0) {
|
|
+ memprintf(err, "%sunable to load SSL private key from PEM file '%s'.\n",
|
|
+ err && *err ? *err : "", path);
|
|
SSL_CTX_free(ctx);
|
|
- return 1;
|
|
+ return 1;
|
|
+ }
|
|
}
|
|
|
|
- if (SSL_CTX_check_private_key(ctx) <= 0) {
|
|
- memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
|
|
- err && *err ? *err : "", path);
|
|
- return 1;
|
|
+ ret = ssl_sock_load_cert_chain_file(ctx, path, bind_conf, sni_filter, fcount);
|
|
+ if (ret <= 0) {
|
|
+ memprintf(err, "%sunable to load SSL certificate from PEM file '%s'.\n",
|
|
+ err && *err ? *err : "", path);
|
|
+ if (ret < 0) /* serious error, must do that ourselves */
|
|
+ SSL_CTX_free(ctx);
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * only match the private key to the public key
|
|
+ * for non TPM mode. This op would never work for
|
|
+ * TPM since the private key has been wrapped, whereas
|
|
+ * the public key is still the original one.
|
|
+ */
|
|
+ if (!global.tpm.tpm_object) {
|
|
+ if (SSL_CTX_check_private_key(ctx) <= 0) {
|
|
+ memprintf(err, "%sinconsistencies between private key and certificate loaded from PEM file '%s'.\n",
|
|
+ err && *err ? *err : "", path);
|
|
+ return 1;
|
|
+ }
|
|
}
|
|
|
|
/* we must not free the SSL_CTX anymore below, since it's already in
|
|
@@ -1725,6 +1828,18 @@ int ssl_sock_prepare_srv_ctx(struct server *srv, struct proxy *curproxy)
|
|
cfgerr++;
|
|
return cfgerr;
|
|
}
|
|
+
|
|
+ /* NOTE (knasim-wrs): US93721: TPM support
|
|
+ * This SSL context applies to SSL backends only.
|
|
+ * Since Titanium backends don't support SSL, there
|
|
+ * is no need to offload these keys in TPM or reuse the
|
|
+ * same TPM key for the frontend engine.
|
|
+ *
|
|
+ * If SSL backends are to be supported in the future,
|
|
+ * over TPM, then create a new TPM Engine context and
|
|
+ * load the backend key in TPM, in a similar fashion to
|
|
+ * the frontend key.
|
|
+ */
|
|
if (srv->ssl_ctx.client_crt) {
|
|
if (SSL_CTX_use_PrivateKey_file(srv->ssl_ctx.ctx, srv->ssl_ctx.client_crt, SSL_FILETYPE_PEM) <= 0) {
|
|
Alert("config : %s '%s', server '%s': unable to load SSL private key from PEM file '%s'.\n",
|
|
--
|
|
1.8.3.1
|
|
|