1 /*
2  * Copyright (c) 2003, 2017, 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 package javax.net.ssl;
27
28 /**
29  * An encapsulation of the result state produced by
30  * {@code SSLEngine} I/O calls.
31  *
32  * <p> A {@code SSLEngine} provides a means for establishing
33  * secure communication sessions between two peers.  {@code SSLEngine}
34  * operations typically consume bytes from an input buffer and produce
35  * bytes in an output buffer.  This class provides operational result
36  * values describing the state of the {@code SSLEngine}, including
37  * indications of what operations are needed to finish an
38  * ongoing handshake.  Lastly, it reports the number of bytes consumed
39  * and produced as a result of this operation.
40  *
41  * @see SSLEngine
42  * @see SSLEngine#wrap(ByteBuffer, ByteBuffer)
43  * @see SSLEngine#unwrap(ByteBuffer, ByteBuffer)
44  *
45  * @author Brad R. Wetmore
46  * @since 1.5
47  */

48
49 public class SSLEngineResult {
50
51     /**
52      * An {@code SSLEngineResult} enum describing the overall result
53      * of the {@code SSLEngine} operation.
54      *
55      * The {@code Status} value does not reflect the
56      * state of a {@code SSLEngine} handshake currently
57      * in progress.  The {@code SSLEngineResult's HandshakeStatus}
58      * should be consulted for that information.
59      *
60      * @author Brad R. Wetmore
61      * @since 1.5
62      */

63     public static enum Status {
64
65         /**
66          * The {@code SSLEngine} was not able to unwrap the
67          * incoming data because there were not enough source bytes
68          * available to make a complete packet.
69          *
70          * <P>
71          * Repeat the call once more bytes are available.
72          */

73         BUFFER_UNDERFLOW,
74
75         /**
76          * The {@code SSLEngine} was not able to process the
77          * operation because there are not enough bytes available in the
78          * destination buffer to hold the result.
79          * <P>
80          * Repeat the call once more bytes are available.
81          *
82          * @see SSLSession#getPacketBufferSize()
83          * @see SSLSession#getApplicationBufferSize()
84          */

85         BUFFER_OVERFLOW,
86
87         /**
88          * The {@code SSLEngine} completed the operation, and
89          * is available to process similar calls.
90          */

91         OK,
92
93         /**
94          * The operation just closed this side of the
95          * {@code SSLEngine}, or the operation
96          * could not be completed because it was already closed.
97          */

98         CLOSED;
99     }
100
101     /**
102      * An {@code SSLEngineResult} enum describing the current
103      * handshaking state of this {@code SSLEngine}.
104      *
105      * @author Brad R. Wetmore
106      * @since 1.5
107      */

108     public static enum HandshakeStatus {
109
110         /**
111          * The {@code SSLEngine} is not currently handshaking.
112          */

113         NOT_HANDSHAKING,
114
115         /**
116          * The {@code SSLEngine} has just finished handshaking.
117          * <P>
118          * This value is only generated by a call to
119          * {@code SSLEngine.wrap()/unwrap()} when that call
120          * finishes a handshake.  It is never generated by
121          * {@code SSLEngine.getHandshakeStatus()}.
122          *
123          * @see SSLEngine#wrap(ByteBuffer, ByteBuffer)
124          * @see SSLEngine#unwrap(ByteBuffer, ByteBuffer)
125          * @see SSLEngine#getHandshakeStatus()
126          */

127         FINISHED,
128
129         /**
130          * The {@code SSLEngine} needs the results of one (or more)
131          * delegated tasks before handshaking can continue.
132          *
133          * @see SSLEngine#getDelegatedTask()
134          */

135         NEED_TASK,
136
137         /**
138          * The {@code SSLEngine} must send data to the remote side
139          * before handshaking can continue, so {@code SSLEngine.wrap()}
140          * should be called.
141          *
142          * @see SSLEngine#wrap(ByteBuffer, ByteBuffer)
143          */

144         NEED_WRAP,
145
146         /**
147          * The {@code SSLEngine} needs to receive data from the
148          * remote side before handshaking can continue.
149          */

150         NEED_UNWRAP,
151
152         /**
153          * The {@code SSLEngine} needs to unwrap before handshaking can
154          * continue.
155          * <P>
156          * This value is used to indicate that not-yet-interpreted data
157          * has been previously received from the remote side, and does
158          * not need to be received again.
159          * <P>
160          * This handshake status only applies to DTLS.
161          *
162          * @since   9
163          */

164         NEED_UNWRAP_AGAIN;
165     }
166
167
168     private final Status status;
169     private final HandshakeStatus handshakeStatus;
170     private final int bytesConsumed;
171     private final int bytesProduced;
172     private final long sequenceNumber;
173
174     /**
175      * Initializes a new instance of this class.
176      *
177      * @param   status
178      *          the return value of the operation.
179      *
180      * @param   handshakeStatus
181      *          the current handshaking status.
182      *
183      * @param   bytesConsumed
184      *          the number of bytes consumed from the source ByteBuffer
185      *
186      * @param   bytesProduced
187      *          the number of bytes placed into the destination ByteBuffer
188      *
189      * @throws  IllegalArgumentException
190      *          if the {@code status} or {@code handshakeStatus}
191      *          arguments are null, or if {@code bytesConsumed} or
192      *          {@code bytesProduced} is negative.
193      */

194     public SSLEngineResult(Status status, HandshakeStatus handshakeStatus,
195             int bytesConsumed, int bytesProduced) {
196         this(status, handshakeStatus, bytesConsumed, bytesProduced, -1);
197     }
198
199     /**
200      * Initializes a new instance of this class.
201      *
202      * @param   status
203      *          the return value of the operation.
204      *
205      * @param   handshakeStatus
206      *          the current handshaking status.
207      *
208      * @param   bytesConsumed
209      *          the number of bytes consumed from the source ByteBuffer
210      *
211      * @param   bytesProduced
212      *          the number of bytes placed into the destination ByteBuffer
213      *
214      * @param   sequenceNumber
215      *          the sequence number (unsigned long) of the produced or
216      *          consumed SSL/TLS/DTLS record, or {@code -1L} if no record
217      *          produced or consumed
218      *
219      * @throws  IllegalArgumentException
220      *          if the {@code status} or {@code handshakeStatus}
221      *          arguments are null, or if {@code bytesConsumed} or
222      *          {@code bytesProduced} is negative
223      *
224      * @since   9
225      */

226     public SSLEngineResult(Status status, HandshakeStatus handshakeStatus,
227             int bytesConsumed, int bytesProduced, long sequenceNumber) {
228
229         if ((status == null) || (handshakeStatus == null) ||
230                 (bytesConsumed < 0) || (bytesProduced < 0)) {
231             throw new IllegalArgumentException("Invalid Parameter(s)");
232         }
233
234         this.status = status;
235         this.handshakeStatus = handshakeStatus;
236         this.bytesConsumed = bytesConsumed;
237         this.bytesProduced = bytesProduced;
238         this.sequenceNumber = sequenceNumber;
239     }
240
241     /**
242      * Gets the return value of this {@code SSLEngine} operation.
243      *
244      * @return  the return value
245      */

246     public final Status getStatus() {
247         return status;
248     }
249
250     /**
251      * Gets the handshake status of this {@code SSLEngine}
252      * operation.
253      *
254      * @return  the handshake status
255      */

256     public final HandshakeStatus getHandshakeStatus() {
257         return handshakeStatus;
258     }
259
260     /**
261      * Returns the number of bytes consumed from the input buffer.
262      *
263      * @return  the number of bytes consumed.
264      */

265     public final int bytesConsumed() {
266         return bytesConsumed;
267     }
268
269     /**
270      * Returns the number of bytes written to the output buffer.
271      *
272      * @return  the number of bytes produced
273      */

274     public final int bytesProduced() {
275         return bytesProduced;
276     }
277
278     /**
279      * Returns the sequence number of the produced or consumed SSL/TLS/DTLS
280      * record (optional operation).
281      *
282      * @apiNote  Note that sequence number is an unsigned long and cannot
283      *           exceed {@code -1L}.  It is desired to use the unsigned
284      *           long comparing mode for comparison of unsigned long values
285      *           (see also {@link java.lang.Long#compareUnsigned(longlong)
286      *           Long.compareUnsigned()}).
287      *           <P>
288      *           For DTLS protocols, the first 16 bits of the sequence
289      *           number is a counter value (epoch) that is incremented on
290      *           every cipher state change.  The remaining 48 bits on the
291      *           right side of the sequence number represents the sequence
292      *           of the record, which is maintained separately for each epoch.
293      *
294      * @implNote It is recommended that providers should never allow the
295      *           sequence number incremented to {@code -1L}.  If the sequence
296      *           number is close to wrapping, renegotiate should be requested,
297      *           otherwise the connection should be closed immediately.
298      *           This should be carried on automatically by the underlying
299      *           implementation.
300      *
301      * @return  the sequence number of the produced or consumed SSL/TLS/DTLS
302      *          record; or {@code -1L} if no record is produced or consumed,
303      *          or this operation is not supported by the underlying provider
304      *
305      * @see     java.lang.Long#compareUnsigned(longlong)
306      *
307      * @since   9
308      */

309     public final long sequenceNumber() {
310         return sequenceNumber;
311     }
312
313     /**
314      * Returns a String representation of this object.
315      */

316     @Override
317     public String toString() {
318         return ("Status = " + status +
319             " HandshakeStatus = " + handshakeStatus +
320             "\nbytesConsumed = " + bytesConsumed +
321             " bytesProduced = " + bytesProduced +
322             (sequenceNumber == -1 ? "" :
323                 " sequenceNumber = " + Long.toUnsignedString(sequenceNumber)));
324     }
325 }
326