blob: 84ed819769b21afe87e64f960ef2a259789efe6d [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1996-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26
27package sun.security.ssl;
28
29import java.io.InputStream;
30import java.io.IOException;
31import java.security.MessageDigest;
32
33import javax.net.ssl.SSLException;
34
35/**
36 * InputStream for handshake data, used internally only. Contains the
37 * handshake message buffer and methods to parse them.
38 *
39 * Once a new handshake record arrives, it is buffered in this class until
40 * processed by the Handshaker. The buffer may also contain incomplete
41 * handshake messages in case the message is split across multiple records.
42 * Handshaker.process_record deals with all that. It may also contain
43 * handshake messages larger than the default buffer size (e.g. large
44 * certificate messages). The buffer is grown dynamically to handle that
45 * (see InputRecord.queueHandshake()).
46 *
47 * Note that the InputRecord used as a buffer here is separate from the
48 * AppInStream.r, which is where data from the socket is initially read
49 * into. This is because once the initial handshake has been completed,
50 * handshake and application data messages may be interleaved arbitrarily
51 * and must be processed independently.
52 *
53 * @author David Brownell
54 */
55class HandshakeInStream extends InputStream {
56
57 InputRecord r;
58
59 /*
60 * Construct the stream; we'll be accumulating hashes of the
61 * input records using two sets of digests.
62 */
63 HandshakeInStream(HandshakeHash handshakeHash) {
64 r = new InputRecord();
65 r.setHandshakeHash(handshakeHash);
66 }
67
68
69 // overridden InputStream methods
70
71 /*
72 * Return the number of bytes available for read().
73 *
74 * Note that this returns the bytes remaining in the buffer, not
75 * the bytes remaining in the current handshake message.
76 */
77 public int available() {
78 return r.available();
79 }
80
81 /*
82 * Get a byte of handshake data.
83 */
84 public int read() throws IOException {
85 int n = r.read();
86 if (n == -1) {
87 throw new SSLException("Unexpected end of handshake data");
88 }
89 return n;
90 }
91
92 /*
93 * Get a bunch of bytes of handshake data.
94 */
95 public int read(byte b [], int off, int len) throws IOException {
96 // we read from a ByteArrayInputStream, it always returns the
97 // data in a single read if enough is available
98 int n = r.read(b, off, len);
99 if (n != len) {
100 throw new SSLException("Unexpected end of handshake data");
101 }
102 return n;
103 }
104
105 /*
106 * Skip some handshake data.
107 */
108 public long skip(long n) throws IOException {
109 return r.skip(n);
110 }
111
112 /*
113 * Mark/ reset code, implemented using InputRecord mark/ reset.
114 *
115 * Note that it currently provides only a limited mark functionality
116 * and should be used with care (once a new handshake record has been
117 * read, data that has already been consumed is lost even if marked).
118 */
119
120 public void mark(int readlimit) {
121 r.mark(readlimit);
122 }
123
124 public void reset() {
125 r.reset();
126 }
127
128 public boolean markSupported() {
129 return true;
130 }
131
132
133 // handshake management functions
134
135 /*
136 * Here's an incoming record with handshake data. Queue the contents;
137 * it might be one or more entire messages, complete a message that's
138 * partly queued, or both.
139 */
140 void incomingRecord(InputRecord in) throws IOException {
141 r.queueHandshake(in);
142 }
143
144 /*
145 * Hash any data we've consumed but not yet hashed. Useful mostly
146 * for processing client certificate messages (so we can check the
147 * immediately following cert verify message) and finished messages
148 * (so we can compute our own finished message).
149 */
150 void digestNow() {
151 r.doHashes();
152 }
153
154 /*
155 * Do more than skip that handshake data ... totally ignore it.
156 * The difference is that the data does not get hashed.
157 */
158 void ignore(int n) {
159 r.ignore(n);
160 }
161
162
163 // Message parsing methods
164
165 /*
166 * Read 8, 16, 24, and 32 bit SSL integer data types, encoded
167 * in standard big-endian form.
168 */
169
170 int getInt8() throws IOException {
171 return read();
172 }
173
174 int getInt16() throws IOException {
175 return (getInt8() << 8) | getInt8();
176 }
177
178 int getInt24() throws IOException {
179 return (getInt8() << 16) | (getInt8() << 8) | getInt8();
180 }
181
182 int getInt32() throws IOException {
183 return (getInt8() << 24) | (getInt8() << 16)
184 | (getInt8() << 8) | getInt8();
185 }
186
187 /*
188 * Read byte vectors with 8, 16, and 24 bit length encodings.
189 */
190
191 byte[] getBytes8() throws IOException {
192 int len = getInt8();
193 byte b[] = new byte[len];
194
195 read(b, 0, len);
196 return b;
197 }
198
199 byte[] getBytes16() throws IOException {
200 int len = getInt16();
201 byte b[] = new byte[len];
202
203 read(b, 0, len);
204 return b;
205 }
206
207 byte[] getBytes24() throws IOException {
208 int len = getInt24();
209 byte b[] = new byte[len];
210
211 read(b, 0, len);
212 return b;
213 }
214
215}