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