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