HandshakeIODataStream.java revision f6c387128427e121477c1b32ad35cdcaa5101ba3
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 Project * @author Alexander Y. Kleymenov
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @version $Revision$
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.xnet.provider.jsse.AlertException;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.xnet.provider.jsse.SSLInputStream;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.PrintStream;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.MessageDigest;
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Arrays;
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.net.ssl.SSLHandshakeException;
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class provides Input/Output data functionality
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * for handshake layer. It provides read and write operations
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and accumulates all sent/received handshake's data.
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This class can be presented as a combination of 2 data pipes.
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The first data pipe is a pipe of income data: append method
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * places the data at the beginning of the pipe, and read methods
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * consume the data from the pipe. The second pipe is an outcoming
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * data pipe: write operations plases the data into the pipe,
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and getData methods consume the data.
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It is important to note that work with pipe cound not be
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * started if there is unconsumed data in another pipe. It is
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * reasoned by the following: handshake protocol performs read
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and write operations consecuently. I.e. it first reads all
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * income data and only than produces the responce and places it
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * into the stream.
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The read operations of the stream presented by the methods
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of SSLInputStream which in its turn is an extension of InputStream.
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * So this stream can be used as an InputStream parameter for
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * certificate generation.
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Also input stream functionality supports marks. The marks
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * help to reset the position of the stream in case of incompleate
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * handshake records. Note that in case of exhausting
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of income data the EndOfBufferException is thown which implies
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the following:
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  1. the stream contains scrappy handshake record,
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  2. the read position should be reseted to marked,
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  3. and more income data is expected.
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The throwing of the exception (instead of returning of -1 value
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * or incompleate filling of destination buffer)
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * helps to speed up the process of scrappy data recognition and
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * processing.
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For more information about TLS handshake process see
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * TLS v 1 specification at http://www.ietf.org/rfc/rfc2246.txt.
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class HandshakeIODataStream
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        extends SSLInputStream implements org.apache.harmony.xnet.provider.jsse.Appendable, DataStream {
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // Objects are used to compute digests of data passed
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // during the handshake phase
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final MessageDigest md5;
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final MessageDigest sha;
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static {
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            md5 = MessageDigest.getInstance("MD5");
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sha = MessageDigest.getInstance("SHA-1");
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (Exception e) {
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            e.printStackTrace();
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new RuntimeException(
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "Could not initialize the Digest Algorithms.");
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public HandshakeIODataStream() {}
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // buffer is used to keep the handshaking data;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int buff_size = 1024;
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int inc_buff_size = 1024;
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private byte[] buffer = new byte[buff_size];
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ---------------- Input related functionality -----------------
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // position of the next byte to read
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int read_pos;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int marked_pos;
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // position of the last byte to read + 1
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int read_pos_end;
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int available() {
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return read_pos_end - read_pos;
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean markSupported() {
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void mark(int limit) {
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        marked_pos = read_pos;
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void mark() {
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        marked_pos = read_pos;
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void reset() {
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos = marked_pos;
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Removes the data from the marked position to
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the current read position. The method is usefull when it is needed
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to delete one message from the internal buffer.
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void removeFromMarkedPosition() {
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(buffer, read_pos,
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                buffer, marked_pos, read_pos_end - read_pos);
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos_end -= (read_pos - marked_pos);
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos = marked_pos;
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * read an opaque value;
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param   byte:   byte
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int read() throws IOException {
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (read_pos == read_pos_end) {
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            //return -1;
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new EndOfBufferException();
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return buffer[read_pos++] & 0xFF;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * reads vector of opaque values
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param   new:    long
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public byte[] read(int length) throws IOException {
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (length > available()) {
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new EndOfBufferException();
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] res = new byte[length];
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(buffer, read_pos, res, 0, length);
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos = read_pos + length;
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return res;
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int read(byte[] dest, int offset, int length) throws IOException {
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (length > available()) {
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new EndOfBufferException();
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(buffer, read_pos, dest, offset, length);
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos = read_pos + length;
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return length;
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ------------------- Extending of the input data ---------------------
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Appends the income data to be read by handshake protocol.
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The attempts to overflow the buffer by meens of this methos
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * seem to be futile because of:
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * 1. The SSL protocol specifies the maximum size of the record
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * and record protocol does not pass huge messages.
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * (see TLS v1 specification http://www.ietf.org/rfc/rfc2246.txt ,
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * p 6.2)
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * 2. After each call of this method, handshake protocol should
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * start (and starts) the operations on received data and recognize
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the fake data if such was provided (to check the size of certificate
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * for example).
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void append(byte[] src) {
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        append(src, 0, src.length);
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void append(byte[] src, int from, int length) {
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (read_pos == read_pos_end) {
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // start reading state after writing
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (write_pos_beg != write_pos) {
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // error: outboud handshake data was not sent,
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // but inbound handshake data has been received.
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new AlertException(
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    AlertProtocol.UNEXPECTED_MESSAGE,
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    new SSLHandshakeException(
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        "Handshake message has been received before "
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + "the last oubound message had been sent."));
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (read_pos < write_pos) {
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                read_pos = write_pos;
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                read_pos_end = read_pos;
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (read_pos_end + length > buff_size) {
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            enlargeBuffer(read_pos_end+length-buff_size);
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(src, from, buffer, read_pos_end, length);
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos_end += length;
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void enlargeBuffer(int size) {
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buff_size = (size < inc_buff_size)
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ? buff_size + inc_buff_size
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            : buff_size + size;
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] new_buff = new byte[buff_size];
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(buffer, 0, new_buff, 0, buffer.length);
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer = new_buff;
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void clearBuffer() {
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos = 0;
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        marked_pos = 0;
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        read_pos_end = 0;
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        write_pos = 0;
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        write_pos_beg = 0;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Arrays.fill(buffer, (byte) 0);
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ------------------- Output related functionality --------------------
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // position in the buffer available for write
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int write_pos;
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // position in the buffer where the last write session has begun
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private int write_pos_beg;
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // checks if the data can be written in the buffer
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void check(int length) {
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // (write_pos == write_pos_beg) iff:
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // 1. there were not write operations yet
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // 2. all written data was demanded by getData methods
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (write_pos == write_pos_beg) {
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // just started to write after the reading
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (read_pos != read_pos_end) {
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // error: attempt to write outbound data into the stream before
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                // all the inbound handshake data had been read
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                throw new AlertException(
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        AlertProtocol.INTERNAL_ERROR,
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        new SSLHandshakeException("Data was not fully read: "
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + read_pos + " " + read_pos_end));
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // set up the write positions
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (write_pos_beg < read_pos_end) {
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                write_pos_beg = read_pos_end;
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                write_pos = write_pos_beg;
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // if there is not enought free space in the buffer - enlarge it:
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (write_pos + length >= buff_size) {
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            enlargeBuffer(length);
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes an opaque value
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param   byte:   byte
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void write(byte b) {
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(1);
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = b;
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes Uint8 value
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param long: the value to be written (last byte)
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeUint8(long n) {
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(1);
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) (n & 0x00ff);
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes Uint16 value
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param long: the value to be written (last 2 bytes)
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeUint16(long n) {
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(2);
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) (n & 0x00ff);
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes Uint24 value
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param long: the value to be written (last 3 bytes)
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeUint24(long n) {
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(3);
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16);
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) (n & 0x00ff);
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes Uint32 value
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param long: the value to be written (last 4 bytes)
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeUint32(long n) {
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(4);
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff000000) >> 24);
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16);
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) (n & 0x00ff);
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Writes Uint64 value
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param long: the value to be written
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void writeUint64(long n) {
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(8);
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00000000000000L) >> 56);
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff000000000000L) >> 48);
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff0000000000L) >> 40);
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00000000L) >> 32);
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff000000) >> 24);
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16);
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8);
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        buffer[write_pos++] = (byte) (n & 0x00ff);
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * writes vector of opaque values
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param  vector the vector to be written
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void write(byte[] vector) {
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        check(vector.length);
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(vector, 0, buffer, write_pos, vector.length);
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        write_pos += vector.length;
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ------------------- Retrieve the written bytes ----------------------
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean hasData() {
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (write_pos > write_pos_beg);
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * returns the chunk of stored data with the length no more than specified.
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param   length: int
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public byte[] getData(int length) {
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] res;
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (write_pos - write_pos_beg < length) {
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            res = new byte[write_pos - write_pos_beg];
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(buffer, write_pos_beg,
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    res, 0, write_pos-write_pos_beg);
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            write_pos_beg = write_pos;
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            res = new byte[length];
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            System.arraycopy(buffer, write_pos_beg, res, 0, length);
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            write_pos_beg += length;
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return res;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ---------------------- Debud functionality -------------------------
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void printContent(PrintStream outstream) {
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int perLine = 20;
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String prefix = " ";
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String delimiter = "";
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i=write_pos_beg; i<write_pos; i++) {
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String tail = Integer.toHexString(
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    0x00ff & buffer[i]).toUpperCase();
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (tail.length() == 1) {
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                tail = "0" + tail;
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            outstream.print(prefix + tail + delimiter);
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (((i-write_pos_beg+1)%10) == 0) {
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outstream.print(" ");
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (((i-write_pos_beg+1)%perLine) == 0) {
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                outstream.println();
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        outstream.println();
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // ---------------------- Message Digest Functionality ----------------
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the MD5 digest of the data passed throught the stream
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return MD5 digest
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] getDigestMD5() {
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (md5) {
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int len = (read_pos_end > write_pos)
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ? read_pos_end
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                : write_pos;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            md5.update(buffer, 0, len);
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return md5.digest();
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     * Returns the SHA-1 digest of the data passed throught the stream
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return SHA-1 digest
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] getDigestSHA() {
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (sha) {
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int len = (read_pos_end > write_pos)
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ? read_pos_end
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                : write_pos;
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sha.update(buffer, 0, len);
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return sha.digest();
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the MD5 digest of the data passed throught the stream
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * except last message
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return MD5 digest
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] getDigestMD5withoutLast() {
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (md5) {
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            md5.update(buffer, 0, marked_pos);
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return md5.digest();
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the SHA-1 digest of the data passed throught the stream
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * except last message
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return SHA-1 digest
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] getDigestSHAwithoutLast() {
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (sha) {
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sha.update(buffer, 0, marked_pos);
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return sha.digest();
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns all the data passed throught the stream
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return all the data passed throught the stream at the moment
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected byte[] getMessages() {
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int len = (read_pos_end > write_pos) ? read_pos_end : write_pos;
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        byte[] res = new byte[len];
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        System.arraycopy(buffer, 0, res, 0, len);
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return res;
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
463