author | sherman |
Tue, 30 Aug 2011 11:53:11 -0700 | |
changeset 10419 | 12c063b39232 |
parent 9035 | 1255eb81cc2f |
child 16915 | 675d1569af3e |
permissions | -rw-r--r-- |
2 | 1 |
/* |
9035
1255eb81cc2f
7033660: Update copyright year to 2011 on any files changed in 2011
ohair
parents:
8158
diff
changeset
|
2 |
* Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 10 |
* |
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
5506 | 21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
2 | 24 |
*/ |
25 |
||
26 |
package sun.security.provider; |
|
27 |
||
28 |
/** |
|
29 |
* <P> This class generates seeds for the cryptographically strong random |
|
30 |
* number generator. |
|
31 |
* <P> The seed is produced using one of two techniques, via a computation |
|
32 |
* of current system activity or from an entropy gathering device. |
|
33 |
* <p> In the default technique the seed is produced by counting the |
|
34 |
* number of times the VM manages to loop in a given period. This number |
|
35 |
* roughly reflects the machine load at that point in time. |
|
36 |
* The samples are translated using a permutation (s-box) |
|
37 |
* and then XORed together. This process is non linear and |
|
38 |
* should prevent the samples from "averaging out". The s-box |
|
39 |
* was designed to have even statistical distribution; it's specific |
|
40 |
* values are not crucial for the security of the seed. |
|
41 |
* We also create a number of sleeper threads which add entropy |
|
42 |
* to the system by keeping the scheduler busy. |
|
43 |
* Twenty such samples should give us roughly 160 bits of randomness. |
|
44 |
* <P> These values are gathered in the background by a daemon thread |
|
45 |
* thus allowing the system to continue performing it's different |
|
46 |
* activites, which in turn add entropy to the random seed. |
|
47 |
* <p> The class also gathers miscellaneous system information, some |
|
48 |
* machine dependent, some not. This information is then hashed together |
|
49 |
* with the 20 seed bytes. |
|
50 |
* <P> The alternative to the above approach is to acquire seed material |
|
51 |
* from an entropy gathering device, such as /dev/random. This can be |
|
52 |
* accomplished by setting the value of the "securerandom.source" |
|
53 |
* security property (in the Java security properties file) to a URL |
|
54 |
* specifying the location of the entropy gathering device. |
|
55 |
* In the event the specified URL cannot be accessed the default |
|
56 |
* mechanism is used. |
|
57 |
* The Java security properties file is located in the file named |
|
58 |
* <JAVA_HOME>/lib/security/java.security. |
|
59 |
* <JAVA_HOME> refers to the value of the java.home system property, |
|
60 |
* and specifies the directory where the JRE is installed. |
|
61 |
* |
|
62 |
* @author Joshua Bloch |
|
63 |
* @author Gadi Guy |
|
64 |
*/ |
|
65 |
||
66 |
import java.security.*; |
|
67 |
import java.io.*; |
|
68 |
import java.util.Properties; |
|
69 |
import java.util.Enumeration; |
|
70 |
import java.net.*; |
|
8158 | 71 |
import java.nio.file.DirectoryStream; |
72 |
import java.nio.file.Files; |
|
73 |
import java.nio.file.Path; |
|
2175
7d7e238cb41a
6705872: SecureRandom number init is taking too long on a java.io.tmpdir with a large number of files.
weijun
parents:
2
diff
changeset
|
74 |
import java.util.Random; |
2 | 75 |
import sun.security.util.Debug; |
76 |
||
77 |
abstract class SeedGenerator { |
|
78 |
||
79 |
// Static instance is created at link time |
|
80 |
private static SeedGenerator instance; |
|
81 |
||
82 |
private static final Debug debug = Debug.getInstance("provider"); |
|
83 |
||
84 |
final static String URL_DEV_RANDOM = SunEntries.URL_DEV_RANDOM; |
|
85 |
final static String URL_DEV_URANDOM = SunEntries.URL_DEV_URANDOM; |
|
86 |
||
87 |
// Static initializer to hook in selected or best performing generator |
|
88 |
static { |
|
89 |
String egdSource = SunEntries.getSeedSource(); |
|
90 |
||
91 |
// Try the URL specifying the source |
|
92 |
// e.g. file:/dev/random |
|
93 |
// |
|
94 |
// The URL file:/dev/random or file:/dev/urandom is used to indicate |
|
95 |
// the SeedGenerator using OS support, if available. |
|
96 |
// On Windows, the causes MS CryptoAPI to be used. |
|
97 |
// On Solaris and Linux, this is the identical to using |
|
98 |
// URLSeedGenerator to read from /dev/random |
|
99 |
||
100 |
if (egdSource.equals(URL_DEV_RANDOM) || egdSource.equals(URL_DEV_URANDOM)) { |
|
101 |
try { |
|
102 |
instance = new NativeSeedGenerator(); |
|
103 |
if (debug != null) { |
|
104 |
debug.println("Using operating system seed generator"); |
|
105 |
} |
|
106 |
} catch (IOException e) { |
|
107 |
if (debug != null) { |
|
108 |
debug.println("Failed to use operating system seed " |
|
109 |
+ "generator: " + e.toString()); |
|
110 |
} |
|
111 |
} |
|
112 |
} else if (egdSource.length() != 0) { |
|
113 |
try { |
|
114 |
instance = new URLSeedGenerator(egdSource); |
|
115 |
if (debug != null) { |
|
116 |
debug.println("Using URL seed generator reading from " |
|
117 |
+ egdSource); |
|
118 |
} |
|
119 |
} catch (IOException e) { |
|
120 |
if (debug != null) |
|
121 |
debug.println("Failed to create seed generator with " |
|
122 |
+ egdSource + ": " + e.toString()); |
|
123 |
} |
|
124 |
} |
|
125 |
||
126 |
// Fall back to ThreadedSeedGenerator |
|
127 |
if (instance == null) { |
|
128 |
if (debug != null) { |
|
129 |
debug.println("Using default threaded seed generator"); |
|
130 |
} |
|
131 |
instance = new ThreadedSeedGenerator(); |
|
132 |
} |
|
133 |
} |
|
134 |
||
135 |
/** |
|
136 |
* Fill result with bytes from the queue. Wait for it if it isn't ready. |
|
137 |
*/ |
|
138 |
static public void generateSeed(byte[] result) { |
|
139 |
instance.getSeedBytes(result); |
|
140 |
} |
|
141 |
||
7546
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
142 |
abstract void getSeedBytes(byte[] result); |
2 | 143 |
|
144 |
/** |
|
145 |
* Retrieve some system information, hashed. |
|
146 |
*/ |
|
147 |
static byte[] getSystemEntropy() { |
|
148 |
byte[] ba; |
|
149 |
final MessageDigest md; |
|
150 |
||
151 |
try { |
|
152 |
md = MessageDigest.getInstance("SHA"); |
|
153 |
} catch (NoSuchAlgorithmException nsae) { |
|
10419
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
154 |
throw new InternalError("internal error: SHA-1 not available." |
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
155 |
, nsae); |
2 | 156 |
} |
157 |
||
158 |
// The current time in millis |
|
159 |
byte b =(byte)System.currentTimeMillis(); |
|
160 |
md.update(b); |
|
161 |
||
162 |
java.security.AccessController.doPrivileged |
|
163 |
(new java.security.PrivilegedAction<Void>() { |
|
164 |
public Void run() { |
|
165 |
||
166 |
try { |
|
167 |
// System properties can change from machine to machine |
|
168 |
String s; |
|
169 |
Properties p = System.getProperties(); |
|
170 |
Enumeration<?> e = p.propertyNames(); |
|
171 |
while (e.hasMoreElements()) { |
|
172 |
s =(String)e.nextElement(); |
|
173 |
md.update(s.getBytes()); |
|
174 |
md.update(p.getProperty(s).getBytes()); |
|
175 |
} |
|
176 |
||
177 |
md.update |
|
178 |
(InetAddress.getLocalHost().toString().getBytes()); |
|
179 |
||
180 |
// The temporary dir |
|
181 |
File f = new File(p.getProperty("java.io.tmpdir")); |
|
8158 | 182 |
int count = 0; |
183 |
try (DirectoryStream<Path> stream = Files.newDirectoryStream(f.toPath())) { |
|
2175
7d7e238cb41a
6705872: SecureRandom number init is taking too long on a java.io.tmpdir with a large number of files.
weijun
parents:
2
diff
changeset
|
184 |
// We use a Random object to choose what file names |
7d7e238cb41a
6705872: SecureRandom number init is taking too long on a java.io.tmpdir with a large number of files.
weijun
parents:
2
diff
changeset
|
185 |
// should be used. Otherwise on a machine with too |
7d7e238cb41a
6705872: SecureRandom number init is taking too long on a java.io.tmpdir with a large number of files.
weijun
parents:
2
diff
changeset
|
186 |
// many files, the same first 1024 files always get |
7d7e238cb41a
6705872: SecureRandom number init is taking too long on a java.io.tmpdir with a large number of files.
weijun
parents:
2
diff
changeset
|
187 |
// used. Any, We make sure the first 512 files are |
7d7e238cb41a
6705872: SecureRandom number init is taking too long on a java.io.tmpdir with a large number of files.
weijun
parents:
2
diff
changeset
|
188 |
// always used. |
7d7e238cb41a
6705872: SecureRandom number init is taking too long on a java.io.tmpdir with a large number of files.
weijun
parents:
2
diff
changeset
|
189 |
Random r = new Random(); |
8158 | 190 |
for (Path entry: stream) { |
191 |
if (count < 512 || r.nextBoolean()) { |
|
192 |
md.update(entry.getFileName().toString().getBytes()); |
|
2175
7d7e238cb41a
6705872: SecureRandom number init is taking too long on a java.io.tmpdir with a large number of files.
weijun
parents:
2
diff
changeset
|
193 |
} |
8158 | 194 |
if (count++ > 1024) { |
195 |
break; |
|
196 |
} |
|
4176
bf303f38f727
6894534: SeedGenerator shouldn't require java.nio.file to be present
weijun
parents:
2175
diff
changeset
|
197 |
} |
2175
7d7e238cb41a
6705872: SecureRandom number init is taking too long on a java.io.tmpdir with a large number of files.
weijun
parents:
2
diff
changeset
|
198 |
} |
2 | 199 |
} catch (Exception ex) { |
200 |
md.update((byte)ex.hashCode()); |
|
201 |
} |
|
202 |
||
203 |
// get Runtime memory stats |
|
204 |
Runtime rt = Runtime.getRuntime(); |
|
205 |
byte[] memBytes = longToByteArray(rt.totalMemory()); |
|
206 |
md.update(memBytes, 0, memBytes.length); |
|
207 |
memBytes = longToByteArray(rt.freeMemory()); |
|
208 |
md.update(memBytes, 0, memBytes.length); |
|
209 |
||
210 |
return null; |
|
211 |
} |
|
212 |
}); |
|
213 |
return md.digest(); |
|
214 |
} |
|
215 |
||
216 |
/** |
|
217 |
* Helper function to convert a long into a byte array (least significant |
|
218 |
* byte first). |
|
219 |
*/ |
|
220 |
private static byte[] longToByteArray(long l) { |
|
221 |
byte[] retVal = new byte[8]; |
|
222 |
||
223 |
for (int i=0; i<8; i++) { |
|
224 |
retVal[i] = (byte) l; |
|
225 |
l >>= 8; |
|
226 |
} |
|
227 |
||
228 |
return retVal; |
|
229 |
} |
|
230 |
||
231 |
/* |
|
232 |
// This method helps the test utility receive unprocessed seed bytes. |
|
233 |
public static int genTestSeed() { |
|
234 |
return myself.getByte(); |
|
235 |
} |
|
236 |
*/ |
|
237 |
||
238 |
||
239 |
private static class ThreadedSeedGenerator extends SeedGenerator implements Runnable { |
|
240 |
// Queue is used to collect seed bytes |
|
241 |
private byte[] pool; |
|
242 |
private int start, end, count; |
|
243 |
||
244 |
// Thread group for our threads |
|
245 |
ThreadGroup seedGroup; |
|
246 |
||
247 |
/** |
|
248 |
* The constructor is only called once to construct the one |
|
249 |
* instance we actually use. It instantiates the message digest |
|
250 |
* and starts the thread going. |
|
251 |
*/ |
|
252 |
||
253 |
ThreadedSeedGenerator() { |
|
254 |
pool = new byte[20]; |
|
255 |
start = end = 0; |
|
256 |
||
257 |
MessageDigest digest; |
|
258 |
||
259 |
try { |
|
260 |
digest = MessageDigest.getInstance("SHA"); |
|
261 |
} catch (NoSuchAlgorithmException e) { |
|
10419
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
262 |
throw new InternalError("internal error: SHA-1 not available." |
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
263 |
, e); |
2 | 264 |
} |
265 |
||
266 |
final ThreadGroup[] finalsg = new ThreadGroup[1]; |
|
267 |
Thread t = java.security.AccessController.doPrivileged |
|
268 |
(new java.security.PrivilegedAction<Thread>() { |
|
269 |
public Thread run() { |
|
270 |
ThreadGroup parent, group = |
|
271 |
Thread.currentThread().getThreadGroup(); |
|
272 |
while ((parent = group.getParent()) != null) |
|
273 |
group = parent; |
|
274 |
finalsg[0] = new ThreadGroup |
|
275 |
(group, "SeedGenerator ThreadGroup"); |
|
276 |
Thread newT = new Thread(finalsg[0], |
|
277 |
ThreadedSeedGenerator.this, |
|
278 |
"SeedGenerator Thread"); |
|
279 |
newT.setPriority(Thread.MIN_PRIORITY); |
|
280 |
newT.setDaemon(true); |
|
281 |
return newT; |
|
282 |
} |
|
283 |
}); |
|
284 |
seedGroup = finalsg[0]; |
|
285 |
t.start(); |
|
286 |
} |
|
287 |
||
288 |
/** |
|
289 |
* This method does the actual work. It collects random bytes and |
|
290 |
* pushes them into the queue. |
|
291 |
*/ |
|
292 |
final public void run() { |
|
293 |
try { |
|
294 |
while (true) { |
|
295 |
// Queue full? Wait till there's room. |
|
296 |
synchronized(this) { |
|
297 |
while (count >= pool.length) |
|
298 |
wait(); |
|
299 |
} |
|
300 |
||
301 |
int counter, quanta; |
|
302 |
byte v = 0; |
|
303 |
||
304 |
// Spin count must not be under 64000 |
|
305 |
for (counter = quanta = 0; (counter < 64000) && (quanta < 6); |
|
306 |
quanta++) { |
|
307 |
||
308 |
// Start some noisy threads |
|
309 |
try { |
|
310 |
BogusThread bt = new BogusThread(); |
|
311 |
Thread t = new Thread |
|
312 |
(seedGroup, bt, "SeedGenerator Thread"); |
|
313 |
t.start(); |
|
314 |
} catch (Exception e) { |
|
315 |
throw new InternalError("internal error: " + |
|
10419
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
316 |
"SeedGenerator thread creation error." |
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
317 |
, e); |
2 | 318 |
} |
319 |
||
320 |
// We wait 250milli quanta, so the minimum wait time |
|
321 |
// cannot be under 250milli. |
|
322 |
int latch = 0; |
|
323 |
latch = 0; |
|
324 |
long l = System.currentTimeMillis() + 250; |
|
325 |
while (System.currentTimeMillis() < l) { |
|
326 |
synchronized(this){}; |
|
327 |
latch++; |
|
328 |
} |
|
329 |
||
330 |
// Translate the value using the permutation, and xor |
|
331 |
// it with previous values gathered. |
|
332 |
v ^= rndTab[latch % 255]; |
|
333 |
counter += latch; |
|
334 |
} |
|
335 |
||
336 |
// Push it into the queue and notify anybody who might |
|
337 |
// be waiting for it. |
|
338 |
synchronized(this) { |
|
339 |
pool[end] = v; |
|
340 |
end++; |
|
341 |
count++; |
|
342 |
if (end >= pool.length) |
|
343 |
end = 0; |
|
344 |
||
345 |
notifyAll(); |
|
346 |
} |
|
347 |
} |
|
348 |
} catch (Exception e) { |
|
349 |
throw new InternalError("internal error: " + |
|
10419
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
350 |
"SeedGenerator thread generated an exception." |
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
351 |
, e); |
2 | 352 |
} |
353 |
} |
|
354 |
||
7546
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
355 |
@Override |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
356 |
void getSeedBytes(byte[] result) { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
357 |
for (int i = 0; i < result.length; i++) { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
358 |
result[i] = getSeedByte(); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
359 |
} |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
360 |
} |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
361 |
|
2 | 362 |
byte getSeedByte() { |
363 |
byte b = 0; |
|
364 |
||
365 |
try { |
|
366 |
// Wait for it... |
|
367 |
synchronized(this) { |
|
368 |
while (count <= 0) |
|
369 |
wait(); |
|
370 |
} |
|
371 |
} catch (Exception e) { |
|
372 |
if (count <= 0) |
|
373 |
throw new InternalError("internal error: " + |
|
10419
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
374 |
"SeedGenerator thread generated an exception." |
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
375 |
,e); |
2 | 376 |
} |
377 |
||
378 |
synchronized(this) { |
|
379 |
// Get it from the queue |
|
380 |
b = pool[start]; |
|
381 |
pool[start] = 0; |
|
382 |
start++; |
|
383 |
count--; |
|
384 |
if (start == pool.length) |
|
385 |
start = 0; |
|
386 |
||
387 |
// Notify the daemon thread, just in case it is |
|
388 |
// waiting for us to make room in the queue. |
|
389 |
notifyAll(); |
|
390 |
} |
|
391 |
||
392 |
return b; |
|
393 |
} |
|
394 |
||
395 |
// The permutation was calculated by generating 64k of random |
|
396 |
// data and using it to mix the trivial permutation. |
|
397 |
// It should be evenly distributed. The specific values |
|
398 |
// are not crucial to the security of this class. |
|
399 |
private static byte[] rndTab = { |
|
400 |
56, 30, -107, -6, -86, 25, -83, 75, -12, -64, |
|
401 |
5, -128, 78, 21, 16, 32, 70, -81, 37, -51, |
|
402 |
-43, -46, -108, 87, 29, 17, -55, 22, -11, -111, |
|
403 |
-115, 84, -100, 108, -45, -15, -98, 72, -33, -28, |
|
404 |
31, -52, -37, -117, -97, -27, 93, -123, 47, 126, |
|
405 |
-80, -62, -93, -79, 61, -96, -65, -5, -47, -119, |
|
406 |
14, 89, 81, -118, -88, 20, 67, -126, -113, 60, |
|
407 |
-102, 55, 110, 28, 85, 121, 122, -58, 2, 45, |
|
408 |
43, 24, -9, 103, -13, 102, -68, -54, -101, -104, |
|
409 |
19, 13, -39, -26, -103, 62, 77, 51, 44, 111, |
|
410 |
73, 18, -127, -82, 4, -30, 11, -99, -74, 40, |
|
411 |
-89, 42, -76, -77, -94, -35, -69, 35, 120, 76, |
|
412 |
33, -73, -7, 82, -25, -10, 88, 125, -112, 58, |
|
413 |
83, 95, 6, 10, 98, -34, 80, 15, -91, 86, |
|
414 |
-19, 52, -17, 117, 49, -63, 118, -90, 36, -116, |
|
415 |
-40, -71, 97, -53, -109, -85, 109, -16, -3, 104, |
|
416 |
-95, 68, 54, 34, 26, 114, -1, 106, -121, 3, |
|
417 |
66, 0, 100, -84, 57, 107, 119, -42, 112, -61, |
|
418 |
1, 48, 38, 12, -56, -57, 39, -106, -72, 41, |
|
419 |
7, 71, -29, -59, -8, -38, 79, -31, 124, -124, |
|
420 |
8, 91, 116, 99, -4, 9, -36, -78, 63, -49, |
|
421 |
-67, -87, 59, 101, -32, 92, 94, 53, -41, 115, |
|
422 |
-66, -70, -122, 50, -50, -22, -20, -18, -21, 23, |
|
423 |
-2, -48, 96, 65, -105, 123, -14, -110, 69, -24, |
|
424 |
-120, -75, 74, 127, -60, 113, 90, -114, 105, 46, |
|
425 |
27, -125, -23, -44, 64 |
|
426 |
}; |
|
427 |
||
428 |
/** |
|
429 |
* This inner thread causes the thread scheduler to become 'noisy', |
|
430 |
* thus adding entropy to the system load. |
|
431 |
* At least one instance of this class is generated for every seed byte. |
|
432 |
*/ |
|
433 |
||
434 |
private static class BogusThread implements Runnable { |
|
435 |
final public void run() { |
|
436 |
try { |
|
437 |
for(int i = 0; i < 5; i++) |
|
438 |
Thread.sleep(50); |
|
439 |
// System.gc(); |
|
440 |
} catch (Exception e) { |
|
441 |
} |
|
442 |
} |
|
443 |
} |
|
444 |
} |
|
445 |
||
446 |
static class URLSeedGenerator extends SeedGenerator { |
|
447 |
||
448 |
private String deviceName; |
|
7546
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
449 |
private InputStream devRandom; |
2 | 450 |
|
451 |
/** |
|
452 |
* The constructor is only called once to construct the one |
|
453 |
* instance we actually use. It opens the entropy gathering device |
|
454 |
* which will supply the randomness. |
|
455 |
*/ |
|
456 |
||
457 |
URLSeedGenerator(String egdurl) throws IOException { |
|
7546
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
458 |
if (egdurl == null) { |
2 | 459 |
throw new IOException("No random source specified"); |
460 |
} |
|
461 |
deviceName = egdurl; |
|
462 |
init(); |
|
463 |
} |
|
464 |
||
465 |
URLSeedGenerator() throws IOException { |
|
466 |
this(SeedGenerator.URL_DEV_RANDOM); |
|
467 |
} |
|
468 |
||
469 |
private void init() throws IOException { |
|
470 |
final URL device = new URL(deviceName); |
|
7546
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
471 |
try { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
472 |
devRandom = java.security.AccessController.doPrivileged |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
473 |
(new java.security.PrivilegedExceptionAction<InputStream>() { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
474 |
public InputStream run() throws IOException { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
475 |
/* |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
476 |
* return a FileInputStream for file URLs and |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
477 |
* avoid buffering. The openStream() call wraps |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
478 |
* InputStream in a BufferedInputStream which |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
479 |
* can buffer up to 8K bytes. This read is a |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
480 |
* performance issue for entropy sources which |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
481 |
* can be slow to replenish. |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
482 |
*/ |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
483 |
if (device.getProtocol().equalsIgnoreCase("file")) { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
484 |
File deviceFile = getDeviceFile(device); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
485 |
return new FileInputStream(deviceFile); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
486 |
} else { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
487 |
return device.openStream(); |
2 | 488 |
} |
489 |
} |
|
490 |
}); |
|
7546
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
491 |
} catch (Exception e) { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
492 |
throw new IOException("Failed to open " + deviceName, e.getCause()); |
2 | 493 |
} |
494 |
} |
|
495 |
||
7546
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
496 |
/* |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
497 |
* Use a URI to access this File. Previous code used a URL |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
498 |
* which is less strict on syntax. If we encounter a |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
499 |
* URISyntaxException we make best efforts for backwards |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
500 |
* compatibility. e.g. space character in deviceName string. |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
501 |
* |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
502 |
* Method called within PrivilegedExceptionAction block. |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
503 |
*/ |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
504 |
private File getDeviceFile(URL device) throws IOException { |
2 | 505 |
try { |
7546
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
506 |
URI deviceURI = device.toURI(); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
507 |
if(deviceURI.isOpaque()) { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
508 |
// File constructor does not accept opaque URI |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
509 |
URI localDir = new File(System.getProperty("user.dir")).toURI(); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
510 |
String uriPath = localDir.toString() + |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
511 |
deviceURI.toString().substring(5); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
512 |
return new File(URI.create(uriPath)); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
513 |
} else { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
514 |
return new File(deviceURI); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
515 |
} |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
516 |
} catch (URISyntaxException use) { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
517 |
/* |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
518 |
* Make best effort to access this File. |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
519 |
* We can try using the URL path. |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
520 |
*/ |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
521 |
return new File(device.getPath()); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
522 |
} |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
523 |
} |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
524 |
|
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
525 |
@Override |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
526 |
void getSeedBytes(byte[] result) { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
527 |
int len = result.length; |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
528 |
int read = 0; |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
529 |
try { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
530 |
while (read < len) { |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
531 |
int count = devRandom.read(result, read, len - read); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
532 |
// /dev/random blocks - should never have EOF |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
533 |
if (count < 0) |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
534 |
throw new InternalError("URLSeedGenerator " + deviceName + |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
535 |
" reached end of file"); |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
536 |
read += count; |
c1915029b924
6998583: NativeSeedGenerator is making 8192 byte read requests from entropy pool on each init.
coffeys
parents:
5506
diff
changeset
|
537 |
} |
2 | 538 |
} catch (IOException ioe) { |
539 |
throw new InternalError("URLSeedGenerator " + deviceName + |
|
540 |
" generated exception: " + |
|
10419
12c063b39232
7084245: Update usages of InternalError to use exception chaining
sherman
parents:
9035
diff
changeset
|
541 |
ioe.getMessage(), ioe); |
2 | 542 |
} |
543 |
} |
|
544 |
||
545 |
} |
|
546 |
} |