tpm2-software / tpm2-openssl

OpenSSL Provider for TPM2 integration
BSD 3-Clause "New" or "Revised" License
88 stars 37 forks source link

Interpret absent emptyAuth field in PEM file to mean authorization is required #121

Open salrashid123 opened 4 months ago

salrashid123 commented 4 months ago

the specs here for emptyAuth field for PEM encoded tpm keys

states that if the emptyauth field is absent, it should get interpreted as 'required'

$ openssl genpkey -provider tpm2 -algorithm RSA  -out private.pem
$ openssl asn1parse -inform PEM -in private.pem
    0:d=0  hl=4 l= 530 cons: SEQUENCE          
    4:d=1  hl=2 l=   6 prim: OBJECT            :2.23.133.10.1.3
   12:d=1  hl=2 l=   3 cons: cont [ 0 ]        
   14:d=2  hl=2 l=   1 prim: BOOLEAN           :1
   17:d=1  hl=2 l=   4 prim: INTEGER           :40000001

### using https://github.com/salrashid123/tpm2genkey
$ go  run cmd/main.go  --out=/tmp/private.pem
$ openssl asn1parse -inform PEM -in /tmp/private.pem
    0:d=0  hl=4 l= 532 cons: SEQUENCE          
    4:d=1  hl=2 l=   6 prim: OBJECT            :2.23.133.10.1.3
   12:d=1  hl=2 l=   3 cons: cont [ 0 ]        
   14:d=2  hl=2 l=   1 prim: BOOLEAN           :255
   17:d=1  hl=2 l=   4 prim: INTEGER           :40000001
$ openssl genpkey -provider tpm2 -algorithm RSA -pkeyopt user-auth:foo -out private.pem
$ openssl asn1parse -inform PEM -in private.pem
    0:d=0  hl=4 l= 530 cons: SEQUENCE          
    4:d=1  hl=2 l=   6 prim: OBJECT            :2.23.133.10.1.3
   12:d=1  hl=2 l=   3 cons: cont [ 0 ]        
   14:d=2  hl=2 l=   1 prim: BOOLEAN           :0
   17:d=1  hl=2 l=   4 prim: INTEGER           :40000001

### using https://github.com/salrashid123/tpm2genkey
$ go  run cmd/main.go --password=foo --out=/tmp/private.pem
$ openssl asn1parse -inform PEM -in /tmp/private.pem
    0:d=0  hl=4 l= 527 cons: SEQUENCE          
    4:d=1  hl=2 l=   6 prim: OBJECT            :2.23.133.10.1.3
   12:d=1  hl=2 l=   4 prim: INTEGER           :40000001

However, tpm2-openssl seems to always look for an explicit definition to be present to trigger userAuath (i.,e it must be present with a zero value for the BOOLEAN ). If this provider doens't see the field at all, it proceeds if it no userAuth is rquired.

unfortuantely, I don't have a 'direct' line in code to cite to back this claim up but i can show it emperically with a utility i wrowup here. With that you can generate akey with user auth with

go run cmd/main.go  --alg=rsa --out=private.pem --password=foo`
## you'll see emptyAuth is omitted
### then using this provider, it looks like its suggests auth isn't rquired
openssl asn1parse -inform PEM -in private.pem  
$ echo -n "bar" > tmp/data.in.raw
$ openssl pkeyutl -provider tpm2  -provider default -inkey private.pem -passin pass:foo -sign -rawin -in /tmp/data.in.raw -out /tmp/data.out.signed
WARNING:esys:src/tss2-esys/api/Esys_Sign.c:314:Esys_Sign_Finish() Received TPM Error 
ERROR:esys:src/tss2-esys/api/Esys_Sign.c:108:Esys_Sign() Esys Finish ErrorCode (0x0000098e) 
Public Key operation error
40A7649AFB7F0000:error:4000000F:tpm2::cannot sign::-1:2446 tpm:session(1):the authorization HMAC check failed and DA counter incremented

the underlying library i used there is Foxboron/go-tpm-keyfiles) where if i edited Marshaller to always emit the emtpyAuth field, openssl works fine

gotthardp commented 1 month ago

Yeah, this is a bug. A missing emptyAuth is read as -1 and thus interpreted as true.