[PATCH] Re: [PATCH] drivers/net: remove network drivers' last fewuses of IRQF_SAMPLE_RANDOM

From: Jeff Garzik
Date: Thu May 15 2008 - 15:57:55 EST


Jeff Garzik wrote:
Someone (hi Jesse?) should implement support for TPM_GetRandom.

Here's an example patch (compile-tested only) to get people started.

This function calls the TPM command, and returns TPM header + RNG data in the supplied buffer.

A hw_random driver for TPM still needs to (a) parse the TPM header for return code, (b) extract RNG bytes out at offset 14, and (c) figure out some way to get a tpm_chip pointer.

Spec at https://www.trustedcomputinggroup.org/specs/TPM/TCPA_Main_TCG_Architecture_v1_1b.pdf describes TPM_GetRandom on page 215.

Jeff


diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index a5d8bcb..4c3963b 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -579,6 +579,31 @@ void tpm_continue_selftest(struct tpm_chip *chip)
}
EXPORT_SYMBOL_GPL(tpm_continue_selftest);

+int tpm_getrandom(struct tpm_chip *chip, void *buf, size_t buflen)
+{
+ u8 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 */
+ };
+ size_t tmp;
+
+ if (buflen <= sizeof(rng_cmd))
+ return -ENOSPC;
+
+ /* patch in requested/returned byte count. TODO: more than 8-bit */
+ tmp = buflen - sizeof(rng_cmd);
+ if (tmp > 255)
+ tmp = 255;
+ rng_cmd[13] = tmp;
+
+ memcpy(buf, rng_cmd, sizeof(rng_cmd));
+
+ return tpm_transmit(chip, buf, buflen);
+}
+EXPORT_SYMBOL_GPL(tpm_getrandom);
+
ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
char *buf)
{
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index e885148..bbab3c8 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -127,6 +127,7 @@ static inline void tpm_write_index(int base, int index, int value)
extern void tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *);
extern void tpm_continue_selftest(struct tpm_chip *);
+extern int tpm_getrandom(struct tpm_chip *, void *, size_t);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern struct tpm_chip* tpm_register_hardware(struct device *,
const struct tpm_vendor_specific *);