integ/base/lighttpd/files/lighttpd-tpm-support.patch

290 lines
11 KiB
Diff

From c58d174a1d2872272bfa9d83c642591f04effcb1 Mon Sep 17 00:00:00 2001
From: Kam Nasim <kam.nasim@windriver.com>
Date: Wed, 29 Mar 2017 21:56:41 -0400
Subject: [PATCH] lighttpd tpm support
---
src/base.h | 24 ++++++++++++
src/configfile.c | 6 ++-
src/mod_openssl.c | 113 +++++++++++++++++++++++++++++++++++++++++++++---------
src/server.c | 17 +++++++-
4 files changed, 139 insertions(+), 21 deletions(-)
diff --git a/src/base.h b/src/base.h
index 2fe60b6..bddcd01 100644
--- a/src/base.h
+++ b/src/base.h
@@ -15,6 +15,21 @@
#include "sock_addr.h"
#include "etag.h"
+#if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
+# define USE_OPENSSL
+# include <openssl/opensslconf.h>
+# ifndef USE_OPENSSL_KERBEROS
+# ifndef OPENSSL_NO_KRB5
+# define OPENSSL_NO_KRB5
+# endif
+# endif
+# include <openssl/ssl.h>
+# include <openssl/engine.h>
+# if ! defined OPENSSL_NO_TLSEXT && ! defined SSL_CTRL_SET_TLSEXT_HOSTNAME
+# define OPENSSL_NO_TLSEXT
+# endif
+#endif
+
struct fdevents; /* declaration */
struct stat_cache; /* declaration */
@@ -360,6 +375,13 @@ typedef struct {
unsigned short high_precision_timestamps;
time_t loadts;
double loadavg[3];
+#ifdef USE_OPENSSL
+ // TPM engine and object configuration
+ buffer *tpm_object;
+ buffer *tpm_engine;
+ ENGINE *tpm_engine_ref;
+ EVP_PKEY *tpm_key;
+#endif
buffer *syslog_facility;
} server_config;
@@ -400,6 +422,8 @@ struct server {
int con_written;
int con_closed;
+ int tpm_is_init; // has TPM been initialized already
+
int max_fds; /* max possible fds */
int cur_fds; /* currently used fds */
int want_fds; /* waiting fds */
diff --git a/src/configfile.c b/src/configfile.c
index c3b0f16..dca2a29 100644
--- a/src/configfile.c
+++ b/src/configfile.c
@@ -276,8 +276,10 @@ static int config_insert(server *srv) {
{ "server.syslog-facility", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 80 */
{ "server.socket-perms", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 81 */
{ "server.http-parseopts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 82 */
+ { "server.tpm-object", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 83 */
+ { "server.tpm-engine", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 84 */
- { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
};
/* all T_CONFIG_SCOPE_SERVER options */
@@ -318,6 +320,8 @@ static int config_insert(server *srv) {
cv[80].destination = srv->srvconf.syslog_facility;
http_parseopts = array_init();
cv[82].destination = http_parseopts;
+ cv[83].destination = srv->srvconf.tpm_object;
+ cv[84].destination = srv->srvconf.tpm_engine;
srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
diff --git a/src/mod_openssl.c b/src/mod_openssl.c
index 75e0873..4cb0335 100644
--- a/src/mod_openssl.c
+++ b/src/mod_openssl.c
@@ -422,6 +422,29 @@ error:
return NULL;
}
+static EVP_PKEY*
+evp_pkey_load_tpm_object_file(server *srv) {
+ if (!srv->tpm_is_init || !srv->srvconf.tpm_engine_ref)
+ return NULL;
+
+ if (srv->srvconf.tpm_key) {
+ // if a TPM key was previously loaded
+ // then return that as there is no need to
+ // reload this key into TPM
+ return srv->srvconf.tpm_key;
+ }
+
+ EVP_PKEY *pkey = ENGINE_load_private_key(srv->srvconf.tpm_engine_ref,
+ srv->srvconf.tpm_object->ptr,
+ NULL, NULL);
+ if (!pkey) {
+ log_error_write(srv, __FILE__, __LINE__, "SSS", "SSL:",
+ ERR_error_string(ERR_get_error(), NULL));
+ return NULL;
+ }
+ srv->srvconf.tpm_key = pkey;
+ return pkey;
+}
static EVP_PKEY *
evp_pkey_load_pem_file (server *srv, const char *file)
@@ -476,15 +499,23 @@ network_openssl_load_pemfile (server *srv, plugin_config *s, size_t ndx)
s->ssl_pemfile_x509 = x509_load_pem_file(srv, s->ssl_pemfile->ptr);
if (NULL == s->ssl_pemfile_x509) return -1;
- s->ssl_pemfile_pkey = evp_pkey_load_pem_file(srv, s->ssl_pemfile->ptr);
- if (NULL == s->ssl_pemfile_pkey) return -1;
-
- if (!X509_check_private_key(s->ssl_pemfile_x509, s->ssl_pemfile_pkey)) {
- log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
- "Private key does not match the certificate public key,"
- " reason:", ERR_error_string(ERR_get_error(), NULL),
- s->ssl_pemfile);
- return -1;
+
+ // if TPM mode is enabled then load the TPM key otherwise load
+ // the regular SSL private key
+ if (srv->tpm_is_init) {
+ if (NULL == (s->ssl_pemfile_pkey = evp_pkey_load_tpm_object_file(srv))) return -1;
+ }
+ else {
+ if (NULL == (s->ssl_pemfile_pkey = evp_pkey_load_pem_file(srv, s->ssl_pemfile->ptr))) return -1;
+
+ if (!X509_check_private_key(s->ssl_pemfile_x509, s->ssl_pemfile_pkey)) {
+ log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
+ "Private key does not match the certificate public key, reason:",
+ ERR_error_string(ERR_get_error(), NULL),
+ s->ssl_pemfile);
+ return -1;
+ }
+
}
return 0;
@@ -651,6 +682,43 @@ network_init_ssl (server *srv, void *p_d)
force_assert(NULL != local_send_buffer);
}
+ /* NOTE (knasim-wrs): US93721: TPM support
+ * if TPM mode is configured, and we have not previously
+ * initialized the engine then do so now
+ */
+ if (!buffer_string_is_empty(srv->srvconf.tpm_object) &&
+ (!srv->tpm_is_init)) {
+ if (!buffer_string_is_empty(srv->srvconf.tpm_engine)) {
+ // load the dynamic TPM engine
+ ENGINE_load_dynamic();
+ ENGINE *engine = ENGINE_by_id("dynamic");
+ if (!engine) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+ "Unable to load the dynamic engine "
+ "(needed for loading custom TPM engine)");
+ return -1;
+ }
+
+ ENGINE_ctrl_cmd_string(engine, "SO_PATH",
+ srv->srvconf.tpm_engine->ptr, 0);
+ ENGINE_ctrl_cmd_string(engine, "LOAD", NULL, 0);
+ if (ENGINE_init(engine) != 1) {
+ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+ ERR_error_string(ERR_get_error(), NULL));
+ ENGINE_finish(engine);
+ return -1;
+ }
+ srv->tpm_is_init = 1;
+ // stow away for ENGINE cleanup
+ srv->srvconf.tpm_engine_ref = engine;
+ }
+ else { // no TPM engine found
+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+ "TPM engine option not set when TPM mode expected");
+ return -1;
+ }
+ }
+
if (!buffer_string_is_empty(s->ssl_pemfile)) {
#ifdef OPENSSL_NO_TLSEXT
data_config *dc = (data_config *)srv->config_context->data[i];
@@ -911,29 +979,36 @@ network_init_ssl (server *srv, void *p_d)
}
}
- if (1 != SSL_CTX_use_certificate_chain_file(s->ssl_ctx,
- s->ssl_pemfile->ptr)) {
+ if (1 != SSL_CTX_use_PrivateKey(s->ssl_ctx, s->ssl_pemfile_pkey)) {
log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
ERR_error_string(ERR_get_error(), NULL),
s->ssl_pemfile);
return -1;
}
- if (1 != SSL_CTX_use_PrivateKey(s->ssl_ctx, s->ssl_pemfile_pkey)) {
+ if (1 != SSL_CTX_use_certificate(s->ssl_ctx, s->ssl_pemfile_x509)) {
log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
ERR_error_string(ERR_get_error(), NULL),
s->ssl_pemfile);
return -1;
}
- if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
- log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
- "Private key does not match the certificate public "
- "key, reason:",
- ERR_error_string(ERR_get_error(), NULL),
- s->ssl_pemfile);
- return -1;
+ /*
+ * Only check private key against loaded
+ * certificate, in non TPM mode, since
+ * if this is a TPM key then it is wrapped
+ * and will not match the public key
+ */
+ if (!srv->tpm_is_init) {
+ if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
+ log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
+ "Private key does not match the certificate public key, reason:",
+ ERR_error_string(ERR_get_error(), NULL),
+ s->ssl_pemfile);
+ return -1;
+ }
}
+
SSL_CTX_set_default_read_ahead(s->ssl_ctx, s->ssl_read_ahead);
SSL_CTX_set_mode(s->ssl_ctx, SSL_CTX_get_mode(s->ssl_ctx)
| SSL_MODE_ENABLE_PARTIAL_WRITE
diff --git a/src/server.c b/src/server.c
index f6409bb..2ace3f8 100644
--- a/src/server.c
+++ b/src/server.c
@@ -246,6 +246,11 @@ static server *server_init(void) {
CLEAN(srvconf.pid_file);
CLEAN(srvconf.syslog_facility);
+#ifdef USE_OPENSSL
+ CLEAN(srvconf.tpm_object);
+ CLEAN(srvconf.tpm_engine);
+#endif
+
CLEAN(tmp_chunk_len);
#undef CLEAN
@@ -347,6 +352,14 @@ static void server_free(server *srv) {
CLEAN(srvconf.xattr_name);
CLEAN(srvconf.syslog_facility);
+#ifdef USE_OPENSSL
+ CLEAN(srvconf.tpm_object);
+ CLEAN(srvconf.tpm_engine);
+ // don't free the tpm_key as that will be freed
+ // below as ssl_pemfile_pkey
+ ENGINE_finish(srv->srvconf.tpm_engine_ref);
+#endif
+
CLEAN(tmp_chunk_len);
#undef CLEAN
@@ -776,7 +789,9 @@ static int log_error_open(server *srv) {
if (-1 == (errfd = fdevent_open_devnull())) {
log_error_write(srv, __FILE__, __LINE__, "ss",
"opening /dev/null failed:", strerror(errno));
- return -1;
+ /* In version 1.4.45 it will also failed here but not check return value of openDevNull(STDERR_FILENO)
+ need further check with upstrean to see if there is a potential bug */
+ //return -1;
}
}
else {
--
2.7.4