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 */