src/java.base/share/classes/sun/security/ssl/HandshakeInStream.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 21,35 **** * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ - package sun.security.ssl; ! import java.io.InputStream; import java.io.IOException; import javax.net.ssl.SSLException; /** * InputStream for handshake data, used internally only. Contains the --- 21,35 ---- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.ssl; ! import java.io.ByteArrayInputStream; import java.io.IOException; + import java.nio.ByteBuffer; import javax.net.ssl.SSLException; /** * InputStream for handshake data, used internally only. Contains the
*** 36,232 **** * handshake message buffer and methods to parse them. * * Once a new handshake record arrives, it is buffered in this class until * processed by the Handshaker. The buffer may also contain incomplete * handshake messages in case the message is split across multiple records. ! * Handshaker.process_record deals with all that. It may also contain * handshake messages larger than the default buffer size (e.g. large ! * certificate messages). The buffer is grown dynamically to handle that ! * (see InputRecord.queueHandshake()). * ! * Note that the InputRecord used as a buffer here is separate from the ! * AppInStream.r, which is where data from the socket is initially read ! * into. This is because once the initial handshake has been completed, ! * handshake and application data messages may be interleaved arbitrarily ! * and must be processed independently. * * @author David Brownell */ - public class HandshakeInStream extends InputStream { ! InputRecord r; /* * Construct the stream; we'll be accumulating hashes of the * input records using two sets of digests. */ ! HandshakeInStream(HandshakeHash handshakeHash) { ! r = new InputRecord(); ! r.setHandshakeHash(handshakeHash); } - // overridden InputStream methods - - /* - * Return the number of bytes available for read(). - * - * Note that this returns the bytes remaining in the buffer, not - * the bytes remaining in the current handshake message. - */ @Override ! public int available() { ! return r.available(); ! } ! ! /* ! * Get a byte of handshake data. ! */ ! @Override ! public int read() throws IOException { ! int n = r.read(); ! if (n == -1) { throw new SSLException("Unexpected end of handshake data"); } - return n; - } ! /* ! * Get a bunch of bytes of handshake data. ! */ ! @Override ! public int read(byte b [], int off, int len) throws IOException { ! // we read from a ByteArrayInputStream, it always returns the ! // data in a single read if enough is available ! int n = r.read(b, off, len); ! if (n != len) { ! throw new SSLException("Unexpected end of handshake data"); } - return n; - } ! /* ! * Skip some handshake data. ! */ ! @Override ! public long skip(long n) throws IOException { ! return r.skip(n); ! } /* ! * Mark/ reset code, implemented using InputRecord mark/ reset. ! * ! * Note that it currently provides only a limited mark functionality ! * and should be used with care (once a new handshake record has been ! * read, data that has already been consumed is lost even if marked). */ ! @Override ! public void mark(int readlimit) { ! r.mark(readlimit); } ! ! @Override ! public void reset() throws IOException { ! r.reset(); } ! @Override ! public boolean markSupported() { ! return true; } ! ! ! // handshake management functions ! ! /* ! * Here's an incoming record with handshake data. Queue the contents; ! * it might be one or more entire messages, complete a message that's ! * partly queued, or both. ! */ ! void incomingRecord(InputRecord in) throws IOException { ! r.queueHandshake(in); } ! /* ! * Hash any data we've consumed but not yet hashed. Useful mostly ! * for processing client certificate messages (so we can check the ! * immediately following cert verify message) and finished messages ! * (so we can compute our own finished message). ! */ ! void digestNow() { ! r.doHashes(); } ! /* ! * Do more than skip that handshake data ... totally ignore it. ! * The difference is that the data does not get hashed. ! */ ! void ignore(int n) { ! r.ignore(n); ! } ! ! // Message parsing methods /* * Read 8, 16, 24, and 32 bit SSL integer data types, encoded * in standard big-endian form. */ - int getInt8() throws IOException { return read(); } int getInt16() throws IOException { return (getInt8() << 8) | getInt8(); } int getInt24() throws IOException { return (getInt8() << 16) | (getInt8() << 8) | getInt8(); } int getInt32() throws IOException { return (getInt8() << 24) | (getInt8() << 16) | (getInt8() << 8) | getInt8(); } /* * Read byte vectors with 8, 16, and 24 bit length encodings. */ - byte[] getBytes8() throws IOException { int len = getInt8(); verifyLength(len); byte b[] = new byte[len]; ! read(b, 0, len); return b; } public byte[] getBytes16() throws IOException { int len = getInt16(); verifyLength(len); byte b[] = new byte[len]; ! read(b, 0, len); return b; } byte[] getBytes24() throws IOException { int len = getInt24(); verifyLength(len); byte b[] = new byte[len]; ! read(b, 0, len); return b; } // Is a length greater than available bytes in the record? private void verifyLength(int len) throws SSLException { if (len > available()) { ! throw new SSLException( ! "Not enough data to fill declared vector size"); } } - } --- 36,179 ---- * handshake message buffer and methods to parse them. * * Once a new handshake record arrives, it is buffered in this class until * processed by the Handshaker. The buffer may also contain incomplete * handshake messages in case the message is split across multiple records. ! * Handshaker.processRecord deals with all that. It may also contain * handshake messages larger than the default buffer size (e.g. large ! * certificate messages). The buffer is grown dynamically to handle that. * ! * Note that this class only handles Handshake messages in TLS format. ! * DTLS Handshake messages should be converted into TLS format before ! * calling into this method. * * @author David Brownell */ ! // This class is used to handle plain text handshake messages. ! // ! public final class HandshakeInStream extends ByteArrayInputStream { /* * Construct the stream; we'll be accumulating hashes of the * input records using two sets of digests. */ ! HandshakeInStream() { ! super(new byte[0]); // lazy to alloacte the internal buffer } + // + // overridden ByteArrayInputStream methods + // @Override ! public int read(byte[] b) throws IOException { ! if (super.read(b) != b.length) { throw new SSLException("Unexpected end of handshake data"); } ! return b.length; } ! // ! // handshake input stream management functions ! // /* ! * Here's an incoming record with handshake data. Queue the contents; ! * it might be one or more entire messages, complete a message that's ! * partly queued, or both. */ + void incomingRecord(ByteBuffer in) throws IOException { + int len; ! // Move any unread data to the front of the buffer. ! if (pos != 0) { ! len = count - pos; ! if (len != 0) { ! System.arraycopy(buf, pos, buf, 0, len); } ! pos = 0; ! count = len; } ! // Grow buffer if needed. ! len = in.remaining() + count; ! if (buf.length < len) { ! byte[] newbuf = new byte[len]; ! if (count != 0) { ! System.arraycopy(buf, 0, newbuf, 0, count); } ! buf = newbuf; } ! // Append the incoming record to the buffer ! in.get(buf, count, in.remaining()); ! count = len; } ! // // Message parsing methods + // /* * Read 8, 16, 24, and 32 bit SSL integer data types, encoded * in standard big-endian form. */ int getInt8() throws IOException { + verifyLength(1); return read(); } int getInt16() throws IOException { + verifyLength(2); return (getInt8() << 8) | getInt8(); } int getInt24() throws IOException { + verifyLength(3); return (getInt8() << 16) | (getInt8() << 8) | getInt8(); } int getInt32() throws IOException { + verifyLength(4); return (getInt8() << 24) | (getInt8() << 16) | (getInt8() << 8) | getInt8(); } /* * Read byte vectors with 8, 16, and 24 bit length encodings. */ byte[] getBytes8() throws IOException { int len = getInt8(); verifyLength(len); byte b[] = new byte[len]; ! read(b); return b; } public byte[] getBytes16() throws IOException { int len = getInt16(); verifyLength(len); byte b[] = new byte[len]; ! read(b); return b; } byte[] getBytes24() throws IOException { int len = getInt24(); verifyLength(len); byte b[] = new byte[len]; ! read(b); return b; } // Is a length greater than available bytes in the record? private void verifyLength(int len) throws SSLException { if (len > available()) { ! throw new SSLException("Unexpected end of handshake data"); } } }