public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Laszlo Ersek" <lersek@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: "qemu devel list" <qemu-devel@nongnu.org>,
	"Daniel P. Berrange" <berrange@redhat.com>,
	edk2-devel-groups-io <devel@edk2.groups.io>,
	"Philippe Mathieu-Daudé" <philmd@redhat.com>,
	"Bret Barkelew" <Bret.Barkelew@microsoft.com>,
	"Sean Brogan" <sean.brogan@microsoft.com>,
	"Jian J Wang" <jian.j.wang@intel.com>,
	"Erik Bjorge" <erik.c.bjorge@intel.com>
Subject: Re: privileged entropy sources in QEMU/KVM guests
Date: Thu, 7 Nov 2019 14:27:52 +0100	[thread overview]
Message-ID: <421cf4ef-ea84-c7e6-81aa-c24a91459de5@redhat.com> (raw)
In-Reply-To: <ef126cd5-7b64-1b8a-ca74-11bd06b5f4b1@redhat.com>

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];
> }
> 


  parent reply	other threads:[~2019-11-07 13:28 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=421cf4ef-ea84-c7e6-81aa-c24a91459de5@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox