tpm2-tools icon indicating copy to clipboard operation
tpm2-tools copied to clipboard

TPM Breaks when Attempting to Persist Externally-Loaded Private Keys

Open dadiestfish2077 opened this issue 1 year ago • 5 comments

My TPM is thrown into an unusable state whenever I try to persist an externally-generated key. Using tpm2_import, it seems that evictcontrol will work momentarily, but wen I attempt to remove the key from the TPM using evictcontrol the TPM becomes a brick. The TPM becomes unusable when I attempt to persist an externally-generated private key loaded via loadexternal. I am confident I am not doing anything wrong.

I do not think it is the intended behavior of the chip to disallow the persistence of externally-generated private keys within the TPM.

I have no idea how to fix it, and any help would be greatly appreciated.

First, I run theses commands to take an externally-generated private and load it into TPM permanently. At the end of these commands, everything works well:

openssl genrsa -out private.pem
openssl rsa -in private.pem -pubout -out pubkey.crt
tpm2_changeauth -c o newpass
tpm2_createprimary -G rsa2048 -C o -c parent.ct -P newpass
tpm2_pcrread -o pcr.bin sha256:10
tpm2_createpolicy --policy-pcr -l sha256:10 -f pcr.bin -L pcr.policy
tpm2_import -C parent.ct -G rsa -i private.pem -u key.pub  -r key.priv -L pcr.policy 
tpm2_load -C parent.ct -u key.pub -r key.priv -c key.ctx
tpm2_evictcontrol -C o -c key.ctx -P newpass 
tpm2_sign -c key.ctx -g sha256 -o sign.rsa -f plain data.bin -p pcr:sha256:10
openssl dgst -verify pubkey.crt -keyform pem -sha256 -signature sign.rsa data.bin

Now, if I want to roll this private key over and replace it I should run evictcontrol. However, once I attempt to remove the private key, the TPM is thrown into an unusable state:

tpm2_evictcontrol -C o -c 0x81000000 -P newpass

ERROR:tcti:src/tss2-tcti/tcti-device.c:198:tcti_device_receive() Failed to get response size fd 3, got errno 14: Bad address ERROR:esys:src/tss2-esys/api/Esys_EvictControl.c:334:Esys_EvictControl_Finish() Received a non-TPM Error ERROR:esys:src/tss2-esys/api/Esys_EvictControl.c:114:Esys_EvictControl() Esys Finish ErrorCode (0x000a000a) ERROR: Esys_EvictControl(0xA000A) - tcti:IO failure ERROR:esys:src/tss2-esys/esys_tr.c:356:Esys_TR_Close() Error: Esys handle does not exist (70018). ERROR: Esys_TR_Close(0x70018) - esapi:The ESYS_TR resource object is bad ERROR:esys:src/tss2-esys/esys_iutil.c:1145:iesys_check_sequence_async() Esys called in bad sequence. ERROR:esys:src/tss2-esys/api/Esys_FlushContext.c:66:Esys_FlushContext() Error in async function ErrorCode (0x00070007) ERROR: Esys_FlushContext(0x70007) - esapi:Function called in the wrong order ERROR: Unable to run tpm2_evictcontrol

After this, nothing else works and the TPM is bricked.

Second, I run the following commands to persist an external private key loaded via loadexternal, and once I run evictcontrol, the TPM is likewise bricked:

    tpm2_loadexternal -G rsa -r key.pem -c key.ctx
     tpm2_evictcontrol -C o -c key.ctx -P newpass

WARNING:esys:src/tss2-esys/api/Esys_EvictControl.c:330:Esys_EvictControl_Finish() Received TPM Error ERROR:esys:src/tss2-esys/api/Esys_EvictControl.c:114:Esys_EvictControl() Esys Finish ErrorCode (0x00000282) ERROR: Esys_EvictControl(0x282) - tpm:handle(2):inconsistent attributes ERROR:esys:src/tss2-esys/esys_tr.c:356:Esys_TR_Close() Error: Esys handle does not exist (70018). ERROR: Esys_TR_Close(0x70018) - esapi:The ESYS_TR resource object is bad ERROR: Unable to run tpm2_evictcontrol

Can't even run tpm2_clear: root@Test:/home/test# tpm2_clear

ERROR:tcti:src/tss2-tcti/tcti-device.c:198:tcti_device_receive() Failed to get response size fd 3, got errno 14: Bad address ERROR:esys:src/tss2-esys/api/Esys_Clear.c:295:Esys_Clear_Finish() Received a non-TPM Error ERROR:esys:src/tss2-esys/api/Esys_Clear.c:97:Esys_Clear() Esys Finish ErrorCode (0x000a000a) ERROR: Esys_Clear(0xA000A) - tcti:IO failure ERROR:esys:src/tss2-esys/esys_iutil.c:1145:iesys_check_sequence_async() Esys called in bad sequence. ERROR:esys:src/tss2-esys/api/Esys_FlushContext.c:66:Esys_FlushContext() Error in async function ErrorCode (0x00070007) ERROR: Esys_FlushContext(0x70007) - esapi:Function called in the wrong order ERROR: Unable to run tpm2_clear

As mentioned, this does not seem like appropriate behavior. I would expect to be able to persist external keys in the TPM.

In case it helps, here is the output to tpm2_getcap propertied-fixed. TPM2_PT_FAMILY_INDICATOR: raw: 0x322E3000 value: "2.0" TPM2_PT_LEVEL: raw: 0 TPM2_PT_REVISION: raw: 0xA4 value: 1.64 TPM2_PT_DAY_OF_YEAR: raw: 0x4B TPM2_PT_YEAR: raw: 0x7E5 TPM2_PT_MANUFACTURER: raw: 0x49424D00 value: "IBM" TPM2_PT_VENDOR_STRING_1: raw: 0x53572020 value: "SW" TPM2_PT_VENDOR_STRING_2: raw: 0x2054504D value: "TPM" TPM2_PT_VENDOR_STRING_3: raw: 0x0 value: "" TPM2_PT_VENDOR_STRING_4: raw: 0x0 value: "" TPM2_PT_VENDOR_TPM_TYPE: raw: 0x1 TPM2_PT_FIRMWARE_VERSION_1: raw: 0x20191023 TPM2_PT_FIRMWARE_VERSION_2: raw: 0x163636 TPM2_PT_INPUT_BUFFER: raw: 0x400 TPM2_PT_HR_TRANSIENT_MIN: raw: 0x3 TPM2_PT_HR_PERSISTENT_MIN: raw: 0x7 TPM2_PT_HR_LOADED_MIN: raw: 0x3 TPM2_PT_ACTIVE_SESSIONS_MAX: raw: 0x40 TPM2_PT_PCR_COUNT: raw: 0x18 TPM2_PT_PCR_SELECT_MIN: raw: 0x3 TPM2_PT_CONTEXT_GAP_MAX: raw: 0xFFFF TPM2_PT_NV_COUNTERS_MAX: raw: 0x0 TPM2_PT_NV_INDEX_MAX: raw: 0x800 TPM2_PT_MEMORY: raw: 0x6 TPM2_PT_CLOCK_UPDATE: raw: 0x1000 TPM2_PT_CONTEXT_HASH: raw: 0xD TPM2_PT_CONTEXT_SYM: raw: 0x6 TPM2_PT_CONTEXT_SYM_SIZE: raw: 0x100 TPM2_PT_ORDERLY_COUNT: raw: 0xFF TPM2_PT_MAX_COMMAND_SIZE: raw: 0x1000 TPM2_PT_MAX_RESPONSE_SIZE: raw: 0x1000 TPM2_PT_MAX_DIGEST: raw: 0x40 TPM2_PT_MAX_OBJECT_CONTEXT: raw: 0xA84 TPM2_PT_MAX_SESSION_CONTEXT: raw: 0x194 TPM2_PT_PS_FAMILY_INDICATOR: raw: 0x322E3000 TPM2_PT_PS_LEVEL: raw: 0x0 TPM2_PT_PS_REVISION: raw: 0xA4 TPM2_PT_PS_DAY_OF_YEAR: raw: 0x4B TPM2_PT_PS_YEAR: raw: 0x7E5 TPM2_PT_SPLIT_MAX: raw: 0x80 TPM2_PT_TOTAL_COMMANDS: raw: 0x6E TPM2_PT_LIBRARY_COMMANDS: raw: 0x6E TPM2_PT_VENDOR_COMMANDS: raw: 0x0 TPM2_PT_NV_BUFFER_MAX: raw: 0x400 TPM2_PT_MODES: raw: 0x0

dadiestfish2077 avatar Jan 04 '24 04:01 dadiestfish2077

@dadiestfish2077 I could run your example with the current master of tss and of the tools with IFX and AMD TPMs without problems. What are the versions of tss and the tools you are using?

JuergenReppSIT avatar Jan 04 '24 08:01 JuergenReppSIT

Interesting... when i run tpm2_getcap --version this is the output:

tool="tpm2_getcap" version="5.2" tctis="libtss2-tctildr" tcti-default=tcti-device"

does that help?

dadiestfish2077 avatar Jan 04 '24 16:01 dadiestfish2077

@dadiestfish2077 tpm2_tools 5.2 and tss 3.0.2 are the versions available on ubuntu 22.04. I tested you example with these two versions but could not reproduce the error.

JuergenReppSIT avatar Jan 05 '24 10:01 JuergenReppSIT

I have tried this on two different VMs within VBOX. All of these below commands work great:

openssl genrsa -out private.pem openssl rsa -in private.pem -pubout -out pubkey.crt tpm2_changeauth -c o newpass tpm2_createprimary -G rsa2048 -C o -c parent.ct -P newpass tpm2_pcrread -o pcr.bin sha256:10 tpm2_createpolicy --policy-pcr -l sha256:10 -f pcr.bin -L pcr.policy tpm2_import -C parent.ct -G rsa -i private.pem -u key.pub -r key.priv -L pcr.policy tpm2_load -C parent.ct -u key.pub -r key.priv -c key.ctx tpm2_evictcontrol -C o -c key.ctx -P newpass tpm2_sign -c key.ctx -g sha256 -o sign.rsa -f plain data.bin -p pcr:sha256:10 openssl dgst -verify pubkey.crt -keyform pem -sha256 -signature sign.rsa data.bin

but, as soon as i try to remove the key by running:

tpm2_evictcontrol -C o -c 0x81000000 -P newpass

when i run tpm2_clear trying to start over, it throws this error:

ERROR:tcti:src/tss2-tcti/tcti-device.c:503:Tss2_Tcti_Device_Init() timeout waiting for response from fd 3 WARNING:esys:src/tss2-esys/api/Esys_StartAuthSession.c:390:Esys_StartAuthSession_Finish() Received TPM Error ERROR:esys:src/tss2-esys/api/Esys_StartAuthSession.c:136:Esys_StartAuthSession() Esys Finish ErrorCode (0x00000101) ERROR: Esys_StartAuthSession(0x101) - tpm:error(2.0): commands not being accepted because of a TPM failure ERROR: Invalid lockout authorization ERROR: Unable to run tpm2_clear

it throws the error pasted above. this happens on each VM i run it on. Do you have suggestions?

One possible workaround is for us to use the NVdefine, NVwrite and NVread to manage the private key. However, I am likewise having issues trying to use a PCR policy as the read authorization.

I do greatly appreciate your help

dadiestfish2077 avatar Jan 05 '24 16:01 dadiestfish2077

@dadiestfish2077 I have tried it with qemu and swtpm used to create a TPM device. It worked there too. Does the error also occur after:

tpm2_changeauth -c o newpass
pm2_createprimary -G rsa2048 -C o -c parent.ct -P newpass
handle=$(tpm2_evictcontrol -C o -c parent.ct -P newpass|head -n 1|awk '{print $2}')

tpm2_evictcontrol -C o -c $handle -P newpass

If the error does not occur in this case: What I noticed in your example is that you are using key.ctx from the key that has just been evicted. That should actually work. But maybe try using the persistent handle for the sign:

openssl genrsa -out private.pem
openssl rsa -in private.pem -pubout -out pubkey.crt
tpm2_changeauth -c o newpass
tpm2_createprimary -G rsa2048 -C o -c parent.ct -P newpass
tpm2_pcrread -o pcr.bin sha256:10
tpm2_createpolicy --policy-pcr -l sha256:10 -f pcr.bin -L pcr.policy
tpm2_import -C parent.ct -G rsa -i private.pem -u key.pub -r key.priv -L pcr.policy
tpm2_load -C parent.ct -u key.pub -r key.priv -c key.ctx
handle=$(tpm2_evictcontrol -C o -c key.ctx -P newpass|head -n 1|awk '{print $2}')
tpm2_sign -c $handle -g sha256 -o sign.rsa -f plain data.bin -p pcr:sha256:10
openssl dgst -verify pubkey.crt -keyform pem -sha256 -signature sign.rsa data.bin

tpm2_evictcontrol -C o -c $handle -P newpass

JuergenReppSIT avatar Jan 06 '24 08:01 JuergenReppSIT

Same thing happens to me in VirtualBox 7.0.14 and Debian 12.5

root@tpmv2:~# tpm2_evictcontrol -C o -c 0x81000000
ERROR:tcti:src/tss2-tcti/tcti-device.c:198:tcti_device_receive() Failed to get response size fd 3, got errno 14: Bad address
ERROR:esys:src/tss2-esys/api/Esys_EvictControl.c:334:Esys_EvictControl_Finish() Received a non-TPM Error
ERROR:esys:src/tss2-esys/api/Esys_EvictControl.c:114:Esys_EvictControl() Esys Finish ErrorCode (0x000a000a)
ERROR: Esys_EvictControl(0xA000A) - tcti:IO failure
ERROR:esys:src/tss2-esys/esys_iutil.c:1145:iesys_check_sequence_async() Esys called in bad sequence.
ERROR:esys:src/tss2-esys/api/Esys_FlushContext.c:66:Esys_FlushContext() Error in async function ErrorCode (0x00070007)
ERROR: Esys_FlushContext(0x70007) - esapi:Function called in the wrong order
ERROR: Unable to run tpm2_evictcontrol

TByte007 avatar Mar 20 '24 15:03 TByte007

I can confirm that this is an issue with vbox. I tried these steps on the actual hardware and it works just as JuergenReppST says. As always, ide like to thank this community for its support.

dadiestfish2077 avatar Apr 08 '24 03:04 dadiestfish2077