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