tpm2_tools suite has a command to generate random data -- a PRNG in TPM 2.0 chip is used:
% tpm2_getrandom --hex 32 1b8114ec9fda3fbcce3b096439af86e34f0e7a077d4e4e54ae6cf6097e49eb09
Let's see what happens inside.
Run it with strace (-xx option is for hex dumping, -s sets max. string size):
% strace -xx -s 10240 tpm2_getrandom --hex 32
Here we can see how tpm2_getrandom communicates with tpm2_abrmd daemon via read/write:
write(3, "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x7b\x00\x08", 12) = 12 read(3, "\x80\x01\x00\x00\x00\x14\x00\x00\x00\x00", 10) = 10 read(3, "\x00\x08\x6b\x13\x20\x08\x71\x4e\x13\x96", 10) = 10 ... write(3, "\x80\x01\x00\x00\x00\x16\x00\x00\x01\x7a\x00\x00\x00\x06\x00\x00\x01\x00\x00\x00\x00\x7f", 22) = 22 read(3, "\x80\x01\x00\x00\x02\x0b\x00\x00\x00\x00", 10) = 10 read(3, "\x01\x00\x00\x00\x06\x00\x00\x00\x3f\x00\x00\x01\x00\x32\x2e\x30\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x01\x02\x00\x00\x00\x74\x00\x00\x01\x03\x00\x00\x01\x09\x00\x00\x01\x04\x00\x00\x07\xe0\x00\x00\x01\x05\x49\x46\x58\x00\x00\x00\x01\x06... ... write(3, "\x80\x01\x00\x00\x00\x16\x00\x00\x01\x7a\x00\x00\x00\x06\x00\x00\x02\x14\x00\x00\x00\x40", 22) = 22 read(3, "\x80\x01\x00\x00\x00\x1b\x00\x00\x00\x00", 10) = 10 read(3, "\x00\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x02\x14\x00\x00\x00\x00", 17) = 17 ... write(3, "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x7b\x00\x20", 12) = 12 read(3, "\x80\x01\x00\x00\x00\x2c\x00\x00\x00\x00", 10) = 10 read(3, "\x00\x20\xfb\x6b\xe8\x10\xc7\xf9\xc7\xd5\x19\x2d\x61\xfa\x8b\xa0\xae\x6d\xbc\x82\x82\xd9\xd6\xee\xca\x38\x07\x2f\x36\x43\xcf\xad\xeb\xa2", 34) = 34
Take a closer look, and note \x01\x7b, that is command number 0x17B:
write(3, "\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x7b\x00\x08", 12) = 12
By grepping 0x17B in various TPM-related source code, I can quickly find that this is for TPM2_CC_GetRandom command.
There are also call of 0x17A command, which is for TPM2_CC_GetCapability.
I don't know why tpm2_getrandom calls TPM2_CC_GetRandom twice (first time it asks for 8-byte random buffer, second time for 32-byte buffer, like we asked).
But I can replay this command using my own script:
#!/usr/bin/python
import os, hexdump
#dev=os.open("/dev/tpm0", os.O_RDWR)
dev=os.open("/dev/tpmrm0", os.O_RDWR)
os.write(dev,b"\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x7b\x00\x20")
buf=os.read(dev,10)
hexdump.hexdump(buf)
buf=os.read(dev,34)
hexdump.hexdump(buf)
(We can easily deduce that the last byte (or 16-bit word?) is requested number of random bytes.)
Also, it's supposed that access rights you have are like:
% ls -la /dev/tpm* crw-rw---- 1 tss root 10, 224 Oct 1 12:21 /dev/tpm0 crw-rw---- 1 tss tss 253, 65536 Oct 1 12:21 /dev/tpmrm0
To access the /dev/tpmrm0 device, add your current user to the 'tss' group:
sudo usermod -aG tss $USER
Run my Python script:
% python3 rnd.py 00000000: 80 01 00 00 00 2C 00 00 00 00 .....,.... 00000000: 00 20 6E 53 CD 8E 81 77 2D AC 8F FC 8C FA 4B 23 . nS...w-.....K# 00000010: D9 A9 B2 77 85 12 99 37 98 73 A9 BC B1 8E D6 50 ...w...7.s.....P 00000020: 9F 45 .E
The answer is: 16-bit size of buffer (big-endian) and 32 random bytes, each time different.
The /dev/tpm0 device can be used as well.
What is inside Linux kernel device driver? It's almost nothing -- only i2c driver that sends our commands via i2c bus to TPM 2.0 chip (if it's discrete).
A TPM 2.0 chip can be connected via i2c bus to Raspberry Pi easily, as well as to USB via USB-i2c 'adapter'.
