Re: [RFC PATCH v2 00/11] x86: Support Intel Key Locker

From: Andy Lutomirski
Date: Wed May 19 2021 - 19:26:38 EST


On 5/18/21 10:52 AM, Sean Christopherson wrote:
> On Tue, May 18, 2021, Andy Lutomirski wrote:
>> On 5/17/21 11:21 AM, Bae, Chang Seok wrote:
>>> First of all, there is an RFC series for KVM [2].
>>>
>>> Each CPU has one internal key state so it needs to reload it between guest and
>>> host if both are enabled. The proposed approach enables it exclusively; expose
>>> it to guests only when disabled in a host. Then, I guess a guest may enable it.
>>
>> I read that series. This is not a good solution.
>>
>> I can think of at least a few reasonable ways that a host and a guest
>> can cooperate to, potentially, make KL useful.
>>
>> a) Host knows that the guest will never migrate, and guest delegates
>> IWKEY management to the host. The host generates a random key and does
>> not permit the guest to use LOADIWKEY. The guest shares the random key
>> with the host. Of course, this means that a host key handle that leaks
>> to a guest can be used within the guest.
>
> If the guest and host share a random key, then they also share the key handle.
> And that handle+key would also need to be shared across all guests. I doubt this
> option is acceptable on the security front.
>

Indeed. Oddly, SGX has the exact same problem for any scenario in which
SGX is used for HSM-like functionality, and people still use SGX.

However, I suspect that there will be use cases in which exactly one VM
is permitted to use KL. Qubes might want that (any Qubes people around?)

> Using multiple random keys is a non-starter because they can't be restored via
> LOADIWKEY.
>
> Using multiple software-defined keys will have moderate overhead because of the
> possibility of using KL from soft IRQ context, i.e. KVM would have to do
> LOADIWKEY on every VM-Enter _and_ VM-Exit. It sounds like LOADIWKEY has latency
> similar to WRMSR, so it's not a deal-breaker, but the added latency on top of the
> restrictions on how the host can use KL certainly lessen the appeal.

Indeed. This stinks.

>
>> b) Host may migrate the guest. Guest delegates IWKEY management to the
>> host, and the host generates and remembers a key for the guest. On
>> migration, the host forwards the key to the new host. The host can
>> still internally any type of key, but context switches may be quite slow.
>
> Migrating is sketchy because the IWKEY has to be exposed to host userspace.
> But, I think the migration aspect is a secondary discussion.
>
>> c) Guest wants to manage its own non-random key. Host lets it and
>> context switches it.
>
> This is essentially a variant of (b). In both cases, the host has full control
> over the guest's key.
>
>> d) Guest does not need KL and leaves CR4.KL clear. Host does whatever
>> it wants with no overhead.
>>
>> All of these have tradeoffs.
>>
>> My current thought is that, if Linux is going to support Key Locker,
>> then this all needs to be explicitly controlled. On initial boot, Linux
>> should not initialize Key Locker. Upon explicit administrator request
>> (via sysfs?), Linux will initialize Key Locker in the mode requested by
>> the administrator.
>
> Deferring KL usage to post-boot can work, but KVM shouldn't be allowed to expose
> KL to a guest until KL has been explicitly configured in the host. If KVM can
> spawn KL guests before the host is configured, the sysfs knob would have to deal
> with the case where the desired configuration is incompatible with exposing KL
> to a guest.

There could be a host configuration "guest_only", perhaps.

>
>> Modes could include:
>>
>> native_random_key: Use a random key per the ISA.
>>
>> native_kernel_key_remember: Use a random key but load it as a non-random
>> key. Remember the key in kernel memory and use it for S3 resume, etc.
>
> What would be the motivation for this mode? It largely defeats the value
> proposition of KL, no?

It lets userspace use KL with some degree of security.

>
>> native_kernel_key_backup: Use a random key, put it in the backup
>> storage, and forget it. Use the backup for resume, etc.
>>
>> native_kernel_key_norestore: Use a random key. The key is lost on any
>> power transition that forgets the key. Backup is not used.
>>
>> paravirt_any: Ask the hypervisor to handle keying. Any mechanism is
>> acceptable.
>>
>> paravirt_random: Ask the hypervisor for a random key. Only succeeds if
>> we get an actual random key.
>
> AFAIK, there's no way for the guest to verify that it got a truly random key.
> Hell, the guest can't even easily verify that KL is even supported. The host
> can lie about CPUID and CR4.KL, and intercept all KL instructions via #UD by
> running the guest with CR4.KL=0.

The guest can use TDX. Oh wait, TDX doesn't support KL.

That being said, a host attack on the guest of this sort would be quite
slow.

>
> I also don't see any reason to define a paravirt interface for a truly random
> key. Using a random key all but requires a single guest to have exclusive access
> to KL, and in that case the host can simply expose KL to only that guest.
>
>> Does this make sense?
>
> I really want to use see concrete guest use cases before we start adding paravirt
> interfaces.
>

I want to see concrete guest use cases before we start adding *any*
guest support. And this cuts both ways -- I think that, until the guest
use cases are at least somewhat worked out, Linux should certainly not
initialize KL by default on boot if the CPUID hypervisor bit is set.