diff options
Diffstat (limited to 'crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java')
-rw-r--r-- | crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java | 435 |
1 files changed, 0 insertions, 435 deletions
diff --git a/crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java b/crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java deleted file mode 100644 index 0723820..0000000 --- a/crypto/src/main/java/org/conscrypt/HandshakeIODataStream.java +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.conscrypt; - -import java.io.IOException; -import java.io.PrintStream; -import java.security.MessageDigest; -import java.util.Arrays; -import java.util.Locale; -import javax.net.ssl.SSLHandshakeException; - -/** - * This class provides Input/Output data functionality - * for handshake layer. It provides read and write operations - * and accumulates all sent/received handshake's data. - * This class can be presented as a combination of 2 data pipes. - * The first data pipe is a pipe of income data: append method - * places the data at the beginning of the pipe, and read methods - * consume the data from the pipe. The second pipe is an outcoming - * data pipe: write operations plases the data into the pipe, - * and getData methods consume the data. - * It is important to note that work with pipe cound not be - * started if there is unconsumed data in another pipe. It is - * reasoned by the following: handshake protocol performs read - * and write operations consecuently. I.e. it first reads all - * income data and only than produces the responce and places it - * into the stream. - * The read operations of the stream presented by the methods - * of SSLInputStream which in its turn is an extension of InputStream. - * So this stream can be used as an InputStream parameter for - * certificate generation. - * Also input stream functionality supports marks. The marks - * help to reset the position of the stream in case of incompleate - * handshake records. Note that in case of exhausting - * of income data the EndOfBufferException is thown which implies - * the following: - * 1. the stream contains scrappy handshake record, - * 2. the read position should be reseted to marked, - * 3. and more income data is expected. - * The throwing of the exception (instead of returning of -1 value - * or incompleate filling of destination buffer) - * helps to speed up the process of scrappy data recognition and - * processing. - * For more information about TLS handshake process see - * TLS v 1 specification at http://www.ietf.org/rfc/rfc2246.txt. - */ -public class HandshakeIODataStream - extends SSLInputStream implements org.conscrypt.Appendable, DataStream { - - // Objects are used to compute digests of data passed - // during the handshake phase - private static final MessageDigest md5; - private static final MessageDigest sha; - - static { - try { - md5 = MessageDigest.getInstance("MD5"); - sha = MessageDigest.getInstance("SHA-1"); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException( - "Could not initialize the Digest Algorithms."); - } - } - - public HandshakeIODataStream() {} - - // buffer is used to keep the handshaking data; - private int buff_size = 1024; - private int inc_buff_size = 1024; - private byte[] buffer = new byte[buff_size]; - - - // ---------------- Input related functionality ----------------- - - // position of the next byte to read - private int read_pos; - private int marked_pos; - // position of the last byte to read + 1 - private int read_pos_end; - - @Override - public int available() { - return read_pos_end - read_pos; - } - - @Override - public boolean markSupported() { - return true; - } - - @Override - public void mark(int limit) { - marked_pos = read_pos; - } - - public void mark() { - marked_pos = read_pos; - } - - @Override - public void reset() { - read_pos = marked_pos; - } - - /** - * Removes the data from the marked position to - * the current read position. The method is usefull when it is needed - * to delete one message from the internal buffer. - */ - protected void removeFromMarkedPosition() { - System.arraycopy(buffer, read_pos, - buffer, marked_pos, read_pos_end - read_pos); - read_pos_end -= (read_pos - marked_pos); - read_pos = marked_pos; - } - - /** - * read an opaque value; - * @param byte: byte - * @return - */ - @Override - public int read() throws IOException { - if (read_pos == read_pos_end) { - //return -1; - throw new EndOfBufferException(); - } - return buffer[read_pos++] & 0xFF; - } - - /** - * reads vector of opaque values - * @param new: long - * @return - */ - @Override - public byte[] read(int length) throws IOException { - if (length > available()) { - throw new EndOfBufferException(); - } - byte[] res = new byte[length]; - System.arraycopy(buffer, read_pos, res, 0, length); - read_pos = read_pos + length; - return res; - } - - @Override - public int read(byte[] dst, int offset, int length) throws IOException { - if (length > available()) { - throw new EndOfBufferException(); - } - System.arraycopy(buffer, read_pos, dst, offset, length); - read_pos = read_pos + length; - return length; - } - - // ------------------- Extending of the input data --------------------- - - /** - * Appends the income data to be read by handshake protocol. - * The attempts to overflow the buffer by means of this methods - * seem to be futile because of: - * 1. The SSL protocol specifies the maximum size of the record - * and record protocol does not pass huge messages. - * (see TLS v1 specification http://www.ietf.org/rfc/rfc2246.txt , - * p 6.2) - * 2. After each call of this method, handshake protocol should - * start (and starts) the operations on received data and recognize - * the fake data if such was provided (to check the size of certificate - * for example). - */ - public void append(byte[] src) { - append(src, 0, src.length); - } - - private void append(byte[] src, int from, int length) { - if (read_pos == read_pos_end) { - // start reading state after writing - if (write_pos_beg != write_pos) { - // error: outboud handshake data was not sent, - // but inbound handshake data has been received. - throw new AlertException( - AlertProtocol.UNEXPECTED_MESSAGE, - new SSLHandshakeException( - "Handshake message has been received before " - + "the last oubound message had been sent.")); - } - if (read_pos < write_pos) { - read_pos = write_pos; - read_pos_end = read_pos; - } - } - if (read_pos_end + length > buff_size) { - enlargeBuffer(read_pos_end+length-buff_size); - } - System.arraycopy(src, from, buffer, read_pos_end, length); - read_pos_end += length; - } - - private void enlargeBuffer(int size) { - buff_size = (size < inc_buff_size) - ? buff_size + inc_buff_size - : buff_size + size; - byte[] new_buff = new byte[buff_size]; - System.arraycopy(buffer, 0, new_buff, 0, buffer.length); - buffer = new_buff; - } - - protected void clearBuffer() { - read_pos = 0; - marked_pos = 0; - read_pos_end = 0; - write_pos = 0; - write_pos_beg = 0; - Arrays.fill(buffer, (byte) 0); - } - - // ------------------- Output related functionality -------------------- - - // position in the buffer available for write - private int write_pos; - // position in the buffer where the last write session has begun - private int write_pos_beg; - - // checks if the data can be written in the buffer - private void check(int length) { - // (write_pos == write_pos_beg) iff: - // 1. there were not write operations yet - // 2. all written data was demanded by getData methods - if (write_pos == write_pos_beg) { - // just started to write after the reading - if (read_pos != read_pos_end) { - // error: attempt to write outbound data into the stream before - // all the inbound handshake data had been read - throw new AlertException( - AlertProtocol.INTERNAL_ERROR, - new SSLHandshakeException("Data was not fully read: " - + read_pos + " " + read_pos_end)); - } - // set up the write positions - if (write_pos_beg < read_pos_end) { - write_pos_beg = read_pos_end; - write_pos = write_pos_beg; - } - } - // if there is not enought free space in the buffer - enlarge it: - if (write_pos + length >= buff_size) { - enlargeBuffer(length); - } - } - - /** - * Writes an opaque value - * @param byte: byte - */ - public void write(byte b) { - check(1); - buffer[write_pos++] = b; - } - - /** - * Writes Uint8 value - * @param long: the value to be written (last byte) - */ - public void writeUint8(long n) { - check(1); - buffer[write_pos++] = (byte) (n & 0x00ff); - } - - /** - * Writes Uint16 value - * @param long: the value to be written (last 2 bytes) - */ - public void writeUint16(long n) { - check(2); - buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8); - buffer[write_pos++] = (byte) (n & 0x00ff); - } - - /** - * Writes Uint24 value - * @param long: the value to be written (last 3 bytes) - */ - public void writeUint24(long n) { - check(3); - buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16); - buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8); - buffer[write_pos++] = (byte) (n & 0x00ff); - } - - /** - * Writes Uint32 value - * @param long: the value to be written (last 4 bytes) - */ - public void writeUint32(long n) { - check(4); - buffer[write_pos++] = (byte) ((n & 0x00ff000000) >> 24); - buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16); - buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8); - buffer[write_pos++] = (byte) (n & 0x00ff); - } - - /** - * Writes Uint64 value - * @param long: the value to be written - */ - public void writeUint64(long n) { - check(8); - buffer[write_pos++] = (byte) ((n & 0x00ff00000000000000L) >> 56); - buffer[write_pos++] = (byte) ((n & 0x00ff000000000000L) >> 48); - buffer[write_pos++] = (byte) ((n & 0x00ff0000000000L) >> 40); - buffer[write_pos++] = (byte) ((n & 0x00ff00000000L) >> 32); - buffer[write_pos++] = (byte) ((n & 0x00ff000000) >> 24); - buffer[write_pos++] = (byte) ((n & 0x00ff0000) >> 16); - buffer[write_pos++] = (byte) ((n & 0x00ff00) >> 8); - buffer[write_pos++] = (byte) (n & 0x00ff); - } - - /** - * writes vector of opaque values - * @param vector the vector to be written - */ - public void write(byte[] vector) { - check(vector.length); - System.arraycopy(vector, 0, buffer, write_pos, vector.length); - write_pos += vector.length; - } - - // ------------------- Retrieve the written bytes ---------------------- - - public boolean hasData() { - return (write_pos > write_pos_beg); - } - - /** - * returns the chunk of stored data with the length no more than specified. - * @param length: int - * @return - */ - public byte[] getData(int length) { - byte[] res; - if (write_pos - write_pos_beg < length) { - res = new byte[write_pos - write_pos_beg]; - System.arraycopy(buffer, write_pos_beg, - res, 0, write_pos-write_pos_beg); - write_pos_beg = write_pos; - } else { - res = new byte[length]; - System.arraycopy(buffer, write_pos_beg, res, 0, length); - write_pos_beg += length; - } - return res; - } - - // ---------------------- Message Digest Functionality ---------------- - - /** - * Returns the MD5 digest of the data passed throught the stream - * @return MD5 digest - */ - protected byte[] getDigestMD5() { - synchronized (md5) { - int len = (read_pos_end > write_pos) - ? read_pos_end - : write_pos; - md5.update(buffer, 0, len); - return md5.digest(); - } - } - - /** - * Returns the SHA-1 digest of the data passed throught the stream - * @return SHA-1 digest - */ - protected byte[] getDigestSHA() { - synchronized (sha) { - int len = (read_pos_end > write_pos) - ? read_pos_end - : write_pos; - sha.update(buffer, 0, len); - return sha.digest(); - } - } - - /** - * Returns the MD5 digest of the data passed throught the stream - * except last message - * @return MD5 digest - */ - protected byte[] getDigestMD5withoutLast() { - synchronized (md5) { - md5.update(buffer, 0, marked_pos); - return md5.digest(); - } - } - - /** - * Returns the SHA-1 digest of the data passed throught the stream - * except last message - * @return SHA-1 digest - */ - protected byte[] getDigestSHAwithoutLast() { - synchronized (sha) { - sha.update(buffer, 0, marked_pos); - return sha.digest(); - } - } - - /** - * Returns all the data passed throught the stream - * @return all the data passed throught the stream at the moment - */ - protected byte[] getMessages() { - int len = (read_pos_end > write_pos) ? read_pos_end : write_pos; - byte[] res = new byte[len]; - System.arraycopy(buffer, 0, res, 0, len); - return res; - } -} |