View Javadoc
1   /*
2    * Copyright 2016 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.handler.ssl;
17  
18  import io.netty.buffer.ByteBuf;
19  import io.netty.buffer.ByteBufAllocator;
20  import io.netty.internal.tcnative.Buffer;
21  import io.netty.internal.tcnative.SSL;
22  import io.netty.util.AbstractReferenceCounted;
23  import io.netty.util.ReferenceCounted;
24  import io.netty.util.ResourceLeakDetector;
25  import io.netty.util.ResourceLeakDetectorFactory;
26  import io.netty.util.ResourceLeakTracker;
27  import io.netty.util.internal.EmptyArrays;
28  import io.netty.util.internal.PlatformDependent;
29  import io.netty.util.internal.StringUtil;
30  import io.netty.util.internal.ThrowableUtil;
31  import io.netty.util.internal.UnstableApi;
32  import io.netty.util.internal.logging.InternalLogger;
33  import io.netty.util.internal.logging.InternalLoggerFactory;
34  
35  import java.nio.ByteBuffer;
36  import java.nio.ReadOnlyBufferException;
37  import java.security.Principal;
38  import java.security.cert.Certificate;
39  import java.util.ArrayList;
40  import java.util.Arrays;
41  import java.util.Collection;
42  import java.util.HashMap;
43  import java.util.List;
44  import java.util.Map;
45  import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
46  import java.util.concurrent.locks.Lock;
47  
48  import javax.net.ssl.SSLEngine;
49  import javax.net.ssl.SSLEngineResult;
50  import javax.net.ssl.SSLException;
51  import javax.net.ssl.SSLHandshakeException;
52  import javax.net.ssl.SSLParameters;
53  import javax.net.ssl.SSLPeerUnverifiedException;
54  import javax.net.ssl.SSLSession;
55  import javax.net.ssl.SSLSessionBindingEvent;
56  import javax.net.ssl.SSLSessionBindingListener;
57  import javax.net.ssl.SSLSessionContext;
58  import javax.security.cert.X509Certificate;
59  
60  import static io.netty.handler.ssl.OpenSsl.memoryAddress;
61  import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V2;
62  import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V2_HELLO;
63  import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V3;
64  import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1;
65  import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_1;
66  import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
67  import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH;
68  import static io.netty.internal.tcnative.SSL.SSL_MAX_PLAINTEXT_LENGTH;
69  import static io.netty.internal.tcnative.SSL.SSL_MAX_RECORD_LENGTH;
70  import static io.netty.util.internal.EmptyArrays.EMPTY_CERTIFICATES;
71  import static io.netty.util.internal.EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
72  import static io.netty.util.internal.ObjectUtil.checkNotNull;
73  import static java.lang.Integer.MAX_VALUE;
74  import static java.lang.Math.min;
75  import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED;
76  import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
77  import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_WRAP;
78  import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
79  import static javax.net.ssl.SSLEngineResult.Status.BUFFER_OVERFLOW;
80  import static javax.net.ssl.SSLEngineResult.Status.BUFFER_UNDERFLOW;
81  import static javax.net.ssl.SSLEngineResult.Status.CLOSED;
82  import static javax.net.ssl.SSLEngineResult.Status.OK;
83  
84  /**
85   * Implements a {@link SSLEngine} using
86   * <a href="https://www.openssl.org/docs/crypto/BIO_s_bio.html#EXAMPLE">OpenSSL BIO abstractions</a>.
87   * <p>Instances of this class must be {@link #release() released} or else native memory will leak!
88   *
89   * <p>Instances of this class <strong>must</strong> be released before the {@link ReferenceCountedOpenSslContext}
90   * the instance depends upon are released. Otherwise if any method of this class is called which uses the
91   * the {@link ReferenceCountedOpenSslContext} JNI resources the JVM may crash.
92   */
93  public class ReferenceCountedOpenSslEngine extends SSLEngine implements ReferenceCounted, ApplicationProtocolAccessor {
94  
95      private static final InternalLogger logger = InternalLoggerFactory.getInstance(ReferenceCountedOpenSslEngine.class);
96  
97      private static final SSLException BEGIN_HANDSHAKE_ENGINE_CLOSED = ThrowableUtil.unknownStackTrace(
98              new SSLException("engine closed"), ReferenceCountedOpenSslEngine.class, "beginHandshake()");
99      private static final SSLException HANDSHAKE_ENGINE_CLOSED = ThrowableUtil.unknownStackTrace(
100             new SSLException("engine closed"), ReferenceCountedOpenSslEngine.class, "handshake()");
101     private static final SSLException RENEGOTIATION_UNSUPPORTED =  ThrowableUtil.unknownStackTrace(
102             new SSLException("renegotiation unsupported"), ReferenceCountedOpenSslEngine.class, "beginHandshake()");
103     private static final ResourceLeakDetector<ReferenceCountedOpenSslEngine> leakDetector =
104             ResourceLeakDetectorFactory.instance().newResourceLeakDetector(ReferenceCountedOpenSslEngine.class);
105     private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2 = 0;
106     private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3 = 1;
107     private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1 = 2;
108     private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1 = 3;
109     private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2 = 4;
110     private static final int[] OPENSSL_OP_NO_PROTOCOLS = {
111             SSL.SSL_OP_NO_SSLv2,
112             SSL.SSL_OP_NO_SSLv3,
113             SSL.SSL_OP_NO_TLSv1,
114             SSL.SSL_OP_NO_TLSv1_1,
115             SSL.SSL_OP_NO_TLSv1_2
116     };
117     /**
118      * <a href="https://www.openssl.org/docs/man1.0.2/crypto/X509_check_host.html">The flags argument is usually 0</a>.
119      */
120     private static final int DEFAULT_HOSTNAME_VALIDATION_FLAGS = 0;
121 
122     /**
123      * Depends upon tcnative ... only use if tcnative is available!
124      */
125     static final int MAX_PLAINTEXT_LENGTH = SSL_MAX_PLAINTEXT_LENGTH;
126     /**
127      * Depends upon tcnative ... only use if tcnative is available!
128      */
129     private static final int MAX_RECORD_SIZE = SSL_MAX_RECORD_LENGTH;
130 
131     private static final AtomicIntegerFieldUpdater<ReferenceCountedOpenSslEngine> DESTROYED_UPDATER =
132             AtomicIntegerFieldUpdater.newUpdater(ReferenceCountedOpenSslEngine.class, "destroyed");
133 
134     private static final String INVALID_CIPHER = "SSL_NULL_WITH_NULL_NULL";
135     private static final SSLEngineResult NEED_UNWRAP_OK = new SSLEngineResult(OK, NEED_UNWRAP, 0, 0);
136     private static final SSLEngineResult NEED_UNWRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_UNWRAP, 0, 0);
137     private static final SSLEngineResult NEED_WRAP_OK = new SSLEngineResult(OK, NEED_WRAP, 0, 0);
138     private static final SSLEngineResult NEED_WRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_WRAP, 0, 0);
139     private static final SSLEngineResult CLOSED_NOT_HANDSHAKING = new SSLEngineResult(CLOSED, NOT_HANDSHAKING, 0, 0);
140 
141     // OpenSSL state
142     private long ssl;
143     private long networkBIO;
144     private boolean certificateSet;
145 
146     private enum HandshakeState {
147         /**
148          * Not started yet.
149          */
150         NOT_STARTED,
151         /**
152          * Started via unwrap/wrap.
153          */
154         STARTED_IMPLICITLY,
155         /**
156          * Started via {@link #beginHandshake()}.
157          */
158         STARTED_EXPLICITLY,
159         /**
160          * Handshake is finished.
161          */
162         FINISHED
163     }
164 
165     private HandshakeState handshakeState = HandshakeState.NOT_STARTED;
166     private boolean receivedShutdown;
167     private volatile int destroyed;
168     private volatile String applicationProtocol;
169 
170     // Reference Counting
171     private final ResourceLeakTracker<ReferenceCountedOpenSslEngine> leak;
172     private final AbstractReferenceCounted refCnt = new AbstractReferenceCounted() {
173         @Override
174         public ReferenceCounted touch(Object hint) {
175             if (leak != null) {
176                 leak.record(hint);
177             }
178 
179             return ReferenceCountedOpenSslEngine.this;
180         }
181 
182         @Override
183         protected void deallocate() {
184             shutdown();
185             if (leak != null) {
186                 boolean closed = leak.close(ReferenceCountedOpenSslEngine.this);
187                 assert closed;
188             }
189         }
190     };
191 
192     private volatile ClientAuth clientAuth = ClientAuth.NONE;
193 
194     // Updated once a new handshake is started and so the SSLSession reused.
195     private volatile long lastAccessed = -1;
196 
197     private String endPointIdentificationAlgorithm;
198     // Store as object as AlgorithmConstraints only exists since java 7.
199     private Object algorithmConstraints;
200     private List<String> sniHostNames;
201 
202     // Mark as volatile as accessed by checkSniHostnameMatch(...) and also not specify the SNIMatcher type to allow us
203     // using it with java7.
204     private volatile Collection<?> matchers;
205 
206     // SSL Engine status variables
207     private boolean isInboundDone;
208     private boolean outboundClosed;
209 
210     final boolean jdkCompatibilityMode;
211     private final boolean clientMode;
212     final ByteBufAllocator alloc;
213     private final OpenSslEngineMap engineMap;
214     private final OpenSslApplicationProtocolNegotiator apn;
215     private final OpenSslSession session;
216     private final Certificate[] localCerts;
217     private final ByteBuffer[] singleSrcBuffer = new ByteBuffer[1];
218     private final ByteBuffer[] singleDstBuffer = new ByteBuffer[1];
219     private final OpenSslKeyMaterialManager keyMaterialManager;
220     private final boolean enableOcsp;
221     private int maxWrapOverhead;
222     private int maxWrapBufferSize;
223 
224     // This is package-private as we set it from OpenSslContext if an exception is thrown during
225     // the verification step.
226     SSLHandshakeException handshakeException;
227 
228     /**
229      * Create a new instance.
230      * @param context Reference count release responsibility is not transferred! The callee still owns this object.
231      * @param alloc The allocator to use.
232      * @param peerHost The peer host name.
233      * @param peerPort The peer port.
234      * @param jdkCompatibilityMode {@code true} to behave like described in
235      *                             https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html.
236      *                             {@code false} allows for partial and/or multiple packets to be process in a single
237      *                             wrap or unwrap call.
238      * @param leakDetection {@code true} to enable leak detection of this object.
239      */
240     ReferenceCountedOpenSslEngine(ReferenceCountedOpenSslContext context, ByteBufAllocator alloc, String peerHost,
241                                   int peerPort, boolean jdkCompatibilityMode, boolean leakDetection) {
242         super(peerHost, peerPort);
243         OpenSsl.ensureAvailability();
244         this.alloc = checkNotNull(alloc, "alloc");
245         apn = (OpenSslApplicationProtocolNegotiator) context.applicationProtocolNegotiator();
246         session = new OpenSslSession(context.sessionContext());
247         clientMode = context.isClient();
248         engineMap = context.engineMap;
249         localCerts = context.keyCertChain;
250         keyMaterialManager = context.keyMaterialManager();
251         enableOcsp = context.enableOcsp;
252         this.jdkCompatibilityMode = jdkCompatibilityMode;
253         Lock readerLock = context.ctxLock.readLock();
254         readerLock.lock();
255         final long finalSsl;
256         try {
257             finalSsl = SSL.newSSL(context.ctx, !context.isClient());
258         } finally {
259             readerLock.unlock();
260         }
261         synchronized (this) {
262             ssl = finalSsl;
263             try {
264                 networkBIO = SSL.bioNewByteBuffer(ssl, context.getBioNonApplicationBufferSize());
265 
266                 // Set the client auth mode, this needs to be done via setClientAuth(...) method so we actually call the
267                 // needed JNI methods.
268                 setClientAuth(clientMode ? ClientAuth.NONE : context.clientAuth);
269 
270                 if (context.protocols != null) {
271                     setEnabledProtocols(context.protocols);
272                 }
273 
274                 // Use SNI if peerHost was specified
275                 // See https://github.com/netty/netty/issues/4746
276                 if (clientMode && peerHost != null) {
277                     SSL.setTlsExtHostName(ssl, peerHost);
278                 }
279 
280                 if (enableOcsp) {
281                     SSL.enableOcsp(ssl);
282                 }
283 
284                 if (!jdkCompatibilityMode) {
285                     SSL.setMode(ssl, SSL.getMode(ssl) | SSL.SSL_MODE_ENABLE_PARTIAL_WRITE);
286                 }
287 
288                 // setMode may impact the overhead.
289                 calculateMaxWrapOverhead();
290             } catch (Throwable cause) {
291                 SSL.freeSSL(ssl);
292                 PlatformDependent.throwException(cause);
293             }
294         }
295 
296         // Only create the leak after everything else was executed and so ensure we don't produce a false-positive for
297         // the ResourceLeakDetector.
298         leak = leakDetection ? leakDetector.track(this) : null;
299     }
300 
301     /**
302      * Sets the OCSP response.
303      */
304     @UnstableApi
305     public void setOcspResponse(byte[] response) {
306         if (!enableOcsp) {
307             throw new IllegalStateException("OCSP stapling is not enabled");
308         }
309 
310         if (clientMode) {
311             throw new IllegalStateException("Not a server SSLEngine");
312         }
313 
314         synchronized (this) {
315             SSL.setOcspResponse(ssl, response);
316         }
317     }
318 
319     /**
320      * Returns the OCSP response or {@code null} if the server didn't provide a stapled OCSP response.
321      */
322     @UnstableApi
323     public byte[] getOcspResponse() {
324         if (!enableOcsp) {
325             throw new IllegalStateException("OCSP stapling is not enabled");
326         }
327 
328         if (!clientMode) {
329             throw new IllegalStateException("Not a client SSLEngine");
330         }
331 
332         synchronized (this) {
333             return SSL.getOcspResponse(ssl);
334         }
335     }
336 
337     @Override
338     public final int refCnt() {
339         return refCnt.refCnt();
340     }
341 
342     @Override
343     public final ReferenceCounted retain() {
344         refCnt.retain();
345         return this;
346     }
347 
348     @Override
349     public final ReferenceCounted retain(int increment) {
350         refCnt.retain(increment);
351         return this;
352     }
353 
354     @Override
355     public final ReferenceCounted touch() {
356         refCnt.touch();
357         return this;
358     }
359 
360     @Override
361     public final ReferenceCounted touch(Object hint) {
362         refCnt.touch(hint);
363         return this;
364     }
365 
366     @Override
367     public final boolean release() {
368         return refCnt.release();
369     }
370 
371     @Override
372     public final boolean release(int decrement) {
373         return refCnt.release(decrement);
374     }
375 
376     @Override
377     public final synchronized SSLSession getHandshakeSession() {
378         // Javadocs state return value should be:
379         // null if this instance is not currently handshaking, or if the current handshake has not
380         // progressed far enough to create a basic SSLSession. Otherwise, this method returns the
381         // SSLSession currently being negotiated.
382         switch(handshakeState) {
383             case NOT_STARTED:
384             case FINISHED:
385                 return null;
386             default:
387                 return session;
388         }
389     }
390 
391     /**
392      * Returns the pointer to the {@code SSL} object for this {@link ReferenceCountedOpenSslEngine}.
393      * Be aware that it is freed as soon as the {@link #release()} or {@link #shutdown()} methods are called.
394      * At this point {@code 0} will be returned.
395      */
396     public final synchronized long sslPointer() {
397         return ssl;
398     }
399 
400     /**
401      * Destroys this engine.
402      */
403     public final synchronized void shutdown() {
404         if (DESTROYED_UPDATER.compareAndSet(this, 0, 1)) {
405             engineMap.remove(ssl);
406             SSL.freeSSL(ssl);
407             ssl = networkBIO = 0;
408 
409             isInboundDone = outboundClosed = true;
410         }
411 
412         // On shutdown clear all errors
413         SSL.clearError();
414     }
415 
416     /**
417      * Write plaintext data to the OpenSSL internal BIO
418      *
419      * Calling this function with src.remaining == 0 is undefined.
420      */
421     private int writePlaintextData(final ByteBuffer src, int len) {
422         final int pos = src.position();
423         final int limit = src.limit();
424         final int sslWrote;
425 
426         if (src.isDirect()) {
427             sslWrote = SSL.writeToSSL(ssl, bufferAddress(src) + pos, len);
428             if (sslWrote > 0) {
429                 src.position(pos + sslWrote);
430             }
431         } else {
432             ByteBuf buf = alloc.directBuffer(len);
433             try {
434                 src.limit(pos + len);
435 
436                 buf.setBytes(0, src);
437                 src.limit(limit);
438 
439                 sslWrote = SSL.writeToSSL(ssl, memoryAddress(buf), len);
440                 if (sslWrote > 0) {
441                     src.position(pos + sslWrote);
442                 } else {
443                     src.position(pos);
444                 }
445             } finally {
446                 buf.release();
447             }
448         }
449         return sslWrote;
450     }
451 
452     /**
453      * Write encrypted data to the OpenSSL network BIO.
454      */
455     private ByteBuf writeEncryptedData(final ByteBuffer src, int len) {
456         final int pos = src.position();
457         if (src.isDirect()) {
458             SSL.bioSetByteBuffer(networkBIO, bufferAddress(src) + pos, len, false);
459         } else {
460             final ByteBuf buf = alloc.directBuffer(len);
461             try {
462                 final int limit = src.limit();
463                 src.limit(pos + len);
464                 buf.writeBytes(src);
465                 // Restore the original position and limit because we don't want to consume from `src`.
466                 src.position(pos);
467                 src.limit(limit);
468 
469                 SSL.bioSetByteBuffer(networkBIO, memoryAddress(buf), len, false);
470                 return buf;
471             } catch (Throwable cause) {
472                 buf.release();
473                 PlatformDependent.throwException(cause);
474             }
475         }
476         return null;
477     }
478 
479     /**
480      * Read plaintext data from the OpenSSL internal BIO
481      */
482     private int readPlaintextData(final ByteBuffer dst) {
483         final int sslRead;
484         final int pos = dst.position();
485         if (dst.isDirect()) {
486             sslRead = SSL.readFromSSL(ssl, bufferAddress(dst) + pos, dst.limit() - pos);
487             if (sslRead > 0) {
488                 dst.position(pos + sslRead);
489             }
490         } else {
491             final int limit = dst.limit();
492             final int len = min(maxEncryptedPacketLength0(), limit - pos);
493             final ByteBuf buf = alloc.directBuffer(len);
494             try {
495                 sslRead = SSL.readFromSSL(ssl, memoryAddress(buf), len);
496                 if (sslRead > 0) {
497                     dst.limit(pos + sslRead);
498                     buf.getBytes(buf.readerIndex(), dst);
499                     dst.limit(limit);
500                 }
501             } finally {
502                 buf.release();
503             }
504         }
505 
506         return sslRead;
507     }
508 
509     /**
510      * Visible only for testing!
511      */
512     final synchronized int maxWrapOverhead() {
513         return maxWrapOverhead;
514     }
515 
516     /**
517      * Visible only for testing!
518      */
519     final synchronized int maxEncryptedPacketLength() {
520         return maxEncryptedPacketLength0();
521     }
522 
523     /**
524      * This method is intentionally not synchronized, only use if you know you are in the EventLoop
525      * thread and visibility on {@link #maxWrapOverhead} is achieved via other synchronized blocks.
526      */
527     final int maxEncryptedPacketLength0() {
528         return maxWrapOverhead + MAX_PLAINTEXT_LENGTH;
529     }
530 
531     /**
532      * This method is intentionally not synchronized, only use if you know you are in the EventLoop
533      * thread and visibility on {@link #maxWrapBufferSize} and {@link #maxWrapOverhead} is achieved
534      * via other synchronized blocks.
535      */
536     final int calculateMaxLengthForWrap(int plaintextLength, int numComponents) {
537         return (int) min(maxWrapBufferSize, plaintextLength + (long) maxWrapOverhead * numComponents);
538     }
539 
540     final synchronized int sslPending() {
541         return sslPending0();
542     }
543 
544     /**
545      * It is assumed this method is called in a synchronized block (or the constructor)!
546      */
547     private void calculateMaxWrapOverhead() {
548         maxWrapOverhead = SSL.getMaxWrapOverhead(ssl);
549 
550         // maxWrapBufferSize must be set after maxWrapOverhead because there is a dependency on this value.
551         // If jdkCompatibility mode is off we allow enough space to encrypt 16 buffers at a time. This could be
552         // configurable in the future if necessary.
553         maxWrapBufferSize = jdkCompatibilityMode ? maxEncryptedPacketLength0() : maxEncryptedPacketLength0() << 4;
554     }
555 
556     private int sslPending0() {
557         // OpenSSL has a limitation where if you call SSL_pending before the handshake is complete OpenSSL will throw a
558         // "called a function you should not call" error. Using the TLS_method instead of SSLv23_method may solve this
559         // issue but this API is only available in 1.1.0+ [1].
560         // [1] https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_new.html
561         return handshakeState != HandshakeState.FINISHED ? 0 : SSL.sslPending(ssl);
562     }
563 
564     private boolean isBytesAvailableEnoughForWrap(int bytesAvailable, int plaintextLength, int numComponents) {
565         return bytesAvailable - (long) maxWrapOverhead * numComponents >= plaintextLength;
566     }
567 
568     @Override
569     public final SSLEngineResult wrap(
570             final ByteBuffer[] srcs, int offset, final int length, final ByteBuffer dst) throws SSLException {
571         // Throw required runtime exceptions
572         if (srcs == null) {
573             throw new IllegalArgumentException("srcs is null");
574         }
575         if (dst == null) {
576             throw new IllegalArgumentException("dst is null");
577         }
578 
579         if (offset >= srcs.length || offset + length > srcs.length) {
580             throw new IndexOutOfBoundsException(
581                     "offset: " + offset + ", length: " + length +
582                             " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
583         }
584 
585         if (dst.isReadOnly()) {
586             throw new ReadOnlyBufferException();
587         }
588 
589         synchronized (this) {
590             if (isOutboundDone()) {
591                 // All drained in the outbound buffer
592                 return isInboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_UNWRAP_CLOSED;
593             }
594 
595             int bytesProduced = 0;
596             ByteBuf bioReadCopyBuf = null;
597             try {
598                 // Setup the BIO buffer so that we directly write the encryption results into dst.
599                 if (dst.isDirect()) {
600                     SSL.bioSetByteBuffer(networkBIO, bufferAddress(dst) + dst.position(), dst.remaining(),
601                             true);
602                 } else {
603                     bioReadCopyBuf = alloc.directBuffer(dst.remaining());
604                     SSL.bioSetByteBuffer(networkBIO, memoryAddress(bioReadCopyBuf), bioReadCopyBuf.writableBytes(),
605                             true);
606                 }
607 
608                 int bioLengthBefore = SSL.bioLengthByteBuffer(networkBIO);
609 
610                 // Explicitly use outboundClosed as we want to drain any bytes that are still present.
611                 if (outboundClosed) {
612                     // If the outbound was closed we want to ensure we can produce the alert to the destination buffer.
613                     // This is true even if we not using jdkCompatibilityMode.
614                     //
615                     // We use a plaintextLength of 2 as we at least want to have an alert fit into it.
616                     // https://tools.ietf.org/html/rfc5246#section-7.2
617                     if (!isBytesAvailableEnoughForWrap(dst.remaining(), 2, 1)) {
618                         return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
619                     }
620 
621                     // There is something left to drain.
622                     // See https://github.com/netty/netty/issues/6260
623                     bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
624                     if (bytesProduced <= 0) {
625                         return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, 0);
626                     }
627                     // It is possible when the outbound was closed there was not enough room in the non-application
628                     // buffers to hold the close_notify. We should keep trying to close until we consume all the data
629                     // OpenSSL can give us.
630                     if (!doSSLShutdown()) {
631                         return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, bytesProduced);
632                     }
633                     bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
634                     return newResultMayFinishHandshake(NEED_WRAP, 0, bytesProduced);
635                 }
636 
637                 // Flush any data that may be implicitly generated by OpenSSL (handshake, close, etc..).
638                 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
639                 // Prepare OpenSSL to work in server mode and receive handshake
640                 if (handshakeState != HandshakeState.FINISHED) {
641                     if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
642                         // Update accepted so we know we triggered the handshake via wrap
643                         handshakeState = HandshakeState.STARTED_IMPLICITLY;
644                     }
645 
646                     // Flush any data that may have been written implicitly during the handshake by OpenSSL.
647                     bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
648 
649                     if (bytesProduced > 0 && handshakeException != null) {
650                         // TODO(scott): It is possible that when the handshake failed there was not enough room in the
651                         // non-application buffers to hold the alert. We should get all the data before progressing on.
652                         // However I'm not aware of a way to do this with the OpenSSL APIs.
653                         // See https://github.com/netty/netty/issues/6385.
654 
655                         // We produced / consumed some data during the handshake, signal back to the caller.
656                         // If there is a handshake exception and we have produced data, we should send the data before
657                         // we allow handshake() to throw the handshake exception.
658                         return newResult(NEED_WRAP, 0, bytesProduced);
659                     }
660 
661                     status = handshake();
662 
663                     // Handshake may have generated more data, for example if the internal SSL buffer is small
664                     // we may have freed up space by flushing above.
665                     bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
666 
667                     if (bytesProduced > 0) {
668                         // If we have filled up the dst buffer and we have not finished the handshake we should try to
669                         // wrap again. Otherwise we should only try to wrap again if there is still data pending in
670                         // SSL buffers.
671                         return newResult(mayFinishHandshake(status != FINISHED ?
672                                          bytesProduced == bioLengthBefore ? NEED_WRAP :
673                                          getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED),
674                                          0, bytesProduced);
675                     }
676 
677                     if (status == NEED_UNWRAP) {
678                         // Signal if the outbound is done or not.
679                         return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
680                     }
681 
682                     // Explicit use outboundClosed and not outboundClosed() as we want to drain any bytes that are
683                     // still present.
684                     if (outboundClosed) {
685                         bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
686                         return newResultMayFinishHandshake(status, 0, bytesProduced);
687                     }
688                 }
689 
690                 final int endOffset = offset + length;
691                 if (jdkCompatibilityMode) {
692                     int srcsLen = 0;
693                     for (int i = offset; i < endOffset; ++i) {
694                         final ByteBuffer src = srcs[i];
695                         if (src == null) {
696                             throw new IllegalArgumentException("srcs[" + i + "] is null");
697                         }
698                         if (srcsLen == MAX_PLAINTEXT_LENGTH) {
699                             continue;
700                         }
701 
702                         srcsLen += src.remaining();
703                         if (srcsLen > MAX_PLAINTEXT_LENGTH || srcsLen < 0) {
704                             // If srcLen > MAX_PLAINTEXT_LENGTH or secLen < 0 just set it to MAX_PLAINTEXT_LENGTH.
705                             // This also help us to guard against overflow.
706                             // We not break out here as we still need to check for null entries in srcs[].
707                             srcsLen = MAX_PLAINTEXT_LENGTH;
708                         }
709                     }
710 
711                     // jdkCompatibilityMode will only produce a single TLS packet, and we don't aggregate src buffers,
712                     // so we always fix the number of buffers to 1 when checking if the dst buffer is large enough.
713                     if (!isBytesAvailableEnoughForWrap(dst.remaining(), srcsLen, 1)) {
714                         return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
715                     }
716                 }
717 
718                 // There was no pending data in the network BIO -- encrypt any application data
719                 int bytesConsumed = 0;
720                 // Flush any data that may have been written implicitly by OpenSSL in case a shutdown/alert occurs.
721                 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
722                 for (; offset < endOffset; ++offset) {
723                     final ByteBuffer src = srcs[offset];
724                     final int remaining = src.remaining();
725                     if (remaining == 0) {
726                         continue;
727                     }
728 
729                     final int bytesWritten;
730                     if (jdkCompatibilityMode) {
731                         // Write plaintext application data to the SSL engine. We don't have to worry about checking
732                         // if there is enough space if jdkCompatibilityMode because we only wrap at most
733                         // MAX_PLAINTEXT_LENGTH and we loop over the input before hand and check if there is space.
734                         bytesWritten = writePlaintextData(src, min(remaining, MAX_PLAINTEXT_LENGTH - bytesConsumed));
735                     } else {
736                         // OpenSSL's SSL_write keeps state between calls. We should make sure the amount we attempt to
737                         // write is guaranteed to succeed so we don't have to worry about keeping state consistent
738                         // between calls.
739                         final int availableCapacityForWrap = dst.remaining() - bytesProduced - maxWrapOverhead;
740                         if (availableCapacityForWrap <= 0) {
741                             return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed,
742                                     bytesProduced);
743                         }
744                         bytesWritten = writePlaintextData(src, min(remaining, availableCapacityForWrap));
745                     }
746 
747                     if (bytesWritten > 0) {
748                         bytesConsumed += bytesWritten;
749 
750                         // Determine how much encrypted data was generated:
751                         final int pendingNow = SSL.bioLengthByteBuffer(networkBIO);
752                         bytesProduced += bioLengthBefore - pendingNow;
753                         bioLengthBefore = pendingNow;
754 
755                         if (jdkCompatibilityMode || bytesProduced == dst.remaining()) {
756                             return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
757                         }
758                     } else {
759                         int sslError = SSL.getError(ssl, bytesWritten);
760                         if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
761                             // This means the connection was shutdown correctly, close inbound and outbound
762                             if (!receivedShutdown) {
763                                 closeAll();
764 
765                                 bytesProduced += bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
766 
767                                 // If we have filled up the dst buffer and we have not finished the handshake we should
768                                 // try to wrap again. Otherwise we should only try to wrap again if there is still data
769                                 // pending in SSL buffers.
770                                 SSLEngineResult.HandshakeStatus hs = mayFinishHandshake(
771                                         status != FINISHED ? bytesProduced == dst.remaining() ? NEED_WRAP
772                                                 : getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO))
773                                                 : FINISHED);
774                                 return newResult(hs, bytesConsumed, bytesProduced);
775                             }
776 
777                             return newResult(NOT_HANDSHAKING, bytesConsumed, bytesProduced);
778                         } else if (sslError == SSL.SSL_ERROR_WANT_READ) {
779                             // If there is no pending data to read from BIO we should go back to event loop and try
780                             // to read more data [1]. It is also possible that event loop will detect the socket has
781                             // been closed. [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
782                             return newResult(NEED_UNWRAP, bytesConsumed, bytesProduced);
783                         } else if (sslError == SSL.SSL_ERROR_WANT_WRITE) {
784                             // SSL_ERROR_WANT_WRITE typically means that the underlying transport is not writable
785                             // and we should set the "want write" flag on the selector and try again when the
786                             // underlying transport is writable [1]. However we are not directly writing to the
787                             // underlying transport and instead writing to a BIO buffer. The OpenSsl documentation
788                             // says we should do the following [1]:
789                             //
790                             // "When using a buffering BIO, like a BIO pair, data must be written into or retrieved
791                             // out of the BIO before being able to continue."
792                             //
793                             // In practice this means the destination buffer doesn't have enough space for OpenSSL
794                             // to write encrypted data to. This is an OVERFLOW condition.
795                             // [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
796                             return newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced);
797                         } else {
798                             // Everything else is considered as error
799                             throw shutdownWithError("SSL_write");
800                         }
801                     }
802                 }
803                 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
804             } finally {
805                 SSL.bioClearByteBuffer(networkBIO);
806                 if (bioReadCopyBuf == null) {
807                     dst.position(dst.position() + bytesProduced);
808                 } else {
809                     assert bioReadCopyBuf.readableBytes() <= dst.remaining() : "The destination buffer " + dst +
810                             " didn't have enough remaining space to hold the encrypted content in " + bioReadCopyBuf;
811                     dst.put(bioReadCopyBuf.internalNioBuffer(bioReadCopyBuf.readerIndex(), bytesProduced));
812                     bioReadCopyBuf.release();
813                 }
814             }
815         }
816     }
817 
818     private SSLEngineResult newResult(SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) {
819         return newResult(OK, hs, bytesConsumed, bytesProduced);
820     }
821 
822     private SSLEngineResult newResult(SSLEngineResult.Status status, SSLEngineResult.HandshakeStatus hs,
823                                       int bytesConsumed, int bytesProduced) {
824         // If isOutboundDone, then the data from the network BIO
825         // was the close_notify message and all was consumed we are not required to wait
826         // for the receipt the peer's close_notify message -- shutdown.
827         if (isOutboundDone()) {
828             if (isInboundDone()) {
829                 // If the inbound was done as well, we need to ensure we return NOT_HANDSHAKING to signal we are done.
830                 hs = NOT_HANDSHAKING;
831 
832                 // As the inbound and the outbound is done we can shutdown the engine now.
833                 shutdown();
834             }
835             return new SSLEngineResult(CLOSED, hs, bytesConsumed, bytesProduced);
836         }
837         return new SSLEngineResult(status, hs, bytesConsumed, bytesProduced);
838     }
839 
840     private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.HandshakeStatus hs,
841                                                         int bytesConsumed, int bytesProduced) throws SSLException {
842         return newResult(mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED),
843                          bytesConsumed, bytesProduced);
844     }
845 
846     private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status,
847                                                         SSLEngineResult.HandshakeStatus hs,
848                                                         int bytesConsumed, int bytesProduced) throws SSLException {
849         return newResult(status, mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED),
850                          bytesConsumed, bytesProduced);
851     }
852 
853     /**
854      * Log the error, shutdown the engine and throw an exception.
855      */
856     private SSLException shutdownWithError(String operations) {
857         String err = SSL.getLastError();
858         return shutdownWithError(operations, err);
859     }
860 
861     private SSLException shutdownWithError(String operation, String err) {
862         if (logger.isDebugEnabled()) {
863             logger.debug("{} failed: OpenSSL error: {}", operation, err);
864         }
865 
866         // There was an internal error -- shutdown
867         shutdown();
868         if (handshakeState == HandshakeState.FINISHED) {
869             return new SSLException(err);
870         }
871         return new SSLHandshakeException(err);
872     }
873 
874     public final SSLEngineResult unwrap(
875             final ByteBuffer[] srcs, int srcsOffset, final int srcsLength,
876             final ByteBuffer[] dsts, int dstsOffset, final int dstsLength) throws SSLException {
877 
878         // Throw required runtime exceptions
879         if (srcs == null) {
880             throw new NullPointerException("srcs");
881         }
882         if (srcsOffset >= srcs.length
883                 || srcsOffset + srcsLength > srcs.length) {
884             throw new IndexOutOfBoundsException(
885                     "offset: " + srcsOffset + ", length: " + srcsLength +
886                             " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
887         }
888         if (dsts == null) {
889             throw new IllegalArgumentException("dsts is null");
890         }
891         if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) {
892             throw new IndexOutOfBoundsException(
893                     "offset: " + dstsOffset + ", length: " + dstsLength +
894                             " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))");
895         }
896         long capacity = 0;
897         final int dstsEndOffset = dstsOffset + dstsLength;
898         for (int i = dstsOffset; i < dstsEndOffset; i ++) {
899             ByteBuffer dst = dsts[i];
900             if (dst == null) {
901                 throw new IllegalArgumentException("dsts[" + i + "] is null");
902             }
903             if (dst.isReadOnly()) {
904                 throw new ReadOnlyBufferException();
905             }
906             capacity += dst.remaining();
907         }
908 
909         final int srcsEndOffset = srcsOffset + srcsLength;
910         long len = 0;
911         for (int i = srcsOffset; i < srcsEndOffset; i++) {
912             ByteBuffer src = srcs[i];
913             if (src == null) {
914                 throw new IllegalArgumentException("srcs[" + i + "] is null");
915             }
916             len += src.remaining();
917         }
918 
919         synchronized (this) {
920             if (isInboundDone()) {
921                 return isOutboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_WRAP_CLOSED;
922             }
923 
924             SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
925             // Prepare OpenSSL to work in server mode and receive handshake
926             if (handshakeState != HandshakeState.FINISHED) {
927                 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
928                     // Update accepted so we know we triggered the handshake via wrap
929                     handshakeState = HandshakeState.STARTED_IMPLICITLY;
930                 }
931 
932                 status = handshake();
933                 if (status == NEED_WRAP) {
934                     return NEED_WRAP_OK;
935                 }
936                 // Check if the inbound is considered to be closed if so let us try to wrap again.
937                 if (isInboundDone) {
938                     return NEED_WRAP_CLOSED;
939                 }
940             }
941 
942             int sslPending = sslPending0();
943             int packetLength;
944             // The JDK implies that only a single SSL packet should be processed per unwrap call [1]. If we are in
945             // JDK compatibility mode then we should honor this, but if not we just wrap as much as possible. If there
946             // are multiple records or partial records this may reduce thrashing events through the pipeline.
947             // [1] https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html
948             if (jdkCompatibilityMode) {
949                 if (len < SSL_RECORD_HEADER_LENGTH) {
950                     return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
951                 }
952 
953                 packetLength = SslUtils.getEncryptedPacketLength(srcs, srcsOffset);
954                 if (packetLength == SslUtils.NOT_ENCRYPTED) {
955                     throw new NotSslRecordException("not an SSL/TLS record");
956                 }
957 
958                 final int packetLengthDataOnly = packetLength - SSL_RECORD_HEADER_LENGTH;
959                 if (packetLengthDataOnly > capacity) {
960                     // Not enough space in the destination buffer so signal the caller that the buffer needs to be
961                     // increased.
962                     if (packetLengthDataOnly > MAX_RECORD_SIZE) {
963                         // The packet length MUST NOT exceed 2^14 [1]. However we do accommodate more data to support
964                         // legacy use cases which may violate this condition (e.g. OpenJDK's SslEngineImpl). If the max
965                         // length is exceeded we fail fast here to avoid an infinite loop due to the fact that we
966                         // won't allocate a buffer large enough.
967                         // [1] https://tools.ietf.org/html/rfc5246#section-6.2.1
968                         throw new SSLException("Illegal packet length: " + packetLengthDataOnly + " > " +
969                                                 session.getApplicationBufferSize());
970                     } else {
971                         session.tryExpandApplicationBufferSize(packetLengthDataOnly);
972                     }
973                     return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
974                 }
975 
976                 if (len < packetLength) {
977                     // We either don't have enough data to read the packet length or not enough for reading the whole
978                     // packet.
979                     return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
980                 }
981             } else if (len == 0 && sslPending <= 0) {
982                 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
983             } else if (capacity == 0) {
984                 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
985             } else {
986                 packetLength = (int) min(MAX_VALUE, len);
987             }
988 
989             // This must always be the case when we reached here as if not we returned BUFFER_UNDERFLOW.
990             assert srcsOffset < srcsEndOffset;
991 
992             // This must always be the case if we reached here.
993             assert capacity > 0;
994 
995             // Number of produced bytes
996             int bytesProduced = 0;
997             int bytesConsumed = 0;
998             try {
999                 srcLoop:
1000                 for (;;) {
1001                     ByteBuffer src = srcs[srcsOffset];
1002                     int remaining = src.remaining();
1003                     final ByteBuf bioWriteCopyBuf;
1004                     int pendingEncryptedBytes;
1005                     if (remaining == 0) {
1006                         if (sslPending <= 0) {
1007                             // We must skip empty buffers as BIO_write will return 0 if asked to write something
1008                             // with length 0.
1009                             if (++srcsOffset >= srcsEndOffset) {
1010                                 break;
1011                             }
1012                             continue;
1013                         } else {
1014                             bioWriteCopyBuf = null;
1015                             pendingEncryptedBytes = SSL.bioLengthByteBuffer(networkBIO);
1016                         }
1017                     } else {
1018                         // Write more encrypted data into the BIO. Ensure we only read one packet at a time as
1019                         // stated in the SSLEngine javadocs.
1020                         pendingEncryptedBytes = min(packetLength, remaining);
1021                         bioWriteCopyBuf = writeEncryptedData(src, pendingEncryptedBytes);
1022                     }
1023                     try {
1024                         for (;;) {
1025                             ByteBuffer dst = dsts[dstsOffset];
1026                             if (!dst.hasRemaining()) {
1027                                 // No space left in the destination buffer, skip it.
1028                                 if (++dstsOffset >= dstsEndOffset) {
1029                                     break srcLoop;
1030                                 }
1031                                 continue;
1032                             }
1033 
1034                             int bytesRead = readPlaintextData(dst);
1035                             // We are directly using the ByteBuffer memory for the write, and so we only know what has
1036                             // been consumed after we let SSL decrypt the data. At this point we should update the
1037                             // number of bytes consumed, update the ByteBuffer position, and release temp ByteBuf.
1038                             int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO);
1039                             bytesConsumed += localBytesConsumed;
1040                             packetLength -= localBytesConsumed;
1041                             pendingEncryptedBytes -= localBytesConsumed;
1042                             src.position(src.position() + localBytesConsumed);
1043 
1044                             if (bytesRead > 0) {
1045                                 bytesProduced += bytesRead;
1046 
1047                                 if (!dst.hasRemaining()) {
1048                                     sslPending = sslPending0();
1049                                     // Move to the next dst buffer as this one is full.
1050                                     if (++dstsOffset >= dstsEndOffset) {
1051                                         return sslPending > 0 ?
1052                                                 newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced) :
1053                                                 newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1054                                                                             bytesConsumed, bytesProduced);
1055                                     }
1056                                 } else if (packetLength == 0 || jdkCompatibilityMode) {
1057                                     // We either consumed all data or we are in jdkCompatibilityMode and have consumed
1058                                     // a single TLS packet and should stop consuming until this method is called again.
1059                                     break srcLoop;
1060                                 }
1061                             } else {
1062                                 int sslError = SSL.getError(ssl, bytesRead);
1063                                 if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1064                                     // break to the outer loop as we want to read more data which means we need to
1065                                     // write more to the BIO.
1066                                     break;
1067                                 } else if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
1068                                     // This means the connection was shutdown correctly, close inbound and outbound
1069                                     if (!receivedShutdown) {
1070                                         closeAll();
1071                                     }
1072                                     return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1073                                                                        bytesConsumed, bytesProduced);
1074                                 } else {
1075                                     return sslReadErrorResult(SSL.getLastErrorNumber(), bytesConsumed,
1076                                                               bytesProduced);
1077                                 }
1078                             }
1079                         }
1080 
1081                         if (++srcsOffset >= srcsEndOffset) {
1082                             break;
1083                         }
1084                     } finally {
1085                         if (bioWriteCopyBuf != null) {
1086                             bioWriteCopyBuf.release();
1087                         }
1088                     }
1089                 }
1090             } finally {
1091                 SSL.bioClearByteBuffer(networkBIO);
1092                 rejectRemoteInitiatedRenegotiation();
1093             }
1094 
1095             // Check to see if we received a close_notify message from the peer.
1096             if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
1097                 closeAll();
1098             }
1099 
1100             return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced);
1101         }
1102     }
1103 
1104     private SSLEngineResult sslReadErrorResult(int err, int bytesConsumed, int bytesProduced) throws SSLException {
1105         // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the
1106         // BIO first or can just shutdown and throw it now.
1107         // This is needed so we ensure close_notify etc is correctly send to the remote peer.
1108         // See https://github.com/netty/netty/issues/3900
1109         if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1110             if (handshakeException == null && handshakeState != HandshakeState.FINISHED) {
1111                 // we seems to have data left that needs to be transfered and so the user needs
1112                 // call wrap(...). Store the error so we can pick it up later.
1113                 handshakeException = new SSLHandshakeException(SSL.getErrorString(err));
1114             }
1115             // We need to clear all errors so we not pick up anything that was left on the stack on the next
1116             // operation. Note that shutdownWithError(...) will cleanup the stack as well so its only needed here.
1117             SSL.clearError();
1118             return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced);
1119         }
1120         throw shutdownWithError("SSL_read", SSL.getErrorString(err));
1121     }
1122 
1123     private void closeAll() throws SSLException {
1124         receivedShutdown = true;
1125         closeOutbound();
1126         closeInbound();
1127     }
1128 
1129     private void rejectRemoteInitiatedRenegotiation() throws SSLHandshakeException {
1130         // As rejectRemoteInitiatedRenegotiation() is called in a finally block we also need to check if we shutdown
1131         // the engine before as otherwise SSL.getHandshakeCount(ssl) will throw an NPE if the passed in ssl is 0.
1132         // See https://github.com/netty/netty/issues/7353
1133         if (!isDestroyed() && SSL.getHandshakeCount(ssl) > 1) {
1134             // TODO: In future versions me may also want to send a fatal_alert to the client and so notify it
1135             // that the renegotiation failed.
1136             shutdown();
1137             throw new SSLHandshakeException("remote-initiated renegotiation not allowed");
1138         }
1139     }
1140 
1141     public final SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException {
1142         return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length);
1143     }
1144 
1145     private ByteBuffer[] singleSrcBuffer(ByteBuffer src) {
1146         singleSrcBuffer[0] = src;
1147         return singleSrcBuffer;
1148     }
1149 
1150     private void resetSingleSrcBuffer() {
1151         singleSrcBuffer[0] = null;
1152     }
1153 
1154     private ByteBuffer[] singleDstBuffer(ByteBuffer src) {
1155         singleDstBuffer[0] = src;
1156         return singleDstBuffer;
1157     }
1158 
1159     private void resetSingleDstBuffer() {
1160         singleDstBuffer[0] = null;
1161     }
1162 
1163     @Override
1164     public final synchronized SSLEngineResult unwrap(
1165             final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException {
1166         try {
1167             return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length);
1168         } finally {
1169             resetSingleSrcBuffer();
1170         }
1171     }
1172 
1173     @Override
1174     public final synchronized SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1175         try {
1176             return wrap(singleSrcBuffer(src), dst);
1177         } finally {
1178             resetSingleSrcBuffer();
1179         }
1180     }
1181 
1182     @Override
1183     public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1184         try {
1185             return unwrap(singleSrcBuffer(src), singleDstBuffer(dst));
1186         } finally {
1187             resetSingleSrcBuffer();
1188             resetSingleDstBuffer();
1189         }
1190     }
1191 
1192     @Override
1193     public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
1194         try {
1195             return unwrap(singleSrcBuffer(src), dsts);
1196         } finally {
1197             resetSingleSrcBuffer();
1198         }
1199     }
1200 
1201     @Override
1202     public final Runnable getDelegatedTask() {
1203         // Currently, we do not delegate SSL computation tasks
1204         // TODO: in the future, possibly create tasks to do encrypt / decrypt async
1205         return null;
1206     }
1207 
1208     @Override
1209     public final synchronized void closeInbound() throws SSLException {
1210         if (isInboundDone) {
1211             return;
1212         }
1213 
1214         isInboundDone = true;
1215 
1216         if (isOutboundDone()) {
1217             // Only call shutdown if there is no outbound data pending.
1218             // See https://github.com/netty/netty/issues/6167
1219             shutdown();
1220         }
1221 
1222         if (handshakeState != HandshakeState.NOT_STARTED && !receivedShutdown) {
1223             throw new SSLException(
1224                     "Inbound closed before receiving peer's close_notify: possible truncation attack?");
1225         }
1226     }
1227 
1228     @Override
1229     public final synchronized boolean isInboundDone() {
1230         return isInboundDone;
1231     }
1232 
1233     @Override
1234     public final synchronized void closeOutbound() {
1235         if (outboundClosed) {
1236             return;
1237         }
1238 
1239         outboundClosed = true;
1240 
1241         if (handshakeState != HandshakeState.NOT_STARTED && !isDestroyed()) {
1242             int mode = SSL.getShutdown(ssl);
1243             if ((mode & SSL.SSL_SENT_SHUTDOWN) != SSL.SSL_SENT_SHUTDOWN) {
1244                 doSSLShutdown();
1245             }
1246         } else {
1247             // engine closing before initial handshake
1248             shutdown();
1249         }
1250     }
1251 
1252     /**
1253      * Attempt to call {@link SSL#shutdownSSL(long)}.
1254      * @return {@code false} if the call to {@link SSL#shutdownSSL(long)} was not attempted or returned an error.
1255      */
1256     private boolean doSSLShutdown() {
1257         if (SSL.isInInit(ssl) != 0) {
1258             // Only try to call SSL_shutdown if we are not in the init state anymore.
1259             // Otherwise we will see 'error:140E0197:SSL routines:SSL_shutdown:shutdown while in init' in our logs.
1260             //
1261             // See also http://hg.nginx.org/nginx/rev/062c189fee20
1262             return false;
1263         }
1264         int err = SSL.shutdownSSL(ssl);
1265         if (err < 0) {
1266             int sslErr = SSL.getError(ssl, err);
1267             if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) {
1268                 if (logger.isDebugEnabled()) {
1269                     logger.debug("SSL_shutdown failed: OpenSSL error: {}", SSL.getLastError());
1270                 }
1271                 // There was an internal error -- shutdown
1272                 shutdown();
1273                 return false;
1274             }
1275             SSL.clearError();
1276         }
1277         return true;
1278     }
1279 
1280     @Override
1281     public final synchronized boolean isOutboundDone() {
1282         // Check if there is anything left in the outbound buffer.
1283         // We need to ensure we only call SSL.pendingWrittenBytesInBIO(...) if the engine was not destroyed yet.
1284         return outboundClosed && (networkBIO == 0 || SSL.bioLengthNonApplication(networkBIO) == 0);
1285     }
1286 
1287     @Override
1288     public final String[] getSupportedCipherSuites() {
1289         return OpenSsl.AVAILABLE_CIPHER_SUITES.toArray(new String[0]);
1290     }
1291 
1292     @Override
1293     public final String[] getEnabledCipherSuites() {
1294         final String[] enabled;
1295         synchronized (this) {
1296             if (!isDestroyed()) {
1297                 enabled = SSL.getCiphers(ssl);
1298             } else {
1299                 return EmptyArrays.EMPTY_STRINGS;
1300             }
1301         }
1302         if (enabled == null) {
1303             return EmptyArrays.EMPTY_STRINGS;
1304         } else {
1305             synchronized (this) {
1306                 for (int i = 0; i < enabled.length; i++) {
1307                     String mapped = toJavaCipherSuite(enabled[i]);
1308                     if (mapped != null) {
1309                         enabled[i] = mapped;
1310                     }
1311                 }
1312             }
1313             return enabled;
1314         }
1315     }
1316 
1317     @Override
1318     public final void setEnabledCipherSuites(String[] cipherSuites) {
1319         checkNotNull(cipherSuites, "cipherSuites");
1320 
1321         final StringBuilder buf = new StringBuilder();
1322         for (String c: cipherSuites) {
1323             if (c == null) {
1324                 break;
1325             }
1326 
1327             String converted = CipherSuiteConverter.toOpenSsl(c);
1328             if (converted == null) {
1329                 converted = c;
1330             }
1331 
1332             if (!OpenSsl.isCipherSuiteAvailable(converted)) {
1333                 throw new IllegalArgumentException("unsupported cipher suite: " + c + '(' + converted + ')');
1334             }
1335 
1336             buf.append(converted);
1337             buf.append(':');
1338         }
1339 
1340         if (buf.length() == 0) {
1341             throw new IllegalArgumentException("empty cipher suites");
1342         }
1343         buf.setLength(buf.length() - 1);
1344 
1345         final String cipherSuiteSpec = buf.toString();
1346 
1347         synchronized (this) {
1348             if (!isDestroyed()) {
1349                 try {
1350                     SSL.setCipherSuites(ssl, cipherSuiteSpec);
1351                 } catch (Exception e) {
1352                     throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e);
1353                 }
1354             } else {
1355                 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec);
1356             }
1357         }
1358     }
1359 
1360     @Override
1361     public final String[] getSupportedProtocols() {
1362         return OpenSsl.SUPPORTED_PROTOCOLS_SET.toArray(new String[0]);
1363     }
1364 
1365     @Override
1366     public final String[] getEnabledProtocols() {
1367         List<String> enabled = new ArrayList<String>(6);
1368         // Seems like there is no way to explicit disable SSLv2Hello in openssl so it is always enabled
1369         enabled.add(PROTOCOL_SSL_V2_HELLO);
1370 
1371         int opts;
1372         synchronized (this) {
1373             if (!isDestroyed()) {
1374                 opts = SSL.getOptions(ssl);
1375             } else {
1376                 return enabled.toArray(new String[0]);
1377             }
1378         }
1379         if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1, PROTOCOL_TLS_V1)) {
1380             enabled.add(PROTOCOL_TLS_V1);
1381         }
1382         if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_1, PROTOCOL_TLS_V1_1)) {
1383             enabled.add(PROTOCOL_TLS_V1_1);
1384         }
1385         if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_2, PROTOCOL_TLS_V1_2)) {
1386             enabled.add(PROTOCOL_TLS_V1_2);
1387         }
1388         if (isProtocolEnabled(opts, SSL.SSL_OP_NO_SSLv2, PROTOCOL_SSL_V2)) {
1389             enabled.add(PROTOCOL_SSL_V2);
1390         }
1391         if (isProtocolEnabled(opts, SSL.SSL_OP_NO_SSLv3, PROTOCOL_SSL_V3)) {
1392             enabled.add(PROTOCOL_SSL_V3);
1393         }
1394         return enabled.toArray(new String[0]);
1395     }
1396 
1397     private static boolean isProtocolEnabled(int opts, int disableMask, String protocolString) {
1398         // We also need to check if the actual protocolString is supported as depending on the openssl API
1399         // implementations it may use a disableMask of 0 (BoringSSL is doing this for example).
1400         return (opts & disableMask) == 0 && OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(protocolString);
1401     }
1402 
1403     /**
1404      * {@inheritDoc}
1405      * TLS doesn't support a way to advertise non-contiguous versions from the client's perspective, and the client
1406      * just advertises the max supported version. The TLS protocol also doesn't support all different combinations of
1407      * discrete protocols, and instead assumes contiguous ranges. OpenSSL has some unexpected behavior
1408      * (e.g. handshake failures) if non-contiguous protocols are used even where there is a compatible set of protocols
1409      * and ciphers. For these reasons this method will determine the minimum protocol and the maximum protocol and
1410      * enabled a contiguous range from [min protocol, max protocol] in OpenSSL.
1411      */
1412     @Override
1413     public final void setEnabledProtocols(String[] protocols) {
1414         if (protocols == null) {
1415             // This is correct from the API docs
1416             throw new IllegalArgumentException();
1417         }
1418         int minProtocolIndex = OPENSSL_OP_NO_PROTOCOLS.length;
1419         int maxProtocolIndex = 0;
1420         for (String p: protocols) {
1421             if (!OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(p)) {
1422                 throw new IllegalArgumentException("Protocol " + p + " is not supported.");
1423             }
1424             if (p.equals(PROTOCOL_SSL_V2)) {
1425                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) {
1426                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1427                 }
1428                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) {
1429                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1430                 }
1431             } else if (p.equals(PROTOCOL_SSL_V3)) {
1432                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) {
1433                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1434                 }
1435                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) {
1436                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1437                 }
1438             } else if (p.equals(PROTOCOL_TLS_V1)) {
1439                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) {
1440                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1441                 }
1442                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) {
1443                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1444                 }
1445             } else if (p.equals(PROTOCOL_TLS_V1_1)) {
1446                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) {
1447                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1448                 }
1449                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) {
1450                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1451                 }
1452             } else if (p.equals(PROTOCOL_TLS_V1_2)) {
1453                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
1454                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1455                 }
1456                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
1457                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1458                 }
1459             }
1460         }
1461         synchronized (this) {
1462             if (!isDestroyed()) {
1463                 // Clear out options which disable protocols
1464                 SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1 |
1465                                       SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2);
1466 
1467                 int opts = 0;
1468                 for (int i = 0; i < minProtocolIndex; ++i) {
1469                     opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1470                 }
1471                 assert maxProtocolIndex != MAX_VALUE;
1472                 for (int i = maxProtocolIndex + 1; i < OPENSSL_OP_NO_PROTOCOLS.length; ++i) {
1473                     opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1474                 }
1475 
1476                 // Disable protocols we do not want
1477                 SSL.setOptions(ssl, opts);
1478             } else {
1479                 throw new IllegalStateException("failed to enable protocols: " + Arrays.asList(protocols));
1480             }
1481         }
1482     }
1483 
1484     @Override
1485     public final SSLSession getSession() {
1486         return session;
1487     }
1488 
1489     @Override
1490     public final synchronized void beginHandshake() throws SSLException {
1491         switch (handshakeState) {
1492             case STARTED_IMPLICITLY:
1493                 checkEngineClosed(BEGIN_HANDSHAKE_ENGINE_CLOSED);
1494 
1495                 // A user did not start handshake by calling this method by him/herself,
1496                 // but handshake has been started already by wrap() or unwrap() implicitly.
1497                 // Because it's the user's first time to call this method, it is unfair to
1498                 // raise an exception.  From the user's standpoint, he or she never asked
1499                 // for renegotiation.
1500 
1501                 handshakeState = HandshakeState.STARTED_EXPLICITLY; // Next time this method is invoked by the user,
1502                 calculateMaxWrapOverhead();
1503                 // we should raise an exception.
1504                 break;
1505             case STARTED_EXPLICITLY:
1506                 // Nothing to do as the handshake is not done yet.
1507                 break;
1508             case FINISHED:
1509                 throw RENEGOTIATION_UNSUPPORTED;
1510             case NOT_STARTED:
1511                 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1512                 handshake();
1513                 calculateMaxWrapOverhead();
1514                 break;
1515             default:
1516                 throw new Error();
1517         }
1518     }
1519 
1520     private void checkEngineClosed(SSLException cause) throws SSLException {
1521         if (isDestroyed()) {
1522             throw cause;
1523         }
1524     }
1525 
1526     private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingStatus) {
1527         // Depending on if there is something left in the BIO we need to WRAP or UNWRAP
1528         return pendingStatus > 0 ? NEED_WRAP : NEED_UNWRAP;
1529     }
1530 
1531     private static boolean isEmpty(Object[] arr) {
1532         return arr == null || arr.length == 0;
1533     }
1534 
1535     private static boolean isEmpty(byte[] cert) {
1536         return cert == null || cert.length == 0;
1537     }
1538 
1539     private SSLEngineResult.HandshakeStatus handshake() throws SSLException {
1540         if (handshakeState == HandshakeState.FINISHED) {
1541             return FINISHED;
1542         }
1543         checkEngineClosed(HANDSHAKE_ENGINE_CLOSED);
1544 
1545         // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the
1546         // BIO first or can just shutdown and throw it now.
1547         // This is needed so we ensure close_notify etc is correctly send to the remote peer.
1548         // See https://github.com/netty/netty/issues/3900
1549         SSLHandshakeException exception = handshakeException;
1550         if (exception != null) {
1551             if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1552                 // There is something pending, we need to consume it first via a WRAP so we don't loose anything.
1553                 return NEED_WRAP;
1554             }
1555             // No more data left to send to the remote peer, so null out the exception field, shutdown and throw
1556             // the exception.
1557             handshakeException = null;
1558             shutdown();
1559             throw exception;
1560         }
1561 
1562         // Adding the OpenSslEngine to the OpenSslEngineMap so it can be used in the AbstractCertificateVerifier.
1563         engineMap.add(this);
1564         if (lastAccessed == -1) {
1565             lastAccessed = System.currentTimeMillis();
1566         }
1567 
1568         if (!certificateSet && keyMaterialManager != null) {
1569             certificateSet = true;
1570             keyMaterialManager.setKeyMaterialServerSide(this);
1571         }
1572 
1573         int code = SSL.doHandshake(ssl);
1574         if (code <= 0) {
1575             // Check if we have a pending exception that was created during the handshake and if so throw it after
1576             // shutdown the connection.
1577             if (handshakeException != null) {
1578                 exception = handshakeException;
1579                 handshakeException = null;
1580                 shutdown();
1581                 throw exception;
1582             }
1583 
1584             int sslError = SSL.getError(ssl, code);
1585             if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1586                 return pendingStatus(SSL.bioLengthNonApplication(networkBIO));
1587             } else {
1588                 // Everything else is considered as error
1589                 throw shutdownWithError("SSL_do_handshake");
1590             }
1591         }
1592         // if SSL_do_handshake returns > 0 or sslError == SSL.SSL_ERROR_NAME it means the handshake was finished.
1593         session.handshakeFinished();
1594         engineMap.remove(ssl);
1595         return FINISHED;
1596     }
1597 
1598     private SSLEngineResult.HandshakeStatus mayFinishHandshake(SSLEngineResult.HandshakeStatus status)
1599             throws SSLException {
1600         if (status == NOT_HANDSHAKING && handshakeState != HandshakeState.FINISHED) {
1601             // If the status was NOT_HANDSHAKING and we not finished the handshake we need to call
1602             // SSL_do_handshake() again
1603             return handshake();
1604         }
1605         return status;
1606     }
1607 
1608     @Override
1609     public final synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
1610         // Check if we are in the initial handshake phase or shutdown phase
1611         return needPendingStatus() ? pendingStatus(SSL.bioLengthNonApplication(networkBIO)) : NOT_HANDSHAKING;
1612     }
1613 
1614     private SSLEngineResult.HandshakeStatus getHandshakeStatus(int pending) {
1615         // Check if we are in the initial handshake phase or shutdown phase
1616         return needPendingStatus() ? pendingStatus(pending) : NOT_HANDSHAKING;
1617     }
1618 
1619     private boolean needPendingStatus() {
1620         return handshakeState != HandshakeState.NOT_STARTED && !isDestroyed()
1621                 && (handshakeState != HandshakeState.FINISHED || isInboundDone() || isOutboundDone());
1622     }
1623 
1624     /**
1625      * Converts the specified OpenSSL cipher suite to the Java cipher suite.
1626      */
1627     private String toJavaCipherSuite(String openSslCipherSuite) {
1628         if (openSslCipherSuite == null) {
1629             return null;
1630         }
1631 
1632         String prefix = toJavaCipherSuitePrefix(SSL.getVersion(ssl));
1633         return CipherSuiteConverter.toJava(openSslCipherSuite, prefix);
1634     }
1635 
1636     /**
1637      * Converts the protocol version string returned by {@link SSL#getVersion(long)} to protocol family string.
1638      */
1639     private static String toJavaCipherSuitePrefix(String protocolVersion) {
1640         final char c;
1641         if (protocolVersion == null || protocolVersion.isEmpty()) {
1642             c = 0;
1643         } else {
1644             c = protocolVersion.charAt(0);
1645         }
1646 
1647         switch (c) {
1648             case 'T':
1649                 return "TLS";
1650             case 'S':
1651                 return "SSL";
1652             default:
1653                 return "UNKNOWN";
1654         }
1655     }
1656 
1657     @Override
1658     public final void setUseClientMode(boolean clientMode) {
1659         if (clientMode != this.clientMode) {
1660             throw new UnsupportedOperationException();
1661         }
1662     }
1663 
1664     @Override
1665     public final boolean getUseClientMode() {
1666         return clientMode;
1667     }
1668 
1669     @Override
1670     public final void setNeedClientAuth(boolean b) {
1671         setClientAuth(b ? ClientAuth.REQUIRE : ClientAuth.NONE);
1672     }
1673 
1674     @Override
1675     public final boolean getNeedClientAuth() {
1676         return clientAuth == ClientAuth.REQUIRE;
1677     }
1678 
1679     @Override
1680     public final void setWantClientAuth(boolean b) {
1681         setClientAuth(b ? ClientAuth.OPTIONAL : ClientAuth.NONE);
1682     }
1683 
1684     @Override
1685     public final boolean getWantClientAuth() {
1686         return clientAuth == ClientAuth.OPTIONAL;
1687     }
1688 
1689     /**
1690      * See <a href="https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_verify.html">SSL_set_verify</a> and
1691      * {@link SSL#setVerify(long, int, int)}.
1692      */
1693     @UnstableApi
1694     public final synchronized void setVerify(int verifyMode, int depth) {
1695         SSL.setVerify(ssl, verifyMode, depth);
1696     }
1697 
1698     private void setClientAuth(ClientAuth mode) {
1699         if (clientMode) {
1700             return;
1701         }
1702         synchronized (this) {
1703             if (clientAuth == mode) {
1704                 // No need to issue any JNI calls if the mode is the same
1705                 return;
1706             }
1707             switch (mode) {
1708                 case NONE:
1709                     SSL.setVerify(ssl, SSL.SSL_CVERIFY_NONE, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
1710                     break;
1711                 case REQUIRE:
1712                     SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
1713                     break;
1714                 case OPTIONAL:
1715                     SSL.setVerify(ssl, SSL.SSL_CVERIFY_OPTIONAL, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
1716                     break;
1717                 default:
1718                     throw new Error(mode.toString());
1719             }
1720             clientAuth = mode;
1721         }
1722     }
1723 
1724     @Override
1725     public final void setEnableSessionCreation(boolean b) {
1726         if (b) {
1727             throw new UnsupportedOperationException();
1728         }
1729     }
1730 
1731     @Override
1732     public final boolean getEnableSessionCreation() {
1733         return false;
1734     }
1735 
1736     @Override
1737     public final synchronized SSLParameters getSSLParameters() {
1738         SSLParameters sslParameters = super.getSSLParameters();
1739 
1740         int version = PlatformDependent.javaVersion();
1741         if (version >= 7) {
1742             sslParameters.setEndpointIdentificationAlgorithm(endPointIdentificationAlgorithm);
1743             Java7SslParametersUtils.setAlgorithmConstraints(sslParameters, algorithmConstraints);
1744             if (version >= 8) {
1745                 if (sniHostNames != null) {
1746                     Java8SslUtils.setSniHostNames(sslParameters, sniHostNames);
1747                 }
1748                 if (!isDestroyed()) {
1749                     Java8SslUtils.setUseCipherSuitesOrder(
1750                             sslParameters, (SSL.getOptions(ssl) & SSL.SSL_OP_CIPHER_SERVER_PREFERENCE) != 0);
1751                 }
1752 
1753                 Java8SslUtils.setSNIMatchers(sslParameters, matchers);
1754             }
1755         }
1756         return sslParameters;
1757     }
1758 
1759     @Override
1760     public final synchronized void setSSLParameters(SSLParameters sslParameters) {
1761         int version = PlatformDependent.javaVersion();
1762         if (version >= 7) {
1763             if (sslParameters.getAlgorithmConstraints() != null) {
1764                 throw new IllegalArgumentException("AlgorithmConstraints are not supported.");
1765             }
1766 
1767             if (version >= 8) {
1768                 if (!isDestroyed()) {
1769                     if (clientMode) {
1770                         final List<String> sniHostNames = Java8SslUtils.getSniHostNames(sslParameters);
1771                         for (String name: sniHostNames) {
1772                             SSL.setTlsExtHostName(ssl, name);
1773                         }
1774                         this.sniHostNames = sniHostNames;
1775                     }
1776                     if (Java8SslUtils.getUseCipherSuitesOrder(sslParameters)) {
1777                         SSL.setOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
1778                     } else {
1779                         SSL.clearOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
1780                     }
1781                 }
1782                 matchers = sslParameters.getSNIMatchers();
1783             }
1784 
1785             final String endPointIdentificationAlgorithm = sslParameters.getEndpointIdentificationAlgorithm();
1786             final boolean endPointVerificationEnabled = isEndPointVerificationEnabled(endPointIdentificationAlgorithm);
1787 
1788             final boolean wasEndPointVerificationEnabled =
1789                     isEndPointVerificationEnabled(this.endPointIdentificationAlgorithm);
1790 
1791             if (wasEndPointVerificationEnabled && !endPointVerificationEnabled) {
1792                 // Passing in null will disable hostname verification again so only do so if it was enabled before.
1793                 SSL.setHostNameValidation(ssl, DEFAULT_HOSTNAME_VALIDATION_FLAGS, null);
1794             } else {
1795                 String host = endPointVerificationEnabled ? getPeerHost() : null;
1796                 if (host != null && !host.isEmpty()) {
1797                     SSL.setHostNameValidation(ssl, DEFAULT_HOSTNAME_VALIDATION_FLAGS, host);
1798                 }
1799             }
1800             // If the user asks for hostname verification we must ensure we verify the peer.
1801             // If the user disables hostname verification we leave it up to the user to change the mode manually.
1802             if (clientMode && endPointVerificationEnabled) {
1803                 SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, -1);
1804             }
1805 
1806             this.endPointIdentificationAlgorithm = endPointIdentificationAlgorithm;
1807             algorithmConstraints = sslParameters.getAlgorithmConstraints();
1808         }
1809         super.setSSLParameters(sslParameters);
1810     }
1811 
1812     private static boolean isEndPointVerificationEnabled(String endPointIdentificationAlgorithm) {
1813         return endPointIdentificationAlgorithm != null && !endPointIdentificationAlgorithm.isEmpty();
1814     }
1815 
1816     private boolean isDestroyed() {
1817         return destroyed != 0;
1818     }
1819 
1820     final boolean checkSniHostnameMatch(String hostname) {
1821         return Java8SslUtils.checkSniHostnameMatch(matchers, hostname);
1822     }
1823 
1824     @Override
1825     public String getNegotiatedApplicationProtocol() {
1826         return applicationProtocol;
1827     }
1828 
1829     private static long bufferAddress(ByteBuffer b) {
1830         assert b.isDirect();
1831         if (PlatformDependent.hasUnsafe()) {
1832             return PlatformDependent.directBufferAddress(b);
1833         }
1834         return Buffer.address(b);
1835     }
1836 
1837     private final class OpenSslSession implements SSLSession {
1838         private final OpenSslSessionContext sessionContext;
1839 
1840         // These are guarded by synchronized(OpenSslEngine.this) as handshakeFinished() may be triggered by any
1841         // thread.
1842         private X509Certificate[] x509PeerCerts;
1843         private Certificate[] peerCerts;
1844         private String protocol;
1845         private String cipher;
1846         private byte[] id;
1847         private long creationTime;
1848         private volatile int applicationBufferSize = MAX_PLAINTEXT_LENGTH;
1849 
1850         // lazy init for memory reasons
1851         private Map<String, Object> values;
1852 
1853         OpenSslSession(OpenSslSessionContext sessionContext) {
1854             this.sessionContext = sessionContext;
1855         }
1856 
1857         @Override
1858         public byte[] getId() {
1859             synchronized (ReferenceCountedOpenSslEngine.this) {
1860                 if (id == null) {
1861                     return EmptyArrays.EMPTY_BYTES;
1862                 }
1863                 return id.clone();
1864             }
1865         }
1866 
1867         @Override
1868         public SSLSessionContext getSessionContext() {
1869             return sessionContext;
1870         }
1871 
1872         @Override
1873         public long getCreationTime() {
1874             synchronized (ReferenceCountedOpenSslEngine.this) {
1875                 if (creationTime == 0 && !isDestroyed()) {
1876                     creationTime = SSL.getTime(ssl) * 1000L;
1877                 }
1878             }
1879             return creationTime;
1880         }
1881 
1882         @Override
1883         public long getLastAccessedTime() {
1884             long lastAccessed = ReferenceCountedOpenSslEngine.this.lastAccessed;
1885             // if lastAccessed is -1 we will just return the creation time as the handshake was not started yet.
1886             return lastAccessed == -1 ? getCreationTime() : lastAccessed;
1887         }
1888 
1889         @Override
1890         public void invalidate() {
1891             synchronized (ReferenceCountedOpenSslEngine.this) {
1892                 if (!isDestroyed()) {
1893                     SSL.setTimeout(ssl, 0);
1894                 }
1895             }
1896         }
1897 
1898         @Override
1899         public boolean isValid() {
1900             synchronized (ReferenceCountedOpenSslEngine.this) {
1901                 if (!isDestroyed()) {
1902                     return System.currentTimeMillis() - (SSL.getTimeout(ssl) * 1000L) < (SSL.getTime(ssl) * 1000L);
1903                 }
1904             }
1905             return false;
1906         }
1907 
1908         @Override
1909         public void putValue(String name, Object value) {
1910             if (name == null) {
1911                 throw new NullPointerException("name");
1912             }
1913             if (value == null) {
1914                 throw new NullPointerException("value");
1915             }
1916             Map<String, Object> values = this.values;
1917             if (values == null) {
1918                 // Use size of 2 to keep the memory overhead small
1919                 values = this.values = new HashMap<String, Object>(2);
1920             }
1921             Object old = values.put(name, value);
1922             if (value instanceof SSLSessionBindingListener) {
1923                 ((SSLSessionBindingListener) value).valueBound(new SSLSessionBindingEvent(this, name));
1924             }
1925             notifyUnbound(old, name);
1926         }
1927 
1928         @Override
1929         public Object getValue(String name) {
1930             if (name == null) {
1931                 throw new NullPointerException("name");
1932             }
1933             if (values == null) {
1934                 return null;
1935             }
1936             return values.get(name);
1937         }
1938 
1939         @Override
1940         public void removeValue(String name) {
1941             if (name == null) {
1942                 throw new NullPointerException("name");
1943             }
1944             Map<String, Object> values = this.values;
1945             if (values == null) {
1946                 return;
1947             }
1948             Object old = values.remove(name);
1949             notifyUnbound(old, name);
1950         }
1951 
1952         @Override
1953         public String[] getValueNames() {
1954             Map<String, Object> values = this.values;
1955             if (values == null || values.isEmpty()) {
1956                 return EmptyArrays.EMPTY_STRINGS;
1957             }
1958             return values.keySet().toArray(new String[0]);
1959         }
1960 
1961         private void notifyUnbound(Object value, String name) {
1962             if (value instanceof SSLSessionBindingListener) {
1963                 ((SSLSessionBindingListener) value).valueUnbound(new SSLSessionBindingEvent(this, name));
1964             }
1965         }
1966 
1967         /**
1968          * Finish the handshake and so init everything in the {@link OpenSslSession} that should be accessible by
1969          * the user.
1970          */
1971         void handshakeFinished() throws SSLException {
1972             synchronized (ReferenceCountedOpenSslEngine.this) {
1973                 if (!isDestroyed()) {
1974                     id = SSL.getSessionId(ssl);
1975                     cipher = toJavaCipherSuite(SSL.getCipherForSSL(ssl));
1976                     protocol = SSL.getVersion(ssl);
1977 
1978                     initPeerCerts();
1979                     selectApplicationProtocol();
1980                     calculateMaxWrapOverhead();
1981 
1982                     handshakeState = HandshakeState.FINISHED;
1983                 } else {
1984                     throw new SSLException("Already closed");
1985                 }
1986             }
1987         }
1988 
1989         /**
1990          * Init peer certificates that can be obtained via {@link #getPeerCertificateChain()}
1991          * and {@link #getPeerCertificates()}.
1992          */
1993         private void initPeerCerts() {
1994             // Return the full chain from the JNI layer.
1995             byte[][] chain = SSL.getPeerCertChain(ssl);
1996             if (clientMode) {
1997                 if (isEmpty(chain)) {
1998                     peerCerts = EMPTY_CERTIFICATES;
1999                     x509PeerCerts = EMPTY_JAVAX_X509_CERTIFICATES;
2000                 } else {
2001                     peerCerts = new Certificate[chain.length];
2002                     x509PeerCerts = new X509Certificate[chain.length];
2003                     initCerts(chain, 0);
2004                 }
2005             } else {
2006                 // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer
2007                 // certificate. We use SSL_get_peer_certificate to get it in this case and add it to our
2008                 // array later.
2009                 //
2010                 // See https://www.openssl.org/docs/ssl/SSL_get_peer_cert_chain.html
2011                 byte[] clientCert = SSL.getPeerCertificate(ssl);
2012                 if (isEmpty(clientCert)) {
2013                     peerCerts = EMPTY_CERTIFICATES;
2014                     x509PeerCerts = EMPTY_JAVAX_X509_CERTIFICATES;
2015                 } else {
2016                     if (isEmpty(chain)) {
2017                         peerCerts = new Certificate[] {new OpenSslX509Certificate(clientCert)};
2018                         x509PeerCerts = new X509Certificate[] {new OpenSslJavaxX509Certificate(clientCert)};
2019                     } else {
2020                         peerCerts = new Certificate[chain.length + 1];
2021                         x509PeerCerts = new X509Certificate[chain.length + 1];
2022                         peerCerts[0] = new OpenSslX509Certificate(clientCert);
2023                         x509PeerCerts[0] = new OpenSslJavaxX509Certificate(clientCert);
2024                         initCerts(chain, 1);
2025                     }
2026                 }
2027             }
2028         }
2029 
2030         private void initCerts(byte[][] chain, int startPos) {
2031             for (int i = 0; i < chain.length; i++) {
2032                 int certPos = startPos + i;
2033                 peerCerts[certPos] = new OpenSslX509Certificate(chain[i]);
2034                 x509PeerCerts[certPos] = new OpenSslJavaxX509Certificate(chain[i]);
2035             }
2036         }
2037 
2038         /**
2039          * Select the application protocol used.
2040          */
2041         private void selectApplicationProtocol() throws SSLException {
2042             ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior = apn.selectedListenerFailureBehavior();
2043             List<String> protocols = apn.protocols();
2044             String applicationProtocol;
2045             switch (apn.protocol()) {
2046                 case NONE:
2047                     break;
2048                 // We always need to check for applicationProtocol == null as the remote peer may not support
2049                 // the TLS extension or may have returned an empty selection.
2050                 case ALPN:
2051                     applicationProtocol = SSL.getAlpnSelected(ssl);
2052                     if (applicationProtocol != null) {
2053                         ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2054                                 protocols, behavior, applicationProtocol);
2055                     }
2056                     break;
2057                 case NPN:
2058                     applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2059                     if (applicationProtocol != null) {
2060                         ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2061                                 protocols, behavior, applicationProtocol);
2062                     }
2063                     break;
2064                 case NPN_AND_ALPN:
2065                     applicationProtocol = SSL.getAlpnSelected(ssl);
2066                     if (applicationProtocol == null) {
2067                         applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2068                     }
2069                     if (applicationProtocol != null) {
2070                         ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2071                                 protocols, behavior, applicationProtocol);
2072                     }
2073                     break;
2074                 default:
2075                     throw new Error();
2076             }
2077         }
2078 
2079         private String selectApplicationProtocol(List<String> protocols,
2080                                                  ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior,
2081                                                  String applicationProtocol) throws SSLException {
2082             if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT) {
2083                 return applicationProtocol;
2084             } else {
2085                 int size = protocols.size();
2086                 assert size > 0;
2087                 if (protocols.contains(applicationProtocol)) {
2088                     return applicationProtocol;
2089                 } else {
2090                     if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.CHOOSE_MY_LAST_PROTOCOL) {
2091                         return protocols.get(size - 1);
2092                     } else {
2093                         throw new SSLException("unknown protocol " + applicationProtocol);
2094                     }
2095                 }
2096             }
2097         }
2098 
2099         @Override
2100         public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
2101             synchronized (ReferenceCountedOpenSslEngine.this) {
2102                 if (isEmpty(peerCerts)) {
2103                     throw new SSLPeerUnverifiedException("peer not verified");
2104                 }
2105                 return peerCerts.clone();
2106             }
2107         }
2108 
2109         @Override
2110         public Certificate[] getLocalCertificates() {
2111             if (localCerts == null) {
2112                 return null;
2113             }
2114             return localCerts.clone();
2115         }
2116 
2117         @Override
2118         public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException {
2119             synchronized (ReferenceCountedOpenSslEngine.this) {
2120                 if (isEmpty(x509PeerCerts)) {
2121                     throw new SSLPeerUnverifiedException("peer not verified");
2122                 }
2123                 return x509PeerCerts.clone();
2124             }
2125         }
2126 
2127         @Override
2128         public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
2129             Certificate[] peer = getPeerCertificates();
2130             // No need for null or length > 0 is needed as this is done in getPeerCertificates()
2131             // already.
2132             return ((java.security.cert.X509Certificate) peer[0]).getSubjectX500Principal();
2133         }
2134 
2135         @Override
2136         public Principal getLocalPrincipal() {
2137             Certificate[] local = localCerts;
2138             if (local == null || local.length == 0) {
2139                 return null;
2140             }
2141             return ((java.security.cert.X509Certificate) local[0]).getIssuerX500Principal();
2142         }
2143 
2144         @Override
2145         public String getCipherSuite() {
2146             synchronized (ReferenceCountedOpenSslEngine.this) {
2147                 if (cipher == null) {
2148                     return INVALID_CIPHER;
2149                 }
2150                 return cipher;
2151             }
2152         }
2153 
2154         @Override
2155         public String getProtocol() {
2156             String protocol = this.protocol;
2157             if (protocol == null) {
2158                 synchronized (ReferenceCountedOpenSslEngine.this) {
2159                     if (!isDestroyed()) {
2160                         protocol = SSL.getVersion(ssl);
2161                     } else {
2162                         protocol = StringUtil.EMPTY_STRING;
2163                     }
2164                 }
2165             }
2166             return protocol;
2167         }
2168 
2169         @Override
2170         public String getPeerHost() {
2171             return ReferenceCountedOpenSslEngine.this.getPeerHost();
2172         }
2173 
2174         @Override
2175         public int getPeerPort() {
2176             return ReferenceCountedOpenSslEngine.this.getPeerPort();
2177         }
2178 
2179         @Override
2180         public int getPacketBufferSize() {
2181             return maxEncryptedPacketLength();
2182         }
2183 
2184         @Override
2185         public int getApplicationBufferSize() {
2186             return applicationBufferSize;
2187         }
2188 
2189         /**
2190          * Expand (or increase) the value returned by {@link #getApplicationBufferSize()} if necessary.
2191          * <p>
2192          * This is only called in a synchronized block, so no need to use atomic operations.
2193          * @param packetLengthDataOnly The packet size which exceeds the current {@link #getApplicationBufferSize()}.
2194          */
2195         void tryExpandApplicationBufferSize(int packetLengthDataOnly) {
2196             if (packetLengthDataOnly > MAX_PLAINTEXT_LENGTH && applicationBufferSize != MAX_RECORD_SIZE) {
2197                 applicationBufferSize = MAX_RECORD_SIZE;
2198             }
2199         }
2200     }
2201 }