1 /*
   2  * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 
  27 package sun.security.ssl;
  28 
  29 import java.io.InputStream;
  30 import java.io.IOException;
  31 
  32 import javax.net.ssl.SSLException;
  33 
  34 /**
  35  * InputStream for handshake data, used internally only. Contains the
  36  * handshake message buffer and methods to parse them.
  37  *
  38  * Once a new handshake record arrives, it is buffered in this class until
  39  * processed by the Handshaker. The buffer may also contain incomplete
  40  * handshake messages in case the message is split across multiple records.
  41  * Handshaker.process_record deals with all that. It may also contain
  42  * handshake messages larger than the default buffer size (e.g. large
  43  * certificate messages). The buffer is grown dynamically to handle that
  44  * (see InputRecord.queueHandshake()).
  45  *
  46  * Note that the InputRecord used as a buffer here is separate from the
  47  * AppInStream.r, which is where data from the socket is initially read
  48  * into. This is because once the initial handshake has been completed,
  49  * handshake and application data messages may be interleaved arbitrarily
  50  * and must be processed independently.
  51  *
  52  * @author David Brownell
  53  */
  54 public class HandshakeInStream extends InputStream {
  55 
  56     InputRecord r;
  57 
  58     /*
  59      * Construct the stream; we'll be accumulating hashes of the
  60      * input records using two sets of digests.
  61      */
  62     HandshakeInStream(HandshakeHash handshakeHash) {
  63         r = new InputRecord();
  64         r.setHandshakeHash(handshakeHash);
  65     }
  66 
  67 
  68     // overridden InputStream methods
  69 
  70     /*
  71      * Return the number of bytes available for read().
  72      *
  73      * Note that this returns the bytes remaining in the buffer, not
  74      * the bytes remaining in the current handshake message.
  75      */
  76     @Override
  77     public int available() {
  78         return r.available();
  79     }
  80 
  81     /*
  82      * Get a byte of handshake data.
  83      */
  84     @Override
  85     public int read() throws IOException {
  86         int n = r.read();
  87         if (n == -1) {
  88             throw new SSLException("Unexpected end of handshake data");
  89         }
  90         return n;
  91     }
  92 
  93     /*
  94      * Get a bunch of bytes of handshake data.
  95      */
  96     @Override
  97     public int read(byte b [], int off, int len) throws IOException {
  98         // we read from a ByteArrayInputStream, it always returns the
  99         // data in a single read if enough is available
 100         int n = r.read(b, off, len);
 101         if (n != len) {
 102             throw new SSLException("Unexpected end of handshake data");
 103         }
 104         return n;
 105     }
 106 
 107     /*
 108      * Skip some handshake data.
 109      */
 110     @Override
 111     public long skip(long n) throws IOException {
 112         return r.skip(n);
 113     }
 114 
 115     /*
 116      * Mark/ reset code, implemented using InputRecord mark/ reset.
 117      *
 118      * Note that it currently provides only a limited mark functionality
 119      * and should be used with care (once a new handshake record has been
 120      * read, data that has already been consumed is lost even if marked).
 121      */
 122 
 123     @Override
 124     public void mark(int readlimit) {
 125         r.mark(readlimit);
 126     }
 127 
 128     @Override
 129     public void reset() throws IOException {
 130         r.reset();
 131     }
 132 
 133     @Override
 134     public boolean markSupported() {
 135         return true;
 136     }
 137 
 138 
 139     // handshake management functions
 140 
 141     /*
 142      * Here's an incoming record with handshake data.  Queue the contents;
 143      * it might be one or more entire messages, complete a message that's
 144      * partly queued, or both.
 145      */
 146     void incomingRecord(InputRecord in) throws IOException {
 147         r.queueHandshake(in);
 148     }
 149 
 150     /*
 151      * Hash any data we've consumed but not yet hashed.  Useful mostly
 152      * for processing client certificate messages (so we can check the
 153      * immediately following cert verify message) and finished messages
 154      * (so we can compute our own finished message).
 155      */
 156     void digestNow() {
 157         r.doHashes();
 158     }
 159 
 160     /*
 161      * Do more than skip that handshake data ... totally ignore it.
 162      * The difference is that the data does not get hashed.
 163      */
 164     void ignore(int n) {
 165         r.ignore(n);
 166     }
 167 
 168 
 169     // Message parsing methods
 170 
 171     /*
 172      * Read 8, 16, 24, and 32 bit SSL integer data types, encoded
 173      * in standard big-endian form.
 174      */
 175 
 176     int getInt8() throws IOException {
 177         return read();
 178     }
 179 
 180     int getInt16() throws IOException {
 181         return (getInt8() << 8) | getInt8();
 182     }
 183 
 184     int getInt24() throws IOException {
 185         return (getInt8() << 16) | (getInt8() << 8) | getInt8();
 186     }
 187 
 188     int getInt32() throws IOException {
 189         return (getInt8() << 24) | (getInt8() << 16)
 190              | (getInt8() << 8) | getInt8();
 191     }
 192 
 193     /*
 194      * Read byte vectors with 8, 16, and 24 bit length encodings.
 195      */
 196 
 197     byte[] getBytes8() throws IOException {
 198         int len = getInt8();
 199         verifyLength(len);
 200         byte b[] = new byte[len];
 201 
 202         read(b, 0, len);
 203         return b;
 204     }
 205 
 206     public byte[] getBytes16() throws IOException {
 207         int len = getInt16();
 208         verifyLength(len);
 209         byte b[] = new byte[len];
 210 
 211         read(b, 0, len);
 212         return b;
 213     }
 214 
 215     byte[] getBytes24() throws IOException {
 216         int len = getInt24();
 217         verifyLength(len);
 218         byte b[] = new byte[len];
 219 
 220         read(b, 0, len);
 221         return b;
 222     }
 223 
 224     // Is a length greater than available bytes in the record?
 225     private void verifyLength(int len) throws SSLException {
 226         if (len > available()) {
 227             throw new SSLException(
 228                         "Not enough data to fill declared vector size");
 229         }
 230     }
 231 
 232 }