All of lore.kernel.org
 help / color / mirror / Atom feed
* privileged entropy sources in QEMU/KVM guests
@ 2019-11-07 10:10 Laszlo Ersek
  2019-11-07 10:18 ` Dr. David Alan Gilbert
                   ` (2 more replies)
  0 siblings, 3 replies; 18+ messages in thread
From: Laszlo Ersek @ 2019-11-07 10:10 UTC (permalink / raw)
  To: qemu devel list
  Cc: Daniel P. Berrange, Ard Biesheuvel, Jian J Wang,
	edk2-devel-groups-io, Bret Barkelew, Erik Bjorge, Sean Brogan,
	Paolo Bonzini, Philippe Mathieu-Daudé

Hi,

related TianoCore BZ:

  https://bugzilla.tianocore.org/show_bug.cgi?id=1871

(I'm starting this thread separately because at least some of the topics
are specific to QEMU, and I didn't want to litter the BZ with a
discussion that may not be interesting to all participants CC'd on the
BZ. I am keeping people CC'd on this initial posting; please speak up if
you'd like to be dropped from the email thread.)

QEMU provides guests with the virtio-rng device, and the OVMF and
ArmVirtQemu* edk2 platforms build EFI_RNG_PROTOCOL on top of that
device. But, that doesn't seem enough for all edk2 use cases.

Also, virtio-rng (hence EFI_RNG_PROTOCOL too) is optional, and its
absence may affect some other use cases.


(1) For UEFI HTTPS boot, TLS would likely benefit from good quality
entropy. If the VM config includes virtio-rng (hence the guest firmware
has EFI_RNG_PROTOCOL), then it should be used as a part of HTTPS boot.

However, what if virtio-rng (hence EFI_RNG_PROTOCOL) are absent? Should
UEFI HTTPS boot be disabled completely (or prevented / rejected
somehow), blaming lack of good entropy? Or should TLS silently fall back
to "mixing some counters [such as TSC] together and applying a
deterministic cryptographic transformation"?

IOW, knowing that the TLS setup may not be based on good quality
entropy, should we allow related firmware services to "degrade silently"
(not functionally, but potentially in security), or should we deny the
services altogether?


(2) It looks like the SMM driver implementing the privileged part of the
UEFI variable runtime service could need access to good quality entropy,
while running in SMM; in the future.

This looks problematic on QEMU. Entropy is a valuable resource, and
whatever resource SMM drivers depend on, should not be possible for e.g.
a 3rd party UEFI driver (or even for the runtime OS) to exhaust.
Therefore, it's not *only* the case that SMM drivers must not consume
EFI_RNG_PROTOCOL (which exists at a less critical privilege level, i.e.
outside of SMM/SMRAM), but also that SMM drivers must not depend on the
same piece of *hardware* that feeds EFI_RNG_PROTOCOL.

Furthermore, assuming we dedicate a hardware entropy device specifically
to SMM drivers, such a device cannot be PCI(e). It would have to be a
platform device at a fixed location (IO port or MMIO) that is only
accessible to such guest code that executes in SMM. IOW, device access
would have to be restricted similarly to pflash. (In fact the variable
SMM driver will need, AIUI, the entropy for encrypting various variable
contents, which are then written into pflash.)

Alternatively, CPU instructions could exist that return entropy, and are
executable only inside SMM. It seems that e.g. RDRAND can be trapped in
guests ("A VMEXIT due to RDRAND will have exit reason 57 (decimal)").
Then KVM / QEMU could provide any particular implementation we wanted --
for example an exception could be injected unless RDRAND had been
executed from within SMM. Unfortunately, such an arbitrary restriction
(of RDRAND to SMM) would diverge from the Intel SDM, and would likely
break other (non-SMM) guest code.

Does a platform device that is dynamically detectable and usable in SMM
only seem like an acceptable design for QEMU?

Thanks,
Laszlo



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 10:10 privileged entropy sources in QEMU/KVM guests Laszlo Ersek
@ 2019-11-07 10:18 ` Dr. David Alan Gilbert
  2019-11-07 11:19   ` Laszlo Ersek
  2019-11-07 10:25 ` Ard Biesheuvel
  2019-11-07 11:52 ` Daniel P. Berrangé
  2 siblings, 1 reply; 18+ messages in thread
From: Dr. David Alan Gilbert @ 2019-11-07 10:18 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Daniel P. Berrange, Ard Biesheuvel, Jian J Wang,
	edk2-devel-groups-io, Bret Barkelew, qemu devel list,
	Erik Bjorge, Sean Brogan, Paolo Bonzini,
	Philippe Mathieu-Daudé

* Laszlo Ersek (lersek@redhat.com) wrote:
> Hi,
> 
> related TianoCore BZ:
> 
>   https://bugzilla.tianocore.org/show_bug.cgi?id=1871
> 
> (I'm starting this thread separately because at least some of the topics
> are specific to QEMU, and I didn't want to litter the BZ with a
> discussion that may not be interesting to all participants CC'd on the
> BZ. I am keeping people CC'd on this initial posting; please speak up if
> you'd like to be dropped from the email thread.)
> 
> QEMU provides guests with the virtio-rng device, and the OVMF and
> ArmVirtQemu* edk2 platforms build EFI_RNG_PROTOCOL on top of that
> device. But, that doesn't seem enough for all edk2 use cases.
> 
> Also, virtio-rng (hence EFI_RNG_PROTOCOL too) is optional, and its
> absence may affect some other use cases.
> 
> 
> (1) For UEFI HTTPS boot, TLS would likely benefit from good quality
> entropy. If the VM config includes virtio-rng (hence the guest firmware
> has EFI_RNG_PROTOCOL), then it should be used as a part of HTTPS boot.
> 
> However, what if virtio-rng (hence EFI_RNG_PROTOCOL) are absent? Should
> UEFI HTTPS boot be disabled completely (or prevented / rejected
> somehow), blaming lack of good entropy? Or should TLS silently fall back
> to "mixing some counters [such as TSC] together and applying a
> deterministic cryptographic transformation"?
> 
> IOW, knowing that the TLS setup may not be based on good quality
> entropy, should we allow related firmware services to "degrade silently"
> (not functionally, but potentially in security), or should we deny the
> services altogether?

I don't see a downside to insisting that if you want to use https then
you must provide an entropy source; they're easy enough to add using
virtio-rng if the CPU doesn't provide it.

> 
> (2) It looks like the SMM driver implementing the privileged part of the
> UEFI variable runtime service could need access to good quality entropy,
> while running in SMM; in the future.
> 
> This looks problematic on QEMU. Entropy is a valuable resource, and
> whatever resource SMM drivers depend on, should not be possible for e.g.
> a 3rd party UEFI driver (or even for the runtime OS) to exhaust.
> Therefore, it's not *only* the case that SMM drivers must not consume
> EFI_RNG_PROTOCOL (which exists at a less critical privilege level, i.e.
> outside of SMM/SMRAM), but also that SMM drivers must not depend on the
> same piece of *hardware* that feeds EFI_RNG_PROTOCOL.
> 
> Furthermore, assuming we dedicate a hardware entropy device specifically
> to SMM drivers, such a device cannot be PCI(e). It would have to be a
> platform device at a fixed location (IO port or MMIO) that is only
> accessible to such guest code that executes in SMM. IOW, device access
> would have to be restricted similarly to pflash. (In fact the variable
> SMM driver will need, AIUI, the entropy for encrypting various variable
> contents, which are then written into pflash.)

Ewww.  I guess a virtio-rng instance wired to virtio-mmio could do that.
It's a bit grim though.

Dave

> Alternatively, CPU instructions could exist that return entropy, and are
> executable only inside SMM. It seems that e.g. RDRAND can be trapped in
> guests ("A VMEXIT due to RDRAND will have exit reason 57 (decimal)").
> Then KVM / QEMU could provide any particular implementation we wanted --
> for example an exception could be injected unless RDRAND had been
> executed from within SMM. Unfortunately, such an arbitrary restriction
> (of RDRAND to SMM) would diverge from the Intel SDM, and would likely
> break other (non-SMM) guest code.
> 
> Does a platform device that is dynamically detectable and usable in SMM
> only seem like an acceptable design for QEMU?
> 
> Thanks,
> Laszlo
> 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 10:10 privileged entropy sources in QEMU/KVM guests Laszlo Ersek
  2019-11-07 10:18 ` Dr. David Alan Gilbert
@ 2019-11-07 10:25 ` Ard Biesheuvel
  2019-11-07 11:37   ` Paolo Bonzini
  2019-11-07 11:58   ` Laszlo Ersek
  2019-11-07 11:52 ` Daniel P. Berrangé
  2 siblings, 2 replies; 18+ messages in thread
From: Ard Biesheuvel @ 2019-11-07 10:25 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Daniel P. Berrange, Jian J Wang, edk2-devel-groups-io,
	Bret Barkelew, qemu devel list, Erik Bjorge, Sean Brogan,
	Paolo Bonzini, Philippe Mathieu-Daudé

Hi Laszlo,

Thanks for starting this thread.


On Thu, 7 Nov 2019 at 11:11, Laszlo Ersek <lersek@redhat.com> wrote:
>
> Hi,
>
> related TianoCore BZ:
>
>   https://bugzilla.tianocore.org/show_bug.cgi?id=1871
>
> (I'm starting this thread separately because at least some of the topics
> are specific to QEMU, and I didn't want to litter the BZ with a
> discussion that may not be interesting to all participants CC'd on the
> BZ. I am keeping people CC'd on this initial posting; please speak up if
> you'd like to be dropped from the email thread.)
>
> QEMU provides guests with the virtio-rng device, and the OVMF and
> ArmVirtQemu* edk2 platforms build EFI_RNG_PROTOCOL on top of that
> device. But, that doesn't seem enough for all edk2 use cases.
>
> Also, virtio-rng (hence EFI_RNG_PROTOCOL too) is optional, and its
> absence may affect some other use cases.
>
>
> (1) For UEFI HTTPS boot, TLS would likely benefit from good quality
> entropy. If the VM config includes virtio-rng (hence the guest firmware
> has EFI_RNG_PROTOCOL), then it should be used as a part of HTTPS boot.
>
> However, what if virtio-rng (hence EFI_RNG_PROTOCOL) are absent? Should
> UEFI HTTPS boot be disabled completely (or prevented / rejected
> somehow), blaming lack of good entropy? Or should TLS silently fall back
> to "mixing some counters [such as TSC] together and applying a
> deterministic cryptographic transformation"?
>
> IOW, knowing that the TLS setup may not be based on good quality
> entropy, should we allow related firmware services to "degrade silently"
> (not functionally, but potentially in security), or should we deny the
> services altogether?
>

TLS uses a source of randomness to establish symmetric session keys
for encryption. So it really depends on the use case whether HTTPS is
used for authentication or for confidentiality, and it seems to me
that it would typically be the former. So disabling HTTPS boot in this
case seems counterproductive to me.

>
> (2) It looks like the SMM driver implementing the privileged part of the
> UEFI variable runtime service could need access to good quality entropy,
> while running in SMM; in the future.
>
> This looks problematic on QEMU. Entropy is a valuable resource, and
> whatever resource SMM drivers depend on, should not be possible for e.g.
> a 3rd party UEFI driver (or even for the runtime OS) to exhaust.
> Therefore, it's not *only* the case that SMM drivers must not consume
> EFI_RNG_PROTOCOL (which exists at a less critical privilege level, i.e.
> outside of SMM/SMRAM), but also that SMM drivers must not depend on the
> same piece of *hardware* that feeds EFI_RNG_PROTOCOL.
>

The typical model is to seed a DRBG [deterministic pseudorandom
sequence generator] using a sufficient amount of high quality entropy.
Once you have done that, it is rather hard to exhaust a DRBG - it is a
mathematical construction that is designed to last for a long time (<=
2^48 invocations [not bytes] according to the NIST spec), after which
it does not degrade although it may have generated so much output that
its internal state may be inferred if you have captured enough of it
(which is a rather theoretical issue IMHO)

The problem is that using the output of a DRBG as a seed is
non-trivial - the spec describes ways to do this, but wiring
virtio-rng to a DRBG in the host and using its output to seed a DRBG
in the guest is slighly problematic.

So it seems to me that the correct way to model this is to make the
host's true entropy source a shared resource like any other.

> Furthermore, assuming we dedicate a hardware entropy device specifically
> to SMM drivers, such a device cannot be PCI(e). It would have to be a
> platform device at a fixed location (IO port or MMIO) that is only
> accessible to such guest code that executes in SMM. IOW, device access
> would have to be restricted similarly to pflash. (In fact the variable
> SMM driver will need, AIUI, the entropy for encrypting various variable
> contents, which are then written into pflash.)
>
> Alternatively, CPU instructions could exist that return entropy, and are
> executable only inside SMM. It seems that e.g. RDRAND can be trapped in
> guests ("A VMEXIT due to RDRAND will have exit reason 57 (decimal)").
> Then KVM / QEMU could provide any particular implementation we wanted --
> for example an exception could be injected unless RDRAND had been
> executed from within SMM. Unfortunately, such an arbitrary restriction
> (of RDRAND to SMM) would diverge from the Intel SDM, and would likely
> break other (non-SMM) guest code.
>
> Does a platform device that is dynamically detectable and usable in SMM
> only seem like an acceptable design for QEMU?
>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 10:18 ` Dr. David Alan Gilbert
@ 2019-11-07 11:19   ` Laszlo Ersek
  2019-11-07 11:36     ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 18+ messages in thread
From: Laszlo Ersek @ 2019-11-07 11:19 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Daniel P. Berrange, Ard Biesheuvel, Jian J Wang,
	edk2-devel-groups-io, Bret Barkelew, qemu devel list,
	Erik Bjorge, Sean Brogan, Paolo Bonzini,
	Philippe Mathieu-Daudé

On 11/07/19 11:18, Dr. David Alan Gilbert wrote:
> * Laszlo Ersek (lersek@redhat.com) wrote:
>> Hi,
>>
>> related TianoCore BZ:
>>
>>   https://bugzilla.tianocore.org/show_bug.cgi?id=1871
>>
>> (I'm starting this thread separately because at least some of the topics
>> are specific to QEMU, and I didn't want to litter the BZ with a
>> discussion that may not be interesting to all participants CC'd on the
>> BZ. I am keeping people CC'd on this initial posting; please speak up if
>> you'd like to be dropped from the email thread.)
>>
>> QEMU provides guests with the virtio-rng device, and the OVMF and
>> ArmVirtQemu* edk2 platforms build EFI_RNG_PROTOCOL on top of that
>> device. But, that doesn't seem enough for all edk2 use cases.
>>
>> Also, virtio-rng (hence EFI_RNG_PROTOCOL too) is optional, and its
>> absence may affect some other use cases.
>>
>>
>> (1) For UEFI HTTPS boot, TLS would likely benefit from good quality
>> entropy. If the VM config includes virtio-rng (hence the guest firmware
>> has EFI_RNG_PROTOCOL), then it should be used as a part of HTTPS boot.
>>
>> However, what if virtio-rng (hence EFI_RNG_PROTOCOL) are absent? Should
>> UEFI HTTPS boot be disabled completely (or prevented / rejected
>> somehow), blaming lack of good entropy? Or should TLS silently fall back
>> to "mixing some counters [such as TSC] together and applying a
>> deterministic cryptographic transformation"?
>>
>> IOW, knowing that the TLS setup may not be based on good quality
>> entropy, should we allow related firmware services to "degrade silently"
>> (not functionally, but potentially in security), or should we deny the
>> services altogether?
> 
> I don't see a downside to insisting that if you want to use https then
> you must provide an entropy source; they're easy enough to add using
> virtio-rng if the CPU doesn't provide it.

Possibly true; however it could be considered a usability regression by
end-users. ("UEFI HTTPS boot used to work, now it breaks with the same
VM config". Unless we can respond, "UEFI HTTPS boot's TLS init has never
been secure enough", they'll have a point. See also Ard's followup.)

> 
>>
>> (2) It looks like the SMM driver implementing the privileged part of the
>> UEFI variable runtime service could need access to good quality entropy,
>> while running in SMM; in the future.
>>
>> This looks problematic on QEMU. Entropy is a valuable resource, and
>> whatever resource SMM drivers depend on, should not be possible for e.g.
>> a 3rd party UEFI driver (or even for the runtime OS) to exhaust.
>> Therefore, it's not *only* the case that SMM drivers must not consume
>> EFI_RNG_PROTOCOL (which exists at a less critical privilege level, i.e.
>> outside of SMM/SMRAM), but also that SMM drivers must not depend on the
>> same piece of *hardware* that feeds EFI_RNG_PROTOCOL.
>>
>> Furthermore, assuming we dedicate a hardware entropy device specifically
>> to SMM drivers, such a device cannot be PCI(e). It would have to be a
>> platform device at a fixed location (IO port or MMIO) that is only
>> accessible to such guest code that executes in SMM. IOW, device access
>> would have to be restricted similarly to pflash. (In fact the variable
>> SMM driver will need, AIUI, the entropy for encrypting various variable
>> contents, which are then written into pflash.)
> 
> Ewww.  I guess a virtio-rng instance wired to virtio-mmio could do that.
> It's a bit grim though.

*shudder* please let's keep virtio-mmio (or any remotely enumerable /
complex "bus" thingy) out of this :( I'm all for extensible hardware
interfaces, but cramming more and more infrastructure code into SMM
looks very questionable to me.

My main concern here is that most physical platform vendors will just
solder some physical entropy-gen chip onto their boards, and then
hard-code the MMIO base address of that as a build-time constant in
their firmware blobs. This obviously won't work for QEMU, where the hw
can change from boot to boot; so the generic edk2 solution (regardless
of the actual chip) need to allow for that kind of dynamism. This is a
recurrent problem between QEMU and edk2, alas. The answer is of course
dynamic detection, but I *still* like to keep the enumeration logic to
the absolute minimum in SMM.

Thanks!
Laszlo

> 
> Dave
> 
>> Alternatively, CPU instructions could exist that return entropy, and are
>> executable only inside SMM. It seems that e.g. RDRAND can be trapped in
>> guests ("A VMEXIT due to RDRAND will have exit reason 57 (decimal)").
>> Then KVM / QEMU could provide any particular implementation we wanted --
>> for example an exception could be injected unless RDRAND had been
>> executed from within SMM. Unfortunately, such an arbitrary restriction
>> (of RDRAND to SMM) would diverge from the Intel SDM, and would likely
>> break other (non-SMM) guest code.
>>
>> Does a platform device that is dynamically detectable and usable in SMM
>> only seem like an acceptable design for QEMU?
>>
>> Thanks,
>> Laszlo
>>
>>
> --
> Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> 



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 11:19   ` Laszlo Ersek
@ 2019-11-07 11:36     ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 18+ messages in thread
From: Dr. David Alan Gilbert @ 2019-11-07 11:36 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Daniel P. Berrange, Ard Biesheuvel, Jian J Wang,
	edk2-devel-groups-io, Bret Barkelew, qemu devel list,
	Erik Bjorge, Sean Brogan, Paolo Bonzini,
	Philippe Mathieu-Daudé

* Laszlo Ersek (lersek@redhat.com) wrote:
> On 11/07/19 11:18, Dr. David Alan Gilbert wrote:
> > * Laszlo Ersek (lersek@redhat.com) wrote:
> >> Hi,
> >>
> >> related TianoCore BZ:
> >>
> >>   https://bugzilla.tianocore.org/show_bug.cgi?id=1871
> >>
> >> (I'm starting this thread separately because at least some of the topics
> >> are specific to QEMU, and I didn't want to litter the BZ with a
> >> discussion that may not be interesting to all participants CC'd on the
> >> BZ. I am keeping people CC'd on this initial posting; please speak up if
> >> you'd like to be dropped from the email thread.)
> >>
> >> QEMU provides guests with the virtio-rng device, and the OVMF and
> >> ArmVirtQemu* edk2 platforms build EFI_RNG_PROTOCOL on top of that
> >> device. But, that doesn't seem enough for all edk2 use cases.
> >>
> >> Also, virtio-rng (hence EFI_RNG_PROTOCOL too) is optional, and its
> >> absence may affect some other use cases.
> >>
> >>
> >> (1) For UEFI HTTPS boot, TLS would likely benefit from good quality
> >> entropy. If the VM config includes virtio-rng (hence the guest firmware
> >> has EFI_RNG_PROTOCOL), then it should be used as a part of HTTPS boot.
> >>
> >> However, what if virtio-rng (hence EFI_RNG_PROTOCOL) are absent? Should
> >> UEFI HTTPS boot be disabled completely (or prevented / rejected
> >> somehow), blaming lack of good entropy? Or should TLS silently fall back
> >> to "mixing some counters [such as TSC] together and applying a
> >> deterministic cryptographic transformation"?
> >>
> >> IOW, knowing that the TLS setup may not be based on good quality
> >> entropy, should we allow related firmware services to "degrade silently"
> >> (not functionally, but potentially in security), or should we deny the
> >> services altogether?
> > 
> > I don't see a downside to insisting that if you want to use https then
> > you must provide an entropy source; they're easy enough to add using
> > virtio-rng if the CPU doesn't provide it.
> 
> Possibly true; however it could be considered a usability regression by
> end-users. ("UEFI HTTPS boot used to work, now it breaks with the same
> VM config". Unless we can respond, "UEFI HTTPS boot's TLS init has never
> been secure enough", they'll have a point. See also Ard's followup.)

You could turn it into a scary warning for a few releases first.

> > 
> >>
> >> (2) It looks like the SMM driver implementing the privileged part of the
> >> UEFI variable runtime service could need access to good quality entropy,
> >> while running in SMM; in the future.
> >>
> >> This looks problematic on QEMU. Entropy is a valuable resource, and
> >> whatever resource SMM drivers depend on, should not be possible for e.g.
> >> a 3rd party UEFI driver (or even for the runtime OS) to exhaust.
> >> Therefore, it's not *only* the case that SMM drivers must not consume
> >> EFI_RNG_PROTOCOL (which exists at a less critical privilege level, i.e.
> >> outside of SMM/SMRAM), but also that SMM drivers must not depend on the
> >> same piece of *hardware* that feeds EFI_RNG_PROTOCOL.
> >>
> >> Furthermore, assuming we dedicate a hardware entropy device specifically
> >> to SMM drivers, such a device cannot be PCI(e). It would have to be a
> >> platform device at a fixed location (IO port or MMIO) that is only
> >> accessible to such guest code that executes in SMM. IOW, device access
> >> would have to be restricted similarly to pflash. (In fact the variable
> >> SMM driver will need, AIUI, the entropy for encrypting various variable
> >> contents, which are then written into pflash.)
> > 
> > Ewww.  I guess a virtio-rng instance wired to virtio-mmio could do that.
> > It's a bit grim though.
> 
> *shudder* please let's keep virtio-mmio (or any remotely enumerable /
> complex "bus" thingy) out of this :( I'm all for extensible hardware
> interfaces, but cramming more and more infrastructure code into SMM
> looks very questionable to me.

The reason I suggested virtio-mmio was because it's not enumerable; it's
a fixed location; so you just check that the device you have there is
what you expect.
It means not inventing a new qemu device (although you would have to
make it addable on x86, and you would have to make it hideable in SMM).
(pci with preallocated addresses is similar).

> My main concern here is that most physical platform vendors will just
> solder some physical entropy-gen chip onto their boards, and then
> hard-code the MMIO base address of that as a build-time constant in
> their firmware blobs. This obviously won't work for QEMU, where the hw
> can change from boot to boot; so the generic edk2 solution (regardless
> of the actual chip) need to allow for that kind of dynamism. This is a
> recurrent problem between QEMU and edk2, alas. The answer is of course
> dynamic detection, but I *still* like to keep the enumeration logic to
> the absolute minimum in SMM.

While the hw can change from boot to boot on qemu, there's no
requirement that as a bios you respect that;  just state where you want
the device.

Dave

> Thanks!
> Laszlo
> 
> > 
> > Dave
> > 
> >> Alternatively, CPU instructions could exist that return entropy, and are
> >> executable only inside SMM. It seems that e.g. RDRAND can be trapped in
> >> guests ("A VMEXIT due to RDRAND will have exit reason 57 (decimal)").
> >> Then KVM / QEMU could provide any particular implementation we wanted --
> >> for example an exception could be injected unless RDRAND had been
> >> executed from within SMM. Unfortunately, such an arbitrary restriction
> >> (of RDRAND to SMM) would diverge from the Intel SDM, and would likely
> >> break other (non-SMM) guest code.
> >>
> >> Does a platform device that is dynamically detectable and usable in SMM
> >> only seem like an acceptable design for QEMU?
> >>
> >> Thanks,
> >> Laszlo
> >>
> >>
> > --
> > Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK
> > 
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 10:25 ` Ard Biesheuvel
@ 2019-11-07 11:37   ` Paolo Bonzini
  2019-11-07 11:55     ` Daniel P. Berrangé
  2019-11-07 13:27     ` Laszlo Ersek
  2019-11-07 11:58   ` Laszlo Ersek
  1 sibling, 2 replies; 18+ messages in thread
From: Paolo Bonzini @ 2019-11-07 11:37 UTC (permalink / raw)
  To: Ard Biesheuvel, Laszlo Ersek
  Cc: Daniel P. Berrange, Jian J Wang, edk2-devel-groups-io,
	Bret Barkelew, qemu devel list, Erik Bjorge, Sean Brogan,
	Philippe Mathieu-Daudé

On 07/11/19 11:25, Ard Biesheuvel wrote:
>> This looks problematic on QEMU. Entropy is a valuable resource, and
>> whatever resource SMM drivers depend on, should not be possible for e.g.
>> a 3rd party UEFI driver (or even for the runtime OS) to exhaust.
>> Therefore, it's not *only* the case that SMM drivers must not consume
>> EFI_RNG_PROTOCOL (which exists at a less critical privilege level, i.e.
>> outside of SMM/SMRAM), but also that SMM drivers must not depend on the
>> same piece of *hardware* that feeds EFI_RNG_PROTOCOL.
>>
> The typical model is to seed a DRBG [deterministic pseudorandom
> sequence generator] using a sufficient amount of high quality entropy.
> Once you have done that, it is rather hard to exhaust a DRBG - it is a
> mathematical construction that is designed to last for a long time (<=
> 2^48 invocations [not bytes] according to the NIST spec), after which
> it does not degrade although it may have generated so much output that
> its internal state may be inferred if you have captured enough of it
> (which is a rather theoretical issue IMHO)
> 
> The problem is that using the output of a DRBG as a seed is
> non-trivial - the spec describes ways to do this, but wiring
> virtio-rng to a DRBG in the host and using its output to seed a DRBG
> in the guest is slighly problematic.
> 
> So it seems to me that the correct way to model this is to make the
> host's true entropy source a shared resource like any other.
> 

Yes, I would make SMM use a cryptographic pseudo-random number generator 
and seed it from virtio-rng from DXE, way before the OS starts and can 
"attack" it.

Once you've gotten a seed, you can create a CSPRNG with a stream cipher 
such as ChaCha20, which is literally 30 lines of code.

Paolo

#define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
#define QR(a, b, c, d) (			\
	a += b,  d ^= a,  d = ROTL(d,16),	\
	c += d,  b ^= c,  b = ROTL(b,12),	\
	a += b,  d ^= a,  d = ROTL(d, 8),	\
	c += d,  b ^= c,  b = ROTL(b, 7))
#define ROUNDS 20

// initial state:
// in[0] = 0x65787061
// in[1] = 0x6e642033
// in[2] = 0x322d6279
// in[3] = 0x7465206b
// in[4]..in[11] = key (seed)
// in[12]..in[13] = 0
// in[14]..in[15] = nonce, can probably use RDTSC?
static uint32_t in[16];

uint32_t chacha_rng(void)
{
	int i;
	static uint32_t x[16], p;
	if (p < 16)
		return in[p++] + x[p++];

	if (++in[12] == 0)
		++in[13];

	for (i = 0; i < 16; ++i)
		x[i] = in[i];

	// 10 loops × 2 rounds/loop = 20 rounds
	for (i = 0; i < ROUNDS; i += 2) {
		// Odd round
		QR(x[0], x[4], x[ 8], x[12]); // column 0
		QR(x[1], x[5], x[ 9], x[13]); // column 1
		QR(x[2], x[6], x[10], x[14]); // column 2
		QR(x[3], x[7], x[11], x[15]); // column 3
		// Even round
		QR(x[0], x[5], x[10], x[15]); // diagonal 1 (main diagonal)
		QR(x[1], x[6], x[11], x[12]); // diagonal 2
		QR(x[2], x[7], x[ 8], x[13]); // diagonal 3
		QR(x[3], x[4], x[ 9], x[14]); // diagonal 4
	}
	p = 1;
	return in[0] + x[0];
}


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 10:10 privileged entropy sources in QEMU/KVM guests Laszlo Ersek
  2019-11-07 10:18 ` Dr. David Alan Gilbert
  2019-11-07 10:25 ` Ard Biesheuvel
@ 2019-11-07 11:52 ` Daniel P. Berrangé
  2019-11-07 12:47   ` Paolo Bonzini
  2 siblings, 1 reply; 18+ messages in thread
From: Daniel P. Berrangé @ 2019-11-07 11:52 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Ard Biesheuvel, Jian J Wang, edk2-devel-groups-io, Bret Barkelew,
	qemu devel list, Erik Bjorge, Sean Brogan, Paolo Bonzini,
	Philippe Mathieu-Daudé

On Thu, Nov 07, 2019 at 11:10:57AM +0100, Laszlo Ersek wrote:
> Hi,
> 
> related TianoCore BZ:
> 
>   https://bugzilla.tianocore.org/show_bug.cgi?id=1871
> 
> (I'm starting this thread separately because at least some of the topics
> are specific to QEMU, and I didn't want to litter the BZ with a
> discussion that may not be interesting to all participants CC'd on the
> BZ. I am keeping people CC'd on this initial posting; please speak up if
> you'd like to be dropped from the email thread.)
> 
> QEMU provides guests with the virtio-rng device, and the OVMF and
> ArmVirtQemu* edk2 platforms build EFI_RNG_PROTOCOL on top of that
> device. But, that doesn't seem enough for all edk2 use cases.
> 
> Also, virtio-rng (hence EFI_RNG_PROTOCOL too) is optional, and its
> absence may affect some other use cases.

The optional nature of virtio-rng is something that results in the
the same problems for Linux.

If virtio-rng is absent, then Linux now has a general purpose fallback
via the CPU timing jitter entropy source:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bb5530e4082446aac3a3d69780cd4dbfa4520013

Is it practical to provide a jitter entropy source for EDK2
too ?

> (1) For UEFI HTTPS boot, TLS would likely benefit from good quality
> entropy. If the VM config includes virtio-rng (hence the guest firmware
> has EFI_RNG_PROTOCOL), then it should be used as a part of HTTPS boot.
> 
> However, what if virtio-rng (hence EFI_RNG_PROTOCOL) are absent? Should
> UEFI HTTPS boot be disabled completely (or prevented / rejected
> somehow), blaming lack of good entropy? Or should TLS silently fall back
> to "mixing some counters [such as TSC] together and applying a
> deterministic cryptographic transformation"?
> 
> IOW, knowing that the TLS setup may not be based on good quality
> entropy, should we allow related firmware services to "degrade silently"
> (not functionally, but potentially in security), or should we deny the
> services altogether?

If we can guarantee we always present fallback like jitterentropy
then the problem with TLS init goes away IIUC.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 11:37   ` Paolo Bonzini
@ 2019-11-07 11:55     ` Daniel P. Berrangé
  2019-11-07 12:50       ` Paolo Bonzini
  2019-11-07 13:27     ` Laszlo Ersek
  1 sibling, 1 reply; 18+ messages in thread
From: Daniel P. Berrangé @ 2019-11-07 11:55 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Ard Biesheuvel, Jian J Wang, edk2-devel-groups-io,
	Philippe Mathieu-Daudé,
	Bret Barkelew, qemu devel list, Erik Bjorge, Sean Brogan,
	Laszlo Ersek

On Thu, Nov 07, 2019 at 12:37:11PM +0100, Paolo Bonzini wrote:
> On 07/11/19 11:25, Ard Biesheuvel wrote:
> >> This looks problematic on QEMU. Entropy is a valuable resource, and
> >> whatever resource SMM drivers depend on, should not be possible for e.g.
> >> a 3rd party UEFI driver (or even for the runtime OS) to exhaust.
> >> Therefore, it's not *only* the case that SMM drivers must not consume
> >> EFI_RNG_PROTOCOL (which exists at a less critical privilege level, i.e.
> >> outside of SMM/SMRAM), but also that SMM drivers must not depend on the
> >> same piece of *hardware* that feeds EFI_RNG_PROTOCOL.
> >>
> > The typical model is to seed a DRBG [deterministic pseudorandom
> > sequence generator] using a sufficient amount of high quality entropy.
> > Once you have done that, it is rather hard to exhaust a DRBG - it is a
> > mathematical construction that is designed to last for a long time (<=
> > 2^48 invocations [not bytes] according to the NIST spec), after which
> > it does not degrade although it may have generated so much output that
> > its internal state may be inferred if you have captured enough of it
> > (which is a rather theoretical issue IMHO)
> > 
> > The problem is that using the output of a DRBG as a seed is
> > non-trivial - the spec describes ways to do this, but wiring
> > virtio-rng to a DRBG in the host and using its output to seed a DRBG
> > in the guest is slighly problematic.
> > 
> > So it seems to me that the correct way to model this is to make the
> > host's true entropy source a shared resource like any other.
> > 
> 
> Yes, I would make SMM use a cryptographic pseudo-random number generator 
> and seed it from virtio-rng from DXE, way before the OS starts and can 
> "attack" it.
> 
> Once you've gotten a seed, you can create a CSPRNG with a stream cipher 
> such as ChaCha20, which is literally 30 lines of code.

If all we need is a one-time seed then virtio-rng is possibly overkill as
that provides a continuous stream. Instead could QEMU read a few bytes
from the host's /dev/urandom and pass it to EDK via fw_cfg, which can
use it for the CSPRNG seed. EDK would have to erase the fw_cfg field
to prevent the seed value leaking to the guest OS, but other than that
its quite straightforward.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 10:25 ` Ard Biesheuvel
  2019-11-07 11:37   ` Paolo Bonzini
@ 2019-11-07 11:58   ` Laszlo Ersek
  1 sibling, 0 replies; 18+ messages in thread
From: Laszlo Ersek @ 2019-11-07 11:58 UTC (permalink / raw)
  To: Ard Biesheuvel
  Cc: Daniel P. Berrange, Jian J Wang, edk2-devel-groups-io,
	Bret Barkelew, qemu devel list, Erik Bjorge, Sean Brogan,
	Paolo Bonzini, Philippe Mathieu-Daudé

On 11/07/19 11:25, Ard Biesheuvel wrote:
> On Thu, 7 Nov 2019 at 11:11, Laszlo Ersek <lersek@redhat.com> wrote:

>> (1) For UEFI HTTPS boot, TLS would likely benefit from good quality
>> entropy. If the VM config includes virtio-rng (hence the guest firmware
>> has EFI_RNG_PROTOCOL), then it should be used as a part of HTTPS boot.
>>
>> However, what if virtio-rng (hence EFI_RNG_PROTOCOL) are absent? Should
>> UEFI HTTPS boot be disabled completely (or prevented / rejected
>> somehow), blaming lack of good entropy? Or should TLS silently fall back
>> to "mixing some counters [such as TSC] together and applying a
>> deterministic cryptographic transformation"?
>>
>> IOW, knowing that the TLS setup may not be based on good quality
>> entropy, should we allow related firmware services to "degrade silently"
>> (not functionally, but potentially in security), or should we deny the
>> services altogether?
>>
> 
> TLS uses a source of randomness to establish symmetric session keys
> for encryption. So it really depends on the use case whether HTTPS is
> used for authentication or for confidentiality, and it seems to me
> that it would typically be the former. So disabling HTTPS boot in this
> case seems counterproductive to me.

OK. So this might be an argument for an RngLib instance that tries to
consume EFI_RNG_PROTOCOL, and if the protocol is absent, the lib
instance falls back to a TSC-seeded PRNG.

We'd have to make sure (or prove) that the protocol lookup in the lib
occurs *after* BDS made an attempt to connect the virtio-rng device(s).

>> (2) It looks like the SMM driver implementing the privileged part of the
>> UEFI variable runtime service could need access to good quality entropy,
>> while running in SMM; in the future.
>>
>> This looks problematic on QEMU. Entropy is a valuable resource, and
>> whatever resource SMM drivers depend on, should not be possible for e.g.
>> a 3rd party UEFI driver (or even for the runtime OS) to exhaust.
>> Therefore, it's not *only* the case that SMM drivers must not consume
>> EFI_RNG_PROTOCOL (which exists at a less critical privilege level, i.e.
>> outside of SMM/SMRAM), but also that SMM drivers must not depend on the
>> same piece of *hardware* that feeds EFI_RNG_PROTOCOL.
>>
> 
> The typical model is to seed a DRBG [deterministic pseudorandom
> sequence generator] using a sufficient amount of high quality entropy.
> Once you have done that, it is rather hard to exhaust a DRBG - it is a
> mathematical construction that is designed to last for a long time (<=
> 2^48 invocations [not bytes] according to the NIST spec), after which
> it does not degrade although it may have generated so much output that
> its internal state may be inferred if you have captured enough of it
> (which is a rather theoretical issue IMHO)

Thanks! I think this helps.

Because then the guest SMM code could read the seed from (for example) a
well-known PCI BDF (such as 0/0/0), at either a fixed config space
offset, or from a vendor capability. This doesn't depend on PCI
enumeration, and it also cannot be interfered with by 3rd party UEFI
code or OS code, because the only such reads would occur in the subject
SMM drivers' entry point functions.

On the Q35 board in QEMU, we already use some config space registers
that are left unspecified in Intel datasheet 316966-002, Table 5-1 "DRAM
Controller Register Address Map (D0:F0)", for various paravirt purposes.
We haven't run out of such "free for the taking" config space registers
yet, and for this particular purpose we only need a single byte
register. (The first read would expose whether the feature were
supported, the other reads would provide bytes for the seed.)

> 
> The problem is that using the output of a DRBG as a seed is
> non-trivial - the spec describes ways to do this, but wiring
> virtio-rng to a DRBG in the host and using its output to seed a DRBG
> in the guest is slighly problematic.

Can we forward /dev/urandom from the host to the guest through an
interface like described above? (Single byte config space register.)

> So it seems to me that the correct way to model this is to make the
> host's true entropy source a shared resource like any other.

I don't know enough to agree or disagree. I guess this might require
additional permission management on the host side.

(NB my only purpose with this thread is to ensure that the internal edk2
interfaces, such as lib class APIs and possible SMM protocols, will
offer the dynamism that's necessary when running on QEMU.)

Thanks!
Laszlo



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 11:52 ` Daniel P. Berrangé
@ 2019-11-07 12:47   ` Paolo Bonzini
  2019-11-07 13:44     ` Laszlo Ersek
  0 siblings, 1 reply; 18+ messages in thread
From: Paolo Bonzini @ 2019-11-07 12:47 UTC (permalink / raw)
  To: Daniel P. Berrangé, Laszlo Ersek
  Cc: Ard Biesheuvel, Jian J Wang, edk2-devel-groups-io, Bret Barkelew,
	qemu devel list, Erik Bjorge, Sean Brogan,
	Philippe Mathieu-Daudé

On 07/11/19 12:52, Daniel P. Berrangé wrote:
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bb5530e4082446aac3a3d69780cd4dbfa4520013
> 
> Is it practical to provide a jitter entropy source for EDK2
> too ?

The hard part is not collecting jitter (though the firmware might be too
deterministic for that), but rather turning it into a random number seed
(mixing data from various sources, crediting entropy, etc.).

Paolo


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 11:55     ` Daniel P. Berrangé
@ 2019-11-07 12:50       ` Paolo Bonzini
  2019-11-07 13:33         ` Laszlo Ersek
  0 siblings, 1 reply; 18+ messages in thread
From: Paolo Bonzini @ 2019-11-07 12:50 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Ard Biesheuvel, Jian J Wang, edk2-devel-groups-io,
	Philippe Mathieu-Daudé,
	Bret Barkelew, qemu devel list, Erik Bjorge, Sean Brogan,
	Laszlo Ersek

On 07/11/19 12:55, Daniel P. Berrangé wrote:
>> Yes, I would make SMM use a cryptographic pseudo-random number generator 
>> and seed it from virtio-rng from DXE, way before the OS starts and can 
>> "attack" it.
>>
>> Once you've gotten a seed, you can create a CSPRNG with a stream cipher 
>> such as ChaCha20, which is literally 30 lines of code.
> If all we need is a one-time seed then virtio-rng is possibly overkill as
> that provides a continuous stream. Instead could QEMU read a few bytes
> from the host's /dev/urandom and pass it to EDK via fw_cfg, which can
> use it for the CSPRNG seed. EDK would have to erase the fw_cfg field
> to prevent the seed value leaking to the guest OS, but other than that
> its quite straightforward.

That would need anyway a change to the emulated hardware.  If the guest
is able to use virtio-rng after the firmware exits (which is the case is
all the firmware needs is a one-time seed), then using virtio-rng is the
simplest alternative as it needs no change at all outside the firmware.

Paolo


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 11:37   ` Paolo Bonzini
  2019-11-07 11:55     ` Daniel P. Berrangé
@ 2019-11-07 13:27     ` Laszlo Ersek
  2019-11-07 13:58       ` Paolo Bonzini
  1 sibling, 1 reply; 18+ messages in thread
From: Laszlo Ersek @ 2019-11-07 13:27 UTC (permalink / raw)
  To: Paolo Bonzini, Ard Biesheuvel
  Cc: Daniel P. Berrange, Jian J Wang, edk2-devel-groups-io,
	Bret Barkelew, qemu devel list, Erik Bjorge, Sean Brogan,
	Philippe Mathieu-Daudé

On 11/07/19 12:37, Paolo Bonzini wrote:
> On 07/11/19 11:25, Ard Biesheuvel wrote:
>>> This looks problematic on QEMU. Entropy is a valuable resource, and
>>> whatever resource SMM drivers depend on, should not be possible for e.g.
>>> a 3rd party UEFI driver (or even for the runtime OS) to exhaust.
>>> Therefore, it's not *only* the case that SMM drivers must not consume
>>> EFI_RNG_PROTOCOL (which exists at a less critical privilege level, i.e.
>>> outside of SMM/SMRAM), but also that SMM drivers must not depend on the
>>> same piece of *hardware* that feeds EFI_RNG_PROTOCOL.
>>>
>> The typical model is to seed a DRBG [deterministic pseudorandom
>> sequence generator] using a sufficient amount of high quality entropy.
>> Once you have done that, it is rather hard to exhaust a DRBG - it is a
>> mathematical construction that is designed to last for a long time (<=
>> 2^48 invocations [not bytes] according to the NIST spec), after which
>> it does not degrade although it may have generated so much output that
>> its internal state may be inferred if you have captured enough of it
>> (which is a rather theoretical issue IMHO)
>>
>> The problem is that using the output of a DRBG as a seed is
>> non-trivial - the spec describes ways to do this, but wiring
>> virtio-rng to a DRBG in the host and using its output to seed a DRBG
>> in the guest is slighly problematic.
>>
>> So it seems to me that the correct way to model this is to make the
>> host's true entropy source a shared resource like any other.
>>
> 
> Yes, I would make SMM use a cryptographic pseudo-random number generator 
> and seed it from virtio-rng from DXE,

The VirtioRngDxe driver is a UEFI driver that follows the UEFI driver
model. Meaning (in this context), it is connected to the virtio-rng
device in the BDS phase, by platform BDS code.

The variable SMM driver is necessary for producing the UEFI Variable and
Variable Write architectural protocols. BDS can only be entered when all
the architectural protocols have been installed.

Therefore we have a circular dependency with the above -- assuming we
intend to delay the *startup* of the variable SMM driver until after
EFI_RNG_PROTOCOL is available.

But, perhaps, could the variable SMM driver start up anyway, and consume
EFI_RNG_PROTOCOL just when it really needs the random seed? I doubt it:
other EFI_RNG_PROTOCOL instances could be produced by other (3rd party)
UEFI drivers. Or other (3rd party) modules could "attack" VirtioRngDxe.
A privileged (SMM) driver should not consume such sensitive data from a
non-privileged driver, unless the latter was built into the platform
firmware, and the consumption occurred before the End-of-Dxe event
(which is signaled by platform BDS, early in the BDS phase).

Put differently, the non-privileged driver that's the source of the
sensitive data would have to be a "platform DXE driver". The virtio
drivers are not such drivers however.

I can imagine a roundabout way to hack this around in OVMF's platform
BDS, quite horribly, but I'd like to consider other approaches first.

Thank you!
Laszlo

> way before the OS starts and can 
> "attack" it.
> 
> Once you've gotten a seed, you can create a CSPRNG with a stream cipher 
> such as ChaCha20, which is literally 30 lines of code.
> 
> Paolo
> 
> #define ROTL(a,b) (((a) << (b)) | ((a) >> (32 - (b))))
> #define QR(a, b, c, d) (			\
> 	a += b,  d ^= a,  d = ROTL(d,16),	\
> 	c += d,  b ^= c,  b = ROTL(b,12),	\
> 	a += b,  d ^= a,  d = ROTL(d, 8),	\
> 	c += d,  b ^= c,  b = ROTL(b, 7))
> #define ROUNDS 20
> 
> // initial state:
> // in[0] = 0x65787061
> // in[1] = 0x6e642033
> // in[2] = 0x322d6279
> // in[3] = 0x7465206b
> // in[4]..in[11] = key (seed)
> // in[12]..in[13] = 0
> // in[14]..in[15] = nonce, can probably use RDTSC?
> static uint32_t in[16];
> 
> uint32_t chacha_rng(void)
> {
> 	int i;
> 	static uint32_t x[16], p;
> 	if (p < 16)
> 		return in[p++] + x[p++];
> 
> 	if (++in[12] == 0)
> 		++in[13];
> 
> 	for (i = 0; i < 16; ++i)
> 		x[i] = in[i];
> 
> 	// 10 loops × 2 rounds/loop = 20 rounds
> 	for (i = 0; i < ROUNDS; i += 2) {
> 		// Odd round
> 		QR(x[0], x[4], x[ 8], x[12]); // column 0
> 		QR(x[1], x[5], x[ 9], x[13]); // column 1
> 		QR(x[2], x[6], x[10], x[14]); // column 2
> 		QR(x[3], x[7], x[11], x[15]); // column 3
> 		// Even round
> 		QR(x[0], x[5], x[10], x[15]); // diagonal 1 (main diagonal)
> 		QR(x[1], x[6], x[11], x[12]); // diagonal 2
> 		QR(x[2], x[7], x[ 8], x[13]); // diagonal 3
> 		QR(x[3], x[4], x[ 9], x[14]); // diagonal 4
> 	}
> 	p = 1;
> 	return in[0] + x[0];
> }
> 



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 12:50       ` Paolo Bonzini
@ 2019-11-07 13:33         ` Laszlo Ersek
  0 siblings, 0 replies; 18+ messages in thread
From: Laszlo Ersek @ 2019-11-07 13:33 UTC (permalink / raw)
  To: Paolo Bonzini, Daniel P. Berrangé
  Cc: Ard Biesheuvel, Jian J Wang, edk2-devel-groups-io, Bret Barkelew,
	qemu devel list, Erik Bjorge, Sean Brogan,
	Philippe Mathieu-Daudé

On 11/07/19 13:50, Paolo Bonzini wrote:
> On 07/11/19 12:55, Daniel P. Berrangé wrote:
>>> Yes, I would make SMM use a cryptographic pseudo-random number generator 
>>> and seed it from virtio-rng from DXE, way before the OS starts and can 
>>> "attack" it.
>>>
>>> Once you've gotten a seed, you can create a CSPRNG with a stream cipher 
>>> such as ChaCha20, which is literally 30 lines of code.
>> If all we need is a one-time seed then virtio-rng is possibly overkill as
>> that provides a continuous stream. Instead could QEMU read a few bytes
>> from the host's /dev/urandom and pass it to EDK via fw_cfg, which can
>> use it for the CSPRNG seed. EDK would have to erase the fw_cfg field
>> to prevent the seed value leaking to the guest OS, but other than that
>> its quite straightforward.
> 
> That would need anyway a change to the emulated hardware.  If the guest
> is able to use virtio-rng after the firmware exits (which is the case is
> all the firmware needs is a one-time seed), then using virtio-rng is the
> simplest alternative as it needs no change at all outside the firmware.

This is a really good point!

I'll think more about using virtio-rng, hopefully without horribly
hacking OVMF's BDS code.

Thanks
Laszlo



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 12:47   ` Paolo Bonzini
@ 2019-11-07 13:44     ` Laszlo Ersek
  2019-11-07 13:54       ` Daniel P. Berrangé
  2019-11-07 14:09       ` Ard Biesheuvel
  0 siblings, 2 replies; 18+ messages in thread
From: Laszlo Ersek @ 2019-11-07 13:44 UTC (permalink / raw)
  To: Paolo Bonzini, Daniel P. Berrangé
  Cc: Ard Biesheuvel, Jian J Wang, edk2-devel-groups-io, Bret Barkelew,
	qemu devel list, Erik Bjorge, Sean Brogan,
	Philippe Mathieu-Daudé

On 11/07/19 13:47, Paolo Bonzini wrote:
> On 07/11/19 12:52, Daniel P. Berrangé wrote:
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bb5530e4082446aac3a3d69780cd4dbfa4520013
>>
>> Is it practical to provide a jitter entropy source for EDK2
>> too ?
> 
> The hard part is not collecting jitter (though the firmware might be too
> deterministic for that), but rather turning it into a random number seed
> (mixing data from various sources, crediting entropy, etc.).

If there is *any* entropy source that (a) we can trust to be random
enough and (b) depends only on the CPU, then we shouldn't struggle with
virtio-rng (or similar devices) at all. RDRAND would be a no-brainer,
but the "community literature" suggests it should not be trusted in itself.

I've read the commit message linked above, and it appears too good to be
true.

    The CPU Jitter RNG provides a source of good entropy by collecting
    CPU executing time jitter. [...] The RNG does not have any
    dependencies on any other service in the kernel. The RNG only needs
    a high-resolution time stamp. [...]

http://www.chronox.de/jent.html

    The CPU Jitter Random Number Generator provides a non-physical true
    random number generator that works equally in kernel and user land.
    The only prerequisite is the availability of a high-resolution timer
    that is available in modern CPUs.

http://www.chronox.de/jent/doc/CPU-Jitter-NPTRNG.html

    Today’s operating systems provide non-physical true random number
    generators which are based on hardware events. With the advent of
    virtualization and the ever growing need of more high-quality random
    numbers, these random number generators reach their limits.
    Additional sources of entropy must be opened up. This document
    introduces an entropy source based on CPU execution time jitter. The
    design and implementation of a non-physical true random number
    generator, the CPU Jitter random number generator, its statistical
    properties and the maintenance and behavior of entropy is discussed
    in this document.

If this construct is legit, a core edk2 implementation (available to all
platforms, and on all edk2 arches) would be a huge win.

On the other hand, we're having this discussion because the premise of
TianoCore#1871 is that we shouldn't rely on just the CPU and a high
resolution timer... I simply cannot decide if this construct is
trustworthy. (With any solution that was based in the host's /dev/random
or /dev/urandom, the trustworthiness question would be side-stepped in
the firmware.)

Laszlo



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 13:44     ` Laszlo Ersek
@ 2019-11-07 13:54       ` Daniel P. Berrangé
  2019-11-07 14:09       ` Ard Biesheuvel
  1 sibling, 0 replies; 18+ messages in thread
From: Daniel P. Berrangé @ 2019-11-07 13:54 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Ard Biesheuvel, Jian J Wang, edk2-devel-groups-io, Bret Barkelew,
	qemu devel list, Erik Bjorge, Sean Brogan, Paolo Bonzini,
	Philippe Mathieu-Daudé

On Thu, Nov 07, 2019 at 02:44:11PM +0100, Laszlo Ersek wrote:
> On 11/07/19 13:47, Paolo Bonzini wrote:
> > On 07/11/19 12:52, Daniel P. Berrangé wrote:
> >>
> >> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bb5530e4082446aac3a3d69780cd4dbfa4520013
> >>
> >> Is it practical to provide a jitter entropy source for EDK2
> >> too ?
> > 
> > The hard part is not collecting jitter (though the firmware might be too
> > deterministic for that), but rather turning it into a random number seed
> > (mixing data from various sources, crediting entropy, etc.).
> 
> If there is *any* entropy source that (a) we can trust to be random
> enough and (b) depends only on the CPU, then we shouldn't struggle with
> virtio-rng (or similar devices) at all. RDRAND would be a no-brainer,
> but the "community literature" suggests it should not be trusted in itself.
> 
> I've read the commit message linked above, and it appears too good to be
> true.
> 
>     The CPU Jitter RNG provides a source of good entropy by collecting
>     CPU executing time jitter. [...] The RNG does not have any
>     dependencies on any other service in the kernel. The RNG only needs
>     a high-resolution time stamp. [...]
> 
> http://www.chronox.de/jent.html
> 
>     The CPU Jitter Random Number Generator provides a non-physical true
>     random number generator that works equally in kernel and user land.
>     The only prerequisite is the availability of a high-resolution timer
>     that is available in modern CPUs.
> 
> http://www.chronox.de/jent/doc/CPU-Jitter-NPTRNG.html
> 
>     Today’s operating systems provide non-physical true random number
>     generators which are based on hardware events. With the advent of
>     virtualization and the ever growing need of more high-quality random
>     numbers, these random number generators reach their limits.
>     Additional sources of entropy must be opened up. This document
>     introduces an entropy source based on CPU execution time jitter. The
>     design and implementation of a non-physical true random number
>     generator, the CPU Jitter random number generator, its statistical
>     properties and the maintenance and behavior of entropy is discussed
>     in this document.
> 
> If this construct is legit, a core edk2 implementation (available to all
> platforms, and on all edk2 arches) would be a huge win.
> 
> On the other hand, we're having this discussion because the premise of
> TianoCore#1871 is that we shouldn't rely on just the CPU and a high
> resolution timer... I simply cannot decide if this construct is
> trustworthy. (With any solution that was based in the host's /dev/random
> or /dev/urandom, the trustworthiness question would be side-stepped in
> the firmware.)

I can't claim to have knowledge of whether the above text is accurate
or not, instead I just defer to the Linux maintainers recommendatiohns.
They've considered it acceptable to merge it into Linux, and to me that
says it should be acceptable to have in EDK2 too.

As a second data point, jitter entropy has been the recommended solution
in RHEL for VMs where there's no RDRAND or virtio-rng available. In RHEL-7
this was implemented in userspace in rng-tools rather than with the kernel
module I link above, but the approach is the same in both cases IIUC.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 13:27     ` Laszlo Ersek
@ 2019-11-07 13:58       ` Paolo Bonzini
  2019-11-07 15:11         ` Laszlo Ersek
  0 siblings, 1 reply; 18+ messages in thread
From: Paolo Bonzini @ 2019-11-07 13:58 UTC (permalink / raw)
  To: Laszlo Ersek, Ard Biesheuvel
  Cc: Daniel P. Berrange, Jian J Wang, edk2-devel-groups-io,
	Bret Barkelew, qemu devel list, Erik Bjorge, Sean Brogan,
	Philippe Mathieu-Daudé

On 07/11/19 14:27, Laszlo Ersek wrote:
> The VirtioRngDxe driver is a UEFI driver that follows the UEFI driver
> model. Meaning (in this context), it is connected to the virtio-rng
> device in the BDS phase, by platform BDS code.
> 
> Put differently, the non-privileged driver that's the source of the
> sensitive data would have to be a "platform DXE driver". The virtio
> drivers are not such drivers however.

Yes, it would have to be a platform DXE driver.  What is it that limits
virtio to the BDS phase?

Paolo


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 13:44     ` Laszlo Ersek
  2019-11-07 13:54       ` Daniel P. Berrangé
@ 2019-11-07 14:09       ` Ard Biesheuvel
  1 sibling, 0 replies; 18+ messages in thread
From: Ard Biesheuvel @ 2019-11-07 14:09 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Daniel P. Berrangé,
	Jian J Wang, edk2-devel-groups-io, Bret Barkelew,
	qemu devel list, Erik Bjorge, Sean Brogan, Paolo Bonzini,
	Philippe Mathieu-Daudé

On Thu, 7 Nov 2019 at 14:44, Laszlo Ersek <lersek@redhat.com> wrote:
>
> On 11/07/19 13:47, Paolo Bonzini wrote:
> > On 07/11/19 12:52, Daniel P. Berrangé wrote:
> >>
> >> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bb5530e4082446aac3a3d69780cd4dbfa4520013
> >>
> >> Is it practical to provide a jitter entropy source for EDK2
> >> too ?
> >
> > The hard part is not collecting jitter (though the firmware might be too
> > deterministic for that), but rather turning it into a random number seed
> > (mixing data from various sources, crediting entropy, etc.).
>
> If there is *any* entropy source that (a) we can trust to be random
> enough and (b) depends only on the CPU, then we shouldn't struggle with
> virtio-rng (or similar devices) at all. RDRAND would be a no-brainer,
> but the "community literature" suggests it should not be trusted in itself.
>
> I've read the commit message linked above, and it appears too good to be
> true.
>
>     The CPU Jitter RNG provides a source of good entropy by collecting
>     CPU executing time jitter. [...] The RNG does not have any
>     dependencies on any other service in the kernel. The RNG only needs
>     a high-resolution time stamp. [...]
>
> http://www.chronox.de/jent.html
>
>     The CPU Jitter Random Number Generator provides a non-physical true
>     random number generator that works equally in kernel and user land.
>     The only prerequisite is the availability of a high-resolution timer
>     that is available in modern CPUs.
>
> http://www.chronox.de/jent/doc/CPU-Jitter-NPTRNG.html
>
>     Today’s operating systems provide non-physical true random number
>     generators which are based on hardware events. With the advent of
>     virtualization and the ever growing need of more high-quality random
>     numbers, these random number generators reach their limits.
>     Additional sources of entropy must be opened up. This document
>     introduces an entropy source based on CPU execution time jitter. The
>     design and implementation of a non-physical true random number
>     generator, the CPU Jitter random number generator, its statistical
>     properties and the maintenance and behavior of entropy is discussed
>     in this document.
>
> If this construct is legit, a core edk2 implementation (available to all
> platforms, and on all edk2 arches) would be a huge win.
>

 "that works equally in kernel and user land"

Firmware running at boot time on a single core without any serious
scheduling or I/O going on is not going to produce any entropy worth
mentioning, I'm afraid. And if it does, it is going to delay the boot
substantially.

> On the other hand, we're having this discussion because the premise of
> TianoCore#1871 is that we shouldn't rely on just the CPU and a high
> resolution timer... I simply cannot decide if this construct is
> trustworthy. (With any solution that was based in the host's /dev/random
> or /dev/urandom, the trustworthiness question would be side-stepped in
> the firmware.)
>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: privileged entropy sources in QEMU/KVM guests
  2019-11-07 13:58       ` Paolo Bonzini
@ 2019-11-07 15:11         ` Laszlo Ersek
  0 siblings, 0 replies; 18+ messages in thread
From: Laszlo Ersek @ 2019-11-07 15:11 UTC (permalink / raw)
  To: Paolo Bonzini, Ard Biesheuvel
  Cc: Daniel P. Berrange, Jian J Wang, edk2-devel-groups-io,
	Bret Barkelew, qemu devel list, Erik Bjorge, Sean Brogan,
	Philippe Mathieu-Daudé

On 11/07/19 14:58, Paolo Bonzini wrote:
> On 07/11/19 14:27, Laszlo Ersek wrote:
>> The VirtioRngDxe driver is a UEFI driver that follows the UEFI driver
>> model. Meaning (in this context), it is connected to the virtio-rng
>> device in the BDS phase, by platform BDS code.
>>
>> Put differently, the non-privileged driver that's the source of the
>> sensitive data would have to be a "platform DXE driver". The virtio
>> drivers are not such drivers however.
> 
> Yes, it would have to be a platform DXE driver.  What is it that limits
> virtio to the BDS phase?

For virtio-pci, we have:

- The PCI host bridge / root bridge driver, which is a platform DXE
driver, and produces PCI Root Bridge IO Protocol instances in its entry
point.

- The PCI bus driver, which is a UEFI driver that follows the UEFI
driver model. It only does its actual job when BDS connects it to the
PCI Root Bridge IO Protocol instances mentioned above. At that point,
the PCI bus driver produces a bunch of PCI IO protocol instances.

- The virtio 0.9.5 and virtio 1.0 PCI transport drivers. They are also
UEFI drivers that follow the UEFI driver model. They bind PCI IO
protocol instances when BDS says so, and produce VIRTIO_DEVICE_PROTOCOL
instances.

- The actual virtio device drivers (scsi, blk, net, rng, gpu) that bind
VIRTIO_DEVICE_PROTOCOL instances, when BDS says so, and produce the
use-case specific UEFI protocols (such as SCSI pass-thru, Block IO,
Simple Network, RNG, and Graphics Output).


For virtio-mmio, we have (on ARM only):

- a platform DXE driver that enumerates the virtio-mmio transports, in
its entry point function, based on the DTB that QEMU exposes. Each
register block / transport is turned into a VIRTIO_DEVICE_PROTOCOL
instances.

- The actual virtio device drivers (scsi, blk, net, rng, gpu) that bind
VIRTIO_DEVICE_PROTOCOL instances, when BDS says so, and produce the
use-case specific UEFI protocols (such as SCSI pass-thru, Block IO,
Simple Network, RNG, and Graphics Output).


UEFI drivers that follow the UEFI driver model allow BDS to orchestrate
device binding, and don't generally do anything unless called from BDS.

Platform DXE drivers do their job in their entry point functions. If
they have protocol dependencies, then they either spell that out as a
DEPEXes (dependency expressions, honored by the DXE Core during driver
dispatch), or else they operate with low-level protocol notification
callbacks (= they automatically take action, regardless of BDS, when a
particular protocol appears in the system). They produce their own
protocols in their entry point functions, or else in said protocol
notify callbacks, without being asked to by BDS.

UEFI-2.* strongly encourages device driver authors to structure their
drivers as such UEFI drivers that follow the UEFI driver model, and not
as platform DXE drivers.


A core idea in BDS is that the largest possible set of devices should
*not* be bound by drivers. If we don't connect anything that we don't
intend to boot off of (and don't need for other booting purposes [*],
then that makes for a speedy & frugal boot.

[*] such as console drivers (keyboard, serial, graphics), or RNG
drivers, ...

The set of devices connected by BDS is, by design, platform policy. When
the device drivers follow the UEFI driver model, platform BDS can manage
a large herd of 3rd party UEFI drivers, and only bind the set of devices
that's actually necessary.

When most device drivers are platform DXE drivers, all doing whatever
they want, and all acting on their own dependencies, it's very difficult
to express or implement a similar policy in a central component.


In OvmfPkg and ArmVirtPkg, we originally connected all drivers to all
devices. That was safe, but not too fast (especially when you had tens
or hundreds of virtio devices in the system). Nowadays, we connect only
what we really need for booting. That selection / binding procedure is
driven by the "bootorder" fw_cfg file from QEMU.

https://lists.01.org/hyperkitty/list/edk2-devel@lists.01.org/message/UAYFGPOQVI4FSHTU6MDLA6ULMUWSQ5HJ/

This selection is so effective that, when we first implemented it, we
actually stopped binding the virtio RNG device. (It was a regression --
I think the kernel's UEFI stub consumes it, if it's available, and we
noticed that the stub started complaining.) That happened because
virtio-rng is never a *bootable* device, and so it's never listed in the
"bootorder" fw_cfg file. Therefore we had to add custom BDS code to bind
virtio RNG devices "forcibly".

https://github.com/tianocore/edk2/commit/7ebad830d6ab6


Now, technically speaking, we could rewrite VirtioRngDxe to be a
platform DXE driver. It would register a protocol notify callback for
VIRTIO_DEVICE_PROTOCOL, it would investigate every such protocol
instance as they appeared in the protocol database, and bind whichever
was a virtio-rng device.

It wouldn't make a difference in the end, because the virtio PCI
transport drivers (producing VIRTIO_DEVICE_PROTOCOL) themselves are UEFI
drivers that follow the UEFI driver model. Thus, they are "kicked" by BDS.

The PCI Bus driver itself (producing the PCI IO instances that the
virtio PCI transport drivers bind) is itself a UEFI Driver that follows
the UEFI driver model. Thus, that too is set in motion by BDS.

--*--

Nonetheless, we might be able to make this work, with a not too terrible
hack.

- In "OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c", hoist the
virtio-rng binding from the end of the
PlatformBootManagerBeforeConsole() function, to just before signaling
End-of-Dxe.

- in the constructor function of OVMF's new SMM-oriented RngLib
instance, register a protocol notify for EFI_RNG_PROTOCOL. Also register
an event notification function for End-of-Dxe.

- In the EFI_RNG_PROTOCOL callback, fetch the seed (and make a note that
the seed has been fetched). Uninstall the same callback.

- In the End-of-Dxe event notification callback, check if the seed has
been fetched. If not, hang the system. (We must not exit the DXE phase
without having a seed.)

- In the RngLib APIs that provide randomness to the caller (and so
depend on a seed having been fetched), hang the system if the seed has
not been fetched. This will never fire if the first such API call is
made at, or after, End-of-Dxe (see above), but it could fire if the API
is called earlier. For example, if the variable SMM driver actually
needed some randomness before the system reaches End-of-Dxe.

I'll take this last design question back to the TianoCore BZ -- can we
expect the SMM drivers to fetch the seed at EndOfDxe (and not earlier)?
Because the EFI_RNG_PROTOCOL instances that are present in the system
*by then* can be trusted to provide the seed.

Thanks,
Laszlo



^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2019-11-07 15:12 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-07 10:10 privileged entropy sources in QEMU/KVM guests Laszlo Ersek
2019-11-07 10:18 ` Dr. David Alan Gilbert
2019-11-07 11:19   ` Laszlo Ersek
2019-11-07 11:36     ` Dr. David Alan Gilbert
2019-11-07 10:25 ` Ard Biesheuvel
2019-11-07 11:37   ` Paolo Bonzini
2019-11-07 11:55     ` Daniel P. Berrangé
2019-11-07 12:50       ` Paolo Bonzini
2019-11-07 13:33         ` Laszlo Ersek
2019-11-07 13:27     ` Laszlo Ersek
2019-11-07 13:58       ` Paolo Bonzini
2019-11-07 15:11         ` Laszlo Ersek
2019-11-07 11:58   ` Laszlo Ersek
2019-11-07 11:52 ` Daniel P. Berrangé
2019-11-07 12:47   ` Paolo Bonzini
2019-11-07 13:44     ` Laszlo Ersek
2019-11-07 13:54       ` Daniel P. Berrangé
2019-11-07 14:09       ` Ard Biesheuvel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.