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