The State of Randomness in Current Java Implementations
Total Page:16
File Type:pdf, Size:1020Kb
Randomly Failed! The State of Randomness in Current Java Implementations Kai Michaelis, Christopher Meyer, and J¨orgSchwenk fkai.michaelis, christopher.meyer, [email protected] Horst G¨ortzInstitute for IT-Security, Ruhr-University Bochum Abstract. This paper investigates the Randomness of several Java Run- time Libraries by inspecting the integrated Pseudo Random Number Generators. Significant weaknesses in different libraries including An- droid, are uncovered. 1 Introduction With a market share of 33-50% [1], [2], [3] Android is currently the most popular mobile OS. Each of the 331-400 million sold devices (cf. [3]) is able to run Java applications written in Java. Java provides inter- faces for different Pseudo Random Number Generators (PRNGs), such as SecureRandom, which is intended for use by cryptographic schemes. But, only the API is specified - each library implements own algorithms. Designing secure and reliable PRNGs is a hard and complicated task [4], as well as implementing these algorithms correctly. One of the worst ideas is to implement own unproved PRNG constructs. This paper examines the quality of the random numbers generated by common Java libraries. In detail, the PRNGs, intended for use in cryp- tographic environments, of Apache Harmony1, GNU Classpath2, Open- JDK3 and BouncyCastle4 are inspected. It is shown that the over-all entropy of the Android PRNG can be reduced to 64 bits. Beyond this, multiple weaknesses of entropy collectors are revealed. However, some of these weaknesses only occur under special conditions (e.g., unavailable /dev/fugrandom device). We clearly point out that we are not going to discuss the quality of random numbers generated by PRNGs shipped with Operating Systems (OS). Discussions of OS provided (P)RNG facilities can be found at e.g., [5], [6], [7]. 1 http://harmony.apache.org/ 2 http://www.gnu.org/software/classpath/ 3 http://openjdk.java.net/ 4 http://www.bouncycastle.org/ 2 Related Work Problems related to weak pseudo random number generators (PRNGs) have been topic of several previously published papers. In 2012 Argyros and Kiayias investigated in [8] the state of PRNGs in PHP5 and out- lined flaws leading to attack vectors. Their results are based on insecure constructions of PRNGs introduced by custom algorithms. Kopf outlined in [9] multiple cryptographic and implementational flaws in widespread Content Management Systems (CMS). These obser- vations focused weak cryptographic constructs and pecularities of PHP. The resulting bugs are not caused by weak PRNGs, but by vulnerable custom algorithms in combination with implementational flaws. Meyer and Somorovsky [10] uncovered a vulnerable use of Secure- Random in WSS4J6. A function responsible for nonce generation, used at various places in the framework, suffered from weak PRNG seeding. Problems related to PRNGs are also topic of multiple CWEs (Com- mon Weakness Enumeration)7 that deal with the misuse or use of weak pseudo random number generators (cf. CWE 330-343). In [11]) Lenstra et al. inspected millions of public keys of different types (RSA, DSA, ElGamal and ECDSA) and found keys violating basic principles for secure cryptographic parameters. According to the authors these weak keys could be a result of poorly seeded PRNGs. More alarming results concerning key quality are presented by Heninger et al. in [7] pointing out that "Randomness is essential for modern cryp- tography". Missing entropy was identified as a root cause for many weak and vulnerable keys. Additionally, the authors identified weak entropy problems under certain conditions in the Linux RNG. A more theory based cryptanalytic set of attacks on PRNGs can be found at e.g., [12]. 2.1 Contribution The results of this paper focus on PRNG implementations of Java core libraries. Even thus all libraries implement the same functionality - gener- ating (pseudo) random numbers - based on the same API, the algorithms for random number generation differ from library to library. 5 http://www.php.net 6 http://ws.apache.org/wss4j/ 7 http://cwe.mitre.org The main contribution is an analysis of algorithms implemented in most commonly used SecureRandom generators. For this analysis tests provided by the Dieharder [13] and STS [14] testsuites are used to check for cryptographic weaknesses. Additionally manual code analysis uncov- ered algorithmical and implementational vulnerabilities. 3 Implementations & Algorithms In Java, random numbers are derived from an initial seed. Two instances of a PRNG seeded with equal values always generate equal random se- quences. The cryptographic strong PRNGs are accessed via the Secure- Random interface which is part of the Java Cryptography Architecture. 3.1 Apache Harmony - Android's version of SecureRandom Apache Harmony, introduced in 2005 as an open source implementation of the Java Core Libraries published under the Apache License8, became obsolete with the publication of SUN Microsystems' reference implemen- tation in 2006. Although discontinued since 2011, the project is further devleoped as part of Google's Android platform. 1 // require cnt: counter >= 0, state: seed bytes and iv: previous output 2 iv = sha1(iv,concat(state,cnt)); 3 cnt = cnt + 1; 4 return iv; Listing 1.1. Apache Harmony's SecureRandom The PRNG shipped with Android uses the SHA-1 [15] hash algorithm to generate pseudo random sequences and is ideally seeded by the random devices provided by the OS. Random numbers are generated by calculat- ing hash sums of an internal state concatenated with a 64 bit integer counter and a padding (algorithm in Listing 1.1). The counter is, starting at zero, incremented each run of the algorithm. Additionally, a padding is required to fill remaining bits of a 85 bytes buffer. This padding fol- lows the SHA-1 padding scheme: The last 64 bits hold the length len of the values to be hashed in bits. Any space between the end of the values and the length field is filled with a single '1' bit followed by zeros. The resulting hash sums are returned as pseudo random sequence. Figure1 illustrates the state buffer. 8 http://www.apache.org/licenses/ 20 byte seed ( 5 * 32 bit words) 8 byte counter 57 byte padding i. s0 s1 s2 s3 s4 0 ··· 0 ii. s0 s1 s2 s3 s4 cnt0 cnt1 10 ··· 0 len Fig. 1. The seed bytes s0; ::; s4 in row i concatenated with a 64 bit counter c0; c1 (two 32bit words), padding bits and the length len as in row ii are hashed repeatedly to generate a stream of pseudorandom bytes. 3.2 GNU Classpath The GNU Classpath project started in 1998 as the first open source im- plementation of Java's core libraries. The library is licensed under GPL 9 and is e.g., partly used by the IcedTea 10 project. 1 // require state : <= 512 bit buffer, iv : current Initialzation Vector 2 byte[] output = sha1(iv,state); 3 state = concat(state,output); 4 if (state .length > 512) f // in bits 5 iv = sha(iv,state [0:512]) ; // first 512 bits 6 state = state[512:−1]; // rest 7 output = sha1(iv,state); 8 g 9 return output; Listing 1.2. GNU Classpath's SecureRandom The SecureRandom implementation (algorithm in Listing 1.2) of GNU Classpath is powered by a class MDGenerator that is parameterized with an arbitrary hash algorithm. A new SecureRandom instance is seeded with 32 bytes yielding an internal state as shown in rowi of Figure2. Based on this start value a digest is computed. The resulting hash (e.g. 160 bit in case of SHA-1) is returned as pseudo random value r0. r0 in turn is concatenated with the former seed forming the new state in row ii. These bytes are hashed again yielding the second output r1. Finally, the seed concatenated with the previous two hash values form the new state (c.f. row iii) whose digest is the third output value r3. r3 is again appended to the previous state resulting in the state illustrated in row iv. Each fourth ri values a block overflow happens causing the implementation to hash the full block and use this hash as initialization vector (IV) for the new block. The only unknown value is the 32 byte long initial seed. All other information are known (as they are parts of former ri value). 9 http://www.gnu.org/licenses/ 10 http://icedtea.classpath.org/wiki/Main_Page Block 1 (64 byte) Block 2 (64 byte) i. seed pad ii. seed r0 pad iii. seed r0 r1h r1l pad iv. seed r0 r1h r1l r2 pad Fig. 2. Hashing the previous pseudo random bytes concatenated with the fomer seed produces the next output value. GNU Classpath includes a \backup" seeding facility (algorithm in Listing 1.3) for Unix-like operating systems. The VMSecureRandom class is able to harvest entropy from the OS' process scheduler. Every call to the seeding facility starts 8 threads, each one incrementing a looped one byte counter. The parent thread waits until at least one of the 8 threads is picked up by the scheduler. The seed value is calculated by XORing each of the one byte counters. This forms the first seed byte. Accordingly, the next seed byte is generated the same way. When the requested amount of seeding material is gathered the threads are stopped. 1 int n = 0 2 byte[] S = new byte[8]; 3 byte[] output = new byte[32]; 4 5 for(int i = 0; i < 8; i++) f 6 S[i ] = start thread(n); // `` spinner'' incrementing a counter starting at n 7 n = (2∗n) % pow(2,32); 8 g 9 10 while(!spinners running()) 11 wait(); 12 13 for(int i = 0; i < 32; i++) f 14 output[i ] = 0; 15 16 for(int j = 0; j < 8; j++) 17 output[i ] = output[i] ^ counter(S[j ]) ; 18 g 19 20 for(int i = 0; i < 8; i++) 21 stop thread(S[i ]) ; 22 23 return output; Listing 1.3.