jdk/src/java.base/unix/classes/sun/security/provider/NativePRNG.java
author darcy
Thu, 23 Apr 2015 18:51:18 -0700
changeset 30033 b9c86c17164a
parent 28542 d50a7783fe02
child 32649 2ee9017c7597
permissions -rw-r--r--
8078468: Update security libraries to use diamond with anonymous classes Reviewed-by: weijun
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
     2
 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
package sun.security.provider;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
import java.io.*;
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    29
import java.net.*;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
import java.security.*;
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    31
import sun.security.util.Debug;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
90ce3da70b43 Initial load
duke
parents:
diff changeset
    33
/**
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    34
 * Native PRNG implementation for Solaris/Linux/MacOS.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    35
 * <p>
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    36
 * It obtains seed and random numbers by reading system files such as
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    37
 * the special device files /dev/random and /dev/urandom.  This
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    38
 * implementation respects the {@code securerandom.source} Security
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    39
 * property and {@code java.security.egd} System property for obtaining
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    40
 * seed material.  If the file specified by the properties does not
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    41
 * exist, /dev/random is the default seed source.  /dev/urandom is
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    42
 * the default source of random numbers.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    43
 * <p>
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    44
 * On some Unix platforms, /dev/random may block until enough entropy is
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    45
 * available, but that may negatively impact the perceived startup
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    46
 * time.  By selecting these sources, this implementation tries to
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    47
 * strike a balance between performance and security.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    48
 * <p>
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    49
 * generateSeed() and setSeed() attempt to directly read/write to the seed
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    50
 * source. However, this file may only be writable by root in many
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    51
 * configurations. Because we cannot just ignore bytes specified via
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    52
 * setSeed(), we keep a SHA1PRNG around in parallel.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    53
 * <p>
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    54
 * nextBytes() reads the bytes directly from the source of random
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    55
 * numbers (and then mixes them with bytes from the SHA1PRNG for the
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    56
 * reasons explained above). Reading bytes from the random generator means
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    57
 * that we are generally getting entropy from the operating system. This
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    58
 * is a notable advantage over the SHA1PRNG model, which acquires
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    59
 * entropy only initially during startup although the VM may be running
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    60
 * for months.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    61
 * <p>
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    62
 * Also note for nextBytes() that we do not need any initial pure random
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    63
 * seed from /dev/random. This is an advantage because on some versions
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    64
 * of Linux entropy can be exhausted very quickly and could thus impact
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    65
 * startup time.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    66
 * <p>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * Finally, note that we use a singleton for the actual work (RandomIO)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 * to avoid having to open and close /dev/[u]random constantly. However,
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    69
 * there may be many NativePRNG instances created by the JCA framework.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * @since   1.5
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 * @author  Andreas Sterbenz
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
public final class NativePRNG extends SecureRandomSpi {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
    private static final long serialVersionUID = -6599091113397072932L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    78
    private static final Debug debug = Debug.getInstance("provider");
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    79
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
    // name of the pure random file (also used for setSeed())
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
    private static final String NAME_RANDOM = "/dev/random";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
    // name of the pseudo random file
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
    private static final String NAME_URANDOM = "/dev/urandom";
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    85
    // which kind of RandomIO object are we creating?
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    86
    private enum Variant {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    87
        MIXED, BLOCKING, NONBLOCKING
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    88
    }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    89
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
    // singleton instance or null if not available
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    91
    private static final RandomIO INSTANCE = initIO(Variant.MIXED);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    93
    /**
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    94
     * Get the System egd source (if defined).  We only allow "file:"
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    95
     * URLs for now. If there is a egd value, parse it.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    96
     *
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    97
     * @return the URL or null if not available.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    98
     */
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
    99
    private static URL getEgdUrl() {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   100
        // This will return "" if nothing was set.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   101
        String egdSource = SunEntries.getSeedSource();
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   102
        URL egdUrl;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   103
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   104
        if (egdSource.length() != 0) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   105
            if (debug != null) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   106
                debug.println("NativePRNG egdUrl: " + egdSource);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   107
            }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   108
            try {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   109
                egdUrl = new URL(egdSource);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   110
                if (!egdUrl.getProtocol().equalsIgnoreCase("file")) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
                    return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
                }
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   113
            } catch (MalformedURLException e) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   114
                return null;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   115
            }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   116
        } else {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   117
            egdUrl = null;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   118
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   119
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   120
        return egdUrl;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   121
    }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   122
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   123
    /**
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   124
     * Create a RandomIO object for all I/O of this Variant type.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   125
     */
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   126
    private static RandomIO initIO(final Variant v) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   127
        return AccessController.doPrivileged(
30033
b9c86c17164a 8078468: Update security libraries to use diamond with anonymous classes
darcy
parents: 28542
diff changeset
   128
            new PrivilegedAction<>() {
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   129
                @Override
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   130
                public RandomIO run() {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   131
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   132
                    File seedFile;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   133
                    File nextFile;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   134
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   135
                    switch(v) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   136
                    case MIXED:
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   137
                        URL egdUrl;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   138
                        File egdFile = null;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   139
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   140
                        if ((egdUrl = getEgdUrl()) != null) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   141
                            try {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   142
                                egdFile = SunEntries.getDeviceFile(egdUrl);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   143
                            } catch (IOException e) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   144
                                // Swallow, seedFile is still null
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   145
                            }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   146
                        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   147
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   148
                        // Try egd first.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   149
                        if ((egdFile != null) && egdFile.canRead()) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   150
                            seedFile = egdFile;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   151
                        } else {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   152
                            // fall back to /dev/random.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   153
                            seedFile = new File(NAME_RANDOM);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   154
                        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   155
                        nextFile = new File(NAME_URANDOM);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   156
                        break;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   157
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   158
                    case BLOCKING:
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   159
                        seedFile = new File(NAME_RANDOM);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   160
                        nextFile = new File(NAME_RANDOM);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   161
                        break;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   162
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   163
                    case NONBLOCKING:
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   164
                        seedFile = new File(NAME_URANDOM);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   165
                        nextFile = new File(NAME_URANDOM);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   166
                        break;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   167
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   168
                    default:
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   169
                        // Shouldn't happen!
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   170
                        return null;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   171
                    }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   172
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   173
                    if (debug != null) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   174
                        debug.println("NativePRNG." + v +
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   175
                            " seedFile: " + seedFile +
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   176
                            " nextFile: " + nextFile);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   177
                    }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   178
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   179
                    if (!seedFile.canRead() || !nextFile.canRead()) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   180
                        if (debug != null) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   181
                            debug.println("NativePRNG." + v +
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   182
                                " Couldn't read Files.");
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   183
                        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   184
                        return null;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   185
                    }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   186
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   187
                    try {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   188
                        return new RandomIO(seedFile, nextFile);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   189
                    } catch (Exception e) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   190
                        return null;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   191
                    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
        });
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
90ce3da70b43 Initial load
duke
parents:
diff changeset
   196
    // return whether the NativePRNG is available
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
    static boolean isAvailable() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
        return INSTANCE != null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
    // constructor, called by the JCA framework
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
    public NativePRNG() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
        super();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
        if (INSTANCE == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
            throw new AssertionError("NativePRNG not available");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
    // set the seed
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   210
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
    protected void engineSetSeed(byte[] seed) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
        INSTANCE.implSetSeed(seed);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
    // get pseudo random bytes
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   216
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   217
    protected void engineNextBytes(byte[] bytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
        INSTANCE.implNextBytes(bytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
    // get true random bytes
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   222
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
    protected byte[] engineGenerateSeed(int numBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
        return INSTANCE.implGenerateSeed(numBytes);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
    /**
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   228
     * A NativePRNG-like class that uses /dev/random for both
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   229
     * seed and random material.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   230
     *
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   231
     * Note that it does not respect the egd properties, since we have
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   232
     * no way of knowing what those qualities are.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   233
     *
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   234
     * This is very similar to the outer NativePRNG class, minimizing any
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   235
     * breakage to the serialization of the existing implementation.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   236
     *
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   237
     * @since   1.8
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   238
     */
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   239
    public static final class Blocking extends SecureRandomSpi {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   240
        private static final long serialVersionUID = -6396183145759983347L;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   241
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   242
        private static final RandomIO INSTANCE = initIO(Variant.BLOCKING);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   243
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   244
        // return whether this is available
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   245
        static boolean isAvailable() {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   246
            return INSTANCE != null;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   247
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   248
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   249
        // constructor, called by the JCA framework
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   250
        public Blocking() {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   251
            super();
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   252
            if (INSTANCE == null) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   253
                throw new AssertionError("NativePRNG$Blocking not available");
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   254
            }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   255
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   256
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   257
        // set the seed
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   258
        @Override
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   259
        protected void engineSetSeed(byte[] seed) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   260
            INSTANCE.implSetSeed(seed);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   261
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   262
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   263
        // get pseudo random bytes
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   264
        @Override
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   265
        protected void engineNextBytes(byte[] bytes) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   266
            INSTANCE.implNextBytes(bytes);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   267
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   268
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   269
        // get true random bytes
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   270
        @Override
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   271
        protected byte[] engineGenerateSeed(int numBytes) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   272
            return INSTANCE.implGenerateSeed(numBytes);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   273
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   274
    }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   275
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   276
    /**
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   277
     * A NativePRNG-like class that uses /dev/urandom for both
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   278
     * seed and random material.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   279
     *
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   280
     * Note that it does not respect the egd properties, since we have
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   281
     * no way of knowing what those qualities are.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   282
     *
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   283
     * This is very similar to the outer NativePRNG class, minimizing any
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   284
     * breakage to the serialization of the existing implementation.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   285
     *
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   286
     * @since   1.8
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   287
     */
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   288
    public static final class NonBlocking extends SecureRandomSpi {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   289
        private static final long serialVersionUID = -1102062982994105487L;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   290
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   291
        private static final RandomIO INSTANCE = initIO(Variant.NONBLOCKING);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   292
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   293
        // return whether this is available
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   294
        static boolean isAvailable() {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   295
            return INSTANCE != null;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   296
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   297
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   298
        // constructor, called by the JCA framework
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   299
        public NonBlocking() {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   300
            super();
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   301
            if (INSTANCE == null) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   302
                throw new AssertionError(
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   303
                    "NativePRNG$NonBlocking not available");
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   304
            }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   305
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   306
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   307
        // set the seed
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   308
        @Override
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   309
        protected void engineSetSeed(byte[] seed) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   310
            INSTANCE.implSetSeed(seed);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   311
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   312
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   313
        // get pseudo random bytes
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   314
        @Override
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   315
        protected void engineNextBytes(byte[] bytes) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   316
            INSTANCE.implNextBytes(bytes);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   317
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   318
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   319
        // get true random bytes
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   320
        @Override
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   321
        protected byte[] engineGenerateSeed(int numBytes) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   322
            return INSTANCE.implGenerateSeed(numBytes);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   323
        }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   324
    }
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   325
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   326
    /**
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
     * Nested class doing the actual work. Singleton, see INSTANCE above.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
    private static class RandomIO {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   331
        // we buffer data we read from the "next" file for efficiency,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
        // but we limit the lifetime to avoid using stale bits
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
        // lifetime in ms, currently 100 ms (0.1 s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
        private final static long MAX_BUFFER_TIME = 100;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   336
        // size of the "next" buffer
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
        private final static int BUFFER_SIZE = 32;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   339
        // Holder for the seedFile.  Used if we ever add seed material.
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   340
        File seedFile;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   342
        // In/OutputStream for "seed" and "next"
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   343
        private final InputStream seedIn, nextIn;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   344
        private OutputStream seedOut;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   345
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   346
        // flag indicating if we have tried to open seedOut yet
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   347
        private boolean seedOutInitialized;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        // SHA1PRNG instance for mixing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
        // initialized lazily on demand to avoid problems during startup
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
        private volatile sun.security.provider.SecureRandom mixRandom;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   353
        // buffer for next bits
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   354
        private final byte[] nextBuffer;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   356
        // number of bytes left in nextBuffer
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
        private int buffered;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   359
        // time we read the data into the nextBuffer
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
        private long lastRead;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
        // mutex lock for nextBytes()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        private final Object LOCK_GET_BYTES = new Object();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   365
        // mutex lock for generateSeed()
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
        private final Object LOCK_GET_SEED = new Object();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
        // mutex lock for setSeed()
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
        private final Object LOCK_SET_SEED = new Object();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
        // constructor, called only once from initIO()
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   372
        private RandomIO(File seedFile, File nextFile) throws IOException {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   373
            this.seedFile = seedFile;
28542
d50a7783fe02 8047769: SecureRandom should be more frugal with file descriptors
plevart
parents: 25859
diff changeset
   374
            seedIn = FileInputStreamPool.getInputStream(seedFile);
d50a7783fe02 8047769: SecureRandom should be more frugal with file descriptors
plevart
parents: 25859
diff changeset
   375
            nextIn = FileInputStreamPool.getInputStream(nextFile);
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   376
            nextBuffer = new byte[BUFFER_SIZE];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        // get the SHA1PRNG for mixing
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
        // initialize if not yet created
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
        private sun.security.provider.SecureRandom getMixRandom() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
            sun.security.provider.SecureRandom r = mixRandom;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
            if (r == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
                synchronized (LOCK_GET_BYTES) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
                    r = mixRandom;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
                    if (r == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
                        r = new sun.security.provider.SecureRandom();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
                        try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
                            byte[] b = new byte[20];
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   390
                            readFully(nextIn, b);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
                            r.engineSetSeed(b);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
                        } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
                            throw new ProviderException("init failed", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
                        mixRandom = r;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
            return r;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
        // read data.length bytes from in
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   403
        // These are not normal files, so we need to loop the read.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
        // just keep trying as long as we are making progress
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
        private static void readFully(InputStream in, byte[] data)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
                throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
            int len = data.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
            int ofs = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
            while (len > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
                int k = in.read(data, ofs, len);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
                if (k <= 0) {
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   412
                    throw new EOFException("File(s) closed?");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   414
                ofs += k;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
                len -= k;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   416
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   417
            if (len > 0) {
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   418
                throw new IOException("Could not read from file(s)");
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   419
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   420
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   421
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   422
        // get true random bytes, just read from "seed"
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   423
        private byte[] implGenerateSeed(int numBytes) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   424
            synchronized (LOCK_GET_SEED) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   425
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   426
                    byte[] b = new byte[numBytes];
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   427
                    readFully(seedIn, b);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   428
                    return b;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   429
                } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   430
                    throw new ProviderException("generateSeed() failed", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   431
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   432
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   433
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   434
90ce3da70b43 Initial load
duke
parents:
diff changeset
   435
        // supply random bytes to the OS
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   436
        // write to "seed" if possible
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
        // always add the seed to our mixing random
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
        private void implSetSeed(byte[] seed) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
            synchronized (LOCK_SET_SEED) {
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   440
                if (seedOutInitialized == false) {
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   441
                    seedOutInitialized = true;
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   442
                    seedOut = AccessController.doPrivileged(
30033
b9c86c17164a 8078468: Update security libraries to use diamond with anonymous classes
darcy
parents: 28542
diff changeset
   443
                            new PrivilegedAction<>() {
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   444
                        @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
                        public OutputStream run() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
                            try {
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   447
                                return new FileOutputStream(seedFile, true);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   448
                            } catch (Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   449
                                return null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   450
                            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   451
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   452
                    });
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
                }
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   454
                if (seedOut != null) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
                    try {
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   456
                        seedOut.write(seed);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   457
                    } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
                        throw new ProviderException("setSeed() failed", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
                getMixRandom().engineSetSeed(seed);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
90ce3da70b43 Initial load
duke
parents:
diff changeset
   465
        // ensure that there is at least one valid byte in the buffer
90ce3da70b43 Initial load
duke
parents:
diff changeset
   466
        // if not, read new bytes
90ce3da70b43 Initial load
duke
parents:
diff changeset
   467
        private void ensureBufferValid() throws IOException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
            long time = System.currentTimeMillis();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
            if ((buffered > 0) && (time - lastRead < MAX_BUFFER_TIME)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
                return;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
            lastRead = time;
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   473
            readFully(nextIn, nextBuffer);
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   474
            buffered = nextBuffer.length;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   476
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
        // get pseudo random bytes
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   478
        // read from "next" and XOR with bytes generated by the
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   479
        // mixing SHA1PRNG
90ce3da70b43 Initial load
duke
parents:
diff changeset
   480
        private void implNextBytes(byte[] data) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   481
            synchronized (LOCK_GET_BYTES) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   482
                try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   483
                    getMixRandom().engineNextBytes(data);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   484
                    int len = data.length;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   485
                    int ofs = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   486
                    while (len > 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   487
                        ensureBufferValid();
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   488
                        int bufferOfs = nextBuffer.length - buffered;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   489
                        while ((len > 0) && (buffered > 0)) {
16915
675d1569af3e 6425477: Better support for generation of high entropy random numbers
wetmore
parents: 5506
diff changeset
   490
                            data[ofs++] ^= nextBuffer[bufferOfs++];
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   491
                            len--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                            buffered--;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
                        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
                    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
                } catch (IOException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
                    throw new ProviderException("nextBytes() failed", e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
}