src/java.base/share/classes/sun/security/provider/SeedGenerator.java

Print this page




  58  * Security property to a URL specifying the location of the entropy
  59  * gathering device, or by setting the {@code java.security.egd} System
  60  * property.
  61  * <p>
  62  * In the event the specified URL cannot be accessed the default
  63  * threading mechanism is used.
  64  *
  65  * @author Joshua Bloch
  66  * @author Gadi Guy
  67  */
  68 
  69 import java.security.*;
  70 import java.io.*;
  71 import java.util.Properties;
  72 import java.util.Enumeration;
  73 import java.net.*;
  74 import java.nio.file.DirectoryStream;
  75 import java.nio.file.Files;
  76 import java.nio.file.Path;
  77 import java.util.Random;
  78 import sun.misc.ManagedLocalsThread;
  79 import sun.security.util.Debug;
  80 
  81 abstract class SeedGenerator {
  82 
  83     // Static instance is created at link time
  84     private static SeedGenerator instance;
  85 
  86     private static final Debug debug = Debug.getInstance("provider");
  87 
  88     // Static initializer to hook in selected or best performing generator
  89     static {
  90         String egdSource = SunEntries.getSeedSource();
  91 
  92         /*
  93          * Try the URL specifying the source (e.g. file:/dev/random)
  94          *
  95          * The URLs "file:/dev/random" or "file:/dev/urandom" are used to
  96          * indicate the SeedGenerator should use OS support, if available.
  97          *
  98          * On Windows, this causes the MS CryptoAPI seeder to be used.


 288 
 289             try {
 290                 digest = MessageDigest.getInstance("SHA");
 291             } catch (NoSuchAlgorithmException e) {
 292                 throw new InternalError("internal error: SHA-1 not available."
 293                         , e);
 294             }
 295 
 296             final ThreadGroup[] finalsg = new ThreadGroup[1];
 297             Thread t = java.security.AccessController.doPrivileged
 298                 (new java.security.PrivilegedAction<>() {
 299                         @Override
 300                         public Thread run() {
 301                             ThreadGroup parent, group =
 302                                 Thread.currentThread().getThreadGroup();
 303                             while ((parent = group.getParent()) != null) {
 304                                 group = parent;
 305                             }
 306                             finalsg[0] = new ThreadGroup
 307                                 (group, "SeedGenerator ThreadGroup");
 308                             Thread newT = new ManagedLocalsThread(finalsg[0],
 309                                 ThreadedSeedGenerator.this,
 310                                 "SeedGenerator Thread");


 311                             newT.setPriority(Thread.MIN_PRIORITY);
 312                             newT.setDaemon(true);
 313                             return newT;
 314                         }
 315                     });
 316             seedGroup = finalsg[0];
 317             t.start();
 318         }
 319 
 320         /**
 321          * This method does the actual work. It collects random bytes and
 322          * pushes them into the queue.
 323          */
 324         @Override
 325         public final void run() {
 326             try {
 327                 while (true) {
 328                     // Queue full? Wait till there's room.
 329                     synchronized(this) {
 330                         while (count >= pool.length) {
 331                             wait();
 332                         }
 333                     }
 334 
 335                     int counter, quanta;
 336                     byte v = 0;
 337 
 338                     // Spin count must not be under 64000
 339                     for (counter = quanta = 0;
 340                             (counter < 64000) && (quanta < 6); quanta++) {
 341 
 342                         // Start some noisy threads
 343                         try {
 344                             BogusThread bt = new BogusThread();
 345                             Thread t = new ManagedLocalsThread
 346                                 (seedGroup, bt, "SeedGenerator Thread");
 347                             t.start();
 348                         } catch (Exception e) {
 349                             throw new InternalError("internal error: " +
 350                                 "SeedGenerator thread creation error.", e);
 351                         }
 352 
 353                         // We wait 250milli quanta, so the minimum wait time
 354                         // cannot be under 250milli.
 355                         int latch = 0;
 356                         long l = System.currentTimeMillis() + 250;
 357                         while (System.currentTimeMillis() < l) {
 358                             synchronized(this){};
 359                             latch++;
 360                         }
 361 
 362                         // Translate the value using the permutation, and xor
 363                         // it with previous values gathered.
 364                         v ^= rndTab[latch % 255];
 365                         counter += latch;
 366                     }




  58  * Security property to a URL specifying the location of the entropy
  59  * gathering device, or by setting the {@code java.security.egd} System
  60  * property.
  61  * <p>
  62  * In the event the specified URL cannot be accessed the default
  63  * threading mechanism is used.
  64  *
  65  * @author Joshua Bloch
  66  * @author Gadi Guy
  67  */
  68 
  69 import java.security.*;
  70 import java.io.*;
  71 import java.util.Properties;
  72 import java.util.Enumeration;
  73 import java.net.*;
  74 import java.nio.file.DirectoryStream;
  75 import java.nio.file.Files;
  76 import java.nio.file.Path;
  77 import java.util.Random;

  78 import sun.security.util.Debug;
  79 
  80 abstract class SeedGenerator {
  81 
  82     // Static instance is created at link time
  83     private static SeedGenerator instance;
  84 
  85     private static final Debug debug = Debug.getInstance("provider");
  86 
  87     // Static initializer to hook in selected or best performing generator
  88     static {
  89         String egdSource = SunEntries.getSeedSource();
  90 
  91         /*
  92          * Try the URL specifying the source (e.g. file:/dev/random)
  93          *
  94          * The URLs "file:/dev/random" or "file:/dev/urandom" are used to
  95          * indicate the SeedGenerator should use OS support, if available.
  96          *
  97          * On Windows, this causes the MS CryptoAPI seeder to be used.


 287 
 288             try {
 289                 digest = MessageDigest.getInstance("SHA");
 290             } catch (NoSuchAlgorithmException e) {
 291                 throw new InternalError("internal error: SHA-1 not available."
 292                         , e);
 293             }
 294 
 295             final ThreadGroup[] finalsg = new ThreadGroup[1];
 296             Thread t = java.security.AccessController.doPrivileged
 297                 (new java.security.PrivilegedAction<>() {
 298                         @Override
 299                         public Thread run() {
 300                             ThreadGroup parent, group =
 301                                 Thread.currentThread().getThreadGroup();
 302                             while ((parent = group.getParent()) != null) {
 303                                 group = parent;
 304                             }
 305                             finalsg[0] = new ThreadGroup
 306                                 (group, "SeedGenerator ThreadGroup");
 307                             Thread newT = new Thread(finalsg[0],
 308                                 ThreadedSeedGenerator.this,
 309                                 "SeedGenerator Thread",
 310                                 0,
 311                                 false);
 312                             newT.setPriority(Thread.MIN_PRIORITY);
 313                             newT.setDaemon(true);
 314                             return newT;
 315                         }
 316                     });
 317             seedGroup = finalsg[0];
 318             t.start();
 319         }
 320 
 321         /**
 322          * This method does the actual work. It collects random bytes and
 323          * pushes them into the queue.
 324          */
 325         @Override
 326         public final void run() {
 327             try {
 328                 while (true) {
 329                     // Queue full? Wait till there's room.
 330                     synchronized(this) {
 331                         while (count >= pool.length) {
 332                             wait();
 333                         }
 334                     }
 335 
 336                     int counter, quanta;
 337                     byte v = 0;
 338 
 339                     // Spin count must not be under 64000
 340                     for (counter = quanta = 0;
 341                             (counter < 64000) && (quanta < 6); quanta++) {
 342 
 343                         // Start some noisy threads
 344                         try {
 345                             BogusThread bt = new BogusThread();
 346                             Thread t = new Thread
 347                                 (seedGroup, bt, "SeedGenerator Thread", 0, false);
 348                             t.start();
 349                         } catch (Exception e) {
 350                             throw new InternalError("internal error: " +
 351                                 "SeedGenerator thread creation error.", e);
 352                         }
 353 
 354                         // We wait 250milli quanta, so the minimum wait time
 355                         // cannot be under 250milli.
 356                         int latch = 0;
 357                         long l = System.currentTimeMillis() + 250;
 358                         while (System.currentTimeMillis() < l) {
 359                             synchronized(this){};
 360                             latch++;
 361                         }
 362 
 363                         // Translate the value using the permutation, and xor
 364                         // it with previous values gathered.
 365                         v ^= rndTab[latch % 255];
 366                         counter += latch;
 367                     }