Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1711274 > unrolled thread

early x86 unseeded randomness

Started byBorislav Petkov <bp@alien8.de>
First post2017-08-14 19:40 +0200
Last post2017-08-15 14:50 +0200
Articles 20 on this page of 25 — 8 participants

Back to article view | Back to linux.kernel


Contents

  early x86 unseeded randomness Borislav Petkov <bp@alien8.de> - 2017-08-14 19:40 +0200
    Re: early x86 unseeded randomness Linus Torvalds <torvalds@linux-foundation.org> - 2017-08-14 19:50 +0200
      Re: early x86 unseeded randomness Borislav Petkov <bp@alien8.de> - 2017-08-14 20:10 +0200
        Re: early x86 unseeded randomness Linus Torvalds <torvalds@linux-foundation.org> - 2017-08-14 20:20 +0200
          Re: early x86 unseeded randomness Borislav Petkov <bp@alien8.de> - 2017-08-14 21:10 +0200
            Re: early x86 unseeded randomness Theodore Ts'o <tytso@mit.edu> - 2017-08-15 03:40 +0200
              Re: early x86 unseeded randomness Willy Tarreau <w@1wt.eu> - 2017-08-15 08:50 +0200
                Re: early x86 unseeded randomness Ingo Molnar <mingo@kernel.org> - 2017-08-15 09:50 +0200
                  Re: early x86 unseeded randomness Willy Tarreau <w@1wt.eu> - 2017-08-15 10:10 +0200
                    Re: early x86 unseeded randomness Ingo Molnar <mingo@kernel.org> - 2017-08-15 10:10 +0200
                      Re: early x86 unseeded randomness Theodore Ts'o <tytso@mit.edu> - 2017-08-15 14:20 +0200
                        Re: early x86 unseeded randomness Willy Tarreau <w@1wt.eu> - 2017-08-15 15:30 +0200
                  Re: early x86 unseeded randomness Thomas Gleixner <tglx@linutronix.de> - 2017-08-15 12:50 +0200
                    Re: early x86 unseeded randomness Borislav Petkov <bp@alien8.de> - 2017-08-15 15:50 +0200
                      Re: early x86 unseeded randomness Thomas Gleixner <tglx@linutronix.de> - 2017-08-15 15:50 +0200
                        Re: early x86 unseeded randomness Theodore Ts'o <tytso@mit.edu> - 2017-08-15 16:30 +0200
                          Re: early x86 unseeded randomness Thomas Gleixner <tglx@linutronix.de> - 2017-08-15 16:50 +0200
                            Re: early x86 unseeded randomness Borislav Petkov <bp@alien8.de> - 2017-08-15 17:30 +0200
                            Re: early x86 unseeded randomness Thomas Gleixner <tglx@linutronix.de> - 2017-08-15 19:40 +0200
                              Re: early x86 unseeded randomness Theodore Ts'o <tytso@mit.edu> - 2017-08-16 05:40 +0200
                                Re: early x86 unseeded randomness Thomas Gleixner <tglx@linutronix.de> - 2017-08-16 11:20 +0200
                                  Re: early x86 unseeded randomness Will Deacon <will.deacon@arm.com> - 2017-08-16 12:00 +0200
                            Re: early x86 unseeded randomness Theodore Ts'o <tytso@mit.edu> - 2017-08-16 05:30 +0200
                        Re: early x86 unseeded randomness Borislav Petkov <bp@alien8.de> - 2017-08-15 17:30 +0200
                  Re: early x86 unseeded randomness Michael Ellerman <mpe@ellerman.id.au> - 2017-08-15 14:50 +0200

Page 1 of 2  [1] 2  Next page →


#1711274 — early x86 unseeded randomness

FromBorislav Petkov <bp@alien8.de>
Date2017-08-14 19:40 +0200
Subjectearly x86 unseeded randomness
Message-ID<uervj-72Y-9@gated-at.bofh.it>
Hi,

how about we address that unseeded randomness usage during early boot by
falling back on the TSC on x86? I mean, we already do that for the stack
canary value anyway...

---
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h
index 8abedf1d650e..e636ac6f8418 100644
--- a/arch/x86/include/asm/stackprotector.h
+++ b/arch/x86/include/asm/stackprotector.h
@@ -71,7 +71,11 @@ static __always_inline void boot_init_stack_canary(void)
 	 * there it already has some randomness on most systems. Later
 	 * on during the bootup the random pool has true entropy too.
 	 */
-	get_random_bytes(&canary, sizeof(canary));
+	if (crng_ready())
+		get_random_bytes(&canary, sizeof(canary));
+	else
+		canary = rdtsc();
+
 	tsc = rdtsc();
 	canary += tsc + (tsc << 32UL);
 	canary &= CANARY_MASK;
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 3b9e220621f8..859009daf345 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -526,8 +526,8 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
 		va_align.mask	  = (upperbit - 1) & PAGE_MASK;
 		va_align.flags    = ALIGN_VA_32 | ALIGN_VA_64;
 
-		/* A random value per boot for bit slice [12:upper_bit) */
-		va_align.bits = get_random_int() & va_align.mask;
+		/* A pseudo-random value per boot for bit slice [12:upper_bit) */
+		va_align.bits = rdtsc() & va_align.mask;
 	}
 
 	if (cpu_has(c, X86_FEATURE_MWAITX))
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 8ad92707e45f..887cca606d7b 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -428,7 +428,6 @@ struct crng_state primary_crng = {
  * its value (from 0->1->2).
  */
 static int crng_init = 0;
-#define crng_ready() (likely(crng_init > 0))
 static int crng_init_cnt = 0;
 #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
 static void _extract_crng(struct crng_state *crng,
@@ -497,6 +496,11 @@ static __u32 const twist_table[8] = {
 	0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158,
 	0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
 
+bool crng_ready(void)
+{
+	return likely(crng_init > 0);
+}
+
 /*
  * This function adds bytes into the entropy "pool".  It does not
  * update the entropy estimate.  The caller should call
diff --git a/include/linux/random.h b/include/linux/random.h
index eafea6a09361..18035ba94e43 100644
--- a/include/linux/random.h
+++ b/include/linux/random.h
@@ -197,4 +197,6 @@ static inline u32 next_pseudo_random32(u32 seed)
 	return seed * 1664525 + 1013904223;
 }
 
+extern bool crng_ready(void);
+
 #endif /* _LINUX_RANDOM_H */

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

[toc] | [next] | [standalone]


#1711284

FromLinus Torvalds <torvalds@linux-foundation.org>
Date2017-08-14 19:50 +0200
Message-ID<uerF1-76t-19@gated-at.bofh.it>
In reply to#1711274
On Mon, Aug 14, 2017 at 10:35 AM, Borislav Petkov <bp@alien8.de> wrote:
>
> how about we address that unseeded randomness usage during early boot by
> falling back on the TSC on x86? I mean, we already do that for the stack
> canary value anyway...

That patch is completely broken:


> +       if (crng_ready())
> +               get_random_bytes(&canary, sizeof(canary));
> +       else
> +               canary = rdtsc();
> +
>         tsc = rdtsc();
>         canary += tsc + (tsc << 32UL);

So now you do rdtsc() twice, and then add them together.

Adding the same value together adds absolutely zero information.
Quite the reverse - it just makes the values cancel out and you're
shifting away one bit.

So the current code that just does an unconditional
"get_random_bytes()" and then adds the TSC into it for noise when it's
not ranom is actually *objectively* better than that broken crap you
just tried.

Plus on modern x86, you'll always get at least the hardware
randomness, which is fundamentally much better anyway.

So this patch is utter and absolute garbage, and should be shot in the
head and buried very very deep.

Please immediately delete it from the whole internet.

               Linus

[toc] | [prev] | [next] | [standalone]


#1711316

FromBorislav Petkov <bp@alien8.de>
Date2017-08-14 20:10 +0200
Message-ID<uerYm-7s4-9@gated-at.bofh.it>
In reply to#1711284
On Mon, Aug 14, 2017 at 10:47:47AM -0700, Linus Torvalds wrote:
> Plus on modern x86, you'll always get at least the hardware
> randomness, which is fundamentally much better anyway.

Right, my only intention was to get rid of those:

[    0.000000] random: get_random_bytes called from start_kernel+0x30/0x3d8 with crng_init=0

What do you propose? Keep 'em?

Or fix the above, snipped bit to conditionally do rdtsc() *once* or
get_random_bytes() depending on the crng state?

> So this patch is utter and absolute garbage, and should be shot in the
> head and buried very very deep.

/me takes out a 44 magnum...

> Please immediately delete it from the whole internet.

Haha, lemme call a guy.

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

[toc] | [prev] | [next] | [standalone]


#1711326

FromLinus Torvalds <torvalds@linux-foundation.org>
Date2017-08-14 20:20 +0200
Message-ID<ues81-7vo-5@gated-at.bofh.it>
In reply to#1711316
On Mon, Aug 14, 2017 at 11:00 AM, Borislav Petkov <bp@alien8.de> wrote:
> On Mon, Aug 14, 2017 at 10:47:47AM -0700, Linus Torvalds wrote:
>> Plus on modern x86, you'll always get at least the hardware
>> randomness, which is fundamentally much better anyway.
>
> Right, my only intention was to get rid of those:
>
> [    0.000000] random: get_random_bytes called from start_kernel+0x30/0x3d8 with crng_init=0

Ok, guys, you ALL need to learn that blindly just trying to get rid of
warnings IS A HORRIBLE IDEA.

People also need to learn that *adding* warnings isn't always a good
idea, exactly because then people will mindlessly react to them.

I *detest* bad compiler warnings for this reason. The number of
garbage patches that actually break working code that I've seen over
the year is mind-numbing.

> What do you propose? Keep 'em?

Keeping the warning (or removing the warning itself without changing
the code) is certainly preferable to trying to "fix" the warning by
bogus measures, yes.

> Or fix the above, snipped bit to conditionally do rdtsc() *once* or
> get_random_bytes() depending on the crng state?

Neither. Let's aim to make sure to fix the warning the *only* correct
way - by making sure the initialization _ordering_ is correct, not by
hacking around the caller code.

Maybe the warning message should be clarified to say that too. Make it
clear that the only acceptable fix is to change code ordering, not to
play games with randomness.

But maybe those places that currently trigger the warning should just
use "get_random_u32()" instead. That at least gets rid of the warning
if there's a fast architected hardware random thing (ie modern x86).

                       Linus

[toc] | [prev] | [next] | [standalone]


#1711358

FromBorislav Petkov <bp@alien8.de>
Date2017-08-14 21:10 +0200
Message-ID<uesUp-83a-11@gated-at.bofh.it>
In reply to#1711326
On Mon, Aug 14, 2017 at 11:17:37AM -0700, Linus Torvalds wrote:
> Ok, guys, you ALL need to learn that blindly just trying to get rid of
> warnings IS A HORRIBLE IDEA.

Not blindly - I was actually suggesting/asking whether falling back to
the TSC that early during boot might make more sense than using unseeded
randomness. Especially add the least significant 32 bits to the most
significant i.e., that thing:

	tsc + (tsc << 32UL)

as they're more unpredictable.

> But maybe those places that currently trigger the warning should just
> use "get_random_u32()" instead. That at least gets rid of the warning
> if there's a fast architected hardware random thing (ie modern x86).

Right, that is better, at least for the RDRAND machines.

We'd still need a proper fix for the older ones. And I don't see an
easy way to change the init ordering for the stack canary as it gets
setup very very early in start_kernel() vs crng_initialize() being an
early_initcall()... Need to sleep on it.

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

[toc] | [prev] | [next] | [standalone]


#1711660

FromTheodore Ts'o <tytso@mit.edu>
Date2017-08-15 03:40 +0200
Message-ID<ueyZR-3cJ-31@gated-at.bofh.it>
In reply to#1711358
On Mon, Aug 14, 2017 at 09:00:13PM +0200, Borislav Petkov wrote:
> On Mon, Aug 14, 2017 at 11:17:37AM -0700, Linus Torvalds wrote:
> > Ok, guys, you ALL need to learn that blindly just trying to get rid of
> > warnings IS A HORRIBLE IDEA.
> 
> Not blindly - I was actually suggesting/asking whether falling back to
> the TSC that early during boot might make more sense than using unseeded
> randomness. Especially add the least significant 32 bits to the most
> significant i.e., that thing:
> 
> 	tsc + (tsc << 32UL)
> 
> as they're more unpredictable.

Part of the initialization step of the entropy pools and the crng
mixes in the jiffies, ktime_get_real() and the TSC.  So if you are one
of those people who believe in the magic of jitter-rng, we do
something somewhat similar to that a part of the initialization.  We
just don't credit any entropy to that step.

> 
> > But maybe those places that currently trigger the warning should just
> > use "get_random_u32()" instead. That at least gets rid of the warning
> > if there's a fast architected hardware random thing (ie modern x86).
> 
> Right, that is better, at least for the RDRAND machines.

Also note that the CRNG will use RDRAND if it is there; it just
doesn't depend on it.  The main thing about get_random_u32() is that
it has a policy decision embedded into it which is that we believe
that RDRAND, or whatever implements arch_get_random_{seed_}{long,int} is 
trusted.  (e.g., that we trust that Intel, Qualcomm, etc., didn't put a
back door into CPU-based random number generator, which we basically have
to take on faith because there is no way to audit it).

I tend to be a bit of pragmatist on these things, which is that I
believe it is *unlikely* that the NSA managed to pay off or blackmail
Intel into subverting RDRAND.  I can't prove it, of course, but if we
can get away with not trusting Intel, it's better if we can avoid
investing all of our trust in Intel.  On the flip side, for very early
boot, unless we can do what OpenBSD does and actually embed into the
boot loader reading a cryptographic seed from trusted store, it's
pretty much hopeless to think we can gather entropy, and we might as
well just use RDRAND, and hope for the best.  Realistically speaking,
the harm done from a bogus stack canary or even a subverted KASLR is
very small compared with introducing a wekaness into the keygen of
long-term public/private key.

And yes, spraying warning around just annoys users and if it inspires
them to do dumb(tm) things, it really doesn't help.  So suppressing
warnings during early boot is probably a good thing, since hopefully
people in early boot won't be stupid enough to generate high-value
keypairs.  :-)

>  We'd still need a proper fix for the older ones. And I don't see an
> easy way to change the init ordering for the stack canary as it gets
> setup very very early in start_kernel() vs crng_initialize() being
> an early_initcall()... Need to sleep on it.

The real fix is to do what OpenBSD does, which is to teach the
bootloader (e.g., grub) to read from some file such as
/var/lib/urandom/random-seed, and then to have the init scripts
overwrite it with a new set of entropy generated from getrandom(2) as
early as possible.

It won't solve the CD-ROM install problem (although there is enough
entropy during the install process that after the install is done, we
should be fine, and again, *hopefully* the distro people won't be
stupid enough to generate high-value keys during the installation
process, or certainly not early in the installation process).  But it
does solve most of the problem.

     	   			- Ted

[toc] | [prev] | [next] | [standalone]


#1711890

FromWilly Tarreau <w@1wt.eu>
Date2017-08-15 08:50 +0200
Message-ID<ueDPQ-6jk-7@gated-at.bofh.it>
In reply to#1711660
Hi Ted,

On Mon, Aug 14, 2017 at 09:31:24PM -0400, Theodore Ts'o wrote:
> The real fix is to do what OpenBSD does, which is to teach the
> bootloader (e.g., grub) to read from some file such as
> /var/lib/urandom/random-seed, and then to have the init scripts
> overwrite it with a new set of entropy generated from getrandom(2) as
> early as possible.
> 
> It won't solve the CD-ROM install problem (although there is enough
> entropy during the install process that after the install is done, we
> should be fine, and again, *hopefully* the distro people won't be
> stupid enough to generate high-value keys during the installation
> process, or certainly not early in the installation process).  But it
> does solve most of the problem.

In my opinion what matters is to combine multiple sources of entropy. I
remember in the good old days when I was coding under DOS, I used to
build my own random numbers using a phase detection method, counting
the time it takes for the RTC to switch to the next second, similar to
this :

  rand:
     xor edx, edx
     mov al, 0
     out 70h, al
     in al, 71h
     mov ah, al
  count:
     inc edx
     in al, 71h
     cmp al, ah
     jz count
     mov eax, edx
     ret

Nowadays we could use similar methods using RDTSC providing more accurate
counting. This doesn't provide a lot of entropy of course, given that a
2 GHz machine will at most count 31 bits there. But I tend to think that
what matters during early boot is to transform something highly predictable
into something unlikely to be predicted (ie: an exploit having to scan 2^31
possible addresses will not be really usable). It's also possible to do the
same with the PIT0 counter ticking at 18.2 Hz without any correlation with
the RTC by the way, and roughly provide 25 more bits. And if you expect
that the BIOS has emitted a 800 Hz beep at boot, you could still have a
divider of 1491 in PIT2 providing 10 more bits, though with a bit of
correlation with PIT0 since they use the same 1.19 MHz source. These
methods increase the boot time by up to one second though, but my point
here is that when you have nothing it's always a bit better.

Willy

[toc] | [prev] | [next] | [standalone]


#1711932

FromIngo Molnar <mingo@kernel.org>
Date2017-08-15 09:50 +0200
Message-ID<ueELT-6RV-1@gated-at.bofh.it>
In reply to#1711890
* Willy Tarreau <w@1wt.eu> wrote:

> Nowadays we could use similar methods using RDTSC providing more accurate
> counting. This doesn't provide a lot of entropy of course, given that a
> 2 GHz machine will at most count 31 bits there. But I tend to think that
> what matters during early boot is to transform something highly predictable
> into something unlikely to be predicted (ie: an exploit having to scan 2^31
> possible addresses will not be really usable). It's also possible to do the
> same with the PIT0 counter ticking at 18.2 Hz without any correlation with
> the RTC by the way, and roughly provide 25 more bits. And if you expect
> that the BIOS has emitted a 800 Hz beep at boot, you could still have a
> divider of 1491 in PIT2 providing 10 more bits, though with a bit of
> correlation with PIT0 since they use the same 1.19 MHz source. These
> methods increase the boot time by up to one second though, but my point
> here is that when you have nothing it's always a bit better.

One other thing besides trying to extract entropy via timing would be to utilize 
more of the machine's environment in seeding the random number generator.

For example on x86 the E820 table is available very early on and its addresses 
could be mixed into the random pool. An external attacker often would not know the 
precise hardware configuration.

Likewise the boot parameters string could be mixed into the initial random pool as 
well - and this way distributions could create per installation seed simply by 
appending a random number to the boot string.

Both methods should be very fast and robust.

Thanks,

	Ingo

[toc] | [prev] | [next] | [standalone]


#1711941

FromWilly Tarreau <w@1wt.eu>
Date2017-08-15 10:10 +0200
Message-ID<ueF5f-7dZ-3@gated-at.bofh.it>
In reply to#1711932
On Tue, Aug 15, 2017 at 09:42:54AM +0200, Ingo Molnar wrote:
> 
> * Willy Tarreau <w@1wt.eu> wrote:
> 
> > Nowadays we could use similar methods using RDTSC providing more accurate
> > counting. This doesn't provide a lot of entropy of course, given that a
> > 2 GHz machine will at most count 31 bits there. But I tend to think that
> > what matters during early boot is to transform something highly predictable
> > into something unlikely to be predicted (ie: an exploit having to scan 2^31
> > possible addresses will not be really usable). It's also possible to do the
> > same with the PIT0 counter ticking at 18.2 Hz without any correlation with
> > the RTC by the way, and roughly provide 25 more bits. And if you expect
> > that the BIOS has emitted a 800 Hz beep at boot, you could still have a
> > divider of 1491 in PIT2 providing 10 more bits, though with a bit of
> > correlation with PIT0 since they use the same 1.19 MHz source. These
> > methods increase the boot time by up to one second though, but my point
> > here is that when you have nothing it's always a bit better.
> 
> One other thing besides trying to extract entropy via timing would be to utilize 
> more of the machine's environment in seeding the random number generator.
> 
> For example on x86 the E820 table is available very early on and its addresses 
> could be mixed into the random pool. An external attacker often would not know the 
> precise hardware configuration.
> 
> Likewise the boot parameters string could be mixed into the initial random pool as 
> well - and this way distributions could create per installation seed simply by 
> appending a random number to the boot string.
> 
> Both methods should be very fast and robust.

Definitely, just like a simple MD5SUM on the first MB of RAM including
the BIOS, and on the CMOS RAM contents, which also differ quite a bit
between systems.

Willy

[toc] | [prev] | [next] | [standalone]


#1711943

FromIngo Molnar <mingo@kernel.org>
Date2017-08-15 10:10 +0200
Message-ID<ueF5g-7dZ-17@gated-at.bofh.it>
In reply to#1711941
* Willy Tarreau <w@1wt.eu> wrote:

> On Tue, Aug 15, 2017 at 09:42:54AM +0200, Ingo Molnar wrote:
> > 
> > * Willy Tarreau <w@1wt.eu> wrote:
> > 
> > > Nowadays we could use similar methods using RDTSC providing more accurate
> > > counting. This doesn't provide a lot of entropy of course, given that a
> > > 2 GHz machine will at most count 31 bits there. But I tend to think that
> > > what matters during early boot is to transform something highly predictable
> > > into something unlikely to be predicted (ie: an exploit having to scan 2^31
> > > possible addresses will not be really usable). It's also possible to do the
> > > same with the PIT0 counter ticking at 18.2 Hz without any correlation with
> > > the RTC by the way, and roughly provide 25 more bits. And if you expect
> > > that the BIOS has emitted a 800 Hz beep at boot, you could still have a
> > > divider of 1491 in PIT2 providing 10 more bits, though with a bit of
> > > correlation with PIT0 since they use the same 1.19 MHz source. These
> > > methods increase the boot time by up to one second though, but my point
> > > here is that when you have nothing it's always a bit better.
> > 
> > One other thing besides trying to extract entropy via timing would be to utilize 
> > more of the machine's environment in seeding the random number generator.
> > 
> > For example on x86 the E820 table is available very early on and its addresses 
> > could be mixed into the random pool. An external attacker often would not know the 
> > precise hardware configuration.
> > 
> > Likewise the boot parameters string could be mixed into the initial random pool as 
> > well - and this way distributions could create per installation seed simply by 
> > appending a random number to the boot string.
> > 
> > Both methods should be very fast and robust.
> 
> Definitely, just like a simple MD5SUM on the first MB of RAM including
> the BIOS, and on the CMOS RAM contents, which also differ quite a bit
> between systems.

In practice it's much faster to process the e820 table and the boot string though 
- and should already give a way to gain very good inter-machine randomization. It 
would also cover odd things like weird machines such as virtualization 
environments that often have nothing in the first 1MB.

I.e. 'e820' and 'boot string' are two universally available pieces of 
environmental data that could be used in a robust and fast fashion.

Thanks,

	Ingo

[toc] | [prev] | [next] | [standalone]


#1712133

FromTheodore Ts'o <tytso@mit.edu>
Date2017-08-15 14:20 +0200
Message-ID<ueIZc-1d4-13@gated-at.bofh.it>
In reply to#1711943
On Tue, Aug 15, 2017 at 10:05:46AM +0200, Ingo Molnar wrote:
> > > * Willy Tarreau <w@1wt.eu> wrote:
> > > > 
> > > > Nowadays we could use similar methods using RDTSC providing more accurate
> > > > counting. This doesn't provide a lot of entropy of course, given that a
> > > > 2 GHz machine will at most count 31 bits there. But I tend to think that
> > > > what matters during early boot is to transform something highly predictable
> > > > into something unlikely to be predicted (ie: an exploit having to scan 2^31
> > > > possible addresses will not be really usable). It's also possible to do the
> > > > same with the PIT0 counter ticking at 18.2 Hz without any correlation with
> > > > the RTC by the way, and roughly provide 25 more bits....

All of this assumes that you have different clock crystals generating
all of these different clock sources.  Otherwise there can be a lot
less entropy than you expected.

> In practice it's much faster to process the e820 table and the boot
> string though - and should already give a way to gain very good
> inter-machine randomization. It would also cover odd things like
> weird machines such as virtualization environments that often have
> nothing in the first 1MB.

There is nothing wrong with doing this --- and architecture
maintainers are encouraged to call add_device_randomness() on any
piece of data which they think might help.  That being said, these
values don't change much (boot string) or at all (e820 table) between
boots, and if you have a large collection of machines that all have
the same hardware (say, Dell desktops), and the same distro installed
on them (say, Ubuntu), it doesn't give you as much inter-machine
randomization as you might expect.

And as far as virtualization environments are concerned, the attacker
can determine quite easily from the IP address range if a VM is being
run out of an Amazon, Google, or Microsoft data center.

Finally, in some cases, we need the entropy *very* early --- for
example for kASLR, right after we get control from the boot loader.
Which is why I believe that we really do need to have the bootloader
fetching random seed material from the root file system or some other
trusted store to solve the inter-boot randomness problem.

Again, if platform code and device drivers want to call
add_device_randomness() early in the boot process --- they should
absolutely be encouraged to do this.  It is a good thing.  *AND* it is
not sufficient by itself.

Cheers,

					- Ted

[toc] | [prev] | [next] | [standalone]


#1712181

FromWilly Tarreau <w@1wt.eu>
Date2017-08-15 15:30 +0200
Message-ID<ueK4W-1Pe-5@gated-at.bofh.it>
In reply to#1712133
On Tue, Aug 15, 2017 at 08:09:50AM -0400, Theodore Ts'o wrote:
> On Tue, Aug 15, 2017 at 10:05:46AM +0200, Ingo Molnar wrote:
> > > > * Willy Tarreau <w@1wt.eu> wrote:
> > > > > 
> > > > > Nowadays we could use similar methods using RDTSC providing more accurate
> > > > > counting. This doesn't provide a lot of entropy of course, given that a
> > > > > 2 GHz machine will at most count 31 bits there. But I tend to think that
> > > > > what matters during early boot is to transform something highly predictable
> > > > > into something unlikely to be predicted (ie: an exploit having to scan 2^31
> > > > > possible addresses will not be really usable). It's also possible to do the
> > > > > same with the PIT0 counter ticking at 18.2 Hz without any correlation with
> > > > > the RTC by the way, and roughly provide 25 more bits....
> 
> All of this assumes that you have different clock crystals generating
> all of these different clock sources.  Otherwise there can be a lot
> less entropy than you expected.

That's what's cool with the RTC, it definitely runs on its own 32kHz
crystal since it continues to beat when everything else is powered off.

Willy

[toc] | [prev] | [next] | [standalone]


#1712065

FromThomas Gleixner <tglx@linutronix.de>
Date2017-08-15 12:50 +0200
Message-ID<ueHA6-bQ-17@gated-at.bofh.it>
In reply to#1711932
On Tue, 15 Aug 2017, Ingo Molnar wrote:
> * Willy Tarreau <w@1wt.eu> wrote:
> 
> > Nowadays we could use similar methods using RDTSC providing more accurate
> > counting. This doesn't provide a lot of entropy of course, given that a
> > 2 GHz machine will at most count 31 bits there. But I tend to think that
> > what matters during early boot is to transform something highly predictable
> > into something unlikely to be predicted (ie: an exploit having to scan 2^31
> > possible addresses will not be really usable). It's also possible to do the
> > same with the PIT0 counter ticking at 18.2 Hz without any correlation with
> > the RTC by the way, and roughly provide 25 more bits. And if you expect
> > that the BIOS has emitted a 800 Hz beep at boot, you could still have a
> > divider of 1491 in PIT2 providing 10 more bits, though with a bit of
> > correlation with PIT0 since they use the same 1.19 MHz source. These
> > methods increase the boot time by up to one second though, but my point
> > here is that when you have nothing it's always a bit better.
> 
> One other thing besides trying to extract entropy via timing would be to utilize 
> more of the machine's environment in seeding the random number generator.
> 
> For example on x86 the E820 table is available very early on and its addresses 
> could be mixed into the random pool. An external attacker often would not know the 
> precise hardware configuration.
> 
> Likewise the boot parameters string could be mixed into the initial random pool as 
> well - and this way distributions could create per installation seed simply by 
> appending a random number to the boot string.
> 
> Both methods should be very fast and robust.

Actually using RDTSC is not the worst approach. See:

  https://lwn.net/images/conf/rtlws11/random-hardware.pdf

Below is a stupid implementation of that. Here are the resulting numbers
from a dozen of boot cycles:

10a3e7af4890c0ae
e7b08c8c18e6d5d9
951e12c77f79e000
ad88753ad11c9b80
db2d4dce466a3da4
b328c76d4e67368d
642edf2265e0c8a7
ef45a9f9326249d0
13e01119498797a6
0a537c8751e0349e
eb67c02dc09326dd
037d4b332020538d
793fbfda06718c69
2231535c514769e5

This mechanism could also be used to seed the random generator.

Thanks,

	tglx

8<-------------------

--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -1360,3 +1360,19 @@ unsigned long calibrate_delay_is_known(v
 	return 0;
 }
 #endif
+
+u64 __init tsc_early_random(void)
+{
+	u64 uninitialized_var(res);
+	int i;
+
+	if (!boot_cpu_has(X86_FEATURE_TSC))
+		return res;
+
+	res ^= rdtsc();
+	for (i = 0; i < BITS_PER_LONG; i++) {
+		res ^= ((rdtsc() & 0x04) >> 2) << i;
+		udelay(2);
+	}
+	return res;
+}

[toc] | [prev] | [next] | [standalone]


#1712192

FromBorislav Petkov <bp@alien8.de>
Date2017-08-15 15:50 +0200
Message-ID<ueKoh-1VC-3@gated-at.bofh.it>
In reply to#1712065
On Tue, Aug 15, 2017 at 12:47:36PM +0200, Thomas Gleixner wrote:
> 8<-------------------
> 
> --- a/arch/x86/kernel/tsc.c
> +++ b/arch/x86/kernel/tsc.c
> @@ -1360,3 +1360,19 @@ unsigned long calibrate_delay_is_known(v
>  	return 0;
>  }
>  #endif
> +
> +u64 __init tsc_early_random(void)
> +{
> +	u64 uninitialized_var(res);
> +	int i;
> +
> +	if (!boot_cpu_has(X86_FEATURE_TSC))
> +		return res;
> +
> +	res ^= rdtsc();
> +	for (i = 0; i < BITS_PER_LONG; i++) {
> +		res ^= ((rdtsc() & 0x04) >> 2) << i;
> +		udelay(2);
> +	}
> +	return res;
> +}

Something like this is exactly what I was aiming at with my dumb patch.
We could use this for early boot randomness on x86.

Should I turn it into proper patches or you want to?

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

[toc] | [prev] | [next] | [standalone]


#1712195

FromThomas Gleixner <tglx@linutronix.de>
Date2017-08-15 15:50 +0200
Message-ID<ueKoh-1VC-15@gated-at.bofh.it>
In reply to#1712192
On Tue, 15 Aug 2017, Borislav Petkov wrote:
> On Tue, Aug 15, 2017 at 12:47:36PM +0200, Thomas Gleixner wrote:
> > 8<-------------------
> > 
> > --- a/arch/x86/kernel/tsc.c
> > +++ b/arch/x86/kernel/tsc.c
> > @@ -1360,3 +1360,19 @@ unsigned long calibrate_delay_is_known(v
> >  	return 0;
> >  }
> >  #endif
> > +
> > +u64 __init tsc_early_random(void)
> > +{
> > +	u64 uninitialized_var(res);
> > +	int i;
> > +
> > +	if (!boot_cpu_has(X86_FEATURE_TSC))
> > +		return res;
> > +
> > +	res ^= rdtsc();
> > +	for (i = 0; i < BITS_PER_LONG; i++) {
> > +		res ^= ((rdtsc() & 0x04) >> 2) << i;
> > +		udelay(2);
> > +	}
> > +	return res;
> > +}
> 
> Something like this is exactly what I was aiming at with my dumb patch.
> We could use this for early boot randomness on x86.
> 
> Should I turn it into proper patches or you want to?

Go ahead. What you actually want to do is to replace boot_cpu_has() with a
real cpuid() check because boot_cpu_has() is not initialized on real early
boot.

Thanks,

	tglx

[toc] | [prev] | [next] | [standalone]


#1712219

FromTheodore Ts'o <tytso@mit.edu>
Date2017-08-15 16:30 +0200
Message-ID<ueL10-2pR-17@gated-at.bofh.it>
In reply to#1712195
On Tue, Aug 15, 2017 at 03:48:18PM +0200, Thomas Gleixner wrote:
> > > +u64 __init tsc_early_random(void)
> > > +{
> > > +	u64 uninitialized_var(res);
> > > +	int i;
> > > +
> > > +	if (!boot_cpu_has(X86_FEATURE_TSC))
> > > +		return res;
> > > +
> > > +	res ^= rdtsc();
> > > +	for (i = 0; i < BITS_PER_LONG; i++) {
> > > +		res ^= ((rdtsc() & 0x04) >> 2) << i;
> > > +		udelay(2);
> > > +	}
> > > +	return res;
> > > +}

Reasons why this is probably not the best idea:

1)  Exactly how udelay is implemented varies from architecture to
architecture and in some cases is different on a subarchitectural
level.  Some of them rely on reading the TSC; others rely on
operations that will have a constant number of CPU cycles (e.g., they
aren't doing much if any operations that might even have a tiny
glimmer of hope of adding unpredictability).

2) Given a dozen numbers and saying, "hmm, my human brain doesn't see
a problem, it *must* be good" is hardly the basis on which to make
this kind of security design.  If you don't understand why this is a
bad idea, and can't come up with a counter example in under 5 seconds,
you probably aren't qualified to be designing a RNG which is supposed
to be cryptographically secure.

3)  Depending on when you use this function in early boot, udelay()
might not even have been calibrated yet.

4) As as standalone function, it doesn't take advantage of whatever
randomness might have been available; and if it turns out that the
tsc_early_random() is trivially predictable by someone spends more
time analyizing it for particular target architectures, it could be
disastrous

5) If you use this in addition to the existing get_random_u32(), it
won't hurt from a cryptographic perspective, but it will end up
burning 64-128 microseconds (or potentially more, depending on how
udelay is implemented on the architecture/subarch and whether udelay
has been calibrated yet).  And it's not clear it's really better(tm).

6) It would be the ultimate in irony if Jason, who tried so hard to
get this warning in because he hoped it would make Linux more secure,
actually ends up making Linux *less* secure because something like
this starts getting used....

					- Ted

[toc] | [prev] | [next] | [standalone]


#1712225

FromThomas Gleixner <tglx@linutronix.de>
Date2017-08-15 16:50 +0200
Message-ID<ueLkm-2ya-15@gated-at.bofh.it>
In reply to#1712219
On Tue, 15 Aug 2017, Theodore Ts'o wrote:
> On Tue, Aug 15, 2017 at 03:48:18PM +0200, Thomas Gleixner wrote:
> > > > +u64 __init tsc_early_random(void)
> > > > +{
> > > > +	u64 uninitialized_var(res);
> > > > +	int i;
> > > > +
> > > > +	if (!boot_cpu_has(X86_FEATURE_TSC))
> > > > +		return res;
> > > > +
> > > > +	res ^= rdtsc();
> > > > +	for (i = 0; i < BITS_PER_LONG; i++) {
> > > > +		res ^= ((rdtsc() & 0x04) >> 2) << i;
> > > > +		udelay(2);
> > > > +	}
> > > > +	return res;
> > > > +}
> 
> Reasons why this is probably not the best idea:
> 
> 1)  Exactly how udelay is implemented varies from architecture to
> architecture and in some cases is different on a subarchitectural
> level.  Some of them rely on reading the TSC; others rely on
> operations that will have a constant number of CPU cycles (e.g., they
> aren't doing much if any operations that might even have a tiny
> glimmer of hope of adding unpredictability).

That's not really true. You can add random shite instead of udelay(2). The
point of this exercise is to somewhat utilize the instruction pipeline,
which causes the TSC readouts to be not even spread over a the loop and
therefor yield random results.

> 2) Given a dozen numbers and saying, "hmm, my human brain doesn't see
> a problem, it *must* be good" is hardly the basis on which to make
> this kind of security design.  If you don't understand why this is a
> bad idea, and can't come up with a counter example in under 5 seconds,
> you probably aren't qualified to be designing a RNG which is supposed
> to be cryptographically secure.

Care to read the paper?

We tried that 6 years ago on a wide range of machines from server to stupid
first generation in order ATOM chips. All of them exposed more or less the
same behaviour and passed RND validation tests.

I'm not saying it's a replacement for the run time random generator, but
it's exceptionally good and reasonably fast for the early boot
randomization.

Thanks,

	tglx

[toc] | [prev] | [next] | [standalone]


#1712252

FromBorislav Petkov <bp@alien8.de>
Date2017-08-15 17:30 +0200
Message-ID<ueLX4-30v-5@gated-at.bofh.it>
In reply to#1712225
On Tue, Aug 15, 2017 at 04:42:47PM +0200, Thomas Gleixner wrote:
> I'm not saying it's a replacement for the run time random generator, but
> it's exceptionally good and reasonably fast for the early boot
> randomization.

... which suffices our purposes. It's not like we're going to generate
long-term key pairs with it.

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

[toc] | [prev] | [next] | [standalone]


#1712385

FromThomas Gleixner <tglx@linutronix.de>
Date2017-08-15 19:40 +0200
Message-ID<ueNYS-4hU-21@gated-at.bofh.it>
In reply to#1712225
On Tue, 15 Aug 2017, Thomas Gleixner wrote:
> On Tue, 15 Aug 2017, Theodore Ts'o wrote:
> > On Tue, Aug 15, 2017 at 03:48:18PM +0200, Thomas Gleixner wrote:
> > > > > +u64 __init tsc_early_random(void)
> > > > > +{
> > > > > +	u64 uninitialized_var(res);
> > > > > +	int i;
> > > > > +
> > > > > +	if (!boot_cpu_has(X86_FEATURE_TSC))
> > > > > +		return res;
> > > > > +
> > > > > +	res ^= rdtsc();
> > > > > +	for (i = 0; i < BITS_PER_LONG; i++) {
> > > > > +		res ^= ((rdtsc() & 0x04) >> 2) << i;
> > > > > +		udelay(2);
> > > > > +	}
> > > > > +	return res;
> > > > > +}
> > 
> > Reasons why this is probably not the best idea:
> > 
> > 1)  Exactly how udelay is implemented varies from architecture to
> > architecture and in some cases is different on a subarchitectural
> > level.  Some of them rely on reading the TSC; others rely on
> > operations that will have a constant number of CPU cycles (e.g., they
> > aren't doing much if any operations that might even have a tiny
> > glimmer of hope of adding unpredictability).
> 
> That's not really true. You can add random shite instead of udelay(2). The
> point of this exercise is to somewhat utilize the instruction pipeline,
> which causes the TSC readouts to be not even spread over a the loop and
> therefor yield random results.

Talking about random shite:

    	memset(foo, 0, sizeof(foo));
	res ^= rdtsc();
	for (i = 0; i < BITS_PER_LONG; i++) {
		/* Will never happen ... */
		if (memchr_inv(foo, i, sizeof(foo)))
			continue;
		res ^= ((rdtsc() & 0x04) >> 2) << i;
		memset(foo, i, sizeof(foo));
		wbinvd();
	}
	return res;

That exploits the fact that the CPU and caches run at a different non
synchronized clock than the memory controller and therefore the execution
time for both the wbinvd() and the memchr_inv() measured in TSC cycles is
non constant and random enough for the early boot randomization.

Thanks,

	tglx

[toc] | [prev] | [next] | [standalone]


#1712637

FromTheodore Ts'o <tytso@mit.edu>
Date2017-08-16 05:40 +0200
Message-ID<ueXlv-1O3-3@gated-at.bofh.it>
In reply to#1712385
On Tue, Aug 15, 2017 at 07:37:05PM +0200, Thomas Gleixner wrote:
> That exploits the fact that the CPU and caches run at a different non
> synchronized clock than the memory controller and therefore the execution
> time for both the wbinvd() and the memchr_inv() measured in TSC cycles is
> non constant and random enough for the early boot randomization.

Um, can we guarantee that is always true for all systems?  Even, say,
for Silermont, Goldmont and Goldmont Plus (Intel's SOC designs) where
the memory may be located in the same chip package as the CPU/caches?

And even if this is true today, can we be sure that it will be true
for the forseeable future?  Using multiple clocks takes more power, so
I would think that on a SOC there would be a strong pressure to use a
single oscillator for the whole package.

If we really want to do this, I'd much rather *not* have code calling
tsc_early_random().  We're better off having the code call
get_random_bytes() and/or get_random_u32(), and having these systems
use RDRAND if available, and if not, falling back to
tsc_early_random() and then mixing it with whatever unpredictability
we may have been able to gather so far if the CRNG hasn't been
initialized yet.

That way something like tsc_early_random() can help, but it can't make
things worse than what we have today (excepting the performance delay
caused by adding whatever random shite that we hope is enough to
introduce unpredictability to the TSC --- for which I still remain
very skeptical).

						- Ted

P.S.  As I recall hpa@ has talked to some Intel architects internally
about how much unpredictability we could really get, and how much of
it is just because there's complex state that we can't see (which if
we could see, might make it much more predictable), and as I recall
they didn't say anyhing definitively; but they were nervous.  I'm
pretty sure that for Intel architects, the right answer from their
perspective is to use RDRAND, and not to play games with the TSC.

The other thing to note here is that because Intel has RDRAND, I'm
actually not that worried about Intel; all of the
drivers/char/random.c will mix in inputs from RDRAND or RDSEED if
available.  I'm actually much more worried about architectures that
don't have a hardware random number generator (e.g., some ARM
subarchitectures and MIPS).  So while you might be able to come up
with something that could work on x86, the real question is it safely
generalizable to other, non-x86 architectures.  And that's where it
gets much more scary.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | linux.kernel


csiph-web