I've rewritten my TPM RNG reader into a form that is useful to rng-tools.
Please see attached patch...

The entropy is not really known, so I took the default stream entropy
value.

This needs 'autoreconf' run to update the build files...

-Kees

-- 
Kees Cook                                            @debian.org
diff -u rng-tools-2-unofficial-mt.12/configure.ac rng-tools-2-unofficial-mt.12/configure.ac
--- rng-tools-2-unofficial-mt.12/configure.ac
+++ rng-tools-2-unofficial-mt.12/configure.ac
@@ -45,6 +45,11 @@
 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
diff -u rng-tools-2-unofficial-mt.12/debian/changelog rng-tools-2-unofficial-mt.12/debian/changelog
--- rng-tools-2-unofficial-mt.12/debian/changelog
+++ rng-tools-2-unofficial-mt.12/debian/changelog
@@ -1,2 +1,10 @@
+rng-tools (2-unofficial-mt.12-2~) unstable; urgency=low
+
+  * Implement TPM RNG engine:
+    - tpm_engine.{c,h}: add TPM RNG.
+    - rngd_entsource.{c,h}, rngd.c, Makefile.am, configure.ac: hook up.
+
+ -- Kees Cook <k...@debian.org>  Fri, 23 Oct 2009 13:57:12 -0700
+
 rng-tools (2-unofficial-mt.12-1) unstable; urgency=low
 
diff -u rng-tools-2-unofficial-mt.12/debian/control rng-tools-2-unofficial-mt.12/debian/control
--- rng-tools-2-unofficial-mt.12/debian/control
+++ rng-tools-2-unofficial-mt.12/debian/control
@@ -3,6 +3,6 @@
 Priority: optional
 Maintainer: Henrique de Moraes Holschuh <h...@debian.org>
-Build-Depends: debhelper (>> 7), autotools-dev
+Build-Depends: debhelper (>> 7), autotools-dev, libtspi-dev
 Standards-Version: 3.8.0.0
 
 Package: rng-tools
only in patch2:
unchanged:
--- rng-tools-2-unofficial-mt.12.orig/tpm_engine.c
+++ rng-tools-2-unofficial-mt.12/tpm_engine.c
@@ -0,0 +1,116 @@
+/*
+ * tpm_engine.c -- TPM RNG interface
+ *
+ * Copyright (C) 2009 Kees Cook <k...@outflux.net>
+ *
+ * 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;
+
+/*
+ * 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)
+{
+    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));
+        return 0;
+    }
+
+    if ((rc=Tspi_Context_GetTpmObject(hContext, &hTPM)) != TSS_SUCCESS) {
+        //fprintf(stderr,"Tspi_Context_GetTpmObject: %s\n", Trspi_Error_String(rc));
+        return 0;
+    }
+
+    tpm_rng_ready = 1;
+
+	return tpm_rng_ready;
+}
+
+/*
+ * 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 */
only in patch2:
unchanged:
--- 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!");
only in patch2:
unchanged:
--- 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);
 		}
only in patch2:
unchanged:
--- 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
 
 
only in patch2:
unchanged:
--- 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/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 Kees Cook <k...@outflux.net>
+ *
+ * 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 */

Reply via email to