1 /*
2  * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
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
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
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  *
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.
24  */
25 
26 package sun.security.provider;
27 
28 import java.io.IOException;
29 import java.security.MessageDigest;
30 import java.security.SecureRandomSpi;
31 import java.security.NoSuchAlgorithmException;
32 import java.security.NoSuchProviderException;
33 
34 /**
35  * <p>This class provides a crytpographically strong pseudo-random number
36  * generator based on the SHA-1 hash algorithm.
37  *
38  * <p>Note that if a seed is not provided, we attempt to provide sufficient
39  * seed bytes to completely randomize the internal state of the generator
40  * (20 bytes).  However, our seed generation algorithm has not been thoroughly
41  * studied or widely deployed.
42  *
43  * <p>Also note that when a random object is deserialized,
44  * <a href="#engineNextBytes(byte[])">engineNextBytes</a> invoked on the
45  * restored random object will yield the exact same (random) bytes as the
46  * original object.  If this behaviour is not desired, the restored random
47  * object should be seeded, using
48  * <a href="#engineSetSeed(byte[])">engineSetSeed</a>.
49  *
50  * @author Benjamin Renaud
51  * @author Josh Bloch
52  * @author Gadi Guy
53  */
54 
55 public final class SecureRandom extends SecureRandomSpi
56 implements java.io.Serializable {
57 
58     @java.io.Serial
59     private static final long serialVersionUID = 3581829991155417889L;
60 
61     private static final int DIGEST_SIZE = 20;
62     private transient MessageDigest digest;
63     private byte[] state;
64     private byte[] remainder;
65     private int remCount;
66 
67     /**
68      * This empty constructor automatically seeds the generator.  We attempt
69      * to provide sufficient seed bytes to completely randomize the internal
70      * state of the generator (20 bytes).  Note, however, that our seed
71      * generation algorithm has not been thoroughly studied or widely deployed.
72      *
73      * <p>The first time this constructor is called in a given Virtual Machine,
74      * it may take several seconds of CPU time to seed the generator, depending
75      * on the underlying hardware.  Successive calls run quickly because they
76      * rely on the same (internal) pseudo-random number generator for their
77      * seed bits.
78      */
SecureRandom()79     public SecureRandom() {
80         init(null);
81     }
82 
83     /**
84      * This constructor is used to instantiate the private seeder object
85      * with a given seed from the SeedGenerator.
86      *
87      * @param seed the seed.
88      */
SecureRandom(byte[] seed)89     private SecureRandom(byte[] seed) {
90         init(seed);
91     }
92 
93     /**
94      * This call, used by the constructors, instantiates the SHA digest
95      * and sets the seed, if given.
96      */
init(byte[] seed)97     private void init(byte[] seed) {
98         try {
99             /*
100              * Use the local SUN implementation to avoid native
101              * performance overhead.
102              */
103             digest = MessageDigest.getInstance("SHA", "SUN");
104         } catch (NoSuchProviderException | NoSuchAlgorithmException e) {
105             // Fallback to any available.
106             try {
107                 digest = MessageDigest.getInstance("SHA");
108             } catch (NoSuchAlgorithmException exc) {
109                 throw new InternalError(
110                     "internal error: SHA-1 not available.", exc);
111             }
112         }
113 
114         if (seed != null) {
115            engineSetSeed(seed);
116         }
117     }
118 
119     /**
120      * Returns the given number of seed bytes, computed using the seed
121      * generation algorithm that this class uses to seed itself.  This
122      * call may be used to seed other random number generators.  While
123      * we attempt to return a "truly random" sequence of bytes, we do not
124      * know exactly how random the bytes returned by this call are.  (See
125      * the empty constructor <a href = "#SecureRandom">SecureRandom</a>
126      * for a brief description of the underlying algorithm.)
127      * The prudent user will err on the side of caution and get extra
128      * seed bytes, although it should be noted that seed generation is
129      * somewhat costly.
130      *
131      * @param numBytes the number of seed bytes to generate.
132      *
133      * @return the seed bytes.
134      */
135     @Override
engineGenerateSeed(int numBytes)136     public byte[] engineGenerateSeed(int numBytes) {
137         // Neither of the SeedGenerator implementations require
138         // locking, so no sync needed here.
139         byte[] b = new byte[numBytes];
140         SeedGenerator.generateSeed(b);
141         return b;
142     }
143 
144     /**
145      * Reseeds this random object. The given seed supplements, rather than
146      * replaces, the existing seed. Thus, repeated calls are guaranteed
147      * never to reduce randomness.
148      *
149      * @param seed the seed.
150      */
151     @Override
engineSetSeed(byte[] seed)152     public synchronized void engineSetSeed(byte[] seed) {
153         if (state != null) {
154             digest.update(state);
155             for (int i = 0; i < state.length; i++) {
156                 state[i] = 0;
157             }
158         }
159         state = digest.digest(seed);
160         remCount = 0;
161     }
162 
updateState(byte[] state, byte[] output)163     private static void updateState(byte[] state, byte[] output) {
164         int last = 1;
165         int v;
166         byte t;
167         boolean zf = false;
168 
169         // state(n + 1) = (state(n) + output(n) + 1) % 2^160;
170         for (int i = 0; i < state.length; i++) {
171             // Add two bytes
172             v = (int)state[i] + (int)output[i] + last;
173             // Result is lower 8 bits
174             t = (byte)v;
175             // Store result. Check for state collision.
176             zf = zf | (state[i] != t);
177             state[i] = t;
178             // High 8 bits are carry. Store for next iteration.
179             last = v >> 8;
180         }
181 
182         // Make sure at least one bit changes!
183         if (!zf) {
184            state[0]++;
185         }
186     }
187 
188     /**
189      * This static object will be seeded by SeedGenerator, and used
190      * to seed future instances of SHA1PRNG SecureRandoms.
191      *
192      * Bloch, Effective Java Second Edition: Item 71
193      */
194     private static class SeederHolder {
195 
196         private static final SecureRandom seeder;
197 
198         static {
199             /*
200              * Call to SeedGenerator.generateSeed() to add additional
201              * seed material (likely from the Native implementation).
202              */
203             seeder = new SecureRandom(SeedGenerator.getSystemEntropy());
204             byte [] b = new byte[DIGEST_SIZE];
205             SeedGenerator.generateSeed(b);
206             seeder.engineSetSeed(b);
207         }
208     }
209 
210     /**
211      * Generates a user-specified number of random bytes.
212      *
213      * @param result the array to be filled in with random bytes.
214      */
215     @Override
engineNextBytes(byte[] result)216     public synchronized void engineNextBytes(byte[] result) {
217         int index = 0;
218         int todo;
219         byte[] output = remainder;
220 
221         if (state == null) {
222             byte[] seed = new byte[DIGEST_SIZE];
223             SeederHolder.seeder.engineNextBytes(seed);
224             state = digest.digest(seed);
225         }
226 
227         // Use remainder from last time
228         int r = remCount;
229         if (r > 0) {
230             // How many bytes?
231             todo = (result.length - index) < (DIGEST_SIZE - r) ?
232                         (result.length - index) : (DIGEST_SIZE - r);
233             // Copy the bytes, zero the buffer
234             for (int i = 0; i < todo; i++) {
235                 result[i] = output[r];
236                 output[r++] = 0;
237             }
238             remCount += todo;
239             index += todo;
240         }
241 
242         // If we need more bytes, make them.
243         while (index < result.length) {
244             // Step the state
245             digest.update(state);
246             output = digest.digest();
247             updateState(state, output);
248 
249             // How many bytes?
250             todo = (result.length - index) > DIGEST_SIZE ?
251                 DIGEST_SIZE : result.length - index;
252             // Copy the bytes, zero the buffer
253             for (int i = 0; i < todo; i++) {
254                 result[index++] = output[i];
255                 output[i] = 0;
256             }
257             remCount += todo;
258         }
259 
260         // Store remainder for next time
261         remainder = output;
262         remCount %= DIGEST_SIZE;
263     }
264 
265     /*
266      * readObject is called to restore the state of the random object from
267      * a stream.  We have to create a new instance of MessageDigest, because
268      * it is not included in the stream (it is marked "transient").
269      *
270      * Note that the engineNextBytes() method invoked on the restored random
271      * object will yield the exact same (random) bytes as the original.
272      * If you do not want this behaviour, you should re-seed the restored
273      * random object, using engineSetSeed().
274      */
275     @java.io.Serial
276     private void readObject(java.io.ObjectInputStream s)
277         throws IOException, ClassNotFoundException {
278 
279         s.defaultReadObject ();
280 
281         try {
282             /*
283              * Use the local SUN implementation to avoid native
284              * performance overhead.
285              */
286             digest = MessageDigest.getInstance("SHA", "SUN");
287         } catch (NoSuchProviderException | NoSuchAlgorithmException e) {
288             // Fallback to any available.
289             try {
290                 digest = MessageDigest.getInstance("SHA");
291             } catch (NoSuchAlgorithmException exc) {
292                 throw new InternalError(
293                     "internal error: SHA-1 not available.", exc);
294             }
295         }
296     }
297 }
298