From 9bbe6492c01d79fccc543d8e5177b8dc9c2bba66 Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Tue, 3 Feb 2009 23:10:58 +0000 Subject: Fix typo and access to VMSecureRandom. 2009-02-03 Andrew John Hughes PR classpath/38417: * gnu/java/security/jce/prng/SecureRandomAdapter.java: Remove unneeded import. * gnu/javax/crypto/jce/prng/FortunaImpl.java: Fix typo. * java/security/SecureRandom.java: Remove duplicate use of VMSecureRandom, call SecureRandomAdapter instead. * vm/reference/gnu/java/security/jce/prng/VMSecureRandom.java: Moved from java/security so SecureRandomAdapter can access it. --- ChangeLog | 14 +++ .../security/jce/prng/SecureRandomAdapter.java | 3 +- gnu/javax/crypto/jce/prng/FortunaImpl.java | 2 +- java/security/SecureRandom.java | 65 +---------- .../gnu/java/security/jce/prng/VMSecureRandom.java | 129 +++++++++++++++++++++ 5 files changed, 147 insertions(+), 66 deletions(-) create mode 100644 vm/reference/gnu/java/security/jce/prng/VMSecureRandom.java diff --git a/ChangeLog b/ChangeLog index 11f04c61c..9514fbf1e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2009-02-03 Andrew John Hughes + + PR classpath/38417: + * gnu/java/security/jce/prng/SecureRandomAdapter.java: + Remove unneeded import. + * gnu/javax/crypto/jce/prng/FortunaImpl.java: + Fix typo. + * java/security/SecureRandom.java: + Remove duplicate use of VMSecureRandom, + call SecureRandomAdapter instead. + * vm/reference/gnu/java/security/jce/prng/VMSecureRandom.java: + Moved from java/security so SecureRandomAdapter can + access it. + 2009-01-22 Mario Torre PR classpath/38417: diff --git a/gnu/java/security/jce/prng/SecureRandomAdapter.java b/gnu/java/security/jce/prng/SecureRandomAdapter.java index a17c6eb1b..5877e3edb 100644 --- a/gnu/java/security/jce/prng/SecureRandomAdapter.java +++ b/gnu/java/security/jce/prng/SecureRandomAdapter.java @@ -45,7 +45,6 @@ import gnu.java.security.prng.MDGenerator; import java.security.AccessController; import java.security.SecureRandom; -import java.security.VMSecureRandom; import java.security.SecureRandomSpi; import java.util.Collections; @@ -101,7 +100,7 @@ public abstract class SecureRandomAdapter } public static final byte[] getSeed(int numBytes) - { + { URL sourceUrl = null; String urlStr = null; diff --git a/gnu/javax/crypto/jce/prng/FortunaImpl.java b/gnu/javax/crypto/jce/prng/FortunaImpl.java index add5b9ee0..b18410c09 100644 --- a/gnu/javax/crypto/jce/prng/FortunaImpl.java +++ b/gnu/javax/crypto/jce/prng/FortunaImpl.java @@ -93,7 +93,7 @@ public final class FortunaImpl } } - protected byte[] engineGenerateSeed(int numbytes) + protected byte[] engineGenerateSeed(int numBytes) { return SecureRandomAdapter.getSeed(numBytes); } diff --git a/java/security/SecureRandom.java b/java/security/SecureRandom.java index f96578236..0c7183879 100644 --- a/java/security/SecureRandom.java +++ b/java/security/SecureRandom.java @@ -42,6 +42,7 @@ import gnu.classpath.SystemProperties; import gnu.java.lang.CPStringBuilder; import gnu.java.security.Engine; import gnu.java.security.action.GetSecurityPropertyAction; +import gnu.java.security.jce.prng.SecureRandomAdapter; import gnu.java.security.jce.prng.Sha160RandomSpi; import java.io.IOException; @@ -401,9 +402,7 @@ public class SecureRandom extends Random */ public static byte[] getSeed(int numBytes) { - byte[] tmp = new byte[numBytes]; - generateSeed(tmp); - return tmp; + return SecureRandomAdapter.getSeed(numBytes); } /** @@ -418,64 +417,4 @@ public class SecureRandom extends Random return secureRandomSpi.engineGenerateSeed(numBytes); } - // Seed methods. - - private static final String SECURERANDOM_SOURCE = "securerandom.source"; - private static final String JAVA_SECURITY_EGD = "java.security.egd"; - private static final Logger logger = Logger.getLogger(SecureRandom.class.getName()); - - private static int generateSeed(byte[] buffer) - { - return generateSeed(buffer, 0, buffer.length); - } - - private static int generateSeed(byte[] buffer, int offset, int length) - { - URL sourceUrl = null; - String urlStr = null; - - GetSecurityPropertyAction action = new GetSecurityPropertyAction(SECURERANDOM_SOURCE); - try - { - urlStr = (String) AccessController.doPrivileged(action); - if (urlStr != null) - sourceUrl = new URL(urlStr); - } - catch (MalformedURLException ignored) - { - logger.log(Level.WARNING, SECURERANDOM_SOURCE + " property is malformed: {0}", - urlStr); - } - - if (sourceUrl == null) - { - try - { - urlStr = SystemProperties.getProperty(JAVA_SECURITY_EGD); - if (urlStr != null) - sourceUrl = new URL(urlStr); - } - catch (MalformedURLException mue) - { - logger.log(Level.WARNING, JAVA_SECURITY_EGD + " property is malformed: {0}", - urlStr); - } - } - - if (sourceUrl != null) - { - try - { - InputStream in = sourceUrl.openStream(); - return in.read(buffer, offset, length); - } - catch (IOException ioe) - { - logger.log(Level.FINE, "error reading random bytes", ioe); - } - } - - // If we get here, we did not get any seed from a property URL. - return VMSecureRandom.generateSeed(buffer, offset, length); - } } diff --git a/vm/reference/gnu/java/security/jce/prng/VMSecureRandom.java b/vm/reference/gnu/java/security/jce/prng/VMSecureRandom.java new file mode 100644 index 000000000..28a021027 --- /dev/null +++ b/vm/reference/gnu/java/security/jce/prng/VMSecureRandom.java @@ -0,0 +1,129 @@ +/* VMSecureRandom.java -- random seed generator. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is a part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or (at +your option) any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; if not, write to the Free Software +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +USA + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.java.security.jce.prng; + +/** + * VM-specific methods for generating real (or almost real) random + * seeds. VM implementors should write a version of this class that + * reads random bytes from some system source. + * + *

The default implementation of this class runs eight threads that + * increment counters in a tight loop, and XORs each counter to + * produce one byte of seed data. This is not very efficient, and is + * not guaranteed to be random (the thread scheduler is probably + * deterministic, after all). If possible, VM implementors should + * reimplement this class so it obtains a random seed from a system + * facility, such as a system entropy gathering device or hardware + * random number generator. + */ +final class VMSecureRandom +{ + + /** + * Generate a random seed. Implementations are free to generate + * fewer random bytes than are requested, and leave the remaining + * bytes of the destination buffer as zeros. Implementations SHOULD, + * however, make a best-effort attempt to satisfy the request. + * + * @param buffer The destination buffer. + * @param offset The offset in the buffer to start putting bytes. + * @param length The number of random bytes to generate. + */ + static int generateSeed(byte[] buffer, int offset, int length) + { + if (length < 0) + throw new IllegalArgumentException("length must be nonnegative"); + if (offset < 0 || offset + length > buffer.length) + throw new IndexOutOfBoundsException(); + + Spinner[] spinners = new Spinner[8]; + int n = 0x1; + for (int i = 0; i < spinners.length; i++) + { + spinners[i] = new Spinner((byte) n); + Thread t = new Thread(spinners[i]); + t.start(); + n <<= 1; + } + + // Wait until at least one spinner has started. + while (!(spinners[0].running || spinners[1].running || spinners[2].running + || spinners[3].running || spinners[4].running || spinners[5].running + || spinners[6].running || spinners[7].running)) + { + Thread.yield(); + } + + for (int i = offset; i < length; i++) + { + buffer[i] = (byte) (spinners[0].value ^ spinners[1].value ^ spinners[2].value + ^ spinners[3].value ^ spinners[4].value ^ spinners[5].value + ^ spinners[6].value ^ spinners[7].value); + Thread.yield(); + } + + for (int i = 0; i < spinners.length; i++) + spinners[i].stop(); + + return length; + } + + static class Spinner implements Runnable + { + volatile byte value; + volatile boolean running; + + Spinner(final byte initial) + { + value = initial; + } + + public void run() + { + running = true; + while (running) + value++; + } + + private void stop() + { + running = false; + } + } +} \ No newline at end of file -- cgit v1.2.1