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