提交 bd490f3a 编写于 作者: C coffeys

6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.

Reviewed-by: wetmore, andrew, vinnie
上级 be15e466
/*
* Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -138,13 +138,7 @@ abstract class SeedGenerator {
instance.getSeedBytes(result);
}
void getSeedBytes(byte[] result) {
for (int i = 0; i < result.length; i++) {
result[i] = getSeedByte();
}
}
abstract byte getSeedByte();
abstract void getSeedBytes(byte[] result);
/**
* Retrieve some system information, hashed.
......@@ -369,6 +363,13 @@ abstract class SeedGenerator {
}
}
@Override
void getSeedBytes(byte[] result) {
for (int i = 0; i < result.length; i++) {
result[i] = getSeedByte();
}
}
byte getSeedByte() {
byte b = 0;
......@@ -455,8 +456,7 @@ abstract class SeedGenerator {
static class URLSeedGenerator extends SeedGenerator {
private String deviceName;
private BufferedInputStream devRandom;
private InputStream devRandom;
/**
* The constructor is only called once to construct the one
......@@ -465,7 +465,7 @@ abstract class SeedGenerator {
*/
URLSeedGenerator(String egdurl) throws IOException {
if (egdurl == null) {
if (egdurl == null) {
throw new IOException("No random source specified");
}
deviceName = egdurl;
......@@ -478,41 +478,78 @@ abstract class SeedGenerator {
private void init() throws IOException {
final URL device = new URL(deviceName);
devRandom = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<BufferedInputStream>() {
public BufferedInputStream run() {
try {
return new BufferedInputStream(device.openStream());
} catch (IOException ioe) {
return null;
try {
devRandom = java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<InputStream>() {
public InputStream run() throws IOException {
/*
* return a FileInputStream for file URLs and
* avoid buffering. The openStream() call wraps
* InputStream in a BufferedInputStream which
* can buffer up to 8K bytes. This read is a
* performance issue for entropy sources which
* can be slow to replenish.
*/
if (device.getProtocol().equalsIgnoreCase("file")) {
File deviceFile = getDeviceFile(device);
return new FileInputStream(deviceFile);
} else {
return device.openStream();
}
}
});
} catch (Exception e) {
throw new IOException("Failed to open " + deviceName, e.getCause());
}
}
if (devRandom == null) {
throw new IOException("failed to open " + device);
/*
* Use a URI to access this File. Previous code used a URL
* which is less strict on syntax. If we encounter a
* URISyntaxException we make best efforts for backwards
* compatibility. e.g. space character in deviceName string.
*
* Method called within PrivilegedExceptionAction block.
*/
private File getDeviceFile(URL device) throws IOException {
try {
URI deviceURI = device.toURI();
if(deviceURI.isOpaque()) {
// File constructor does not accept opaque URI
URI localDir = new File(System.getProperty("user.dir")).toURI();
String uriPath = localDir.toString() +
deviceURI.toString().substring(5);
return new File(URI.create(uriPath));
} else {
return new File(deviceURI);
}
} catch (URISyntaxException use) {
/*
* Make best effort to access this File.
* We can try using the URL path.
*/
return new File(device.getPath());
}
}
byte getSeedByte() {
byte b[] = new byte[1];
int stat;
@Override
void getSeedBytes(byte[] result) {
int len = result.length;
int read = 0;
try {
stat = devRandom.read(b, 0, b.length);
while (read < len) {
int count = devRandom.read(result, read, len - read);
// /dev/random blocks - should never have EOF
if (count < 0)
throw new InternalError("URLSeedGenerator " + deviceName +
" reached end of file");
read += count;
}
} catch (IOException ioe) {
throw new InternalError("URLSeedGenerator " + deviceName +
" generated exception: " +
ioe.getMessage());
}
if (stat == b.length) {
return b[0];
} else if (stat == -1) {
throw new InternalError("URLSeedGenerator " + deviceName +
" reached end of file");
} else {
throw new InternalError("URLSeedGenerator " + deviceName +
" failed read");
}
}
}
......
/*
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -53,6 +53,7 @@ class NativeSeedGenerator extends SeedGenerator {
*/
private static native boolean nativeGenerateSeed(byte[] result);
@Override
void getSeedBytes(byte[] result) {
// fill array as a side effect
if (nativeGenerateSeed(result) == false) {
......@@ -62,9 +63,4 @@ class NativeSeedGenerator extends SeedGenerator {
}
}
byte getSeedByte() {
byte[] b = new byte[1];
getSeedBytes(b);
return b[0];
}
}
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6998583
* @summary NativeSeedGenerator is making 8192 byte read requests from
* entropy pool on each init.
* @run main SeedGeneratorChoice
* @run main/othervm -Djava.security.egd=file:/dev/random SeedGeneratorChoice
* @run main/othervm -Djava.security.egd=file:filename SeedGeneratorChoice
*/
/*
* Side testcase introduced to ensure changes for 6998583 will always
* succeed in falling back to ThreadedSeedGenerator if issues are found
* with the native OS generator request. We should never see an exception
* causing exit.
* We should always fall back to the ThreadedSeedGenerator if exceptions
* are encountered with user defined source of entropy.
*/
import java.security.SecureRandom;
public class SeedGeneratorChoice {
public static void main(String... arguments) throws Exception {
byte[] bytes;
SecureRandom prng = SecureRandom.getInstance("SHA1PRNG");
bytes = prng.generateSeed(1);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册