Salt the result that comes from the TPM RNG with random bytes from the kernel RNG. This will allow to use tpm_get_random() as a substitute for get_random_bytes(). TPM could have a bug (making results predicatable), backdoor or even an inteposer in the bus. Salting gives protections against these concerns. Cc: David Safford <david.safford@xxxxxx> Cc: Pascal Van Leeuwen <pvanleeuwen@xxxxxxxxxxxxxx> Cc: James Bottomley <James.Bottomley@xxxxxxxxxxxxxxxxxxxxx> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@xxxxxxxxxxxxxxx> --- drivers/char/tpm/tpm-interface.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 7f105490604c..a135b1cd5a17 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -22,6 +22,7 @@ #include <linux/poll.h> #include <linux/slab.h> #include <linux/mutex.h> +#include <linux/random.h> #include <linux/spinlock.h> #include <linux/suspend.h> #include <linux/freezer.h> @@ -431,16 +432,24 @@ int tpm_pm_resume(struct device *dev) EXPORT_SYMBOL_GPL(tpm_pm_resume); /** - * tpm_get_random() - get random bytes from the TPM's RNG + * tpm_get_random() - Get random bytes from the TPM's RNG * @chip: a &struct tpm_chip instance, %NULL for the default chip * @out: destination buffer for the random bytes * @max: the max number of bytes to write to @out * - * Return: number of random bytes read or a negative error value. + * Get random bytes from the TPM's RNG and salt the result with the same amount + * of bytes from the kernel RNG. Salting allows to call this function as a + * substitute for get_random_bytes() where appropriate. + * + * Return: + * number of random bytes on success, + * -errno on error */ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) { + u8 salt[TPM_MAX_RNG_DATA]; int rc; + int i; if (!out || max > TPM_MAX_RNG_DATA) return -EINVAL; @@ -455,6 +464,14 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) rc = tpm1_get_random(chip, out, max); tpm_put_ops(chip); + + if (rc > 0) { + get_random_bytes(salt, rc); + + for (i = 0; i < rc; i++) + out[i] ^= salt[i]; + } + return rc; } EXPORT_SYMBOL_GPL(tpm_get_random); -- 2.20.1