* Calculating HMAC-SHA1 on TPM 2.0 Previously: https://yurichev.com/blog/TOTP1/ https://yurichev.com/blog/TOTP2/ https://yurichev.com/blog/TPM1/ ** First, generate (semi-)random HMAC key We use a string of 0x11....0x11 as an HMAC key. This is on purpose, so that it will be visible in strace logs: echo "1111111111111111111111111111111111111111" | xxd -p -r > hmac.key ** First example *** Creating context with HMAC key Run: strace -xx -s 8192 tpm2 loadexternal -C n -G hmac:sha1 -a "sign|userwithauth" -r hmac.key -c hmac.ctx I run the tpm2 executable with strace, so to see what's going on. I'm interesting, how tpm2 open files and communicates with TPM chip via tpm2-abrmd daemon. I added my comments here: #+BEGIN_CODE Read HMAC key from the file: read(8, "\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11", 20) = 20 Send HMAC key to TPM. The HMAC key (0x11...0x11) is visible in the buffer. The command is 0x167 (big-endian 16-bit word in 8th and 9th byte) --- TPM_CC_LoadExternal. Where did I find the command name? There are many places in TPM-related source code, to be grepped. I found a command list in ibmswtpm2-tpm2/src/TpmTypes.h file. ( The repo is: https://sourceforge.net/projects/ibmswtpm2/ ) sendto(7, "\x80\x01\x00\x00\x00\x7e\x00\x00\x01\x67\x00\x3c\x00\x08\x00\x00\x00\x20\xce\xbc\x87\x55\xe6\x94\x51\xf4\xef\x5d\xd4\x1c\xda\x95\x94\xab\x34\x0e\x6b\xa1\x34\x5b\x0d\x6a\x8a\x2a\xec\xef\x7c\x48\x39\xad\x00\x14\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x00\x30\x00\x08\x00\x0b\x00\x04\x00\x40\x00\x00\x00\x05\x00\x04\x00\x20\xd5\x04\x03\xc2\x28\x18\xac\xaf\xb3\x5e\x15\x73\xb0\xc9\xe1\x9b\xd7\x68\x24\x86\xf7\x32\x2a\x81\xcc\xda\x5b\xd9\x01\xfd\x90\x84\x40\x00\x00\x07", 126, MSG_NOSIGNAL, NULL, 0) = 126 recvfrom(7, "\x80\x01\x00\x00\x00\x32\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 recvfrom(7, "\x80\x00\x00\xff\x00\x22\x00\x0b\xcd\xdb\x68\xf7\x3c\x2b\x8f\xe0\x5e\xcc\xfb\x66\x8b\x7c\x4c\xd3\x0f\x8f\xd4\x58\xdd\x3f\xdb\xc8\xd8\x0f\x39\x45\x2f\x5b\x03\xeb", 40, 0, NULL, NULL) = 40 Send the 0x162 - TPM_CC_ContextSave command: sendto(7, "\x80\x01\x00\x00\x00\x0e\x00\x00\x01\x62\x80\x00\x00\xff", 14, MSG_NOSIGNAL, NULL, 0) = 14 recvfrom(7, "\x80\x01\x00\x00\x06\xd6\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 Read encrypted blob: recvfrom(7, "\x00\x00\x00\x00\x00\x00\x00\x02\x80\x00\x00\x00\x40\x00\x00\x07<... 1724 bytes ...>", 1740, 0, NULL, NULL) = 1740 Save that blob to hmac.ctx file: write(8, "\xba\xdc\xc0\xde\x00\x00\x00\x01\x40\x00\x00\x07\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x07\x20\x00\x00\x00\x00<... 1724 bytes ...>\x00\x00\x80\x00\x00\xff\x00\x22\x00\x0b\xcd\xdb\x68\xf7\x3c\x2b\x8f\xe0\x5e\xcc\xfb\x66\x8b\x7c\x4c\xd3\x0f\x8f\xd4\x58\xdd\x3f\xdb\xc8\xd8\x0f\x39\x45\x2f\x5b\x03\xeb\x00\x00\x00\x01\x00\x30\x00\x08\x00\x0b\x00\x04\x00\x40\x00\x00\x00\x05\x00\x04\x00\x20\xd5\x04\x03\xc2\x28\x18\xac\xaf\xb3\x5e\x15\x73\xb0\xc9\xe1\x9b\xd7\x68\x24\x86\xf7\x32\x2a\x81\xcc\xda\x5b\xd9\x01\xfd\x90\x84", 1850) = 1850 #+END_CODE I wrote an util that finds a longest common subsequence ( https://en.wikipedia.org/wiki/Longest_common_subsequence ) in two strings and replaces it with the "<... 1724 bytes ...>" string. There is a high-entropy blob of 1724 bytes. This is a current context, encrypted with TPM's internal key (which is unique). It can be decrypted only on the same TPM. Theoretically (modulo bugs/vulns) ( https://www.catb.org/jargon/html/M/modulo.html ) it cannot be decrypted without your TPM. And now it contains our HMAC key. Blob size may be different on other TPM chips. On ASUS PRIME H610M-K D4 motherboard and 12th Gen Intel(R) Core(TM) i5-12400F it has size of 1724 bytes. On Thinkcentre m920x and Intel(R) Core(TM) i5-8500 CPU @ 3.00GHz, it has size of 676 bytes. On swtpm simulator it has size of 356 bytes, No, HMAC key is not stored in your TPM chip. That means, you can use infinitely many HMAC keys with a TPM chip. One can say, TPM *wraps* a (HMAC) key so that it can be *unwrapped* only by the same TPM. Something from hmac.ctx can be printed tpm2_print, but there is not much info: #+BEGIN_TEXT % tpm2_print -t TPMS_CONTEXT hmac.ctx version: 1 hierarchy: null handle: 0x80000000 (2147483648) sequence: 2 contextBlob: size: 1824 #+END_TEXT Now the hmac.key file can be deleted. *** Calculating HMAC for some plain text We use a string of zeroes as plain text, again, to see it in logs. "000000000000" % xxd -g 1 plain.txt 00000000: 30 30 30 30 30 30 30 30 30 30 30 30 0a 000000000000. Run: strace -xx -s 8192 tpm2 hmac -g sha1 -c hmac.ctx -o hmac-result.bin plain.txt #+BEGIN_CODE Send the 0x176 - TPM_CC_StartAuthSession command: sendto(8, "\x80\x01\x00\x00\x00\x3b\x00\x00\x01\x76\x40\x00\x00\x07\x40\x00\x00\x07\x00\x20\x5a\x4b\x57\x41\x26\x44\xb9\x9c\x0c\xba\x13\x33\x46\x17\x36\xd6\xd9\x45\xe0\xa1\x17\xba\xe4\xd1\xc2\x7d\x0d\xd8\x47\x7a\xfc\x7d\x00\x00\x00\x00\x10\x00\x0b", 59, MSG_NOSIGNAL, NULL, 0) = 59 recvfrom(8, "\x80\x01\x00\x00\x00\x30\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 recvfrom(8, "\x02\x00\x00\x00\x00\x20\xcc\x1a\x68\x0c\x89\x08\x4b\xb7\x4b\x26\xcc\x78\xdd\x12\xac\x1c\x84\xae\x9a\x1f\x08\xab\xd8\x0a\x1f\xde\xec\x54\xfc\x85\x25\x31", 38, 0, NULL, NULL) = 38 Read the hmac.ctx file: read(10, "\xba\xdc\xc0\xde\x00\x00\x00\x01\x40\x00\x00\x07\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x07\x20\x00\x00\x00\x00<... 1724 bytes ...>\x00\x00\x80\x00\x00\xff\x00\x22\x00\x0b\xcd\xdb\x68\xf7\x3c\x2b\x8f\xe0\x5e\xcc\xfb\x66\x8b\x7c\x4c\xd3\x0f\x8f\xd4\x58\xdd\x3f\xdb\xc8\xd8\x0f\x39\x45\x2f\x5b\x03\xeb\x00\x00\x00\x01\x00\x30\x00\x08\x00\x0b\x00\x04\x00\x40\x00\x00\x00\x05\x00\x04\x00\x20\xd5\x04\x03\xc2\x28\x18\xac\xaf\xb3\x5e\x15\x73\xb0\xc9\xe1\x9b\xd7\x68\x24\x86\xf7\x32\x2a\x81\xcc\xda\x5b\xd9\x01\xfd\x90\x84", 4096) = 1850 Send the 0x161 - TPM_CC_ContextLoad command with encrypted blob, from hmac.ctx: sendto(8, "\x80\x01\x00\x00\x06\xd6\x00\x00\x01\x61\x00\x00\x00\x00\x00\x00\x00\x02\x80\x00\x00\x00\x40\x00\x00\x07<... 1724 bytes ...>", 1750, MSG_NOSIGNAL, NULL, 0) = 1750 recvfrom(8, "\x80\x01\x00\x00\x00\x0e\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 recvfrom(8, "\x80\x00\x00\xff", 4, 0, NULL, NULL) = 4 Read plain text from a file: read(3, "\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a", 13) = 13 Send the 0x155 --- TPM_CC_MAC command with the string of zeroes visible at the end (0x30...0x30): sendto(8, "\x80\x02\x00\x00\x00\x6c\x00\x00\x01\x55\x80\x00\x00\xff\x00\x00\x00\x49\x02\x00\x00\x00\x00\x20\xc2\x98\x7a\x4a\x3c\x28\x05\x55\xfa\x9a\xbf\xa7\xf9\x60\x0a\x6d\x04\x1e\x1e\x09\xc5\xc4\x37\xf4\x7b\xb1\x30\x9f\x47\xf6\xa3\x98\x01\x00\x20\x4c\xbe\xba\xaf\x7d\x64\xe6\x53\xb9\xcb\xc9\xaa\x23\xab\xb3\x3f\x14\xf3\x3c\xdf\xd7\xa8\xcd\x1b\xe7\x60\x0f\xb6\xed\xf8\x8b\xdc\x00\x0d\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a\x00\x04", 108, MSG_NOSIGNAL, NULL, 0) = 108 recvfrom(8, "\x80\x02\x00\x00\x00\x69\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 Get the HMAC hash from TPM. It's visible in buffer ("\x9f\xbb...\xff\x44"): recvfrom(8, "\x00\x00\x00\x16\x00\x14\x9f\xbb\x1d\xf2\xe1\x9e\x27\x89\xa3\xbc\x7c\x38\xdd\xee\xde\xcd\xb5\x45\xff\x44\x00\x20\xb4\x15\x12\xa4\x31\x82\x19\x44\xfc\xa5\x37\x8c\x7d\x42\xbb\x38\x6f\x2e\x17\x7b\xa5\x50\xa4\xc1\x23\x5a\xcf\xc8\xf7\x34\xa0\xc7\x01\x00\x20\x66\x4f\xb1\x57\xec\xdc\xf2\xae\x69\x1f\xe5\xab\x81\x59\x12\x1e\x47\x27\x71\x09\x1b\x5d\x0e\xca\x80\x35\x0e\x9a\x13\x29\x82\xa7", 95, 0, NULL, NULL) = 95 Save the hash to a file: write(10, "\x9f\xbb\x1d\xf2\xe1\x9e\x27\x89\xa3\xbc\x7c\x38\xdd\xee\xde\xcd\xb5\x45\xff\x44", 20) = 20 Send the 0x165 - TPM_CC_FlushContext command: sendto(8, "\x80\x01\x00\x00\x00\x0e\x00\x00\x01\x65\x02\x00\x00\x00", 14, MSG_NOSIGNAL, NULL, 0) = 14 recvfrom(8, "\x80\x01\x00\x00\x00\x0a\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 #+END_CODE Now dump the resulting file. The HMAC is correct. % xxd -g 1 hmac-result.bin 00000000: 9f bb 1d f2 e1 9e 27 89 a3 bc 7c 38 dd ee de cd ......'...|8.... 00000010: b5 45 ff 44 .E.D *** Summary: a short list of commands to run: # create hmac.key tpm2 loadexternal -C n -G hmac:sha1 -a "sign|userwithauth" -r hmac.key -c hmac.ctx rm hmac.key # create plain.txt tpm2 hmac -g sha1 -c hmac.ctx -o hmac-result.bin plain.txt ** With password A password can be used as authorization for TPM object. Here we will pass it via '-p' option: *** Creating context with HMAC key Run: strace -xx -s 8192 tpm2 loadexternal -C n -G hmac:sha1 -a "sign|userwithauth" -r hmac.key -c hmac.ctx -p AAAAAAAA #+BEGIN_CODE Read HMAC key from the file: read(8, "\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11", 20) = 20 Send HMAC key to TPM. Command 0x167 --- TPM_CC_LoadExternal. The password (a string of \x41 bytes (ASCII for 'A')) is visible in the buffer: sendto(7, "\x80\x01\x00\x00\x00\x86\x00\x00\x01\x67\x00\x44\x00\x08\x00\x08\x41\x41\x41\x41\x41\x41\x41\x41\x00\x20\x8c\x70\xcc\x7c\x60\x40\xbd\x73\xaf\x5e\x4d\xa8\x74\x06\x0c\x29\x09\xb4\xe5\x00\x2a\x2a\x20\x63\x51\xe4\x7f\x5f\x32\xb7\x24\xaa\x00\x14\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x00\x30\x00\x08\x00\x0b\x00\x04\x00\x40\x00\x00\x00\x05\x00\x04\x00\x20\x2f\x09\x97\x8b\x2f\x8f\x2f\x6f\x32\xcf\x6b\x04\xb6\xb1\xb8\x9b\x9c\xbe\x2a\x4b\x0d\xe1\x0c\x65\xe1\xdb\xa6\x55\x93\x5e\x59\xf3\x40\x00\x00\x07", 134, MSG_NOSIGNAL, NULL, 0) = 134 recvfrom(7, "\x80\x01\x00\x00\x00\x32\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 recvfrom(7, "\x80\x00\x00\xff\x00\x22\x00\x0b\xd8\x80\xf6\xd5\xa3\x96\x15\x57\x57\xb0\xa8\x65\x9f\x50\x07\x2f\x97\x2d\xa3\xd5\xa7\x60\xf3\x4a\x6a\x7b\xe3\xff\xa5\x48\x06\x99", 40, 0, NULL, NULL) = 40 Send the 0x162 - TPM_CC_ContextSave command: sendto(7, "\x80\x01\x00\x00\x00\x0e\x00\x00\x01\x62\x80\x00\x00\xff", 14, MSG_NOSIGNAL, NULL, 0) = 14 recvfrom(7, "\x80\x01\x00\x00\x06\xd6\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 Read encrypted blob from TPM: recvfrom(7, "\x00\x00\x00\x00\x00\x00\x00\x02\x80\x00\x00\x00\x40\x00\x00\x07<... 1724 bytes ...>", 1740, 0, NULL, NULL) = 1740 Save that blob to hmac.ctx file: write(8, "\xba\xdc\xc0\xde\x00\x00\x00\x01\x40\x00\x00\x07\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x07\x20\x00\x00\x00\x00<... 1724 bytes ...>\x00\x00\x80\x00\x00\xff\x00\x22\x00\x0b\xd8\x80\xf6\xd5\xa3\x96\x15\x57\x57\xb0\xa8\x65\x9f\x50\x07\x2f\x97\x2d\xa3\xd5\xa7\x60\xf3\x4a\x6a\x7b\xe3\xff\xa5\x48\x06\x99\x00\x00\x00\x01\x00\x30\x00\x08\x00\x0b\x00\x04\x00\x40\x00\x00\x00\x05\x00\x04\x00\x20\x2f\x09\x97\x8b\x2f\x8f\x2f\x6f\x32\xcf\x6b\x04\xb6\xb1\xb8\x9b\x9c\xbe\x2a\x4b\x0d\xe1\x0c\x65\xe1\xdb\xa6\x55\x93\x5e\x59\xf3", 1850) = 1850 #+END_CODE Now hmac.key can be deleted. *** Calculating HMAC for some plain text Run: strace -xx -s 8192 tpm2 hmac -g sha1 -c hmac.ctx -o hmac-result.bin plain.txt -p AAAAAAAA #+BEGIN_CODE Send the 0x176 - TPM_CC_StartAuthSession command. The password is not visible. Possibly encrypted or obfuscated. sendto(8, "\x80\x01\x00\x00\x00\x3b\x00\x00\x01\x76\x40\x00\x00\x07\x40\x00\x00\x07\x00\x20\xb3\x9d\x79\xe0\xc7\x7e\x02\x92\xe2\x5e\x59\x43\x08\x68\xbf\x99\x3b\x92\x8b\x42\x4f\xb3\xd9\x69\x4d\x74\x81\x33\xb9\x4f\x56\xc2\x00\x00\x00\x00\x10\x00\x0b", 59, MSG_NOSIGNAL, NULL, 0) = 59 recvfrom(8, "\x80\x01\x00\x00\x00\x30\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 recvfrom(8, "\x02\x00\x00\x00\x00\x20\x90\xc0\xbf\x67\x2c\xa6\xca\x2b\xcd\xda\x17\x09\xde\x30\x26\x91\xbc\xa5\xa9\x8f\x4b\xe4\xed\x84\x35\xc1\x74\x15\xc8\x52\x30\x61", 38, 0, NULL, NULL) = 38 Read the hmac.ctx file: read(10, "\xba\xdc\xc0\xde\x00\x00\x00\x01\x40\x00\x00\x07\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x07\x20\x00\x00\x00\x00<... 1724 bytes ...>\x00\x00\x80\x00\x00\xff\x00\x22\x00\x0b\xd8\x80\xf6\xd5\xa3\x96\x15\x57\x57\xb0\xa8\x65\x9f\x50\x07\x2f\x97\x2d\xa3\xd5\xa7\x60\xf3\x4a\x6a\x7b\xe3\xff\xa5\x48\x06\x99\x00\x00\x00\x01\x00\x30\x00\x08\x00\x0b\x00\x04\x00\x40\x00\x00\x00\x05\x00\x04\x00\x20\x2f\x09\x97\x8b\x2f\x8f\x2f\x6f\x32\xcf\x6b\x04\xb6\xb1\xb8\x9b\x9c\xbe\x2a\x4b\x0d\xe1\x0c\x65\xe1\xdb\xa6\x55\x93\x5e\x59\xf3", 4096) = 1850 Send the 0x161 - TPM_CC_ContextLoad command: sendto(8, "\x80\x01\x00\x00\x06\xd6\x00\x00\x01\x61\x00\x00\x00\x00\x00\x00\x00\x02\x80\x00\x00\x00\x40\x00\x00\x07<... 1724 bytes ...>", 1750, MSG_NOSIGNAL, NULL, 0) = 1750 recvfrom(8, "\x80\x01\x00\x00\x00\x0e\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 recvfrom(8, "\x80\x00\x00\xff", 4, 0, NULL, NULL) = 4 Read plain text: read(3, "\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a", 13) = 13 Send the 0x155 - TPM_CC_MAC command with the string of zeroes at the end: sendto(8, "\x80\x02\x00\x00\x00\x6c\x00\x00\x01\x55\x80\x00\x00\xff\x00\x00\x00\x49\x02\x00\x00\x00\x00\x20\x1f\x59\x16\x8c\x86\x80\xf2\x5c\x99\xb8\xc4\xfc\x43\x34\x55\xcf\xcb\x16\xa0\x7e\xa9\xed\x99\x8c\xd1\xe2\xb1\x81\x67\x7c\x30\x08\x01\x00\x20\x7b\xca\x88\xc7\xa1\x5e\x8b\x48\xee\x7b\x78\x4d\xd7\x55\xa7\xe7\x03\xe2\x05\x9c\x30\x7e\x60\x45\xa5\xe1\x2b\x2f\x44\x67\xd3\x9f\x00\x0d\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a\x00\x04", 108, MSG_NOSIGNAL, NULL, 0) = 108 recvfrom(8, "\x80\x02\x00\x00\x00\x69\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 Get the HMAC hash ("\x9f\xbb...\xff\x44"): recvfrom(8, "\x00\x00\x00\x16\x00\x14\x9f\xbb\x1d\xf2\xe1\x9e\x27\x89\xa3\xbc\x7c\x38\xdd\xee\xde\xcd\xb5\x45\xff\x44\x00\x20\xf8\xc8\x36\xb9\xa8\x76\x5e\x83\x7e\xca\x2c\x03\x2a\xd8\xb9\x0f\x07\x83\x51\x5e\xed\x96\x92\xe9\x60\xd4\x87\x94\x02\xa3\xb9\xee\x01\x00\x20\x7a\x1f\xfe\x0b\x39\x37\xcd\xef\xbd\x8a\x77\xc9\x11\x9a\x70\x24\x8d\xcd\x0f\x1f\x60\xb7\xc8\x7d\x84\xde\xb7\x25\x9b\xa2\x0e\xff", 95, 0, NULL, NULL) = 95 Save the hash to a file: write(10, "\x9f\xbb\x1d\xf2\xe1\x9e\x27\x89\xa3\xbc\x7c\x38\xdd\xee\xde\xcd\xb5\x45\xff\x44", 20) = 20 Send the 0x165 - TPM_CC_FlushContext command: sendto(8, "\x80\x01\x00\x00\x00\x0e\x00\x00\x01\x65\x02\x00\x00\x00", 14, MSG_NOSIGNAL, NULL, 0) = 14 recvfrom(8, "\x80\x01\x00\x00\x00\x0a\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 #+END_CODE *** Summary: a short list of commands # create hmac.key tpm2 loadexternal -C n -G hmac:sha1 -a "sign|userwithauth" -r hmac.key -c hmac.ctx -p AAAAAAAA rm hmac.key # create plain.txt tpm2 hmac -g sha1 -c hmac.ctx -o hmac-result.bin plain.txt -p AAAAAAAA ** Calculating HMAC with incorrect password supplied Run: strace -xx -s 8192 tpm2 hmac -g sha1 -c hmac.ctx -o hmac-result.bin plain.txt -p AAAAAAA1 You'll get: #+BEGIN_CODE WARNING:esys:src/tss2-esys/api/Esys_HMAC.c:300:Esys_HMAC_Finish() Received TPM Error ERROR:esys:src/tss2-esys/api/Esys_HMAC.c:100:Esys_HMAC() Esys Finish ErrorCode (0x0000098e) ERROR: Esys_HMAC(0x98E) - tpm:session(1):the authorization HMAC check failed and DA counter incremented ERROR: Unable to run hmac #+END_CODE The 'DA counter' (Dictionary Attack) is a counter of incorrect password attempts. If it gets too high, the TPM chip will lock itself for some time (but not forever). Let's see strace logs: #+BEGIN_CODE Send the 0x176 - TPM_CC_StartAuthSession command. The (incorrect) password is not visible. Possibly encrypted or obfuscated. sendto(8, "\x80\x01\x00\x00\x00\x3b\x00\x00\x01\x76\x40\x00\x00\x07\x40\x00\x00\x07\x00\x20\xcf\x57\x5c\x7e\x73\x3a\x34\x6d\xc2\x91\x56\x93\x15\xf8\x78\x43\xf4\x18\x07\x0a\x89\x7e\x30\x7e\xad\xce\xaa\x0e\xb6\x18\x1d\x45\x00\x00\x00\x00\x10\x00\x0b", 59, MSG_NOSIGNAL, NULL, 0) = 59 recvfrom(8, "\x80\x01\x00\x00\x00\x30\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 recvfrom(8, "\x02\x00\x00\x00\x00\x20\x57\x0f\x3b\xb1\x7c\x71\xce\x1e\xc9\x7f\x00\xe5\x06\x78\xfd\x1a\x14\xab\xad\x4f\xb0\x59\xbc\xa0\xcf\x10\x69\x6b\x7e\x6a\xd1\x16", 38, 0, NULL, NULL) = 38 Read the hmac.ctx file: read(10, "\xba\xdc\xc0\xde\x00\x00\x00\x01\x40\x00\x00\x07\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x07\x20\x00\x00\x00\x00<... 1724 bytes ...>\x00\x00\x80\x00\x00\xff\x00\x22\x00\x0b\xec\x3e\x5d\x8f\xfb\x97\xf1\x73\x93\xa8\x6d\x67\x46\xbd\x45\xc3\xa2\x6e\xf0\xb9\xce\xc5\xe4\xd1\x0f\x18\x3a\xab\x7c\xf8\xa5\xb6\x00\x00\x00\x01\x00\x30\x00\x08\x00\x0b\x00\x04\x00\x40\x00\x00\x00\x05\x00\x04\x00\x20\xff\xc0\x65\x9a\x98\xf9\x90\x53\x8e\xd6\x48\x9f\x76\xe8\x3f\xaa\x4a\x79\x10\x9f\x0d\x87\x25\x5d\x52\xbf\x1a\x29\x68\xec\x04\xa9", 4096) = 1850 Send the 0x161 - TPM_CC_ContextLoad command, with encrypted blob: sendto(8, "\x80\x01\x00\x00\x06\xd6\x00\x00\x01\x61\x00\x00\x00\x00\x00\x00\x00\x02\x80\x00\x00\x00\x40\x00\x00\x07<... 1724 bytes ...>", 1750, MSG_NOSIGNAL, NULL, 0) = 1750 recvfrom(8, "\x80\x01\x00\x00\x00\x0e\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 recvfrom(8, "\x80\x00\x00\xff", 4, 0, NULL, NULL) = 4 Read plain text from file: read(3, "\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a", 13) = 13 Send the 0x155 - TPM_CC_MAC command with the string of zeroes at the end: sendto(8, "\x80\x02\x00\x00\x00\x6c\x00\x00\x01\x55\x80\x00\x00\xff\x00\x00\x00\x49\x02\x00\x00\x00\x00\x20\x3b\x26\x3a\x21\x78\x84\xfb\xba\x33\xd2\xdd\x7b\x36\xf1\x53\xaa\x5f\x5c\xb8\x72\xb8\x14\x7a\x71\x2b\x72\x5e\x52\xd6\xb5\x6e\x70\x01\x00\x20\x60\x79\x6c\x46\x67\x90\x6d\x2b\xc4\x0a\x65\x78\xf2\x5d\x8b\x2c\x9d\x33\xfb\xd9\xdc\xcf\xfa\x0c\xa9\x63\xc6\xde\x1e\x0d\x97\xf5\x00\x0d\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x30\x0a\x00\x04", 108, MSG_NOSIGNAL, NULL, 0) = 108 Getting 0x98E error from TPM (error code in big-endian 16-bit word, 8th and 9th bytes): recvfrom(8, "\x80\x01\x00\x00\x00\x0a\x00\x00\x09\x8e", 10, 0, NULL, NULL) = 10 ) = 86 #+END_CODE ** Calculating HMAC on wrong TPM chip Since I have no two identical computers with TPMs, I use swtpm simulator here. And the blob size is smaller (356 bytes). Run: strace -xx -s 8192 tpm2 hmac -g sha1 -c hmac.ctx -o hmac-result.bin plain.txt #+BEGIN_CODE WARNING:esys:src/tss2-esys/api/Esys_ContextLoad.c:279:Esys_ContextLoad_Finish() Received TPM Error ERROR:esys:src/tss2-esys/api/Esys_ContextLoad.c:93:Esys_ContextLoad() Esys Finish ErrorCode (0x000001df) ERROR: Esys_ContextLoad(0x1DF) - tpm:parameter(1):integrity check failed ERROR: Incorrect handle value, got: "hmac.ctx", expected expected [o|p|e|n|l] or a handle number ERROR: Unable to read PEM from provided BIO/file ERROR: Unable to fetch public/private portions of TSS PRIVKEY ERROR: Cannot make sense of object context "hmac.ctx" ERROR: Invalid key handle authorization ERROR: Unable to run hmac #+END_CODE 'integrity check failed' -- a second TPM can't decrypt a context that was created on first TPM. #+BEGIN_CODE Send the 0x176 - TPM_CC_StartAuthSession command. sendto(8, "\x80\x01\x00\x00\x00\x3b\x00\x00\x01\x76\x40\x00\x00\x07\x40\x00\x00\x07\x00\x20\x29\xbc\xf0\x2c\x58\x15\x37\x50\x31\xb0\x2b\xf4\x2e\x23\xdf\xed\x79\x1e\x33\xdd\xf9\xd6\x29\xff\xe4\xb0\x09\x4f\x44\x60\xcb\xff\x00\x00\x00\x00\x10\x00\x0b", 59, MSG_NOSIGNAL, NULL, 0) = 59 recvfrom(8, "\x80\x01\x00\x00\x00\x30\x00\x00\x00\x00", 10, 0, NULL, NULL) = 10 recvfrom(8, "\x02\x00\x00\x00\x00\x20\x32\x53\x7a\x8a\x94\x0b\x19\xb9\xa4\x26\x40\x03\x27\x79\x0d\x38\x1c\x5d\x2a\x32\x0e\xef\xd0\x49\x02\x6b\xc7\x63\x32\xbe\x5b\x91", 38, 0, NULL, NULL) = 38 Read the hmac.ctx file: read(10, "\xba\xdc\xc0\xde\x00\x00\x00\x01\x40\x00\x00\x07\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x01\xc8\x00\x00\x00\x00<... 356 bytes ...>\x00\x00\x80\x00\x00\xff\x00\x22\x00\x0b\xee\x54\x0c\x10\x8d\xb4\xf2\xb8\x00\xd5\xf6\x31\x48\x77\xac\x51\xfa\x49\x32\x5c\xd3\x3c\xf2\xa4\x36\xa4\xd6\xa5\x14\xb1\x29\x50\x00\x00\x00\x01\x00\x30\x00\x08\x00\x0b\x00\x04\x00\x40\x00\x00\x00\x05\x00\x04\x00\x20\x8f\xd8\x6e\x01\x87\x5d\xe5\xec\x0d\xdf\xa4\x3e\xb0\x51\x47\x42\x4d\x32\xa8\x95\xbd\xdb\x62\xb7\x92\xe9\x48\xcb\x0a\xc3\xef\xae", 4096) = 482 Send the 0x161 - TPM_CC_ContextLoad command: sendto(8, "\x80\x01\x00\x00\x01\x7e\x00\x00\x01\x61\x00\x00\x00\x00\x00\x00\x00\x02\x80\x00\x00\x00\x40\x00\x00\x07<... 356 bytes ...>", 382, MSG_NOSIGNAL, NULL, 0) = 382 Getting 0x1DF error: recvfrom(8, "\x80\x01\x00\x00\x00\x0a\x00\x00\x01\xdf", 10, 0, NULL, NULL) = 10 #+END_CODE ** Thanks for help: Jürgen Repp https://github.com/JuergenReppSIT Moritz (ᠮᠣᠷᠢᠲᡯ 王亢宝) Buhl https://github.com/moritzbuhl Examples from this repo I found useful: https://github.com/salrashid123/tpm2/