Combining PolicyAuthorize + PolicyAuthorizeNV into one policy?

Lennart Poettering <[email protected]> Wed, 29 May 2024 10:53:59 +0200
Newsgroups dev.linux.lists.tpm2
Message-ID <ZlbtJ0jcy8rrUbUg@gardel-login>
Hi!

In systemd we nowadays implement various PCR-related TPM policies for disk
encryption and other purposes. In particular two of them are relevant:

1. We support a "signed PCR" policy. This is actually a
   PolicyAuthorize policy, where the intended use case is that an OS
   kernel vendor signs a PolicyPCR-based policy with some vendor key
   pair ahead of time, and that this would cover PCR extensions made
   if a specific vendor kernel is booted. This mostly covers PCR 11
   measurements if systemd's EFI stub is used (which measures the
   kernel to the otherwise unused PCR 11). Or in other words: if this
   is used you can lock secrets to only be released if kernels of that
   specific vendor are booted.

2. We support a "locally managed PCR" (which we dubbed "pcrlock"
   policy). This is actually a PolicyAuthorizeNV, where the intended
   use case is that a local tool manages a complex PolicyPCR/PolicyOR
   policy covering PCRs which are outside of OS vendor control,
   i.e. all the firmware PCRs and so on. The policy is recalculated
   whenever firmware updates are made, or boot loaders updated and so
   on, and the nvindex updated.

With these two mechanisms we could in theory cover most relevant PCRs
really nicely: the OS vendor controlled ones with an OS vendor signed
policy and the inherently local PCRs with the locally managed
nvindex-based policy.

Except that there's one big problem with this: I couldn't find a nice
way to join both policies into one combined policy. The problem is
that both PolicyAuthorize and PolicyAuthorizeNV do not *extend* the
policy so far sent to the TPM, but *replace* it. Thus I see no nice
way how I could fire first one of the two policies above and then the
other, and get the AND combination of both.

I guess I could include the signed PCR policy inside the policy I
stash in the NV index, but this sucks a bit, since it would mean the
objects I actually want to protect then would not carry a policy
themselves that enforces both policies to be enforced, but would
delegate enforcement of the OS vendor policy always to the local
policy. (I mean, this is not a total desaster, but I find it less than
ideal).

Does anyone have a good idea what I could do here?

I looked into use the "ticket" based policies. AFAIU i could get a
ticket for both policies and the put a policy together as combination
of those two tickets. But I think this would not be that great either
because it would mean that we cannot instantly invalidate policies via
a PCR extension anymore, and instead the time-out of the tickets would
allow accessing protected objects long after PCR extensions would
invalidate it.

Hence, anyone has a good idea about this?

(I asked around in other places already, noone could come up with a
really convincing solution yet I'd say, hence my hope that this bigger
forum can come up with a solution for this?)

Any help and suggestions greatly appreciated!

Lennart