ECC Endorsement Certificate not generated by swtpm_setup
janwytze opened this issue · 9 comments
Describe the bug
ECC Endorsement Certificate not generated by swtpm_setup while using the --ecc
is used.
To Reproduce
- Use
swtpm_setup --tpmstate /tmp/mytpm2 --ecc --create-ek-cert --create-platform-cert --tpm2 --lock-nvram
to setup swtpm. - Run
tpm2_getekcertificate -o ek_rsa.crt -o ek_ecc.crt
, will outputWARN: Ignoring the additional output file since only 1 cert found on NV
.
Expected behavior
An EC Endorsement Key Certificate is expected at nv index 0x01C0000A
.
Desktop:
- OS: Debian (Docker)
- Version
bullseye-slim
Versions of relevant components
- swtpm: 0.8.0 and 0.7.4
- libtpms: 0.8.8
- openssl: OpenSSL 1.1.1n 15 Mar 2022
- gnutls: gnutls-cli 3.7.1
Additional context
The RSA EK certificate is generated, but the ECC is not.
Here's the output of the swtpm_setup run:
$ swtpm_setup --tpmstate ./ --overwrite --ecc --create-ek-cert --create-platform-cert --tpm2 --lock-nvram
Starting vTPM manufacturing as stefanb:stefanb @ Wed 07 Dec 2022 09:48:09 AM EST
TPM is listening on Unix socket.
Successfully created RSA 2048 EK with handle 0x81010001.
Invoking /usr/share/swtpm/swtpm-localca --type ek --ek e3d36ac7107c42db6567fb344a82724ca27dff57a3c4005bbc4c39f0ea3d1a4132550330b97aa3981f43cc3ed8291310106722c3d818a8a6d43c9ca3dbabffb79679ec400860750e58b395e644fb89d314cc53d565d8f732e32b217d4eefbb872c443e444eddf4af2de6f8864d0da381d59234fc3222f0bac1d5a5da3c4ae865d34d0074a3f6e07c9d54df792583d8107d71e41ddc1060fbe5a0b92760a794b4e34991ccd7f382eb3bffb93cb6d33b8731edad3948757fbf0968b599e467bd6e2195a66a703c4fdfce077cebb3a30855ea6c64e8f89c9c6498223c734f64822842bfca03c948d6e934ca11ef344371094838d008d7b1ac9d8e98f96ac0517f09 --dir /tmp/swtpm_setup.certs.SUW1W1 --tpm-spec-family 2.0 --tpm-spec-level 0 --tpm-spec-revision 164 --tpm-manufacturer id:00001014 --tpm-model swtpm --tpm-version id:20191023 --tpm2 --configfile /home/stefanb/.config/swtpm-localca.conf --optsfile /home/stefanb/.config/swtpm-localca.options
swtpm-localca: Successfully created EK certificate locally.
Invoking /usr/share/swtpm/swtpm-localca --type platform --ek e3d36ac7107c42db6567fb344a82724ca27dff57a3c4005bbc4c39f0ea3d1a4132550330b97aa3981f43cc3ed8291310106722c3d818a8a6d43c9ca3dbabffb79679ec400860750e58b395e644fb89d314cc53d565d8f732e32b217d4eefbb872c443e444eddf4af2de6f8864d0da381d59234fc3222f0bac1d5a5da3c4ae865d34d0074a3f6e07c9d54df792583d8107d71e41ddc1060fbe5a0b92760a794b4e34991ccd7f382eb3bffb93cb6d33b8731edad3948757fbf0968b599e467bd6e2195a66a703c4fdfce077cebb3a30855ea6c64e8f89c9c6498223c734f64822842bfca03c948d6e934ca11ef344371094838d008d7b1ac9d8e98f96ac0517f09 --dir /tmp/swtpm_setup.certs.SUW1W1 --tpm-spec-family 2.0 --tpm-spec-level 0 --tpm-spec-revision 164 --tpm-manufacturer id:00001014 --tpm-model swtpm --tpm-version id:20191023 --tpm2 --configfile /home/stefanb/.config/swtpm-localca.conf --optsfile /home/stefanb/.config/swtpm-localca.options
swtpm-localca: Successfully created platform certificate locally.
Successfully created NVRAM area 0x1c00002 for RSA 2048 EK certificate.
Successfully created NVRAM area 0x1c08000 for platform certificate.
Successfully created ECC EK with handle 0x81010016.
Invoking /usr/share/swtpm/swtpm-localca --type ek --ek x=54fdad930ed32a0ad7bb801da48ce7526fb86745af63959e652d42b275231c9caf8c3defc42ab58593897d3384110712,y=e1a7f26bb0bfacca7b2c6540839018457fe7764252032879f70362b5457df0ce3aaef742f40525016cf4c8354098651f,id=secp384r1 --dir /tmp/swtpm_setup.certs.SUW1W1 --tpm-spec-family 2.0 --tpm-spec-level 0 --tpm-spec-revision 164 --tpm-manufacturer id:00001014 --tpm-model swtpm --tpm-version id:20191023 --tpm2 --configfile /home/stefanb/.config/swtpm-localca.conf --optsfile /home/stefanb/.config/swtpm-localca.options
swtpm-localca: Successfully created EK certificate locally.
Successfully created NVRAM area 0x1c00016 for ECC EK certificate.
Successfully activated PCR banks sha256 among sha1,sha256,sha384,sha512.
Successfully authored TPM state.
Ending vTPM manufacturing @ Wed 07 Dec 2022 09:48:09 AM EST
Since swtpm 0.4 swtpm_setup has been creating a NIST-P384/secp384r1 key and stores it at location 0x1c00016
. You will have to search through known NVRAM locations to find what is provided.
Documentation is here: https://github.com/stefanberger/swtpm/wiki/Certificates-created-by-swtpm_setup#tpm-2-certificates
TCG docs section 2.2.1.5.1: https://trustedcomputinggroup.org/wp-content/uploads/TCG_IWG_Credential_Profile_EK_V2.1_R13.pdf
Thanks! I somehow expected a NIST P-256
certificate to be created. The NIST P-256
is also hardcoded in the tpm2_getekcertificate command. Why has the switch from NIST P-256
to NIST P-384
been made?
Why has the switch from
NIST P-256
toNIST P-384
been made?
Primarily to get the switch to NIST-P384 behind us asap. I would expect this to come in the future anyway.
Is there a way I can write an P-256 EK key to the NVRAM? I've used the following command to generate one:
$ swtpm_localca --tpm2 --type ek --tpm-manufacturer 00001014 --tpm-model swtpm --tpm-version 20221208 --tpm-spec-family 2.0 --tpm-spec-level 0 --tpm-spec-revision 146 --ek x=$(openssl rand -hex 32 | tr -d '\n '),y=$(openssl rand -hex 32 | tr -d '\n '),id=secp256r1
But I am not able to find a way I can write it from a Dockerfile. The swtpm daemon can not run during a Docker build process, so I can not just write to the tpm using tpm-tools.
I've found the C function that writes the EK, but I cannot just run that from the command line:
Line 1336 in c6b78f4
But I am not able to find a way I can write it from a Dockerfile. The swtpm daemon can not run during a Docker build process, so I can not just write to the tpm using tpm-tools.
Can you run a script from within the Dockerfile that RUNs swtpm and lets you use the tpm tools to write the cert into it and terminates swtpm in the end?
Executing this script in a single RUN
seems to work:
dbus-daemon --fork --system
swtpm socket --tpmstate dir=/tmp/mytpm2 --tpm2 --ctrl type=tcp,port=2322 --server type=tcp,port=2321 --flags not-need-init -d
tpm2-abrmd --tcti="swtpm:port=2321" --allow-root &
tpm2_nvdefine 0x01c0000a -C p -a 'ppwrite|writedefine|ppread|ownerread|authread|no_da|platformcreate'
tpm2_nvwrite 0x01c0000a -C p -i ek.cert
tpm2_nvwritelock 0x01c0000a -C p
rm /run/dbus/pid
@stefanberger why does the create certificate does not have a public key included?
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 5 (0x5)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = swtpm-localca
Validity
Not Before: Dec 14 12:07:16 2022 GMT
Not After : Dec 31 23:59:59 9999 GMT
Subject: CN = unknown
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Unable to load Public Key
139884896372032:error:1012606B:elliptic curve routines:EC_POINT_set_affine_coordinates:point is not on curve:../crypto/ec/ec_lib.c:813:
139884896372032:error:10098010:elliptic curve routines:o2i_ECPublicKey:EC lib:../crypto/ec/ec_asn1.c:1200:
139884896372032:error:100D708E:elliptic curve routines:eckey_pub_decode:decode error:../crypto/ec/ec_ameth.c:174:
139884896372032:error:0B09407D:x509 certificate routines:x509_pubkey_decode:public key decode error:../crypto/x509/x_pubkey.c:125:
X509v3 extensions:
X509v3 Extended Key Usage:
2.23.133.8.1
X509v3 Subject Alternative Name: critical
DirName:/2.23.133.2.1=00001014/2.23.133.2.2=swtpm/2.23.133.2.3=20221208
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Directory Attributes:
0.0...g....1.0...2.0.......
X509v3 Authority Key Identifier:
keyid:F4:68:DF:93:F4:24:28:6D:82:5B:5F:01:93:0B:C5:E0:9F:DE:CB:76
X509v3 Key Usage: critical
Key Agreement
Signature Algorithm: sha256WithRSAEncryption
73:08:7c:f0:d0:fa:9f:73:22:f5:fb:f9:70:2e:ab:48:9b:75:
13:38:b7:86:5a:ac:10:8a:cd:82:2c:d5:40:00:70:08:08:5e:
16:42:9f:5d:44:78:55:3b:9c:e3:37:4d:99:d3:02:12:e4:7f:
99:a6:0a:00:db:d0:43:59:7c:2b:c7:b7:18:82:fa:0a:ab:2f:
ee:de:a4:69:11:71:c5:9b:3d:1d:77:0e:5d:f6:8e:a4:04:4d:
2b:d1:d5:c8:b7:34:a4:21:cd:a9:e3:e2:91:3e:35:45:15:e9:
06:57:9f:b1:f5:75:87:d4:a9:e8:e6:e4:2c:6b:74:d7:27:ce:
fa:ed:75:9d:09:0b:1b:ff:ce:d1:a8:58:5f:f1:6a:f6:49:c5:
ad:2b:99:b4:b5:17:d7:28:d7:b4:66:e7:8a:42:b1:2e:e7:13:
a9:02:7e:d7:99:9c:04:98:b4:56:49:d2:f1:a1:da:c3:d0:7d:
b3:24:ab:5d:88:55:d4:1c:b4:4b:4f:37:4e:a0:28:4e:97:bd:
f3:db:f6:26:3d:79:0c:52:c7:b2:78:c2:f3:48:81:04:6c:3f:
53:02:51:97:b3:71:14:ad:af:99:72:73:87:e2:f4:00:d7:07:
1a:24:73:b9:38:33:05:3a:b4:77:3b:d2:7f:cc:84:96:69:2a:
31:e6:d0:34:49:1f:be:89:c9:af:40:ca:c4:59:43:73:cf:aa:
09:94:7c:8a:c6:8a:8d:0a:e1:9d:35:ec:10:6c:ff:58:59:79:
54:56:70:9f:69:e9:29:1b:3d:64:fb:87:c2:8b:e4:fc:2d:dc:
bf:60:b7:28:8e:a9:39:67:d2:43:8c:5e:3a:f4:8c:07:e7:63:
e1:9f:77:cd:ea:d1:93:54:87:b0:27:5a:9c:5f:60:40:81:bc:
3b:7e:14:2c:2e:20:71:9d:24:35:ed:2f:d7:a1:2a:92:27:dd:
64:8a:27:79:fe:f3:d6:d3:44:61:b9:02:c0:05:34:4f:b6:79:
aa:16:ed:3c:24:9b
When I take the logging output from above I get the following for sec384r1:
> mkdir -p /tmp/swtpm_setup.certs.SUW1W1
> /usr/share/swtpm/swtpm-localca --type ek --ek x=54fdad930ed32a0ad7bb801da48ce7526fb86745af63959e652d42b275231c9caf8c3defc42ab58593897d3384110712,y=e1a7f26bb0bfacca7b2c6540839018457fe7764252032879f70362b5457df0ce3aaef742f40525016cf4c8354098651f,id=secp384r1 --dir /tmp/swtpm_setup.certs.SUW1W1 --tpm-spec-family 2.0 --tpm-spec-level 0 --tpm-spec-revision 164 --tpm-manufacturer id:00001014 --tpm-model swtpm --tpm-version id:20191023 --tpm2 --configfile /home/stefanb/.config/swtpm-localca.conf --optsfile /home/stefanb/.config/swtpm-localca.options
> openssl x509 -inform der -in /tmp/swtpm_setup.certs.SUW1W1/ek.cert -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 44 (0x2c)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = swtpm-localca
Validity
Not Before: Dec 14 13:37:57 2022 GMT
Not After : Dec 31 23:59:59 9999 GMT
Subject: CN = unknown
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (384 bit)
pub:
04:54:fd:ad:93:0e:d3:2a:0a:d7:bb:80:1d:a4:8c:
e7:52:6f:b8:67:45:af:63:95:9e:65:2d:42:b2:75:
23:1c:9c:af:8c:3d:ef:c4:2a:b5:85:93:89:7d:33:
84:11:07:12:e1:a7:f2:6b:b0:bf:ac:ca:7b:2c:65:
40:83:90:18:45:7f:e7:76:42:52:03:28:79:f7:03:
62:b5:45:7d:f0:ce:3a:ae:f7:42:f4:05:25:01:6c:
f4:c8:35:40:98:65:1f
ASN1 OID: secp384r1
NIST CURVE: P-384
X509v3 extensions:
[...]
So this looks good with secp384r1.
I created a prime256v1 (= secp256r1) key:
> openssl ecparam -genkey -out eckey.der -outform der -name prime256v1
> openssl ec -in eckey.der -inform der -text -noout
read EC key
Private-Key: (256 bit)
priv:
32:c5:b9:70:3b:f1:c2:f6:bc:c3:6c:ca:96:25:96:
03:85:56:9b:b4:e4:c8:7b:cb:be:f0:e7:61:3f:d1:
2f:a7
pub:
04:f8:39:c2:5e:f9:16:27:6b:ff:3f:af:8d:52:a1:
09:8f:2e:fa:d2:20:b9:83:20:03:a0:ec:25:91:77:
8b:74:4a:9f:c9:3e:1c:ce:21:f1:7b:fd:0e:5a:1e:
64:a5:cf:f5:72:4c:6d:0a:e5:66:7d:e4:57:9f:f7:
ad:93:c3:66:cc
ASN1 OID: prime256v1
NIST CURVE: P-256
Get x and y from it and create cert:
> x=$(echo 'f8:39:c2:5e:f9:16:27:6b:ff:3f:af:8d:52:a1:09:8f:2e:fa:d2:20:b9:83:20:03:a0:ec:25:91:77:8b:74:4a' | sed 's/://g' )
> y=$(echo '9f:c9:3e:1c:ce:21:f1:7b:fd:0e:5a:1e:64:a5:cf:f5:72:4c:6d:0a:e5:66:7d:e4:57:9f:f7:ad:93:c3:66:cc' | sed 's/://g')
> /usr/share/swtpm/swtpm-localca --type ek --ek x=${x},y=${y},id=secp256r1 --dir /tmp/swtpm_setup.certs.SUW1W1 --tpm-spec-family 2.0 --tpm-spec-level 0 --tpm-spec-revision 164 --tpm-manufacturer id:00001014 --tpm-model swtpm --tpm-version id:20191023 --tpm2 --configfile /home/stefanb/.config/swtpm-localca.conf --optsfile /home/stefanb/.config/swtpm-localca.options
> openssl x509 -inform der -in /tmp/swtpm_setup.certs.SUW1W1/ek.cert -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 53 (0x35)
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN = swtpm-localca
Validity
Not Before: Dec 14 23:10:41 2022 GMT
Not After : Dec 31 23:59:59 9999 GMT
Subject: CN = unknown
Subject Public Key Info:
Public Key Algorithm: id-ecPublicKey
Public-Key: (256 bit)
pub:
04:f8:39:c2:5e:f9:16:27:6b:ff:3f:af:8d:52:a1:
09:8f:2e:fa:d2:20:b9:83:20:03:a0:ec:25:91:77:
8b:74:4a:9f:c9:3e:1c:ce:21:f1:7b:fd:0e:5a:1e:
64:a5:cf:f5:72:4c:6d:0a:e5:66:7d:e4:57:9f:f7:
ad:93:c3:66:cc
ASN1 OID: prime256v1
NIST CURVE: P-256
X509v3 extensions:
X509v3 Extended Key Usage:
2.23.133.8.1
[...]
So the output is as expected for secp256r1. I would suggest to check your input or work with a real key's x and y parameters rather than random numbers.
Edit: OpenSSL checks whether the points are on the curve and bails out if they are not - this is due to the random numbers. The certificate is basically useless and shouldn't be created though GnuTLS in this doesn't seem to care creating this certificate. For as long as GnuTLS checks that the point is on the curve when it does math with it, that's important.
Thanks!! I made a simple bash script to extract the X and Y from the P256 EK:
tpm2_createek -G ecc -c - -u ek.pub -f der
PUBLIC_KEY=$(openssl ec -pubin -in ek.pub -inform DER -pubout -text | head -n 7 | tail -n 5 | tr -d '[:space:]:' | tail -c128)
PUBLIC_KEY_X=$(echo -n $PUBLIC_KEY | head -c64)
PUBLIC_KEY_Y=$(echo -n $PUBLIC_KEY | tail -c64)
swtpm_localca --tpm2 --type ek --tpm-manufacturer 00001014 --tpm-model swtpm --tpm-version 20221208 --tpm-spec-family 2.0 --tpm-spec-level 0 --tpm-spec-revision 146 --ek x=$PUBLIC_KEY_X,y=$PUBLIC_KEY_Y,id=secp256r1
tpm2_nvdefine 0x01c0000a -C p -a 'ppwrite|writedefine|ppread|ownerread|authread|no_da|platformcreate' -s $(stat --printf="%s" ek.cert)
tpm2_nvwrite 0x01c0000a -C p -i ek.cert
tpm2_nvwritelock 0x01c0000a -C p