stefanberger / swtpm

Libtpms-based TPM emulator with socket, character device, and Linux CUSE interface.
Other
567 stars 136 forks source link

Inconsistent EK public key with certificate #424

Closed baloo closed 3 years ago

baloo commented 3 years ago

Describe the bug When trying to create a local EK and verifying it against the EK certificate I get an inconsistent RSA moduli:

$ tpm2 createek --ek-context ek.ctx --key-algorithm rsa --public ek.pub
$ tpm2 print --type TPM2B_PUBLIC ek.pub
name-alg:
  value: sha256
  raw: 0xb
attributes:
  value: fixedtpm|fixedparent|sensitivedataorigin|adminwithpolicy|restricted|decrypt
  raw: 0x300b2
type:
  value: rsa
  raw: 0x1
exponent: 65537
bits: 2048
scheme:
  value: null
  raw: 0x10
scheme-halg:
  value: (null)
  raw: 0x0
sym-alg:
  value: aes
  raw: 0x6
sym-mode:
  value: cfb
  raw: 0x43
sym-keybits: 128
rsa: d45b1b39059419845ca8500f24f882b21d5c642c782197c4277a1cd4772bff16fa40327bf6630ffa1393518defb03be6a66ccf5ff3741c471f9f4bfea98aa10b74577f8b38cd50e69bf8dc80d2ee59eedd2a4fa47be4251582a27b397aeea8b8b6975eb3bdef2815f3f1d2f859c5bbacb3e8495a897fef21cf2fac3b0a4f62ec42fcddd3d83b84e6865593df32606ed4873a981b733adb61f8ebf5801b9cf420eb0f013434abddf6402b865c90f4221372db353e3d0dfb972845df3f1c6e5b5df8e9c2c212527370ab4fae06b4cd75e05b3519b4b95fca72ecf29976649dfd5c1f08d708c4a4c6c9aa0b9ad60f0d05dbd755300eaeea00932440c88a8f9c4953
authorization policy: 837197674484b3f81a90cc8d46a5d724fd52d76e06520b64f2a1da1b331469aa
$ tpm2 nvread -o ek.crt 0x01c00002
$ openssl x509 -inform der -in ek.crt -noout -modulus
Modulus=F916CD6E49D4C8ACF50F715AF1BE68E39BA23A74EFB079804C77AC9F23052DA5E7B26B315584E397513AAE28DB2E388C32A69DDFE877E557E7CC0381313467C919982E47768DEE00C8257D2884ABFB6627703CF741789416357EAD8C1C97F8F0D52E892F5FD8D7EB9C75C9817E371B1B82F6FE7CE9986A85D429100F4536C856DD5FE0C6D5A9DBBE5762F17F20CD808E9AB341EB8F328236FD86EB87A8D881BA4FC583C429A86AD381036F98CE0B9BD440B1C704E4E489271D372A7FF6429103A2CC25E51627B780FAE95D00848510DD9053B5BD57E151E0CACA629F8376EF8106C4CF5CB9FD2B7A7E4F6ACEAB08246FB907412D1F0C2EA92D155786CF97F5FD

My swtpm configuration is available here: https://github.com/baloo/reproducibility-lab/blob/baloo/wip/pcr-eventlog-attestation/pkgs/pcr-eventlog-attestation/shell.nix#L33-L169

The same configuration works when used within QEMU with the same version of tpm2-tools. That problem is only triggered when I start swtpm manually and try to talk with it with tpm2-tools. I think I'm missing an initialization or something, but I've been looking for it for hours now and I have been unable to find what I'm missing. Thanks for your help (and software!!)!

To Reproduce Steps to reproduce the behavior:

  1. start swtpm
  2. tpm2 createek --ek-context ek.ctx --key-algorithm rsa --public ek.pub
  3. tpm2 nvread -o ek.crt 0x01c00002

Expected behavior Have createek produce the same moduli as the ek certificate

Desktop (please complete the following information):

Versions of relevant components

Additional context Add any other context about the problem here.

baloo commented 3 years ago

For what it's worth, the moduli for the ek_cert is the one created by the localca and put in the tpm state file. The createek is "wrong"

stefanberger commented 3 years ago

The createek is "wrong"

Does that mean you found the bug?

baloo commented 3 years ago

Sadly no. What I meant is, my swtpm_setup issues commands like:

Invoking /nix/store/4l5qsbh4fam5k6893nfm8v5ip4hvxmcr-swtpm-0.5.2/share/swtpm/swtpm-localca --type ek --ek 97096cb00000283fcbdbdfd7feea53b58c3816cabc34c17ed0844a6e8e744e7d049bc3781cb85c09a00e45d4c60045249414f43c61a6c8adbcba8c5e577faccfcecfe877cf7040d4bfd0940ef62b2bf514880194de55cf0d54c667a07c3289beab86c70f6245d2c281f364da6f19f215ffc3841fc52941e69a64e718a846fc4bcf07ae49c2080844955e90500d5161a4159ab3ebebcc2b46fa6e59a1e7d09a83de40b89b2cbc621144f8e1dd104779185a3b4cbfcc729071e2b05d5b080649ce499f251e9bc611ebfd8489979ca5a89387122ca20f419f922d6ece87745f821553436211b4a15b558567a50cabb66d2f20f171ffe1f20188e2b8b62602ef54d1 --dir target/data --tpm-spec-family 2.0 --tpm-spec-level 0 --tpm-spec-revision 150 --tpm-manufacturer id:00001014 --tpm-model swtpm --tpm-version id:20170619 --tpm2 --configfile /nix/store/9ijrsli43qvmcwwdgd2nj8dqzxpi3jjs-swtpm-localca.conf --optsfile /nix/store/4l5qsbh4fam5k6893nfm8v5ip4hvxmcr-swtpm-0.5.2/etc/swtpm-localca.options

then the nvram looks like the correct one:

$ tpm2 nvread -o ek.crt 0x01c00002; openssl x509 -inform der -in ek.crt -noout -modulus
Modulus=97096CB00000283FCBDBDFD7FEEA53B58C3816CABC34C17ED0844A6E8E744E7D049BC3781CB85C09A00E45D4C60045249414F43C61A6C8ADBCBA8C5E577FACCFCECFE877CF7040D4BFD0940EF62B2BF514880194DE55CF0D54C667A07C3289BEAB86C70F6245D2C281F364DA6F19F215FFC3841FC52941E69A64E718A846FC4BCF07AE49C2080844955E90500D5161A4159AB3EBEBCC2B46FA6E59A1E7D09A83DE40B89B2CBC621144F8E1DD104779185A3B4CBFCC729071E2B05D5B080649CE499F251E9BC611EBFD8489979CA5A89387122CA20F419F922D6ECE87745F821553436211B4A15B558567A50CABB66D2F20F171FFE1F20188E2B8B62602EF54D1

Which admittedly makes sense, since it is what's written the the state file and left untouched

But if I try to createek immediately after that, I get:

$ rm ek.ctx; tpm2 createek --ek-context ek.ctx --key-algorithm rsa --public ek.pub; tpm2 print --type TPM2B_PUBLIC ek.pub | tail -2
rm: cannot remove 'ek.ctx': No such file or directory
rsa: ca90f1ee0000a9931a32db2df248473e88aaea934c92fccfb03aa7ff3947c3bf8312d6014d3db96eae3801a5860b01d77d0323a084fa50bbd074b66ab77ab395f4a45e5fa7fb0d55e17833e882c2b218af041c85a03142b176a5454628a83675ebe0b6b7a70bf0d59db3f056ad68bee6cb534bbfa385416ddb7696f6828fec25a02072234ab212ccaa772b1bbf3065ab0cd6c132fb520fd72c8ac66c7140ae20eb8bf926cde1da3d5b3020ae22d8f743bbbbb68a65971b0cf7503c1ce2deb69a3e52cb28bc7189c35834e4864c591fc3dc55da975044ae4b395258b7c90aaf3b7413b743e8664f2fd19b39655cd3790fd5e6fb0bdf0d8ec40613124c3b6a3f81
authorization policy: 837197674484b3f81a90cc8d46a5d724fd52d76e06520b64f2a1da1b331469aa

Which is not the expected moduli.

Again, I'm pretty convince this is not a bug in swtpm, but more on a startup sequence needed for the tpm to works as expected. I setup the tpm, start the swtpm, then immediately read the nvram and createek. I think I miss a startup command or something (do I need to authenticate to the tpm?). But even after passing --flags not-need-init,startup-clear that does not work as expected.

stefanberger commented 3 years ago

I recently created this wiki entry here: https://github.com/stefanberger/swtpm/wiki/Certificates-created-by-swtpm_setup#creating-the-ek

Can you follow the commands described there?

> tpm2_createek -c - -G rsa -u myek.tpm2 -c ekcontext.bin
> tpm2_readpublic -c ekcontext.bin -f pem -o myek.pem
> openssl rsa -pubin -in myek.pem -text -noout
# Compare the modulus against ek.cert from 0x01c00002
> openssl x509 -inform der -in ekcert.der -pubkey  -noout | openssl rsa -pubin -text -noout
baloo commented 3 years ago

Yes! I've read the wiki, and I'm trying to do exactly that

Here the commands output you asked:

$ tpm2 createek -c - -G rsa -u myek.tpm2 -c ekcontext.bin
$ tpm2 readpublic -c ekcontext.bin -f pem -o myek.pem
name: 000b1226035fd9fac594ac564422792f275ebfa79ef6518db6cd4d6ca23dd2459452
qualified name: 000b9ff62f9e6dda3de182fdd2ec3ddb95efa031ac170919312541db1d5e9a1c5f59
name-alg:
  value: sha256
  raw: 0xb
attributes:
  value: fixedtpm|fixedparent|sensitivedataorigin|adminwithpolicy|restricted|decrypt
  raw: 0x300b2
type:
  value: rsa
  raw: 0x1
exponent: 65537
bits: 2048
scheme:
  value: null
  raw: 0x10
scheme-halg:
  value: (null)
  raw: 0x0
sym-alg:
  value: aes
  raw: 0x6
sym-mode:
  value: cfb
  raw: 0x43
sym-keybits: 128
rsa: ca90f1ee0000a9931a32db2df248473e88aaea934c92fccfb03aa7ff3947c3bf8312d6014d3db96eae3801a5860b01d77d0323a084fa50bbd074b66ab77ab395f4a45e5fa7fb0d55e17833e882c2b218af041c85a03142b176a5454628a83675ebe0b6b7a70bf0d59db3f056ad68bee6cb534bbfa385416ddb7696f6828fec25a02072234ab212ccaa772b1bbf3065ab0cd6c132fb520fd72c8ac66c7140ae20eb8bf926cde1da3d5b3020ae22d8f743bbbbb68a65971b0cf7503c1ce2deb69a3e52cb28bc7189c35834e4864c591fc3dc55da975044ae4b395258b7c90aaf3b7413b743e8664f2fd19b39655cd3790fd5e6fb0bdf0d8ec40613124c3b6a3f81
authorization policy: 837197674484b3f81a90cc8d46a5d724fd52d76e06520b64f2a1da1b331469aa
$ openssl rsa -pubin -in myek.pem -text -noout
RSA Public-Key: (2048 bit)
Modulus:
    00:ca:90:f1:ee:00:00:a9:93:1a:32:db:2d:f2:48:
    47:3e:88:aa:ea:93:4c:92:fc:cf:b0:3a:a7:ff:39:
    47:c3:bf:83:12:d6:01:4d:3d:b9:6e:ae:38:01:a5:
    86:0b:01:d7:7d:03:23:a0:84:fa:50:bb:d0:74:b6:
    6a:b7:7a:b3:95:f4:a4:5e:5f:a7:fb:0d:55:e1:78:
    33:e8:82:c2:b2:18:af:04:1c:85:a0:31:42:b1:76:
    a5:45:46:28:a8:36:75:eb:e0:b6:b7:a7:0b:f0:d5:
    9d:b3:f0:56:ad:68:be:e6:cb:53:4b:bf:a3:85:41:
    6d:db:76:96:f6:82:8f:ec:25:a0:20:72:23:4a:b2:
    12:cc:aa:77:2b:1b:bf:30:65:ab:0c:d6:c1:32:fb:
    52:0f:d7:2c:8a:c6:6c:71:40:ae:20:eb:8b:f9:26:
    cd:e1:da:3d:5b:30:20:ae:22:d8:f7:43:bb:bb:b6:
    8a:65:97:1b:0c:f7:50:3c:1c:e2:de:b6:9a:3e:52:
    cb:28:bc:71:89:c3:58:34:e4:86:4c:59:1f:c3:dc:
    55:da:97:50:44:ae:4b:39:52:58:b7:c9:0a:af:3b:
    74:13:b7:43:e8:66:4f:2f:d1:9b:39:65:5c:d3:79:
    0f:d5:e6:fb:0b:df:0d:8e:c4:06:13:12:4c:3b:6a:
    3f:81
Exponent: 65537 (0x10001)
$ tpm2 nvread -o ek.crt 0x01c00002;openssl x509 -inform der -in ek.crt -pubkey  -noout | openssl rsa -pubin -text -noout
RSA Public-Key: (2048 bit)
Modulus:
    00:97:09:6c:b0:00:00:28:3f:cb:db:df:d7:fe:ea:
    53:b5:8c:38:16:ca:bc:34:c1:7e:d0:84:4a:6e:8e:
    74:4e:7d:04:9b:c3:78:1c:b8:5c:09:a0:0e:45:d4:
    c6:00:45:24:94:14:f4:3c:61:a6:c8:ad:bc:ba:8c:
    5e:57:7f:ac:cf:ce:cf:e8:77:cf:70:40:d4:bf:d0:
    94:0e:f6:2b:2b:f5:14:88:01:94:de:55:cf:0d:54:
    c6:67:a0:7c:32:89:be:ab:86:c7:0f:62:45:d2:c2:
    81:f3:64:da:6f:19:f2:15:ff:c3:84:1f:c5:29:41:
    e6:9a:64:e7:18:a8:46:fc:4b:cf:07:ae:49:c2:08:
    08:44:95:5e:90:50:0d:51:61:a4:15:9a:b3:eb:eb:
    cc:2b:46:fa:6e:59:a1:e7:d0:9a:83:de:40:b8:9b:
    2c:bc:62:11:44:f8:e1:dd:10:47:79:18:5a:3b:4c:
    bf:cc:72:90:71:e2:b0:5d:5b:08:06:49:ce:49:9f:
    25:1e:9b:c6:11:eb:fd:84:89:97:9c:a5:a8:93:87:
    12:2c:a2:0f:41:9f:92:2d:6e:ce:87:74:5f:82:15:
    53:43:62:11:b4:a1:5b:55:85:67:a5:0c:ab:b6:6d:
    2f:20:f1:71:ff:e1:f2:01:88:e2:b8:b6:26:02:ef:
    54:d1
Exponent: 65537 (0x10001)
stefanberger commented 3 years ago

And you are sure that the tools are always talking to the same swtpm instance ? No hardware TPM is involved or so, right? And it works from inside a VM?

I just tried tried this with the IBM TSS2 tools without a VM and it works as expected:

In one terminal as root (to use the default CA):

mkdir /tmp/testtpm
swtpm_setup --tpmstate /tmp/testtpm --tpm2 --create-ek-cert --create-platform-cert --overwrite
swtpm socket --tpmstate dir=/tmp/testtpm --tpm2 --ctrl type=tcp,port=2322 --server type=tcp,port=2321 --flags not-need-init

2nd terminal:

export TPM_COMMAND_PORT=2321 TPM_PLATFORM_PORT=2322 \
  TPM_SERVER_NAME=localhost TPM_INTERFACE_TYPE=socsim \
  TPM_SERVER_TYPE=raw

tssstartup
tssnvread -hia o -ha 0x01c00002 -of rsa2048ekcert.der

tsscreateek -cp -rsa 2048
echo "--------------------------------------"
openssl x509 -inform der -in rsa2048ekcert.der -pubkey  -noout | openssl rsa -pubin -noout -modulus

The parameter -rsa 2048 to tsscreateek may be different depending on version.

The tsscreateek command displays the same modulus as the last command. You may want to try this if you can install the IBM TSS2 tools.

stefanberger commented 3 years ago

And you don't happen to create the swtpm state in one directory with swtpm_setup and the start swtpm with another state directory (--tpmstate)?

stefanberger commented 3 years ago

Are these directories always the same? swtpm_datastore == target/data ?

      ${swtpm'}/bin/swtpm_setup \
        --tpm2 \
        --tpmstate ${swtpm_datastore} \
        --createek --allow-signing --decryption --create-ek-cert \
        --create-platform-cert \
        --display
      ${swtpm'}/bin/swtpm socket \
        --tpm2 \
        --tpmstate dir=target/data \
        -p 2321 --ctrl type=tcp,port=2322 \
        --log fd=1,level=5 \
        --flags startup-clear
baloo commented 3 years ago

It is! but you're definitely right. I'm doing something wrong in my wrapper. Starting swtpm manually fixes my issues. I'm so sorry for the noise and thank you for the help

baloo commented 3 years ago

If I remove the --allow-signing off the swtpm_setup call, it works as expected.

(I dont actually need my EK to sign, I just added all the parameters until I could make sense of them and because "that would not hurt").

stefanberger commented 3 years ago

The --allow-signing is there because a TCG infrastructure specification 'allows' it. It can be used but then requires a template to be used for EK re-creation.

baloo commented 3 years ago

So, if I add allow-signing, I need to set the keyflags = keyflags | 0x000400b2 in my key template to match, correct?

I dont need it, I'm just trying to understand things here.

stefanberger commented 3 years ago

Yes, it may either be this (https://github.com/stefanberger/swtpm/blob/stable-0.5/src/swtpm_setup/py_swtpm_setup/swtpm.py#L489) or the other case (https://github.com/stefanberger/swtpm/blob/stable-0.5/src/swtpm_setup/py_swtpm_setup/swtpm.py#L482), depend on whether decryption is also allowed. I am not sure whether there are tools that support re-creating such EKs since these are non-standard cases. For this swtpm_setup command line here:

swtpm_setup --tpmstate /tmp/testtpm --tpm2 --create-ek-cert --create-platform-cert --overwrite  --allow-signing

you get these keys and templates.

Successfully created RSA 2048 EK with handle 0x81010001.
Successfully created NVRAM area 0x1c00004 for RSA 2048 EK template.
[...]
Successfully created NVRAM area 0x1c00002 for RSA 2048 EK certificate.
Successfully created ECC EK with handle 0x81010016.
Successfully created NVRAM area 0x1c00017 for ECC EK template.
[...]

Note, the availability of templates indicates that keys were created with non-standard parameters:

You then have all of these NV indices:

tssgetcapability -cap 1 -pr 0x01c00000
5 handles
    01c00002
    01c00004
    01c00016
    01c00017
    01c08000

I'll add a note to swtpm_setup screen saying that --allow-signing will create a non-standard EK.

baloo commented 3 years ago

Thank you so much!

stefanberger commented 3 years ago

The man page already states this:

Note that the TCG specification "EK Credential Profile For TPM Family 2.0; Level 0"
suggests in its section on "EK Usage" that "the Endorsement Key can be a
created as a decryption or signing key." However, some platforms will
not accept an EK as a signing key, or as a signing and encryption key, and
therefore this option should be used very carefully.