You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Kylene Jo Hall <kj...@us.ibm.com> on 2006/04/03 18:57:24 UTC

RFC: Protecting mod_ssl key with TPM

Here is a patch that adds a feature to allow the mod_ssl key to be bound to a
platform TPM (Trusted Platform Module described in specifications by the
Trusted Computing Group).  This feature is desirable to protect the key
from being stolen by an attacker and used on another machine to spoof
the secure site.  The feature works by encrypting the mod_ssl key with 
an AES key which is then bound to a TPM and thus usable only on that 
platform.

The tpm_unseal library and tpm_sealdata command for binding the key to
the TPM can be found at www.sourceforge.net/projects/trousers in the
tpm-tools package.

What do others think of this idea?  Suggestions on the patch?

Thanks,
Kylie Hall
---
Index: modules/ssl/ssl_util_ssl.c
===================================================================
--- modules/ssl/ssl_util_ssl.c	(revision 384633)
+++ modules/ssl/ssl_util_ssl.c	(working copy)
@@ -1,6 +1,8 @@
 /* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
  * applicable.
  *
+ * TPMUNSEAL Portions Copyright (C) 2006 IBM Corporation
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -25,6 +27,9 @@
  */
 
 #include "ssl_private.h"
+#ifdef HAVE_TPMUNSEAL
+#include <tpm_tools/tpm_unseal.h>
+#endif
 
 /*  _________________________________________________________________
 **
@@ -127,35 +132,49 @@
 
 EVP_PKEY *SSL_read_PrivateKey(char* filename, EVP_PKEY **key, modssl_read_bio_cb_fn *cb, void *s)
 {
-    EVP_PKEY *rc;
-    BIO *bioS;
-    BIO *bioF;
+    EVP_PKEY *rc = NULL;
+    BIO *bioS = NULL;
+    BIO *bioF = NULL;
 
+#ifdef HAVE_TPMUNSEAL
+    unsigned char *data = NULL;
+    int data_len;
+    int tpmRc = tpmUnsealFile(filename, &data, &data_len);
+
+    if (tpmRc != 0) {
+        ap_log_error(APLOG_MARK,
+                     ((tpmRc == TPMSEAL_FILE_ERROR && tpm_errno == ENOTSSHDR)
+                      ? APLOG_DEBUG : APLOG_ERR), 0, s, "%s",
+                     tpmUnsealStrerror(tpmRc));
+    }
+    else {
+        if ((bioS = BIO_new_mem_buf(data, data_len)) == NULL)
+            return NULL;
+        BIO_set_close(bioS, BIO_NOCLOSE);
+    }
+#endif
+
+    if (bioS == NULL && (bioS = BIO_new_file(filename, "r")) == NULL)
+        return NULL;
+
     /* 1. try PEM (= DER+Base64+headers) */
-    if ((bioS=BIO_new_file(filename, "r")) == NULL)
-        return NULL;
     rc = modssl_PEM_read_bio_PrivateKey(bioS, key, cb, s);
-    BIO_free(bioS);
+    BIO_reset(bioS);
 
     if (rc == NULL) {
         /* 2. try DER+Base64 */
-        if ((bioS = BIO_new_file(filename, "r")) == NULL)
-            return NULL;
+        if ((bioF = BIO_new(BIO_f_base64())) == NULL)
+            goto out;
 
-        if ((bioF = BIO_new(BIO_f_base64())) == NULL) {
-            BIO_free(bioS);
-            return NULL;
-        }
-        bioS = BIO_push(bioF, bioS);
-        rc = d2i_PrivateKey_bio(bioS, NULL);
-        BIO_free_all(bioS);
+        BIO_push(bioF, bioS);
+        rc = d2i_PrivateKey_bio(bioF, NULL);
+        BIO_pop(bioF);
+        BIO_free(bioF);
+        BIO_reset(bioS);
 
         if (rc == NULL) {
             /* 3. try plain DER */
-            if ((bioS = BIO_new_file(filename, "r")) == NULL)
-                return NULL;
             rc = d2i_PrivateKey_bio(bioS, NULL);
-            BIO_free(bioS);
         }
     }
     if (rc != NULL && key != NULL) {
@@ -163,6 +182,13 @@
             EVP_PKEY_free(*key);
         *key = rc;
     }
+
+  out:
+#ifdef HAVE_TPMUNSEAL
+    if (data)
+        tpmUnsealShred(data, data_len);
+#endif
+    BIO_free(bioS);
     return rc;
 }
 
Index: modules/ssl/config.m4
===================================================================
--- modules/ssl/config.m4	(revision 384633)
+++ modules/ssl/config.m4	(working copy)
@@ -12,6 +12,26 @@
 dnl  See the License for the specific language governing permissions and
 dnl  limitations under the License.
 
+AC_DEFUN([CHECK_TPMUNSEAL], [
+  AC_MSG_CHECKING(for tpm-tools unseal library)
+    save_libs=$LIBS
+    LIBS="$LIBS -ltpm_unseal"
+    AC_TRY_LINK(
+      [#include <tpm_tools/tpm_unseal.h>],
+      [tpmUnsealStrerror(0);],
+      [],
+      [tmp_no_message="failed to link with tpm_unseal library"
+      ap_ssltk_ts="no"])
+    LIBS=$save_libs
+    AC_MSG_RESULT($ap_ssltk_ts)
+    if test "x$ap_ssltk_ts" = "xno"; then
+      AC_MSG_WARN(tpm_unseal support failed: $tmp_nomessage)
+    else
+      APR_ADDTO(MOD_SSL_LDADD,[-ltpm_unseal])
+      AC_DEFINE(HAVE_TPMUNSEAL, 1, [Define if tpm_unseal support is enabled])
+    fi
+])
+
 AC_DEFUN([CHECK_DISTCACHE], [
   AC_MSG_CHECKING(whether Distcache is required)
   ap_ssltk_dc="no"
@@ -117,6 +137,7 @@
     APACHE_CHECK_SSL_TOOLKIT
     APR_SETVAR(MOD_SSL_LDADD, [\$(SSL_LIBS)])
     CHECK_DISTCACHE
+    CHECK_TPMUNSEAL
     if test "x$enable_ssl" = "xshared"; then
        # The only symbol which needs to be exported is the module
        # structure, so ask libtool to hide everything else: