Hi,
Here is an updated patch that pauses for 5 seconds waiting to connect to
trousers, in the case that trousers is starting up at the same time as
rngd.
Thanks,
-Kees
--
Kees Cook @debian.org
--- rng-tools-2-unofficial-mt.12.orig/rngd_entsource.h
+++ rng-tools-2-unofficial-mt.12/rngd_entsource.h
@@ -31,7 +31,8 @@
typedef enum {
RNGD_ENTSOURCE_NONE,
RNGD_ENTSOURCE_UNIXSTREAM,
- RNGD_ENTSOURCE_VIAPADLOCK
+ RNGD_ENTSOURCE_VIAPADLOCK,
+ RNGD_ENTSOURCE_TPM,
} entropy_source_driver_t;
extern const char *entropy_source_driver_name(entropy_source_driver_t driver);
--- rng-tools-2-unofficial-mt.12.orig/Makefile.am
+++ rng-tools-2-unofficial-mt.12/Makefile.am
@@ -9,13 +9,14 @@
man_MANS = rngd.8 rngtest.1
noinst_LIBRARIES = librngd.a
-common_sources = exits.h fips.h stats.h util.h viapadlock_engine.h
+common_sources = exits.h fips.h stats.h util.h viapadlock_engine.h \
+ tpm_engine.h
rngd_SOURCES = $(common_sources) rngd.h rngd.c \
rngd_threads.h rngd_threads.c \
rngd_signals.h rngd_signals.c \
rngd_entsource.h rngd_entsource.c \
rngd_linux.h rngd_linux.c
-rngd_LDADD = librngd.a @LIB_PTHREAD@
+rngd_LDADD = librngd.a @LIB_PTHREAD@ @LIB_TSPI@
rngtest_SOURCES = $(common_sources) rngtest.c
rngtest_LDADD = librngd.a
@@ -23,6 +24,7 @@
librngd_a_SOURCES = fips.h fips.c \
stats.h stats.c \
util.h util.c \
+ tpm_engine.h tpm_engine.c \
viapadlock_engine.h viapadlock_engine.c
--- rng-tools-2-unofficial-mt.12.orig/tpm_engine.h
+++ rng-tools-2-unofficial-mt.12/tpm_engine.h
@@ -0,0 +1,53 @@
+/*
+ * tpm_engine.h -- TPM RNG interface
+ *
+ * Copyright (C) 2009, 2010 Kees Cook <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TPM_RNG__H
+#define TPM_RNG__H
+
+#define _GNU_SOURCE
+#include "rng-tools-config.h"
+
+#ifdef TPM_ENTSOURCE_DRIVER
+
+/*
+ * Initialize TPM RNG
+ *
+ * Returns:
+ * 0 if no functional TPM RNG was detected
+ * 1 if a functional TPM RNG set was detected
+ * -1 if an error happened (errno will be set)
+ */
+extern int tpm_rng_init(void);
+
+/*
+ * Free up resources used by the TPM RNG
+ */
+extern void tpm_rng_free(void);
+
+/*
+ * Read data from TPM RNG
+ *
+ * Returns the number of bytes read if no errors happen
+ * -1 if an error happened, with errno set.
+ */
+extern ssize_t tpm_rng_read(void* buf, size_t size);
+
+#endif /* TPM_ENTSOURCE_DRIVER */
+#endif /* TPM_RNG__H */
--- rng-tools-2-unofficial-mt.12.orig/tpm_engine.c
+++ rng-tools-2-unofficial-mt.12/tpm_engine.c
@@ -0,0 +1,131 @@
+/*
+ * tpm_engine.c -- TPM RNG interface
+ *
+ * Copyright (C) 2009 Kees Cook <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _GNU_SOURCE
+
+#include "rng-tools-config.h"
+#ifdef TPM_ENTSOURCE_DRIVER
+
+#include <errno.h>
+#include <string.h>
+#include <trousers/tss.h>
+#include <trousers/trousers.h>
+
+#include "tpm_engine.h"
+
+static TSS_HCONTEXT hContext;
+static TSS_HTPM hTPM;
+static int tpm_rng_ready;
+
+int tpm_rng_init_attempt(void)
+{
+ TSS_RESULT rc;
+
+ if (tpm_rng_ready) return 1;
+
+ if ((rc=Tspi_Context_Create(&hContext)) != TSS_SUCCESS) {
+ //fprintf(stderr,"Tspi_Context_Create: %s\n", Trspi_Error_String(rc));
+ return 0;
+ }
+
+ if ((rc=Tspi_Context_Connect(hContext, NULL)) != TSS_SUCCESS) {
+ //fprintf(stderr,"Tspi_Context_Connect: %s\n", Trspi_Error_String(rc));
+ Tspi_Context_Close(hContext);
+ return 0;
+ }
+
+ if ((rc=Tspi_Context_GetTpmObject(hContext, &hTPM)) != TSS_SUCCESS) {
+ //fprintf(stderr,"Tspi_Context_GetTpmObject: %s\n", Trspi_Error_String(rc));
+ Tspi_Context_Close(hContext);
+ return 0;
+ }
+
+ tpm_rng_ready = 1;
+
+ return tpm_rng_ready;
+}
+
+/*
+ * Initialize TPM RNG
+ *
+ * Returns:
+ * 0 if no working TPM RNG was detected
+ * 1 if a TPM RNG has been detected
+ * -1 if an error happened (errno will be set)
+ */
+int tpm_rng_init(void)
+{
+ int count, rc = 0;
+
+ /* wait 5 seconds for TPM to become available */
+ for (count = 0; count < 5; count++) {
+ if ( (rc = tpm_rng_init_attempt()) ) break;
+ sleep(1);
+ }
+
+ return rc;
+}
+
+/*
+ * Free up any resources used by the TPM RNG.
+ * It is legal to call tpm_rng_init() after this.
+ */
+void tpm_rng_free(void)
+{
+ if (tpm_rng_ready) {
+ Tspi_Context_Close(hContext);
+ tpm_rng_ready = 0;
+ }
+}
+
+/*
+ * Read data from a TPM RNG
+ *
+ * Returns the number of bytes read if no errors happen
+ * -1 if an error happened, with errno set.
+ */
+ssize_t tpm_rng_read(void* buf, size_t size)
+{
+ TSS_RESULT rc;
+ BYTE *bytes;
+
+ if (!tpm_rng_ready) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ if (!buf) {
+ errno = EOVERFLOW;
+ return -1;
+ }
+
+ if (size > 32) size = 32;
+ if ((rc=Tspi_TPM_GetRandom(hTPM, size, &bytes)) != TSS_SUCCESS) {
+ //fprintf(stderr,"Tspi_TPM_GetRandom: %s\n", Trspi_Error_String(rc));
+ errno = EIO;
+ return -1;
+ }
+ memcpy(buf, bytes, size);
+ Tspi_Context_FreeMemory(hContext, bytes);
+
+ return size;
+}
+
+#endif /* TPM_ENTSOURCE_DRIVER */
--- rng-tools-2-unofficial-mt.12.orig/configure.ac
+++ rng-tools-2-unofficial-mt.12/configure.ac
@@ -45,12 +45,17 @@
dnl -----------------------------
AC_CHECK_LIB([pthread], [pthread_create],
[LIB_PTHREAD="-lpthread"],
- [AC_MSG_ERROR([Can't compile without pthreads])])
+ [AC_MSG_ERROR([Can not compile without pthreads])])
AC_SUBST(LIB_PTHREAD)
dnl -------------------------------------
dnl Checks for optional library functions
dnl -------------------------------------
+AC_CHECK_LIB([tspi], [Tspi_Context_Create],
+ [LIB_TSPI="-ltspi"
+ AC_DEFINE(TPM_ENTSOURCE_DRIVER, 1,
+ [Include code for TPM RNG driver]) ], )
+AC_SUBST(LIB_TSPI)
dnl -----------------
dnl Configure options
--- rng-tools-2-unofficial-mt.12.orig/rng-tools-config.h.in
+++ rng-tools-2-unofficial-mt.12/rng-tools-config.h.in
@@ -21,6 +21,9 @@
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
/* Define to the version of this package. */
#undef PACKAGE_VERSION
@@ -30,6 +33,9 @@
/* Syslog facility to use. */
#undef SYSLOG_FACILITY
+/* Include code for TPM RNG driver */
+#undef TPM_ENTSOURCE_DRIVER
+
/* Version number of package */
#undef VERSION
--- rng-tools-2-unofficial-mt.12.orig/rngd.c
+++ rng-tools-2-unofficial-mt.12/rngd.c
@@ -265,6 +265,13 @@
.entropy = 0.0,
.driver = RNGD_ENTSOURCE_VIAPADLOCK,
},
+ { .name = "TPM RNG",
+ .tag = "tpm",
+ .width = 256,
+ .buffers = 1,
+ .entropy = 0.75,
+ .driver = RNGD_ENTSOURCE_TPM,
+ },
{ NULL },
};
@@ -391,6 +398,9 @@
if (! (seen_opt & SEEN_OPT_RNGENTROPY))
arguments->rng_entropy = 0.0;
seen_opt |= SEEN_OPT_RNGDRIVER;
+ } else if (strcasecmp(arg, "tpm") == 0) {
+ arguments->rng_driver = RNGD_ENTSOURCE_TPM;
+ seen_opt |= SEEN_OPT_RNGDRIVER;
} else {
argp_usage(state);
}
--- rng-tools-2-unofficial-mt.12.orig/rngd_entsource.c
+++ rng-tools-2-unofficial-mt.12/rngd_entsource.c
@@ -49,6 +49,7 @@
#include "stats.h"
#include "exits.h"
#include "viapadlock_engine.h"
+#include "tpm_engine.h"
#include "rngd_threads.h"
#include "rngd_signals.h"
#include "rngd_entsource.h"
@@ -87,6 +88,8 @@
return "UNIX stream";
case RNGD_ENTSOURCE_VIAPADLOCK:
return "VIA PadLock TRNG";
+ case RNGD_ENTSOURCE_TPM:
+ return "TPM RNG";
default:
return "(unknown)";
};
@@ -130,6 +133,12 @@
break;
}
#endif
+#ifdef TPM_ENTSOURCE_DRIVER
+ case RNGD_ENTSOURCE_TPM: {
+ r = tpm_rng_read((unsigned char *)buf + off, size);
+ break;
+ }
+#endif
default:
errno = ENXIO;
return -1;
@@ -231,6 +240,31 @@
die(EXIT_USAGE);
#endif /* VIA_ENTSOURCE_DRIVER */
}
+ case RNGD_ENTSOURCE_TPM: {
+#ifdef TPM_ENTSOURCE_DRIVER
+ switch (tpm_rng_init()) {
+ case 0:
+ message(LOG_ERR,
+ "Could not detect a TPM "
+ "RNG, check that TPM is "
+ "available and enabled.");
+ die(EXIT_OSERR);
+ case 1:
+ break;
+ default:
+ message_strerr(LOG_ERR, errno,
+ "Error initializing TPM "
+ "RNG");
+ die(EXIT_OSERR);
+ }
+ break;
+#else
+ message(LOG_ERR,
+ "Support for the TPM RNG entropy source "
+ "driver has not been compiled in.");
+ die(EXIT_USAGE);
+#endif /* TPM_ENTSOURCE_DRIVER */
+ }
default:
message(LOG_ERR,
"Unknown entropy source driver, internal program error!");