Kristjan Kelt - CryptoLUX · 2013-12-18 · Entropy Entropy is just the size of the pool from where...

Preview:

Citation preview

Kristjan Kelt

Survey of random number generators

on various platforms

University of Luxembourg 2013

Objective

● Investigate random number generation in several open source libraries, frameworks and applications that are based on cryptography

● Investigated– Pure-Python ECDSA

– PyBitmessage

– BitcoinJS

– Bitaddress.org

– CryptoCat

● Part II (if time permits), Trusting random generators (based on Intel RDRAND)

Importance

● Good random generator is cornerstone of good cryptography– Everything that must be hard to predict needs a

good random source

Importance

● Example attack– September 2006, buy commenting out few lines in

OpenSSL library, Debian developers created a bug that rendered OpenSSL random source useless

● Bug was discovered May 2008 by Luciano Bello● All cryptographic keys generated on Debian (or derived

distributions like Ubuntu) with OpenSSL turned out to have only 15 bit entropy provided by process id)

● All keys generated were possible to break with brute force

Importance

● Second attack example– In 2013 vulnerability in Android SecureRandom

class implementation was described by Michaelis, Meyer, Schwenk

– Cascade of bugs reduced entropy to 31 bits making random numbers generated on Android guessable

– Vulnerability was previously used to steal at least 55 BTC from different wallets that used keys generated on Android

What is a good random number?

● Is 7 a good random number?● What about 21299212?● Or 9?

What is a good random number?

● They all can be either good or bad random numbers depending on how they are generated

Entropy

● Entropy is just the size of the pool from where the numbers are randomly picked– Entropy of 1 coin flip is 1 bit – To get more entropy (in bits), we need more flips

(random events)

● Real random numbers are hard to generate (read: slow) both for brain and computer– But entropy can be mixed, combined and distilled– Unfortunately entropy is also consumed fast by

todays cryptographic applications

PRNG (Pseudo random number generator)

● Benefits– Provides statistically good distribution

– Need very low entropy as a source (i.e. current time)

– Fast

● Why are PRNGs not secure?– Predictability

– Linear dependencies

CSPRNG(Cryptographically Secure Pseudo Random Number

Generator)

● Requirements– Forward secrecy

– Backward secrecy

– State security

– Sufficiently large entropy● RFC 1750 Randomness Recommendations for Security,

Schiller, Crocker, Eastlake 1994

● Cryptanalytic Attacks on Pseudorandom Number Generator, Schneier, Kelsey, Wagner, 1998

Generalized CSPRNG, with periodic reseeding

Generalized CSPRNG, with periodic reseeding

Proposed in 1998 by Schneier, Kelsey, Wagner, Hall in Cryptanalytic Attacks on Pseudorandom Number Generators

Presentation of investigated random number generators

● First operation system provided generators were investigated

● Then platform libraries and browsers ● Finally libraries, frameworks and applications in

question

Operating systems

Linux***

Entropy pool

Entropy sources

Non blocking pool

Blockingpool

/dev/urandom /dev/random

ApplicationHardware entropy

source feedback in user space when available

Saved entropy during boot

get_random_bytes

*** without Intel RDRAND

Linux(few comments)

● Entropy estimator seems to be based upon Kolmogorov complexity rather than Shannon entropy (2012 Pousse, Short communication: An interpretation of the Linux entropy estimator)

● Analysis of the Linux Random Number Generator by Gutterman, Pinkas, Reinman 2006

● The Linux Pseudorandom Number Generator Revisited by Lacharme, Röck, Strubel, Videau 2012

Yarrow-160

OSX

Entropy pool(non blocking)

Entropy sources

/dev/random /dev/urandom

Entropy sources

Windows XP

?????

CryptGetRandom

Application

Windows Vista & 7

?????

CryptGetRandom

Application

BCryptGenRandom

?????

?=

Windows 8

?????

CryptGetRandom????

Application

BcryptGenRandomFIPS ?? NIST ??

?????

?=

CryptographicBuffer.GenerateRandom

??

?????

?=

Platform libraries

Windows *Linux, OSX

Python

os.urandom(direct wrapper)

random.SystemRandom

/dev/urandom CryptGetRandom

Application

OpenSSL

Windows *Linux, OSX

RAND_bytes(OpenSSL has different engines but according to documentation

seeds at least once at first call)

/dev/urandom CryptGetRandom

Application

Browsers

Firefoxsince version 21

Windows *Linux, OSX

window.crypto.getRandomValues()

/dev/urandom CryptGetRandom

Application

NIST SP 800-90 - Hash_DRBG (SHA256)(seed length 440 bits, reseeded after 2^48 bytes,

generator is shared between threads)

Internet Explorersince version 11

Windows 7, Windows 8

window.crypto.getRandomValues()

BCryptGetRandom

Application

Webkit(Safari, Chrome, Opera, browser specific)

Windows *Linux, OSX

window.crypto.getRandomValues()

/dev/urandom CryptGetRandom

Application

ARC4 stream cipher based random number generator(seed length 1024 bits, reseeded after 1600000 bytes,

generator is shared between threads)

Libraries, frameworks and applications in question

CryptoCat

window.crypto.getRandomValues

Salsa20/20(seed size 256 bits, reseed never)

Chat Application

Pure-Python ECDSA (library)

os.urandom

ApplicationClass PRNG

Sha256 + counter

Class SigningKey(default NIST192p)

util.randrange(small wrapper around

os.urandom)

OpenSSL library

PyBitmessage (library)

OpenSSL.RAND_bytes

Application

OpenSSL.rand(a library wrapper)

RAND_bytes

addressGenerator

BitcoinJS

● Library crypto.js – contains Crypto.util namespace that with function randomBytes that uses Math.random()

● Library rng.js, provides class SecureRandom– on pool initialization calls window.crypto.random in case of

specific browser version (this interface does not exist) – Then continues to fill pool with Math.random()– Finally adds current time (in ms) to the end of the pool

BitcoinJS

● Library rng.js, prototype SecureRandom– When generating first random byte, creates a ARC4

generator seeded by current pool + current time

– Seed size is 1024 and it is calculated over potentially larger entropy pool

– Generator is never seeded again

BitcoinJS

● At the top of the rng.js is a suggestion to call rng_seed_time() on body.onClick and body.onKeyPress – As generator is never seeded again, it has effect

only till first byte is generated

– Does not suggest mouse movements

– Sample user interface implementation does not follow this suggestion

BitcoinJS

Math.random()

Application

SecureRandom.nextBytes

ARC4(seed size 1024,

from potentially larger entropy pool, never reseeded)

Mouse and keyboard Current time

Bitaddress.org

● Incorporates code from different libraries including BitcoinJS

● Uses similar SecureRandom class but indeed follows the suggestion to fill the pool based on random user generated events

● Uses mouse move event in addition– Uses current time and mouse pointer coordinates

(X*Y)

Bitaddress.org

● Uses seed count to collect enough entropy● Seed count threshold is generated with

Math.random() (from Crypto.util.randomBytes)

Bitaddress.org

● When generating random bytes, checks for existence of window.crypto.getRandomValues– When present, returns bytes using this interface

instead

– In practice this renders seed counting useless as it does not change seed for the window.crypto.getRandomValues

Bitaddress.org

window.crypto.getRandomValues

SecureRandom.nextBytes

ARC4(seed size 1024,

from potentially larger entropy pool, never reseeded)

OR

Application

Full Random Generation Chains

● Pure-Python ECDSA ● PyBitmessage● Bitaddress.org (including parts of BitcoinJS)● CryptoCat

Pure-Python ECDSArandom generation chain

Windows *OSX

/dev/urandom CryptGetRandom

????? ?????

Entropy pool

Linux

/dev/urandom

?????

Entropy pool

Non blocking pool

os.urandom(direct wrapper)

Application

Class SigningKey(default NIST192p)

util.randrange(wrapper around os.urandom)

PyBitmessagerandom generation chain

Windows *OSX

/dev/urandom CryptGetRandom

????? ?????

Entropy pool

Linux

/dev/urandom

?????

Entropy pool

Non blocking pool

OpenSSL.RAND_bytes

Application

addressGenerator

OpenSSL.rand(a library wrapper)

FirefoxNIST SP 800-90 - Hash_DRBG (SHA256)

CryptoCatrandom generation chain

window.crypto.getRandomValues

Salsa20/20

Chat Application

WebkitARC4

Windows *OSX

/dev/urandom CryptGetRandom

window.crypto.getRandomValues

????? ?????

Entropy pool

Linux

/dev/urandom

?????

Entropy pool

Non blocking pool

FirefoxNIST SP 800-90 - Hash_DRBG (SHA256)

Bitaddress.orgrandom generation chain

window.crypto.getRandomValues

WebkitARC4

Windows *OSX

/dev/urandom CryptGetRandom

window.crypto.getRandomValues

????? ?????

Entropy pool

Linux

/dev/urandom

?????

Entropy pool

Non blocking pool

SecureRandom.nextBytes

Application

OR

Math.random()

ARC4

Mouse and keyboard

Current time

Conclusion

● In general most investigated projects got things right– Only really problematic project is

BitcoinJS that can not be used directly out of the box

– Bitaddress.org that extends on BitcoinJS got the things (relatively) right though

Conclusion continues

● Random number generation consist very often different linked random number generators

● Cryptography application writer must understand full random generation chain of target platforms

Questions or Part II(if time permits)

Trusting Random Generators

Trusting Random Generators

● Dual_EC_DRBG (Dual Elliptic Curve Deterministic Random Bit Generator)

● Intel RDRAND instruction in Linux

Dual_EC_DRBG(Dual Elliptic Curve Deterministic Random Bit Generator)

● Part of NIST Special Publication 800-90A– National Institute of Standards and Technology

– Recommendation for Random Number Generation Using Deterministic Random Bit Generators

– Contains 4 specifications

● Contains possible backdoor– Showed by Dan Shumow and Niels Ferguson at the

CRYPTO 2007 conference in August

– Still used (after 2007) by RSA security (confirmed) and possibly by Intel and Microsoft (suspected)

– Backdoor somewhat confirmed in 2013

Intel RDRAND in Linux

● Documentation of Linux random driver (comments of random.c) states that hardware random sources are not part of the kernel and entropy from them should be feed back into the pool externally

● 2011 Intel engineers approached Linux and suggested to incorporate Intel RDRAND instruction directly into Linux kernel as an architectural entropy source

Intel RDRAND in Linux

● Everything went (relatively) smoothly and patches went into kernel

● Fast forward to third quarter of 2013 when revelations of Dual_EC_DRBG came out

● Suddenly people noticed that documentation of RDRAND mentions NIST SP 800-90A– But this contains also Dual_EC_DRBG

– But Linux uses RDRAND

Intel RDRAND in Linux

● Linus Torvalds made a statement that– Kernel maintainers actually know what they are doing

– Output of RDRAND is mixed into entropy pool before it is returned to the user

● Theodore Ts said– "I am so glad I resisted pressure from Intel engineers

to let /dev/random rely only on the RDRAND instruction.”

Intel RDRAND in Linux(change history)

void get_random_bytes(void *buf, int nbytes){- extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);+ char *p = buf;++ while (nbytes) {+ unsigned long v;+ int chunk = min(nbytes, (int)sizeof(unsigned long));++ if (!arch_get_random_long(&v))+ break;++ memcpy(buf, &v, chunk);+ p += chunk;+ nbytes -= chunk;+ }++ extract_entropy(&nonblocking_pool, p, nbytes, 0, 0);}EXPORT_SYMBOL(get_random_bytes);

author Linus Torvalds <torvalds@linux-foundation.org> 2011-10-28 12:29:07 (GMT)committer Linus Torvalds <torvalds@linux-foundation.org> 2011-10-28 12:29:07 (GMT)

Intel RDRAND in Linux(change history)

static void add_timer_randomness(struct timer_rand_state *state, unsigned num){

struct {- cycles_t cycles;long jiffies;+ unsigned cycles;unsigned num;

} sample;long delta, delta2, delta3;

@@ -637,7 +637,11 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)

goto out;

sample.jiffies = jiffies;- sample.cycles = get_cycles();++ /* Use arch random value, fall back to cycles */+ if (!arch_get_random_int(&sample.cycles))+ sample.cycles = get_cycles();+

sample.num = num;mix_pool_bytes(&input_pool, &sample, sizeof(sample));

author Linus Torvalds <torvalds@linux-foundation.org> 2011-12-22 19:36:22 (GMT)committer H. Peter Anvin <hpa@linux.intel.com> 2011-12-30 00:49:45 (GMT)

Intel RDRAND in Linux(change history)

● Function add_input_randomness is called by– add_input_randomness

– add_disk_randomness

Intel RDRAND in Linux(change history)

author Theodore Ts'o <tytso@mit.edu> 2011-12-22 21:28:01 (GMT)committer H. Peter Anvin <hpa@linux.intel.com> 2012-01-16 19:18:21 (GMT)

static void init_std_data(struct entropy_store *r){

+ int i;ktime_t now;unsigned long flags;

@@ -974,6 +975,11 @@ static void init_std_data(struct entropy_store *r)now = ktime_get_real();mix_pool_bytes(r, &now, sizeof(now));

+ for (i = r->poolinfo->poolwords; i; i--) {+ if (!arch_get_random_long(&flags))+ break;+ mix_pool_bytes(r, &flags, sizeof(flags));+ }

mix_pool_bytes(r, utsname(), sizeof(*(utsname())));}

Intel RDRAND in Linux(change history)

author Linus Torvalds <torvalds@linux-foundation.org> 2012-01-17 02:23:09 (GMT)committer Linus Torvalds <torvalds@linux-foundation.org> 2012-01-17 02:23:09 (GMT)

static void init_std_data(struct entropy_store *r){+ int i;

ktime_t now;unsigned long flags;

@@ -974,6 +975,11 @@ static void init_std_data(struct entropy_store *r)now = ktime_get_real();

mix_pool_bytes(r, &now, sizeof(now));+ for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) {+ if (!arch_get_random_long(&flags))+ break;+ mix_pool_bytes(r, &flags, sizeof(flags));+ }

mix_pool_bytes(r, utsname(), sizeof(*(utsname())));}

Intel RDRAND in Linux(change history)

● If the CPU supports a hardware random number generator, use it in xfer_secondary_pool(), where it will significantly improve things and where we can afford it.

● Also, remove the use of the arch-specific rng in add_timer_randomness(), since the call is significantly slower than get_cycles(), and we're much better off using it in xfer_secondary_pool() anyway.

author Theodore Ts'o <tytso@mit.edu> 2012-07-05 14:21:01 (GMT)committer Theodore Ts'o <tytso@mit.edu> 2012-07-15 00:17:46 (GMT)

Intel RDRAND in Linux(change history)

● Mix in any architectural randomness in extract_buf() instead of xfer_secondary_buf(). This allows us to mix in more architectural randomness, and it also makes xfer_secondary_buf() faster, moving a tiny bit of additional CPU overhead to process which is extracting the randomness.

author H. Peter Anvin <hpa@linux.intel.com> 2012-07-28 02:26:08 (GMT)committer Theodore Ts'o <tytso@mit.edu> 2012-07-28 02:37:20 (GMT)

Intel RDRAND in Linux(change history)

author H. Peter Anvin <hpa@linux.intel.com> 2012-07-28 02:26:08 (GMT)committer Theodore Ts'o <tytso@mit.edu> 2012-07-28 02:37:20 (GMT)

static void extract_buf(struct entropy_store *r, __u8 *out){

[...............]

+ /*+ * If we have a architectural hardware random number+ * generator, mix that in, too.+ */+ for (i = 0; i < LONGS(EXTRACT_SIZE); i++) {+ unsigned long v;+ if (!arch_get_random_long(&v))+ break;+ hash.l[i] ^= v;+ }++ memcpy(out, &hash, EXTRACT_SIZE);+ memset(&hash, 0, sizeof(hash));}

Code of the previous slide

Possible attack of Intel RDRAND in Linux

● Taylor Hornby– At the first sight there is no problem as RANDOM

xor INDEPENDENTLY_BIASED = RANDOM

– What if RDRAND is used as a marker to activate malicious behavior of the CPU?

– Then when it sees the RDRAND followed by XOR, it could bias the RDRAND output according to the second input of the XOR (in this case the state of the entropy buffer)

Intel RDRAND in Linux(change history, current fix of the previous problem)

author Theodore Ts'o <tytso@mit.edu> 2013-09-21 22:06:02 (GMT)committer Theodore Ts'o <tytso@mit.edu> 2013-10-10 18:32:13 (GMT)

● Previously if CPU chip had a built-in random number generator (i.e., RDRAND on newer x86 chips), we mixed it in at the very end of extract_buf() using an XOR operation.

● We now mix it in right after the calculate a hash across the entire pool. […]

Conclusion

● Random number generator in the CPU can not be trusted

Recommended