1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.security.provider.crypto;
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
21b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughesimport dalvik.system.BlockGuard;
22b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughesimport java.io.File;
23b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughesimport java.io.FileInputStream;
247365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.io.IOException;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectInputStream;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.ObjectOutputStream;
277365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.io.Serializable;
287365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.security.InvalidParameterException;
29b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughesimport java.security.ProviderException;
307365de1056414750d0a7d1fdd26025fd247f0d04Jesse Wilsonimport java.security.SecureRandomSpi;
31f5309a39506c967feda8766feeba7f7271a458cbElliott Hughesimport libcore.io.Streams;
326186821cb13f4ac7ff50950c813394367e021eaeJesse Wilsonimport libcore.util.EmptyArray;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
34b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughesimport static org.apache.harmony.security.provider.crypto.SHA1Constants.*;
35b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
37b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes * This class extends the SecureRandomSpi class implementing all its abstract methods.
38b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes *
39b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes * <p>To generate pseudo-random bits, the implementation uses technique described in
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the "Random Number Generator (RNG) algorithms" section, Appendix A,
41b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes * JavaTM Cryptography Architecture, API Specification & Reference.
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
43b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughespublic class SHA1PRNG_SecureRandomImpl extends SecureRandomSpi implements Serializable {
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final long serialVersionUID = 283736797212159675L;
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
47b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes    private static FileInputStream devURandom;
48b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes    static {
49b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes        try {
50b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            devURandom = new FileInputStream(new File("/dev/urandom"));
51b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes        } catch (IOException ex) {
52b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            throw new RuntimeException(ex);
53b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes        }
54b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes    }
55b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // constants to use in expressions operating on bytes in int and long variables:
57f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // END_FLAGS - final bytes in words to append to message;
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //             see "ch.5.1 Padding the Message, FIPS 180-2"
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // RIGHT1    - shifts to right for left half of long
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // RIGHT2    - shifts to right for right half of long
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // LEFT      - shifts to left for bytes
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // MASK      - mask to select counter's bytes after shift to right
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int[] END_FLAGS = { 0x80000000, 0x800000, 0x8000, 0x80 };
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int[] RIGHT1 = { 0, 40, 48, 56 };
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int[] RIGHT2 = { 0, 8, 16, 24 };
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int[] LEFT = { 0, 24, 16, 8 };
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int[] MASK = { 0xFFFFFFFF, 0x00FFFFFF, 0x0000FFFF,
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            0x000000FF };
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // HASHBYTES_TO_USE defines # of bytes returned by "computeHash(byte[])"
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // to use to form byte array returning by the "nextBytes(byte[])" method
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Note, that this implementation uses more bytes than it is defined
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // in the above specification.
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int HASHBYTES_TO_USE = 20;
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // value of 16 defined in the "SECURE HASH STANDARD", FIPS PUB 180-2
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int FRAME_LENGTH = 16;
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // miscellaneous constants defined in this implementation:
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // COUNTER_BASE - initial value to set to "counter" before computing "nextBytes(..)";
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                note, that the exact value is not defined in STANDARD
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // HASHCOPY_OFFSET   - offset for copy of current hash in "copies" array
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // EXTRAFRAME_OFFSET - offset for extra frame in "copies" array;
89f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //                     as the extra frame follows the current hash frame,
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                     EXTRAFRAME_OFFSET is equal to length of current hash frame
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // FRAME_OFFSET      - offset for frame in "copies" array
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // MAX_BYTES - maximum # of seed bytes processing which doesn't require extra frame
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //             see (1) comments on usage of "seed" array below and
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //             (2) comments in "engineNextBytes(byte[])" method
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // UNDEFINED  - three states of engine; initially its state is "UNDEFINED"
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // SET_SEED     call to "engineSetSeed"  sets up "SET_SEED" state,
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // NEXT_BYTES   call to "engineNextByte" sets up "NEXT_BYTES" state
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int COUNTER_BASE = 0;
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int HASHCOPY_OFFSET = 0;
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int EXTRAFRAME_OFFSET = 5;
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int FRAME_OFFSET = 21;
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int MAX_BYTES = 48;
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int UNDEFINED = 0;
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int SET_SEED = 1;
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static final int NEXT_BYTES = 2;
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static SHA1PRNG_SecureRandomImpl myRandom;
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
118f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // Structure of "seed" array:
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // -  0-79 - words for computing hash
120f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // - 80    - unused
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // - 81    - # of seed bytes in current seed frame
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // - 82-86 - 5 words, current seed hash
123171dc20afe5071d5cbfad7103903bfa2c1f8d00fElliott Hughes    private transient int[] seed;
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // total length of seed bytes, including all processed
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient long seedLength;
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Structure of "copies" array
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // -  0-4  - 5 words, copy of current seed hash
130f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // -  5-20 - extra 16 words frame;
131f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //           is used if final padding exceeds 512-bit length
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // - 21-36 - 16 word frame to store a copy of remaining bytes
133171dc20afe5071d5cbfad7103903bfa2c1f8d00fElliott Hughes    private transient int[] copies;
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // ready "next" bytes; needed because words are returned
136171dc20afe5071d5cbfad7103903bfa2c1f8d00fElliott Hughes    private transient byte[] nextBytes;
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // index of used bytes in "nextBytes" array
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient int nextBIndex;
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // variable required according to "SECURE HASH STANDARD"
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient long counter;
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
144f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // contains int value corresponding to engine's current state
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private transient int state;
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // The "seed" array is used to compute both "current seed hash" and "next bytes".
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // As the "SHA1" algorithm computes a hash of entire seed by splitting it into
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // a number of the 512-bit length frames (512 bits = 64 bytes = 16 words),
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // "current seed hash" is a hash (5 words, 20 bytes) for all previous full frames;
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // remaining bytes are stored in the 0-15 word frame of the "seed" array.
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // As for calculating "next bytes",
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // both remaining bytes and "current seed hash" are used,
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // to preserve the latter for following "setSeed(..)" commands,
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // the following technique is used:
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // - upon getting "nextBytes(byte[])" invoked, single or first in row,
159f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //   which requires computing new hash, that is,
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //   there is no more bytes remaining from previous "next bytes" computation,
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //   remaining bytes are copied into the 21-36 word frame of the "copies" array;
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // - upon getting "setSeed(byte[])" invoked, single or first in row,
163f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //   remaining bytes are copied back.
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  Creates object and sets implementation variables to their initial values
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SHA1PRNG_SecureRandomImpl() {
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed = new int[HASH_OFFSET + EXTRAFRAME_OFFSET];
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[HASH_OFFSET] = H0;
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[HASH_OFFSET + 1] = H1;
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[HASH_OFFSET + 2] = H2;
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[HASH_OFFSET + 3] = H3;
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[HASH_OFFSET + 4] = H4;
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seedLength = 0;
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        copies = new int[2 * FRAME_LENGTH + EXTRAFRAME_OFFSET];
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextBytes = new byte[DIGEST_LENGTH];
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextBIndex = HASHBYTES_TO_USE;
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        counter = COUNTER_BASE;
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        state = UNDEFINED;
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method invokes the SHA1Impl's "updateHash(..)" method
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to update current seed frame and
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to compute new intermediate hash value if the frame is full.
189f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * After that it computes a length of whole seed.
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void updateSeed(byte[] bytes) {
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // on call:   "seed" contains current bytes and current hash;
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // on return: "seed" contains new current bytes and possibly new current hash
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //            if after adding, seed bytes overfill its buffer
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SHA1Impl.updateHash(seed, bytes, 0, bytes.length - 1);
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seedLength += bytes.length;
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Changes current seed by supplementing a seed argument to the current seed,
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * if this already set;
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the argument is used as first seed otherwise. <BR>
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method overrides "engineSetSeed(byte[])" in class SecureRandomSpi.
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       seed - byte array
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       NullPointerException - if null is passed to the "seed" argument
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
2147d71a13aa0cb794f14152b36b3873bf8ca595cdcBrian Carlstrom    protected synchronized void engineSetSeed(byte[] seed) {
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (seed == null) {
217897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new NullPointerException("seed == null");
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (state == NEXT_BYTES) { // first setSeed after NextBytes; restoring hash
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(copies, HASHCOPY_OFFSET, this.seed, HASH_OFFSET,
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    EXTRAFRAME_OFFSET);
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        state = SET_SEED;
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (seed.length != 0) {
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            updateSeed(seed);
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns a required number of random bytes. <BR>
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method overrides "engineGenerateSeed (int)" in class SecureRandomSpi. <BR>
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       numBytes - number of bytes to return; should be >= 0.
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       byte array containing bits in order from left to right
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       InvalidParameterException - if numBytes < 0
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
2437d71a13aa0cb794f14152b36b3873bf8ca595cdcBrian Carlstrom    protected synchronized byte[] engineGenerateSeed(int numBytes) {
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] myBytes; // byte[] for bytes returned by "nextBytes()"
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (numBytes < 0) {
248897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new NegativeArraySizeException(Integer.toString(numBytes));
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (numBytes == 0) {
251693eacca9fa67ad79d1b35dbaad61c5ac1ac457cElliott Hughes            return EmptyArray.BYTE;
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (myRandom == null) {
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            myRandom = new SHA1PRNG_SecureRandomImpl();
256b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            myRandom.engineSetSeed(getRandomBytes(DIGEST_LENGTH));
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        myBytes = new byte[numBytes];
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        myRandom.engineNextBytes(myBytes);
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return myBytes;
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Writes random bytes into an array supplied.
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Bits in a byte are from left to right. <BR>
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * To generate random bytes, the "expansion of source bits" method is used,
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * that is,
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the current seed with a 64-bit counter appended is used to compute new bits.
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The counter is incremented by 1 for each 20-byte output. <BR>
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method overrides engineNextBytes in class SecureRandomSpi.
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       bytes - byte array to be filled in with bytes
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *       NullPointerException - if null is passed to the "bytes" argument
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
2817d71a13aa0cb794f14152b36b3873bf8ca595cdcBrian Carlstrom    protected synchronized void engineNextBytes(byte[] bytes) {
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int i, n;
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        long bits; // number of bits required by Secure Hash Standard
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int nextByteToReturn; // index of ready bytes in "bytes" array
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int lastWord; // index of last word in frame containing bytes
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        final int extrabytes = 7;// # of bytes to add in order to computer # of 8 byte words
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (bytes == null) {
291897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new NullPointerException("bytes == null");
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        lastWord = seed[BYTES_OFFSET] == 0 ? 0
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                : (seed[BYTES_OFFSET] + extrabytes) >> 3 - 1;
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (state == UNDEFINED) {
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // no seed supplied by user, hence it is generated thus randomizing internal state
300b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            updateSeed(getRandomBytes(DIGEST_LENGTH));
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextBIndex = HASHBYTES_TO_USE;
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
303ab6d7714b47c04cc4bd812b32e6a6370181a06e4Kenny Root            // updateSeed(...) updates where the last word of the seed is, so we
304ab6d7714b47c04cc4bd812b32e6a6370181a06e4Kenny Root            // have to read it again.
305ab6d7714b47c04cc4bd812b32e6a6370181a06e4Kenny Root            lastWord = seed[BYTES_OFFSET] == 0 ? 0
306ab6d7714b47c04cc4bd812b32e6a6370181a06e4Kenny Root                    : (seed[BYTES_OFFSET] + extrabytes) >> 3 - 1;
307ab6d7714b47c04cc4bd812b32e6a6370181a06e4Kenny Root
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (state == SET_SEED) {
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(seed, HASH_OFFSET, copies, HASHCOPY_OFFSET,
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    EXTRAFRAME_OFFSET);
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // possible cases for 64-byte frame:
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //
315f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // seed bytes < 48      - remaining bytes are enough for all, 8 counter bytes,
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //                        0x80, and 8 seedLength bytes; no extra frame required
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // 48 < seed bytes < 56 - remaining 9 bytes are for 0x80 and 8 counter bytes
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //                        extra frame contains only seedLength value at the end
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // seed bytes > 55      - extra frame contains both counter's bytes
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //                        at the beginning and seedLength value at the end;
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //                        note, that beginning extra bytes are not more than 8,
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //                        that is, only 2 extra words may be used
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
324f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // no need to set to "0" 3 words after "lastWord" and
325f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // more than two words behind frame
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (i = lastWord + 3; i < FRAME_LENGTH + 2; i++) {
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[i] = 0;
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
330caea65e6c3a5b69bc485ca73808df659df251b2dNick Kralevich            bits = (seedLength << 3) + 64; // transforming # of bytes into # of bits
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
332f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // putting # of bits into two last words (14,15) of 16 word frame in
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // seed or copies array depending on total length after padding
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (seed[BYTES_OFFSET] < MAX_BYTES) {
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[14] = (int) (bits >>> 32);
336adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[15] = (int) (bits & 0xFFFFFFFF);
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[EXTRAFRAME_OFFSET + 14] = (int) (bits >>> 32);
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[EXTRAFRAME_OFFSET + 15] = (int) (bits & 0xFFFFFFFF);
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextBIndex = HASHBYTES_TO_USE; // skipping remaining random bits
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        state = NEXT_BYTES;
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (bytes.length == 0) {
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextByteToReturn = 0;
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
352f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        // possibly not all of HASHBYTES_TO_USE bytes were used previous time
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        n = (HASHBYTES_TO_USE - nextBIndex) < (bytes.length - nextByteToReturn) ? HASHBYTES_TO_USE
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                - nextBIndex
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                : bytes.length - nextByteToReturn;
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (n > 0) {
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(nextBytes, nextBIndex, bytes, nextByteToReturn, n);
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextBIndex += n;
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextByteToReturn += n;
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (nextByteToReturn >= bytes.length) {
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return; // return because "bytes[]" are filled in
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        n = seed[BYTES_OFFSET] & 0x03;
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (;;) {
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (n == 0) {
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord] = (int) (counter >>> 32);
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord + 1] = (int) (counter & 0xFFFFFFFF);
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord + 2] = END_FLAGS[0];
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord] |= (int) ((counter >>> RIGHT1[n]) & MASK[n]);
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord + 1] = (int) ((counter >>> RIGHT2[n]) & 0xFFFFFFFF);
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[lastWord + 2] = (int) ((counter << LEFT[n]) | END_FLAGS[n]);
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (seed[BYTES_OFFSET] > MAX_BYTES) {
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[EXTRAFRAME_OFFSET] = seed[FRAME_LENGTH];
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[EXTRAFRAME_OFFSET + 1] = seed[FRAME_LENGTH + 1];
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            SHA1Impl.computeHash(seed);
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (seed[BYTES_OFFSET] > MAX_BYTES) {
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                System.arraycopy(seed, 0, copies, FRAME_OFFSET, FRAME_LENGTH);
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                System.arraycopy(copies, EXTRAFRAME_OFFSET, seed, 0,
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        FRAME_LENGTH);
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                SHA1Impl.computeHash(seed);
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                System.arraycopy(copies, FRAME_OFFSET, seed, 0, FRAME_LENGTH);
395adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            counter++;
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int j = 0;
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (i = 0; i < EXTRAFRAME_OFFSET; i++) {
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int k = seed[HASH_OFFSET + i];
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextBytes[j] = (byte) (k >>> 24); // getting first  byte from left
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextBytes[j + 1] = (byte) (k >>> 16); // getting second byte from left
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextBytes[j + 2] = (byte) (k >>> 8); // getting third  byte from left
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextBytes[j + 3] = (byte) (k); // getting fourth byte from left
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                j += 4;
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            nextBIndex = 0;
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            j = HASHBYTES_TO_USE < (bytes.length - nextByteToReturn) ? HASHBYTES_TO_USE
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    : bytes.length - nextByteToReturn;
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (j > 0) {
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                System.arraycopy(nextBytes, 0, bytes, nextByteToReturn, j);
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextByteToReturn += j;
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                nextBIndex += j;
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (nextByteToReturn >= bytes.length) {
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void writeObject(ObjectOutputStream oos) throws IOException {
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int[] intData = null;
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        final int only_hash = EXTRAFRAME_OFFSET;
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        final int hashes_and_frame = EXTRAFRAME_OFFSET * 2 + FRAME_LENGTH;
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        final int hashes_and_frame_extra = EXTRAFRAME_OFFSET * 2 + FRAME_LENGTH
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                * 2;
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.writeLong(seedLength);
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.writeLong(counter);
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.writeInt(state);
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.writeInt(seed[BYTES_OFFSET]);
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int nRemaining = (seed[BYTES_OFFSET] + 3) >> 2; // converting bytes in words
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // result may be 0
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (state != NEXT_BYTES) {
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
442f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // either the state is UNDEFINED or previous method was "setSeed(..)"
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // so in "seed[]" to serialize are remaining bytes (seed[0-nRemaining]) and
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // current hash (seed[82-86])
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            intData = new int[only_hash + nRemaining];
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(seed, 0, intData, 0, nRemaining);
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(seed, HASH_OFFSET, intData, nRemaining,
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    EXTRAFRAME_OFFSET);
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // previous method was "nextBytes(..)"
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // so, data to serialize are all the above (two first are in "copies" array)
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // and current words in both frame and extra frame (as if)
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int offset = 0;
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (seed[BYTES_OFFSET] < MAX_BYTES) { // no extra frame
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData = new int[hashes_and_frame + nRemaining];
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else { // extra frame is used
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData = new int[hashes_and_frame_extra + nRemaining];
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData[offset] = seed[FRAME_LENGTH];
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData[offset + 1] = seed[FRAME_LENGTH + 1];
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData[offset + 2] = seed[FRAME_LENGTH + 14];
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                intData[offset + 3] = seed[FRAME_LENGTH + 15];
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                offset += 4;
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(seed, 0, intData, offset, FRAME_LENGTH);
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            offset += FRAME_LENGTH;
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(copies, FRAME_LENGTH + EXTRAFRAME_OFFSET, intData,
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    offset, nRemaining);
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            offset += nRemaining;
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(copies, 0, intData, offset, EXTRAFRAME_OFFSET);
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            offset += EXTRAFRAME_OFFSET;
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            System.arraycopy(seed, HASH_OFFSET, intData, offset,
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    EXTRAFRAME_OFFSET);
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i = 0; i < intData.length; i++) {
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            oos.writeInt(intData[i]);
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.writeInt(nextBIndex);
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        oos.write(nextBytes, nextBIndex, HASHBYTES_TO_USE - nextBIndex);
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void readObject(ObjectInputStream ois) throws IOException,
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ClassNotFoundException {
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed = new int[HASH_OFFSET + EXTRAFRAME_OFFSET];
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        copies = new int[2 * FRAME_LENGTH + EXTRAFRAME_OFFSET];
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextBytes = new byte[DIGEST_LENGTH];
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seedLength = ois.readLong();
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        counter = ois.readLong();
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        state = ois.readInt();
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        seed[BYTES_OFFSET] = ois.readInt();
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int nRemaining = (seed[BYTES_OFFSET] + 3) >> 2; // converting bytes in words
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (state != NEXT_BYTES) {
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < nRemaining; i++) {
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[i] = ois.readInt();
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < EXTRAFRAME_OFFSET; i++) {
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[HASH_OFFSET + i] = ois.readInt();
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (seed[BYTES_OFFSET] >= MAX_BYTES) {
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // reading next bytes in seed extra frame
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[FRAME_LENGTH] = ois.readInt();
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[FRAME_LENGTH + 1] = ois.readInt();
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[FRAME_LENGTH + 14] = ois.readInt();
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[FRAME_LENGTH + 15] = ois.readInt();
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // reading next bytes in seed frame
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < FRAME_LENGTH; i++) {
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[i] = ois.readInt();
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
529f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            // reading remaining seed bytes
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < nRemaining; i++) {
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[FRAME_LENGTH + EXTRAFRAME_OFFSET + i] = ois.readInt();
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // reading copy of current hash
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < EXTRAFRAME_OFFSET; i++) {
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                copies[i] = ois.readInt();
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // reading current hash
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < EXTRAFRAME_OFFSET; i++) {
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                seed[HASH_OFFSET + i] = ois.readInt();
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nextBIndex = ois.readInt();
544f5309a39506c967feda8766feeba7f7271a458cbElliott Hughes        Streams.readFully(ois, nextBytes, nextBIndex, HASHBYTES_TO_USE - nextBIndex);
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
546b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes
547b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes    private static byte[] getRandomBytes(int byteCount) {
548b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes        if (byteCount <= 0) {
549b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            throw new IllegalArgumentException("Too few bytes requested: " + byteCount);
550b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes        }
551b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes
552b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes        BlockGuard.Policy originalPolicy = BlockGuard.getThreadPolicy();
553b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes        try {
554b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            BlockGuard.setThreadPolicy(BlockGuard.LAX_POLICY);
555b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            byte[] result = new byte[byteCount];
556b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            Streams.readFully(devURandom, result, 0, byteCount);
557b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            return result;
558b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes        } catch (Exception ex) {
559b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            throw new ProviderException("Couldn't read " + byteCount + " random bytes", ex);
560b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes        } finally {
561b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes            BlockGuard.setThreadPolicy(originalPolicy);
562b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes        }
563b2da4ac2b5c8ddedf5e08aed31481471e408da5fElliott Hughes    }
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
565