Patch taken from http://sourceforge.net/tracker/?func=detail&aid=2261574&group_id=3242&atid=353242 diff -uNr rng-tools-2-orig/rngd.c rng-tools-2/rngd.c --- rng-tools-2-orig/rngd.c 2004-08-24 23:30:00.000000000 +0530 +++ rng-tools-2/rngd.c 2008-11-11 15:39:31.000000000 +0530 @@ -91,6 +91,8 @@ { "timeout", 't', "nnn", 0, "Interval written to random-device when the entropy pool is full, in seconds (default: 60)" }, + { "no-tpm", 'n', "1|0", 0, + "do not use tpm as a source of random number input (default: 0)" }, { 0 }, }; @@ -102,6 +104,7 @@ .random_step = 64, .fill_watermark = 2048, .daemon = 1, + .no_tpm =0, }; struct arguments *arguments = &default_arguments; @@ -147,6 +150,15 @@ arguments->fill_watermark = n; break; } + case 'n': { + int n; + if ((sscanf(arg,"%i", &n) == 0) || ((n | 1)!=1)) + argp_usage(state); + else + arguments->no_tpm=0; + break; + + } default: return ARGP_ERR_UNKNOWN; @@ -162,26 +174,41 @@ double poll_timeout) { unsigned char buf[FIPS_RNG_BUFFER_SIZE]; - unsigned char *p; - int fips; + int fips,retval; for (;;) { - xread(buf, sizeof buf); + if (arguments->no_tpm == 0) { + retval=xread_tpm(buf, sizeof buf); + if (retval < 0) + sleep(1); + else + update_kernel_random(random_step, + poll_timeout, buf, &tpm_fipsctx); + } + retval=xread(buf, sizeof buf); + if (retval > 0) + update_kernel_random(random_step, + poll_timeout, buf, &fipsctx); + } +} - fips = fips_run_rng_test(&fipsctx, buf); +int update_kernel_random(int random_step, double poll_timeout, + unsigned char *buf, fips_ctx_t *fipsctx) { - if (fips) { - message(LOG_DAEMON|LOG_ERR, "failed fips test\n"); - sleep(1); - continue; - } + int fips; + unsigned char *p; + fips = fips_run_rng_test(fipsctx, buf); + if (fips) { + message(LOG_DAEMON|LOG_ERR, "failed fips test\n"); + return 1; + } - for (p = buf; p + random_step <= &buf[sizeof buf]; - p += random_step) { - random_add_entropy(p, random_step); - random_sleep(poll_timeout); - } + for (p = buf; p + random_step <= &buf[FIPS_RNG_BUFFER_SIZE]; + p += random_step) { + random_add_entropy(p, random_step); + random_sleep(poll_timeout); } + return 0; } diff -uNr rng-tools-2-orig/rngd_entsource.c rng-tools-2/rngd_entsource.c --- rng-tools-2-orig/rngd_entsource.c 2004-04-15 10:36:17.000000000 +0530 +++ rng-tools-2/rngd_entsource.c 2008-11-11 15:39:31.000000000 +0530 @@ -35,6 +35,7 @@ #include #include #include +#include #include "rngd.h" #include "fips.h" @@ -42,17 +43,27 @@ #include "rngd_entsource.h" -/* Logic and contexts */ -static int rng_fd; /* rng data source */ -fips_ctx_t fipsctx; /* Context for the FIPS tests */ +/* The overhead incured when tpm returns the random nos as per TCG spec + * it is 14 bytes.*/ +#define TPM_GET_RNG_OVERHEAD 14 +static const char *rng_device="/dev/tpm0"; +/* Logic and contexts */ +static int rng_fd; /* rng data source */ +fips_ctx_t fipsctx; /* Context for the FIPS tests */ +fips_ctx_t tpm_fipsctx; /* Context for the tpm FIPS tests */ /* Read data from the entropy source */ -void xread(void *buf, size_t size) +int xread(void *buf, size_t size) { size_t off = 0; ssize_t r; + /* Do nothing if we have no hw rng, maybe we have tpm */ + if (rng_fd < 0) { + message(LOG_DAEMON|LOG_ERR, "Invalid file handle\n"); + return -1; + } while (size > 0) { do { r = read(rng_fd, buf + off, size); @@ -65,8 +76,85 @@ if (size) { message(LOG_DAEMON|LOG_ERR, "read error\n"); - exit(1); + return -1; + } + return 0; +} + +alarm_handler(int i) { + ; +} +/* tpm rng read call to kernel has 13 bytes of overhead + * the logic to process this involves reading to a temporary_buf + * and copying the no generated to buf*/ +int xread_tpm(void *buf, size_t size) +{ + size_t bytes_read = 0; + ssize_t r; + int retval,rngtpm_fd; + unsigned char *temp_buf=NULL; + unsigned char rng_cmd[] = { + 0, 193, /* TPM_TAG_RQU_COMMAND */ + 0, 0, 0, 14, /* length */ + 0, 0, 0, 70, /* TPM_ORD_GetRandom */ + 0, 0, 0, 0, /* number of bytes to return */ + }; + char *offset; + + rngtpm_fd=open(rng_device, O_RDWR); + if (rngtpm_fd < 0) { + message(LOG_ERR|LOG_INFO, + "Unable to open %s: %s\n",rng_device,strerror(errno)); + return -1; + } + + temp_buf= (unsigned char *) malloc(size + TPM_GET_RNG_OVERHEAD); + memset(temp_buf,0,(size+TPM_GET_RNG_OVERHEAD)); + if (temp_buf == NULL) { + message(LOG_ERR|LOG_INFO,"No memory"); + return -1; + } + /* 32 bits has been reserved for random byte size */ + rng_cmd[13]=(unsigned char)(size & 0xFF); + rng_cmd[12]=(unsigned char)((size >> 8) & 0xFF); + rng_cmd[11]=(unsigned char)((size >> 16) & 0xFF); + rng_cmd[10]=(unsigned char)((size >> 24) & 0xFF); + offset=buf; + while (bytes_read < size) { + r=0; + while (r < sizeof(rng_cmd)) { + retval=write(rngtpm_fd,rng_cmd + r,sizeof(rng_cmd)-r); + if (retval < 0) { + message(LOG_ERR|LOG_INFO, + "Error writing %s\n",rng_device); + retval=-1; + goto error_out; + } + r+=retval; + } + if (r < sizeof(rng_cmd)) { + message(LOG_ERR|LOG_INFO, + "Error writing %s\n",rng_device); + retval=-1; + goto error_out; + } + r=read(rngtpm_fd,temp_buf,size); + r=(r - TPM_GET_RNG_OVERHEAD); + bytes_read=bytes_read + r; + if (bytes_read > size) { + memcpy(offset,temp_buf + TPM_GET_RNG_OVERHEAD, + r - (bytes_read - size)); + break; + } + memcpy(offset, temp_buf + TPM_GET_RNG_OVERHEAD, + r); + offset=offset+r; } + retval=0; +error_out: + free(temp_buf); + close(rngtpm_fd); + return retval; } /* Initialize entropy source */ @@ -93,14 +181,31 @@ */ void init_entropy_source(const char* sourcedev) { + /* We cannot keep the tpm device open always. + * We need to open get random data and close + * to allow tpm-tools and other utilities + * access to /dev/tpm */ + int tpm_fd; rng_fd = open(sourcedev, O_RDONLY); if (rng_fd == -1) { message(LOG_DAEMON|LOG_ERR, "can't open %s: %s", sourcedev, strerror(errno)); - exit(EXIT_FAIL); + /* Try to open tpm this is just a test, no point in proceeding further + * if no source of entropy is present + */ + tpm_fd = open(rng_device, O_RDONLY); + if (tpm_fd < 0 ) { + message(LOG_DAEMON|LOG_ERR, + "can't open entropy source(tpm or intel/amd rng) %s", + strerror(errno)); + message(LOG_DAEMON|LOG_ERR,"Maybe RNG device modules are not loaded\n"); + exit(1); + } + close(tpm_fd); } /* Bootstrap FIPS tests */ fips_init(&fipsctx, discard_initial_data()); + fips_init(&tpm_fipsctx, 0); } diff -uNr rng-tools-2-orig/rngd_entsource.h rng-tools-2/rngd_entsource.h --- rng-tools-2-orig/rngd_entsource.h 2004-04-15 10:34:45.000000000 +0530 +++ rng-tools-2/rngd_entsource.h 2008-11-11 15:39:31.000000000 +0530 @@ -28,7 +28,7 @@ /* Logic and contexts */ extern fips_ctx_t fipsctx; /* Context for the FIPS tests */ - +extern fips_ctx_t tpm_fipsctx; /* Context for the tpm FIPS tests */ /* * Initialize entropy source and entropy conditioning * @@ -37,6 +37,6 @@ extern void init_entropy_source(const char* sourcedev); /* Read data from the entropy source */ -void xread(void *buf, size_t size); +int xread(void *buf, size_t size); #endif /* RNGD_ENTSOURCE__H */ diff -uNr rng-tools-2-orig/rngd.h rng-tools-2/rngd.h --- rng-tools-2-orig/rngd.h 2004-08-24 23:23:04.000000000 +0530 +++ rng-tools-2/rngd.h 2008-11-11 15:39:31.000000000 +0530 @@ -42,6 +42,7 @@ double poll_timeout; int daemon; + int no_tpm; }; extern struct arguments *arguments;