OSDN Git Service

Sync libgcj with GNU Classpath 0.98.
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / security / jce / prng / SecureRandomAdapter.java
index 5be402f..5877e3e 100644 (file)
@@ -38,35 +38,57 @@ exception statement from your version.  */
 
 package gnu.java.security.jce.prng;
 
+import gnu.java.security.action.GetSecurityPropertyAction;
+import gnu.classpath.SystemProperties;
 import gnu.java.security.prng.LimitReachedException;
 import gnu.java.security.prng.MDGenerator;
 
+import java.security.AccessController;
+import java.security.SecureRandom;
 import java.security.SecureRandomSpi;
+
 import java.util.Collections;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import java.io.InputStream;
+import java.io.IOException;
+
+import java.net.MalformedURLException;
+import java.net.URL;
 
 /**
- * The implementation of a generic {@link java.security.SecureRandom} adapter
- * class to wrap GNU PRNG instances based on Message Digest algorithms.
- * <p>
- * This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for
+ * <p>The implementation of a generic {@link java.security.SecureRandom} adapter
+ * class to wrap gnu.crypto prng instances based on Message Digest algorithms.</p>
+ *
+ * <p>This class defines the <i>Service Provider Interface</i> (<b>SPI</b>) for
  * the {@link java.security.SecureRandom} class, which provides the
- * functionality of a cryptographically strong pseudo-random number generator.
- * <p>
- * All the abstract methods in the {@link SecureRandomSpi} class are implemented
- * by this class and all its sub-classes.
+ * functionality of a cryptographically strong pseudo-random number generator.</p>
+ *
+ * <p>All the abstract methods in the {@link SecureRandomSpi} class are
+ * implemented by this class and all its sub-classes.</p>
  */
-abstract class SecureRandomAdapter
-    extends SecureRandomSpi
+public abstract class SecureRandomAdapter 
+  extends SecureRandomSpi
 {
+
+  private boolean isSeeded = false;
+
   /** Our underlying prng instance. */
   private MDGenerator adaptee = new MDGenerator();
 
   /** The name of the message digest algorithm used by the adaptee. */
   private String mdName;
 
+  private static final Logger logger =
+    Logger.getLogger(SecureRandom.class.getName());
+
+  private static final String SECURERANDOM_SOURCE = "securerandom.source";
+  private static final String JAVA_SECURITY_EGD = "java.security.egd";
+
   /**
-   * Trivial protected constructor.
-   * 
+   * <p>Trivial protected constructor.</p>
+   *
    * @param mdName the canonical name of the underlying hash algorithm.
    */
   protected SecureRandomAdapter(String mdName)
@@ -74,23 +96,77 @@ abstract class SecureRandomAdapter
     super();
 
     this.mdName = mdName;
-    adaptee.init(Collections.singletonMap(MDGenerator.MD_NAME, mdName));
+    adaptee.init (Collections.singletonMap (MDGenerator.MD_NAME, mdName));
+  }
+
+  public static final byte[] getSeed(int numBytes)
+  {  
+    URL sourceUrl = null;
+    String urlStr = null;
+
+    byte[] buffer = new byte[numBytes];
+
+    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();
+            in.read(buffer);
+            return buffer;
+          }
+        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.
+    VMSecureRandom.generateSeed(buffer, 0, buffer.length);
+    return buffer;
   }
 
   public byte[] engineGenerateSeed(int numBytes)
   {
-    if (numBytes < 1)
-      return new byte[0];
-
-    byte[] result = new byte[numBytes];
-    this.engineNextBytes(result);
-    return result;
+    return getSeed(numBytes);
   }
 
   public void engineNextBytes(byte[] bytes)
   {
-    if (! adaptee.isInitialised())
-      this.engineSetSeed(new byte[0]);
+    if (!isSeeded)
+      {
+        engineSetSeed(engineGenerateSeed(32));
+      }
     try
       {
         adaptee.nextBytes(bytes, 0, bytes.length);
@@ -102,6 +178,7 @@ abstract class SecureRandomAdapter
 
   public void engineSetSeed(byte[] seed)
   {
-    adaptee.addRandomBytes(seed);
+    adaptee.addRandomBytes (seed);
+    isSeeded = true;
   }
 }