This updates systemd-tpm2-setup to create and persist an endorsement
key if there isn't one already. For each supported EK template profile,
it will read the EK certificate from its NV index if there is one.
When there is an EK certificate present, a primary key is created using
the corresponding template. If the resulting EKpub matches the public
key in the certificate, the created EK is persisted and the process is
complete.
The low-range templates and the high-range RSA 2048/3072 and ECC NIST
P256/P384 storage templates are supported, as detailed in section
5.3 of the "TCG EK Credential Profile For TPM Family 2.0" spec v2.7.
High-range templates are preferred because these permit EK usage without
requiring knowledge of the authorization value for the endorsement
hierarchy, meaning that, like with the SRK, it is possible to restrict
the usage of the endorsement hierarchy whilst still permitting use of
the persistent EK.
The EK is always persisted at handle 0x81010001. This handle is
reserved in Table 2 of the "TCG TPM v2.0 Provisioning Guidance" spec
v1.0r1.0, although this is only a recommendation. This
handle is within the block of handles reserved for endorsement
primary keys in the "Registry of Reserved TPM 2.0 Handles and
Localities" spec v1.2r1.00. Section 2.3.2 of this specification also
makes a suggestion that there should be a relationship between the EK
certificate NV index and a corresponding persistent EK handle by
using handles at the same offsets within their respective ranges.
However, this contradicts the provisioning guidance spec which reserves
0x81010001 when there isn't a certificate at 0x01c00001. For simplicity,
I've chosen to use a single handle for the EK regardless of which profile
it is created with.
The "TCG EK Credential Profile For TPM Family 2.0" spec also provides a
way for endorsement keys to be certified with non-standard templates by
storing the template in a NV index. This is also supported.
The EK creation is not executed with tpm2-setup --early, as there's no
need for it to be created so early, unlike with the SRK. I also haven't
stored EKpub in /var/lib/systemd like with the SRKpub, as I'm not sure
there will be a use case for this yet.
A follow-up PR may be needed to add some internal helpers to make use
of the persisted EK, as use of low-range EKs requires a policy session.
High-range EKs can be used with a HMAC session because they have the
userWithAuth attribute set and we are creating them with an empty
authorization value.
https://trustedcomputinggroup.org/resource/http-trustedcomputinggroup-org-wp-content-uploads-tcg-ek-credential-profile/https://trustedcomputinggroup.org/resource/tcg-tpm-v2-0-provisioning-guidance/https://trustedcomputinggroup.org/resource/registry/
We already save it in PEM format, also store it TPM2_PUBLIC format next
to it. This is useful for usage with systemd-cryptenroll's
--tpm2-device-key= switch.
This adds an explicit service for initializing the TPM2 SRK. This is
implicitly also done by systemd-cryptsetup, hence strictly speaking
redundant, but doing this early has the benefit that we can parallelize
this in a nicer way. This also write a copy of the SRK public key in PEM
format to /run/ + /var/lib/, thus pinning the disk image to the TPM.
Making the SRK public key is also useful for allowing easy offline
encryption for a specific TPM.
Sooner or later we should probably grow what this service does, the
above is just the first step. For example, the service should probably
offer the ability to reset the TPM (clear the owner hierarchy?) on a
factory reset, if such a policy is needed. And we might want to install
some default AK (?).
Fixes: #27986
Also see: #22637