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