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