Re: privileged entropy sources in QEMU/KVM guests
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-de...@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_PROTOC
Re: privileged entropy sources in QEMU/KVM guests
On Thu, 7 Nov 2019 at 14:44, 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. > "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.) >
Re: privileged entropy sources in QEMU/KVM guests
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
Re: privileged entropy sources in QEMU/KVM guests
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 :|
Re: privileged entropy sources in QEMU/KVM guests
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
Re: privileged entropy sources in QEMU/KVM guests
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
Re: privileged entropy sources in QEMU/KVM guests
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]; > } >
Re: privileged entropy sources in QEMU/KVM guests
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
Re: privileged entropy sources in QEMU/KVM guests
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
Re: privileged entropy sources in QEMU/KVM guests
On 11/07/19 11:25, Ard Biesheuvel wrote: > On Thu, 7 Nov 2019 at 11:11, Laszlo Ersek 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
Re: privileged entropy sources in QEMU/KVM guests
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 :|
Re: privileged entropy sources in QEMU/KVM guests
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 :|
Re: privileged entropy sources in QEMU/KVM guests
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]; }
Re: privileged entropy sources in QEMU/KVM guests
* Laszlo Ersek (ler...@redhat.com) wrote: > On 11/07/19 11:18, Dr. David Alan Gilbert wrote: > > * Laszlo Ersek (ler...@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; ju
Re: privileged entropy sources in QEMU/KVM guests
On 11/07/19 11:18, Dr. David Alan Gilbert wrote: > * Laszlo Ersek (ler...@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
Re: privileged entropy sources in QEMU/KVM guests
Hi Laszlo, Thanks for starting this thread. On Thu, 7 Nov 2019 at 11:11, 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. > > > (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? >
Re: privileged entropy sources in QEMU/KVM guests
* Laszlo Ersek (ler...@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 / dgilb...@redhat.com / Manchester, UK