tpm2-software / tpm2-tools

The source repository for the Trusted Platform Module (TPM2.0) tools
https://tpm2-software.github.io
725 stars 379 forks source link

Can't read EKCert after tpm2_changeauth #2302

Closed dnoliver closed 3 years ago

dnoliver commented 3 years ago

The following test is aimed to reproduce the problem described in https://github.com/keylime/keylime/issues/503

#!/bin/bash

set -euxo pipefail

# Start with a clean tpm
tpm2_clear
# Check that the EK Certficate can be read
tpm2_nvread -C o 0x1c00002 > ek.cert
# Change the owner hierarchy
tpm2_changeauth -c o keylime
# Trying to read the EK Certificate now fails
tpm2_nvread 0x1c00002 -P keylime || echo "Failed"
tpm2_nvread 0x1c00002 -C o -P keylime || echo "Failed"
tpm2_nvread 0x1c00002 || echo "Failed"

The output of the test is the following:

[test@fedora-server ~]$ bash test.sh
+ tpm2_clear
+ tpm2_nvread -C o 0x1c00002
+ tpm2_changeauth -c o keylime
+ tpm2_nvread 0x1c00002 -P keylime
WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:315:Esys_NV_Read_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x000009a2)
ERROR: Esys_NV_Read(0x9A2) - tpm:session(1):authorization failure without DA implications
ERROR: Failed to read NVRAM area at index 0x1C00002
ERROR: Unable to run tpm2_nvread
+ echo Failed
Failed
+ tpm2_nvread 0x1c00002 -C o -P keylime
WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:315:Esys_NV_Read_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x000001c4)
ERROR: Esys_NV_Read(0x1C4) - tpm:parameter(1):value is out of range or is not correct for the context
ERROR: Failed to read NVRAM area at index 0x1C00002
ERROR: Unable to run tpm2_nvread
+ echo Failed
Failed
+ tpm2_nvread 0x1c00002
WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:315:Esys_NV_Read_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x000009a2)
ERROR: Esys_NV_Read(0x9A2) - tpm:session(1):authorization failure without DA implications
ERROR: Failed to read NVRAM area at index 0x1C00002
ERROR: Unable to run tpm2_nvread
+ echo Failed
Failed

The first tpm2_nvread is able to get the EKCert without problems. But after setting the keylime password in the owner hierarchy, the EKCert is no longer accessible.

The versions are:

[test@fedora-server ~]$ rpm -qa tpm2*
tpm2-tss-3.0.1-1.fc33.x86_64
tpm2-tools-4.3.0-1.fc33.x86_64
tpm2-abrmd-selinux-2.3.1-2.fc33.noarch
tpm2-abrmd-2.3.3-1.fc33.x86_64

[test@fedora-server ~]$ cat /etc/redhat-release
Fedora release 33 (Thirty Three)

This is a HyperV VM with vTPM.

idesai commented 3 years ago

What are the attributes on the NV index? nvreadpublic

dnoliver commented 3 years ago
[root@fedora-server f32]# tpm2_nvreadpublic
0x1c00002:
  name: 000b7edfdc67e42c405ac7cbd754282988a72c1d7218cf77364b6ea91dffd959f051
  hash algorithm:
    friendly: sha256
    value: 0xB
  attributes:
    friendly: authwrite|ownerread|authread|no_da|written|platformcreate
    value: 0x4000662
  size: 1536

0x1c08001:
  name: 000b065d490a7af4cd2838544b3d4946a153fbd7a3bf3dcad4d024151466c8bd2d79
  hash algorithm:
    friendly: sha256
    value: 0xB
  attributes:
    friendly: authwrite|ownerread|authread|no_da|written|platformcreate
    value: 0x4000662
  size: 2048
idesai commented 3 years ago

Try this

tpm2_nvread 0x1c00002 -P keylime -C o
idesai commented 3 years ago

Try this

tpm2_nvread 0x1c00002 -P keylime -C o

I guess you already did.

dnoliver commented 3 years ago

yes,

[root@fedora-server test]# tpm2_nvread 0x1c00002 -P keylime -C o
WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:315:Esys_NV_Read_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x000001c4)
ERROR: Esys_NV_Read(0x1C4) - tpm:parameter(1):value is out of range or is not correct for the context
ERROR: Failed to read NVRAM area at index 0x1C00002
ERROR: Unable to run tpm2_nvread
idesai commented 3 years ago

Is the owner auth set? Can you check the output of tpm2_getcap? If it is set, can you try creating an object under the owner hierarchy which should require you to specify the owner-auth.

dnoliver commented 3 years ago

Owner auth is set after running the test

[root@fedora-server test]#  tpm2_getcap properties-variable
TPM2_PT_PERSISTENT:
  ownerAuthSet:              1
  endorsementAuthSet:        0
  lockoutAuthSet:            0
  reserved1:                 0
  disableClear:              0
  inLockout:                 0
  tpmGeneratedEPS:           1
  reserved2:                 0
TPM2_PT_STARTUP_CLEAR:
  phEnable:                  0
  shEnable:                  1
  ehEnable:                  1
  phEnableNV:                1
  reserved1:                 0
  orderly:                   1
TPM2_PT_HR_NV_INDEX: 0x2
TPM2_PT_HR_LOADED: 0x0
TPM2_PT_HR_LOADED_AVAIL: 0x3
TPM2_PT_HR_ACTIVE: 0x0
TPM2_PT_HR_ACTIVE_AVAIL: 0x40
TPM2_PT_HR_TRANSIENT_AVAIL: 0x3
TPM2_PT_HR_PERSISTENT: 0x0
TPM2_PT_HR_PERSISTENT_AVAIL: 0x6
TPM2_PT_NV_COUNTERS: 0x0
TPM2_PT_NV_COUNTERS_AVAIL: 0x20
TPM2_PT_ALGORITHM_SET: 0x0
TPM2_PT_LOADED_CURVES: 0x3
TPM2_PT_LOCKOUT_COUNTER: 0x0
TPM2_PT_MAX_AUTH_FAIL: 0x3
TPM2_PT_LOCKOUT_INTERVAL: 0x3E8
TPM2_PT_LOCKOUT_RECOVERY: 0x3E8
TPM2_PT_AUDIT_COUNTER_0: 0x0
TPM2_PT_AUDIT_COUNTER_1: 0x0

And I can create the EK using the "keylime" password for ownerauth

[root@fedora-server test]# tpm2_createek -c - -G rsa -u ek.pub -w keylime
persistent-handle: 0x81000000
idesai commented 3 years ago

Interestingly, using the owner auth to read an NV index is specifically tested in the integration-tests.

dnoliver commented 3 years ago

Is there something wrong with my EKCert attributes?

The test uses policyread|policywrite|authread|authwrite|ownerwrite|ownerread And my cert has authwrite|ownerread|authread|no_da|written|platformcreate

See https://github.com/keylime/keylime/issues/503#issuecomment-760263181

dnoliver commented 3 years ago

The integration test works fine in with my vTPM.

I tried modifying it to have the same attributes as my EKCert, but I am getting an error:

[root@fedora-server test]# bash test-2.sh
+ echo please123abc
+ tpm2_changeauth -c o owner
+ tpm2_nvdefine 0x1500015 -C o -s 32 -a 'authwrite|ownerread|authread|no_da|written|platformcreate' -p index -P owner
WARNING:esys:src/tss2-esys/api/Esys_NV_DefineSpace.c:337:Esys_NV_DefineSpace_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_DefineSpace.c:122:Esys_NV_DefineSpace() Esys Finish ErrorCode (0x000002c2)
ERROR: Failed to define NV area at index 0x1500015
ERROR: Esys_NV_DefineSpace(0x2C2) - tpm:parameter(2):inconsistent attributes
ERROR: Failed to create NV index 0x1500015.
ERROR: Unable to run tpm2_nvdefine
idesai commented 3 years ago

what is the output if you skip platformcreate attribute

dnoliver commented 3 years ago
+ tpm2_nvdefine 0x1500015 -C o -s 32 -a 'authwrite|ownerread|authread|no_da|written' -p index -P owner
WARNING:esys:src/tss2-esys/api/Esys_NV_DefineSpace.c:337:Esys_NV_DefineSpace_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_DefineSpace.c:122:Esys_NV_DefineSpace() Esys Finish ErrorCode (0x000002c2)
ERROR: Failed to define NV area at index 0x1500015
ERROR: Esys_NV_DefineSpace(0x2C2) - tpm:parameter(2):inconsistent attributes
ERROR: Failed to create NV index 0x1500015.
ERROR: Unable to run tpm2_nvdefine
idesai commented 3 years ago
+ tpm2_nvdefine 0x1500015 -C o -s 32 -a 'authwrite|ownerread|authread|no_da|written' -p index -P owner
WARNING:esys:src/tss2-esys/api/Esys_NV_DefineSpace.c:337:Esys_NV_DefineSpace_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_DefineSpace.c:122:Esys_NV_DefineSpace() Esys Finish ErrorCode (0x000002c2)
ERROR: Failed to define NV area at index 0x1500015
ERROR: Esys_NV_DefineSpace(0x2C2) - tpm:parameter(2):inconsistent attributes
ERROR: Failed to create NV index 0x1500015.
ERROR: Unable to run tpm2_nvdefine

you cannot define an nv-index with written set. that attribute is set by the TPM after the NV is written.

dnoliver commented 3 years ago

It is starting to look like the original error :D

+ echo please123abc
+ tpm2_changeauth -c o owner
+ tpm2_nvdefine 0x1500015 -C o -s 32 -a 'authwrite|ownerread|authread|no_da' -p index -P owner
nv-index: 0x1500015
+ tpm2_nvwrite -Q 0x1500015 -C o -P owner -i nv.test_w
WARNING:esys:src/tss2-esys/api/Esys_NV_Write.c:310:Esys_NV_Write_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Write.c:110:Esys_NV_Write() Esys Finish ErrorCode (0x00000149)
ERROR: Failed to write NV area at index 0x1500015
ERROR: Tss2_Sys_NV_Write(0x149) - tpm:error(2.0): NV access authorization fails in command actions
ERROR: Unable to run tpm2_nvwrite
idesai commented 3 years ago

It is starting to look like the original error :D

+ echo please123abc
+ tpm2_changeauth -c o owner
+ tpm2_nvdefine 0x1500015 -C o -s 32 -a 'authwrite|ownerread|authread|no_da' -p index -P owner
nv-index: 0x1500015
+ tpm2_nvwrite -Q 0x1500015 -C o -P owner -i nv.test_w
WARNING:esys:src/tss2-esys/api/Esys_NV_Write.c:310:Esys_NV_Write_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Write.c:110:Esys_NV_Write() Esys Finish ErrorCode (0x00000149)
ERROR: Failed to write NV area at index 0x1500015
ERROR: Tss2_Sys_NV_Write(0x149) - tpm:error(2.0): NV access authorization fails in command actions
ERROR: Unable to run tpm2_nvwrite

Your write files because attribute ownerwrite is not set and you are using owner auth to write.

dnoliver commented 3 years ago

Ok, so I am doing this:

#!/bin/bash

set -euxo pipefail
echo "please123abc" > nv.test_w
tpm2_clear
tpm2_nvdefine 0x1500015 -C o -s 32 -a "authwrite|ownerwrite|authread|ownerread|no_da"
tpm2_nvwrite -Q 0x1500015 -C o -i nv.test_w
tpm2_changeauth -c o "owner"
tpm2_nvread -Q 0x1500015 -C o -P "owner"
tpm2_nvread -Q 0x1c00002 -C o -P "owner"

The output of that is:

[root@fedora-server test]# bash test.sh
+ echo please123abc
+ tpm2_clear
+ tpm2_nvdefine 0x1500015 -C o -s 32 -a 'authwrite|ownerwrite|authread|ownerread|no_da'
nv-index: 0x1500015
+ tpm2_nvwrite -Q 0x1500015 -C o -i nv.test_w
+ tpm2_changeauth -c o owner
+ tpm2_nvread -Q 0x1500015 -C o -P owner
+ tpm2_nvread -Q 0x1c00002 -C o -P owner
WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:315:Esys_NV_Read_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x000001c4)
ERROR: Esys_NV_Read(0x1C4) - tpm:parameter(1):value is out of range or is not correct for the context
ERROR: Failed to read NVRAM area at index 0x1C00002
ERROR: Unable to run tpm2_nvread

[root@fedora-server test]# tpm2_nvreadpublic
0x1500015:
  name: 000bfd6fe1c34d09246aa38a0a3bfaf4cb00770bba9297f517f4c29f28348c8e868e
  hash algorithm:
    friendly: sha256
    value: 0xB
  attributes:
    friendly: ownerwrite|authwrite|ownerread|authread|no_da|written
    value: 0x6000622
  size: 32

0x1c00002:
  name: 000b7edfdc67e42c405ac7cbd754282988a72c1d7218cf77364b6ea91dffd959f051
  hash algorithm:
    friendly: sha256
    value: 0xB
  attributes:
    friendly: authwrite|ownerread|authread|no_da|written|platformcreate
    value: 0x4000662
  size: 1536

0x1c08001:
  name: 000b065d490a7af4cd2838544b3d4946a153fbd7a3bf3dcad4d024151466c8bd2d79
  hash algorithm:
    friendly: sha256
    value: 0xB
  attributes:
    friendly: authwrite|ownerread|authread|no_da|written|platformcreate
    value: 0x4000662
  size: 2048

I can access the created object in 0x1500015 with the owner password. But I can't access the EKCert in 0x1c00002 with the owner password. The diff between the objects attributes is the ownerwrite in 0x1500015, and platformcreate in 0x1c00002

Any ideas how to read 0x1c00002 after changing the owner auth?

idesai commented 3 years ago

I cannot think of anything special that needs to happen to read the index a second time with the owner auth. To ascertain, I did try to read the NV index 1c00002 on my NUC and was able to read the certificate off it after setting owner-auth. Can you try reading a smaller size?

dnoliver commented 3 years ago

you nailed it @idesai :D

I can read up to 1024 bytes. It fails with 1025

@stefanberger this seems to be the issue reported in https://github.com/keylime/keylime/issues/503. Keylime will fail with any cert bigger than 1024 bytes?

[root@fedora-server test]# tpm2_nvread 0x1c00002 -C o -P owner --size=1024
0yƇ1R6G?*H      O0
010
220115163145Z0(1&0$U CA0
0       *H          Microsoft Hyper-V Virtual TPM0"0
y/<b;}OS        9XVC?zŇu>AD?Wwk/:gVrFcte^6aVY\SZ{ҧQ|X^SnX-<̓_KC/l(Q*0c)
)}k_IA_Ci*i*QXQ>2L|pۄd
         4&㠡&t<00U
0U 0aUW0US0Q10g
               id:201%0#g
                         Firmware:538247443.139472210g

0                                                     id:4D5346540!U    00g1

 2.0t0U 0U
0@0U%   00U#0;(
        *H     ckt6zu0
"W?(7("ۈt?@j FRh6+KoOh"_;O߰KTH*Jlj0^&e{
lN3 8.XDl\*^o^&)BFt3Knm
                       ?7wV':]-ef5Em:ު.aE1l,MS]*[B.:bj4YC?\"<}c

[root@fedora-server test]# tpm2_nvread 0x1c00002 -C o -P owner --size=1025
WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:315:Esys_NV_Read_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x000001c4)
ERROR: Esys_NV_Read(0x1C4) - tpm:parameter(1):value is out of range or is not correct for the context
ERROR: Failed to read NVRAM area at index 0x1C00002
ERROR: Unable to run tpm2_nvread

This is my cert size (1536)

0x1c00002:
  name: 000b7edfdc67e42c405ac7cbd754282988a72c1d7218cf77364b6ea91dffd959f051
  hash algorithm:
    friendly: sha256
    value: 0xB
  attributes:
    friendly: authwrite|ownerread|authread|no_da|written|platformcreate
    value: 0x4000662
  size: 1536
dnoliver commented 3 years ago

This works:

#!/bin/bash

set -euxo pipefail
tpm2_clear
tpm2_nvread -Q 0x1c00002 -C o -o ek.expected.crt
tpm2_changeauth -c o "owner"
tpm2_nvread -Q 0x1c00002 -C o -P "owner" || echo "This fails"
tpm2_nvread -Q 0x1c00002 -C o -P "owner" -s 1024 -o ek.actual.crt
tpm2_nvread -Q 0x1c00002 -C o -P "owner" -s 512 --offset 1024 -o ek.offset.crt
cat ek.offset.crt >> ek.actual.crt
diff ek.expected.crt ek.actual.crt

The output is:

[root@fedora-server test]# bash test.sh
+ tpm2_clear
+ tpm2_nvread -Q 0x1c00002 -C o -o ek.expected.crt
+ tpm2_changeauth -c o owner
+ tpm2_nvread -Q 0x1c00002 -C o -P owner
WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:315:Esys_NV_Read_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x000001c4)
ERROR: Esys_NV_Read(0x1C4) - tpm:parameter(1):value is out of range or is not correct for the context
ERROR: Failed to read NVRAM area at index 0x1C00002
ERROR: Unable to run tpm2_nvread
+ echo 'This fails'
This fails
+ tpm2_nvread -Q 0x1c00002 -C o -P owner -s 1024 -o ek.actual.crt
+ tpm2_nvread -Q 0x1c00002 -C o -P owner -s 512 --offset 1024 -o ek.offset.crt
+ cat ek.offset.crt
+ diff ek.expected.crt ek.actual.crt

So, without owner password, tpm2_nvread can read the complete cert After adding a password, you can read a max of 1024 bytes. The workaround is reading multiple times with the --offset option

idesai commented 3 years ago

This works:

#!/bin/bash

set -euxo pipefail
tpm2_clear
tpm2_nvread -Q 0x1c00002 -C o -o ek.expected.crt
tpm2_changeauth -c o "owner"
tpm2_nvread -Q 0x1c00002 -C o -P "owner" || echo "This fails"
tpm2_nvread -Q 0x1c00002 -C o -P "owner" -s 1024 -o ek.actual.crt
tpm2_nvread -Q 0x1c00002 -C o -P "owner" -s 512 --offset 1024 -o ek.offset.crt
cat ek.offset.crt >> ek.actual.crt
diff ek.expected.crt ek.actual.crt

The output is:

[root@fedora-server test]# bash test.sh
+ tpm2_clear
+ tpm2_nvread -Q 0x1c00002 -C o -o ek.expected.crt
+ tpm2_changeauth -c o owner
+ tpm2_nvread -Q 0x1c00002 -C o -P owner
WARNING:esys:src/tss2-esys/api/Esys_NV_Read.c:315:Esys_NV_Read_Finish() Received TPM Error
ERROR:esys:src/tss2-esys/api/Esys_NV_Read.c:105:Esys_NV_Read() Esys Finish ErrorCode (0x000001c4)
ERROR: Esys_NV_Read(0x1C4) - tpm:parameter(1):value is out of range or is not correct for the context
ERROR: Failed to read NVRAM area at index 0x1C00002
ERROR: Unable to run tpm2_nvread
+ echo 'This fails'
This fails
+ tpm2_nvread -Q 0x1c00002 -C o -P owner -s 1024 -o ek.actual.crt
+ tpm2_nvread -Q 0x1c00002 -C o -P owner -s 512 --offset 1024 -o ek.offset.crt
+ cat ek.offset.crt
+ diff ek.expected.crt ek.actual.crt

So, without owner password, tpm2_nvread can read the complete cert After adding a password, you can read a max of 1024 bytes. The workaround is reading multiple times with the --offset option

Strange. @dnoliver is this behavior specific to swtpm?

dnoliver commented 3 years ago

This is happening in a Microsoft HyperV VM with vTPM.

idesai commented 3 years ago

This is happening in a Microsoft HyperV VM with vTPM.

I see. Thank you, it is good to be aware.

dnoliver commented 3 years ago

I confirmed that the Microsoft Hyper-V vTPM is misbehaving :(

The following test creates an nv item with the same size of the vTPM EKCert, and tries to read it after changing auth

#!/bin/bash
set -euxo pipefail
head -c 1536 /dev/urandom > nv.test
tpm2_clear
tpm2_nvdefine 0x1500015 -C o -s 1536 -a "authwrite|ownerwrite|authread|ownerread|no_da"
tpm2_nvwrite -Q 0x1500015 -C o -i nv.test
tpm2_nvread -Q 0x1500015 -C o
tpm2_changeauth -c o "owner"
tpm2_nvread -Q 0x1500015 -C o -P "owner"

Running it in a container with the vTPM resource manager mounted fails at the last tpm2_nvread And running it in a container using the TPM Simulator (https://github.com/nokia/TPMCourse) does not fail.

Is this something that should be reported to Microsoft?