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 engines;
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         engines = context.engines;
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         // Register for the SSL* -> engine reverse lookup used by native callbacks; held weakly (see OpenSslEngineMap).
419         engines.add(ssl, this);
420 
421         // Only create the leak after everything else was executed and so ensure we don't produce a false-positive for
422         // the ResourceLeakDetector.
423         leak = leakDetection ? leakDetector.track(this) : null;
424     }
425 
426     final synchronized String[] authMethods() {
427         if (isDestroyed()) {
428             return EMPTY_STRINGS;
429         }
430         return SSL.authenticationMethods(ssl);
431     }
432 
433     final boolean setKeyMaterial(OpenSslKeyMaterial keyMaterial) throws  Exception {
434         synchronized (this) {
435             if (isDestroyed()) {
436                 return false;
437             }
438             SSL.setKeyMaterial(ssl, keyMaterial.certificateChainAddress(), keyMaterial.privateKeyAddress());
439         }
440         session.setLocalCertificate(keyMaterial.certificateChain());
441         return true;
442     }
443 
444     final synchronized SecretKeySpec masterKey() {
445         if (isDestroyed()) {
446             return null;
447         }
448         return new SecretKeySpec(SSL.getMasterKey(ssl), "AES");
449     }
450 
451     synchronized boolean isSessionReused() {
452         if (isDestroyed()) {
453             return false;
454         }
455         return SSL.isSessionReused(ssl);
456     }
457 
458     /**
459      * Sets the OCSP response.
460      */
461     @UnstableApi
462     public void setOcspResponse(byte[] response) {
463         if (!enableOcsp) {
464             throw new IllegalStateException("OCSP stapling is not enabled");
465         }
466 
467         if (clientMode) {
468             throw new IllegalStateException("Not a server SSLEngine");
469         }
470 
471         synchronized (this) {
472             if (!isDestroyed()) {
473                 SSL.setOcspResponse(ssl, response);
474             }
475         }
476     }
477 
478     /**
479      * Returns the OCSP response or {@code null} if the server didn't provide a stapled OCSP response.
480      */
481     @UnstableApi
482     public byte[] getOcspResponse() {
483         if (!enableOcsp) {
484             throw new IllegalStateException("OCSP stapling is not enabled");
485         }
486 
487         if (!clientMode) {
488             throw new IllegalStateException("Not a client SSLEngine");
489         }
490 
491         synchronized (this) {
492             if (isDestroyed()) {
493                 return EmptyArrays.EMPTY_BYTES;
494             }
495             return SSL.getOcspResponse(ssl);
496         }
497     }
498 
499     @Override
500     public final int refCnt() {
501         return refCnt.refCnt();
502     }
503 
504     @Override
505     public final ReferenceCounted retain() {
506         refCnt.retain();
507         return this;
508     }
509 
510     @Override
511     public final ReferenceCounted retain(int increment) {
512         refCnt.retain(increment);
513         return this;
514     }
515 
516     @Override
517     public final ReferenceCounted touch() {
518         refCnt.touch();
519         return this;
520     }
521 
522     @Override
523     public final ReferenceCounted touch(Object hint) {
524         refCnt.touch(hint);
525         return this;
526     }
527 
528     @Override
529     public final boolean release() {
530         return refCnt.release();
531     }
532 
533     @Override
534     public final boolean release(int decrement) {
535         return refCnt.release(decrement);
536     }
537 
538     // These method will override the method defined by Java 8u251 and later. As we may compile with an earlier
539     // java8 version we don't use @Override annotations here.
540     public String getApplicationProtocol() {
541         return applicationProtocol;
542     }
543 
544     // These method will override the method defined by Java 8u251 and later. As we may compile with an earlier
545     // java8 version we don't use @Override annotations here.
546     public String getHandshakeApplicationProtocol() {
547         return applicationProtocol;
548     }
549 
550     @Override
551     public final synchronized SSLSession getHandshakeSession() {
552         // Javadocs state return value should be:
553         // null if this instance is not currently handshaking, or if the current handshake has not
554         // progressed far enough to create a basic SSLSession. Otherwise, this method returns the
555         // SSLSession currently being negotiated.
556         switch(handshakeState) {
557             case NOT_STARTED:
558             case FINISHED:
559                 return null;
560             default:
561                 return session;
562         }
563     }
564 
565     /**
566      * Returns the pointer to the {@code SSL} object for this {@link ReferenceCountedOpenSslEngine}.
567      * Be aware that it is freed as soon as the {@link #release()} or {@link #shutdown()} methods are called.
568      * At this point {@code 0} will be returned.
569      */
570     public final synchronized long sslPointer() {
571         return ssl;
572     }
573 
574     /**
575      * Destroys this engine.
576      */
577     public final synchronized void shutdown() {
578         if (!destroyed) {
579             destroyed = true;
580             // Let's check if engines is null as it could be in theory if we throw an OOME during the construction of
581             // ReferenceCountedOpenSslEngine (before we assign the field). This is needed as shutdown() is called from
582             // the finalizer as well.
583             if (engines != null) {
584                 engines.remove(ssl);
585             }
586             SSL.freeSSL(ssl);
587             ssl = networkBIO = 0;
588 
589             isInboundDone = outboundClosed = true;
590         }
591 
592         // On shutdown clear all errors
593         SSL.clearError();
594     }
595 
596     /**
597      * Write plaintext data to the OpenSSL internal BIO
598      *
599      * Calling this function with src.remaining == 0 is undefined.
600      */
601     private int writePlaintextData(final ByteBuffer src, int len) {
602         final int pos = src.position();
603         final int limit = src.limit();
604         final int sslWrote;
605 
606         if (src.isDirect()) {
607             sslWrote = SSL.writeToSSL(ssl, bufferAddress(src) + pos, len);
608             if (sslWrote > 0) {
609                 src.position(pos + sslWrote);
610             }
611         } else {
612             ByteBuf buf = alloc.directBuffer(len);
613             try {
614                 src.limit(pos + len);
615 
616                 buf.setBytes(0, src);
617                 src.limit(limit);
618 
619                 sslWrote = SSL.writeToSSL(ssl, memoryAddress(buf), len);
620                 if (sslWrote > 0) {
621                     src.position(pos + sslWrote);
622                 } else {
623                     src.position(pos);
624                 }
625             } finally {
626                 buf.release();
627             }
628         }
629         return sslWrote;
630     }
631 
632    synchronized void bioSetFd(int fd) {
633         if (!isDestroyed()) {
634             SSL.bioSetFd(this.ssl, fd);
635         }
636     }
637 
638     /**
639      * Write encrypted data to the OpenSSL network BIO.
640      */
641     private ByteBuf writeEncryptedData(final ByteBuffer src, int len) throws SSLException {
642         final int pos = src.position();
643         if (src.isDirect()) {
644             SSL.bioSetByteBuffer(networkBIO, bufferAddress(src) + pos, len, false);
645         } else {
646             final ByteBuf buf = alloc.directBuffer(len);
647             try {
648                 final int limit = src.limit();
649                 src.limit(pos + len);
650                 buf.writeBytes(src);
651                 // Restore the original position and limit because we don't want to consume from `src`.
652                 src.position(pos);
653                 src.limit(limit);
654 
655                 SSL.bioSetByteBuffer(networkBIO, memoryAddress(buf), len, false);
656                 return buf;
657             } catch (Throwable cause) {
658                 buf.release();
659                 PlatformDependent.throwException(cause);
660             }
661         }
662         return null;
663     }
664 
665     /**
666      * Read plaintext data from the OpenSSL internal BIO
667      */
668     private int readPlaintextData(final ByteBuffer dst) throws SSLException {
669         final int sslRead;
670         final int pos = dst.position();
671         if (dst.isDirect()) {
672             sslRead = SSL.readFromSSL(ssl, bufferAddress(dst) + pos, dst.limit() - pos);
673             if (sslRead > 0) {
674                 dst.position(pos + sslRead);
675             }
676         } else {
677             final int limit = dst.limit();
678             final int len = min(maxEncryptedPacketLength0(), limit - pos);
679             final ByteBuf buf = alloc.directBuffer(len);
680             try {
681                 sslRead = SSL.readFromSSL(ssl, memoryAddress(buf), len);
682                 if (sslRead > 0) {
683                     dst.limit(pos + sslRead);
684                     buf.getBytes(buf.readerIndex(), dst);
685                     dst.limit(limit);
686                 }
687             } finally {
688                 buf.release();
689             }
690         }
691 
692         return sslRead;
693     }
694 
695     /**
696      * Visible only for testing!
697      */
698     final synchronized int maxWrapOverhead() {
699         return maxWrapOverhead;
700     }
701 
702     /**
703      * Visible only for testing!
704      */
705     final synchronized int maxEncryptedPacketLength() {
706         return maxEncryptedPacketLength0();
707     }
708 
709     /**
710      * This method is intentionally not synchronized, only use if you know you are in the EventLoop
711      * thread and visibility on {@link #maxWrapOverhead} is achieved via other synchronized blocks.
712      */
713     final int maxEncryptedPacketLength0() {
714         return maxWrapOverhead + MAX_PLAINTEXT_LENGTH;
715     }
716 
717     /**
718      * This method is intentionally not synchronized, only use if you know you are in the EventLoop
719      * thread and visibility on {@link #maxWrapBufferSize} and {@link #maxWrapOverhead} is achieved
720      * via other synchronized blocks.
721      * <br>
722      * Calculates the max size of a single wrap operation for the given plaintextLength and
723      * numComponents.
724      */
725     final int calculateMaxLengthForWrap(int plaintextLength, int numComponents) {
726         return (int) min(maxWrapBufferSize, plaintextLength + (long) maxWrapOverhead * numComponents);
727     }
728 
729     /**
730      * This method is intentionally not synchronized, only use if you know you are in the EventLoop
731      * thread and visibility on {@link #maxWrapOverhead} is achieved via other synchronized blocks.
732      * <br>
733      * Calculates the size of the out net buf to create for the given plaintextLength and numComponents.
734      * This is not related to the max size per wrap, as we can wrap chunks at a time into one out net buf.
735      */
736     final int calculateOutNetBufSize(int plaintextLength, int numComponents) {
737         return (int) min(MAX_VALUE, plaintextLength + (long) maxWrapOverhead * numComponents);
738     }
739 
740     final synchronized int sslPending() {
741         return sslPending0();
742     }
743 
744     /**
745      * It is assumed this method is called in a synchronized block (or the constructor)!
746      */
747     private void calculateMaxWrapOverhead() {
748         maxWrapOverhead = SSL.getMaxWrapOverhead(ssl);
749 
750         // maxWrapBufferSize must be set after maxWrapOverhead because there is a dependency on this value.
751         // If jdkCompatibility mode is off we allow enough space to encrypt 16 buffers at a time. This could be
752         // configurable in the future if necessary.
753         maxWrapBufferSize = jdkCompatibilityMode ? maxEncryptedPacketLength0() : maxEncryptedPacketLength0() << 4;
754     }
755 
756     private int sslPending0() {
757         // OpenSSL has a limitation where if you call SSL_pending before the handshake is complete OpenSSL will throw a
758         // "called a function you should not call" error. Using the TLS_method instead of SSLv23_method may solve this
759         // issue but this API is only available in 1.1.0+ [1].
760         // [1] https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_new.html
761         return handshakeState != HandshakeState.FINISHED ? 0 : SSL.sslPending(ssl);
762     }
763 
764     private boolean isBytesAvailableEnoughForWrap(int bytesAvailable, int plaintextLength, int numComponents) {
765         return bytesAvailable - (long) maxWrapOverhead * numComponents >= plaintextLength;
766     }
767 
768     @Override
769     public final SSLEngineResult wrap(
770             final ByteBuffer[] srcs, int offset, final int length, final ByteBuffer dst) throws SSLException {
771         // Throw required runtime exceptions
772         checkNotNullWithIAE(srcs, "srcs");
773         checkNotNullWithIAE(dst, "dst");
774 
775         if (offset >= srcs.length || offset + length > srcs.length) {
776             throw new IndexOutOfBoundsException(
777                     "offset: " + offset + ", length: " + length +
778                             " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
779         }
780 
781         if (dst.isReadOnly()) {
782             throw new ReadOnlyBufferException();
783         }
784 
785         synchronized (this) {
786             if (isOutboundDone()) {
787                 // All drained in the outbound buffer
788                 return isInboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_UNWRAP_CLOSED;
789             }
790 
791             int bytesProduced = 0;
792             ByteBuf bioReadCopyBuf = null;
793             try {
794                 // Setup the BIO buffer so that we directly write the encryption results into dst.
795                 if (dst.isDirect()) {
796                     SSL.bioSetByteBuffer(networkBIO, bufferAddress(dst) + dst.position(), dst.remaining(),
797                             true);
798                 } else {
799                     bioReadCopyBuf = alloc.directBuffer(dst.remaining());
800                     SSL.bioSetByteBuffer(networkBIO, memoryAddress(bioReadCopyBuf), bioReadCopyBuf.writableBytes(),
801                             true);
802                 }
803 
804                 int bioLengthBefore = SSL.bioLengthByteBuffer(networkBIO);
805 
806                 // Explicitly use outboundClosed as we want to drain any bytes that are still present.
807                 if (outboundClosed) {
808                     // If the outbound was closed we want to ensure we can produce the alert to the destination buffer.
809                     // This is true even if we not using jdkCompatibilityMode.
810                     //
811                     // We use a plaintextLength of 2 as we at least want to have an alert fit into it.
812                     // https://tools.ietf.org/html/rfc5246#section-7.2
813                     if (!isBytesAvailableEnoughForWrap(dst.remaining(), 2, 1)) {
814                         return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
815                     }
816 
817                     // There is something left to drain.
818                     // See https://github.com/netty/netty/issues/6260
819                     bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
820                     if (bytesProduced <= 0) {
821                         return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, 0);
822                     }
823                     // It is possible when the outbound was closed there was not enough room in the non-application
824                     // buffers to hold the close_notify. We should keep trying to close until we consume all the data
825                     // OpenSSL can give us.
826                     if (!doSSLShutdown()) {
827                         return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, bytesProduced);
828                     }
829                     bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
830                     return newResultMayFinishHandshake(NEED_WRAP, 0, bytesProduced);
831                 }
832 
833                 // Flush any data that may be implicitly generated by OpenSSL (handshake, close, etc..).
834                 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
835                 HandshakeState oldHandshakeState = handshakeState;
836 
837                 // Prepare OpenSSL to work in server mode and receive handshake
838                 if (handshakeState != HandshakeState.FINISHED) {
839                     if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
840                         // Update accepted so we know we triggered the handshake via wrap
841                         handshakeState = HandshakeState.STARTED_IMPLICITLY;
842                     }
843 
844                     // Flush any data that may have been written implicitly during the handshake by OpenSSL.
845                     bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
846 
847                     if (pendingException != null) {
848                         // TODO(scott): It is possible that when the handshake failed there was not enough room in the
849                         // non-application buffers to hold the alert. We should get all the data before progressing on.
850                         // However I'm not aware of a way to do this with the OpenSSL APIs.
851                         // See https://github.com/netty/netty/issues/6385.
852 
853                         // We produced / consumed some data during the handshake, signal back to the caller.
854                         // If there is a handshake exception and we have produced data, we should send the data before
855                         // we allow handshake() to throw the handshake exception.
856                         //
857                         // When the user calls wrap() again we will propagate the handshake error back to the user as
858                         // soon as there is no more data to was produced (as part of an alert etc).
859                         if (bytesProduced > 0) {
860                             return newResult(NEED_WRAP, 0, bytesProduced);
861                         }
862                         // Nothing was produced see if there is a handshakeException that needs to be propagated
863                         // to the caller by calling handshakeException() which will return the right HandshakeStatus
864                         // if it can "recover" from the exception for now.
865                         return newResult(handshakeException(), 0, 0);
866                     }
867 
868                     status = handshake();
869 
870                     // Handshake may have generated more data, for example if the internal SSL buffer is small
871                     // we may have freed up space by flushing above.
872                     bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
873 
874                     if (status == NEED_TASK) {
875                         return newResult(status, 0, bytesProduced);
876                     }
877 
878                     if (bytesProduced > 0) {
879                         // If we have filled up the dst buffer and we have not finished the handshake we should try to
880                         // wrap again. Otherwise we should only try to wrap again if there is still data pending in
881                         // SSL buffers.
882                         return newResult(mayFinishHandshake(status != FINISHED ?
883                                          bytesProduced == bioLengthBefore ? NEED_WRAP :
884                                          getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED),
885                                          0, bytesProduced);
886                     }
887 
888                     if (status == NEED_UNWRAP) {
889                         // Signal if the outbound is done or not.
890                         return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
891                     }
892 
893                     // Explicit use outboundClosed and not outboundClosed() as we want to drain any bytes that are
894                     // still present.
895                     if (outboundClosed) {
896                         bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
897                         return newResultMayFinishHandshake(status, 0, bytesProduced);
898                     }
899                 }
900 
901                 final int endOffset = offset + length;
902                 if (jdkCompatibilityMode ||
903                         // If the handshake was not finished before we entered the method, we also ensure we only
904                         // wrap one record. We do this to ensure we not produce any extra data before the caller
905                         // of the method is able to observe handshake completion and react on it.
906                         oldHandshakeState != HandshakeState.FINISHED) {
907                     int srcsLen = 0;
908                     for (int i = offset; i < endOffset; ++i) {
909                         final ByteBuffer src = srcs[i];
910                         if (src == null) {
911                             throw new IllegalArgumentException("srcs[" + i + "] is null");
912                         }
913                         if (srcsLen == MAX_PLAINTEXT_LENGTH) {
914                             continue;
915                         }
916 
917                         srcsLen += src.remaining();
918                         if (srcsLen > MAX_PLAINTEXT_LENGTH || srcsLen < 0) {
919                             // If srcLen > MAX_PLAINTEXT_LENGTH or secLen < 0 just set it to MAX_PLAINTEXT_LENGTH.
920                             // This also help us to guard against overflow.
921                             // We not break out here as we still need to check for null entries in srcs[].
922                             srcsLen = MAX_PLAINTEXT_LENGTH;
923                         }
924                     }
925 
926                     // jdkCompatibilityMode will only produce a single TLS packet, and we don't aggregate src buffers,
927                     // so we always fix the number of buffers to 1 when checking if the dst buffer is large enough.
928                     if (!isBytesAvailableEnoughForWrap(dst.remaining(), srcsLen, 1)) {
929                         return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
930                     }
931                 }
932 
933                 // There was no pending data in the network BIO -- encrypt any application data
934                 int bytesConsumed = 0;
935                 assert bytesProduced == 0;
936 
937                 // Flush any data that may have been written implicitly by OpenSSL in case a shutdown/alert occurs.
938                 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
939 
940                 if (bytesProduced > 0) {
941                     return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
942                 }
943                 // There was a pending exception that we just delayed because there was something to produce left.
944                 // Throw it now and shutdown the engine.
945                 if (pendingException != null) {
946                     Throwable error = pendingException;
947                     pendingException = null;
948                     shutdown();
949                     // Throw a new exception wrapping the pending exception, so the stacktrace is meaningful and
950                     // contains all the details.
951                     throw new SSLException(error);
952                 }
953 
954                 for (; offset < endOffset; ++offset) {
955                     final ByteBuffer src = srcs[offset];
956                     final int remaining = src.remaining();
957                     if (remaining == 0) {
958                         continue;
959                     }
960 
961                     final int bytesWritten;
962                     if (jdkCompatibilityMode) {
963                         // Write plaintext application data to the SSL engine. We don't have to worry about checking
964                         // if there is enough space if jdkCompatibilityMode because we only wrap at most
965                         // MAX_PLAINTEXT_LENGTH and we loop over the input before hand and check if there is space.
966                         bytesWritten = writePlaintextData(src, min(remaining, MAX_PLAINTEXT_LENGTH - bytesConsumed));
967                     } else {
968                         // OpenSSL's SSL_write keeps state between calls. We should make sure the amount we attempt to
969                         // write is guaranteed to succeed so we don't have to worry about keeping state consistent
970                         // between calls.
971                         final int availableCapacityForWrap = dst.remaining() - bytesProduced - maxWrapOverhead;
972                         if (availableCapacityForWrap <= 0) {
973                             return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed,
974                                     bytesProduced);
975                         }
976                         bytesWritten = writePlaintextData(src, min(remaining, availableCapacityForWrap));
977                     }
978 
979                     // Determine how much encrypted data was generated.
980                     //
981                     // Even if SSL_write doesn't consume any application data it is possible that OpenSSL will
982                     // produce non-application data into the BIO. For example session tickets....
983                     // See https://github.com/netty/netty/issues/10041
984                     final int pendingNow = SSL.bioLengthByteBuffer(networkBIO);
985                     bytesProduced += bioLengthBefore - pendingNow;
986                     bioLengthBefore = pendingNow;
987 
988                     if (bytesWritten > 0) {
989                         bytesConsumed += bytesWritten;
990 
991                         if (jdkCompatibilityMode || bytesProduced == dst.remaining()) {
992                             return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
993                         }
994                     } else {
995                         int sslError = SSL.getError(ssl, bytesWritten);
996                         if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
997                             // This means the connection was shutdown correctly, close inbound and outbound
998                             if (!receivedShutdown) {
999                                 closeAll();
1000 
1001                                 bytesProduced += bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
1002 
1003                                 // If we have filled up the dst buffer and we have not finished the handshake we should
1004                                 // try to wrap again. Otherwise we should only try to wrap again if there is still data
1005                                 // pending in SSL buffers.
1006                                 SSLEngineResult.HandshakeStatus hs = mayFinishHandshake(
1007                                         status != FINISHED ? bytesProduced == dst.remaining() ? NEED_WRAP
1008                                                 : getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO))
1009                                                 : FINISHED);
1010                                 return newResult(hs, bytesConsumed, bytesProduced);
1011                             }
1012 
1013                             return newResult(NOT_HANDSHAKING, bytesConsumed, bytesProduced);
1014                         } else if (sslError == SSL.SSL_ERROR_WANT_READ) {
1015                             // If there is no pending data to read from BIO we should go back to event loop and try
1016                             // to read more data [1]. It is also possible that event loop will detect the socket has
1017                             // been closed. [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
1018                             return newResult(NEED_UNWRAP, bytesConsumed, bytesProduced);
1019                         } else if (sslError == SSL.SSL_ERROR_WANT_WRITE) {
1020                             // SSL_ERROR_WANT_WRITE typically means that the underlying transport is not writable
1021                             // and we should set the "want write" flag on the selector and try again when the
1022                             // underlying transport is writable [1]. However we are not directly writing to the
1023                             // underlying transport and instead writing to a BIO buffer. The OpenSsl documentation
1024                             // says we should do the following [1]:
1025                             //
1026                             // "When using a buffering BIO, like a BIO pair, data must be written into or retrieved
1027                             // out of the BIO before being able to continue."
1028                             //
1029                             // In practice this means the destination buffer doesn't have enough space for OpenSSL
1030                             // to write encrypted data to. This is an OVERFLOW condition.
1031                             // [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
1032                             if (bytesProduced > 0) {
1033                                 // If we produced something we should report this back and let the user call
1034                                 // wrap again.
1035                                 return newResult(NEED_WRAP, bytesConsumed, bytesProduced);
1036                             }
1037                             return newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced);
1038                         } else if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP ||
1039                                 sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY ||
1040                                 sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1041 
1042                             return newResult(NEED_TASK, bytesConsumed, bytesProduced);
1043                         } else {
1044                             // Everything else is considered as error
1045                             throw shutdownWithError("SSL_write", sslError, SSL.getLastErrorNumber());
1046                         }
1047                     }
1048                 }
1049                 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
1050             } finally {
1051                 SSL.bioClearByteBuffer(networkBIO);
1052                 if (bioReadCopyBuf == null) {
1053                     dst.position(dst.position() + bytesProduced);
1054                 } else {
1055                     assert bioReadCopyBuf.readableBytes() <= dst.remaining() : "The destination buffer " + dst +
1056                             " didn't have enough remaining space to hold the encrypted content in " + bioReadCopyBuf;
1057                     dst.put(bioReadCopyBuf.internalNioBuffer(bioReadCopyBuf.readerIndex(), bytesProduced));
1058                     bioReadCopyBuf.release();
1059                 }
1060             }
1061         }
1062     }
1063 
1064     private SSLEngineResult newResult(SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) {
1065         return newResult(OK, hs, bytesConsumed, bytesProduced);
1066     }
1067 
1068     private SSLEngineResult newResult(SSLEngineResult.Status status, SSLEngineResult.HandshakeStatus hs,
1069                                       int bytesConsumed, int bytesProduced) {
1070         // If isOutboundDone, then the data from the network BIO
1071         // was the close_notify message and all was consumed we are not required to wait
1072         // for the receipt the peer's close_notify message -- shutdown.
1073         if (isOutboundDone()) {
1074             if (isInboundDone()) {
1075                 // If the inbound was done as well, we need to ensure we return NOT_HANDSHAKING to signal we are done.
1076                 hs = NOT_HANDSHAKING;
1077 
1078                 // As the inbound and the outbound is done we can shutdown the engine now.
1079                 shutdown();
1080             }
1081             return new SSLEngineResult(CLOSED, hs, bytesConsumed, bytesProduced);
1082         }
1083         if (hs == NEED_TASK) {
1084             // Set needTask to true so getHandshakeStatus() will return the correct value.
1085             needTask = true;
1086         }
1087         return new SSLEngineResult(status, hs, bytesConsumed, bytesProduced);
1088     }
1089 
1090     private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.HandshakeStatus hs,
1091                                                         int bytesConsumed, int bytesProduced) throws SSLException {
1092         return newResult(mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced);
1093     }
1094 
1095     private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status,
1096                                                         SSLEngineResult.HandshakeStatus hs,
1097                                                         int bytesConsumed, int bytesProduced) throws SSLException {
1098         return newResult(status, mayFinishHandshake(hs, bytesConsumed, bytesProduced), bytesConsumed, bytesProduced);
1099     }
1100 
1101     /**
1102      * Log the error, shutdown the engine and throw an exception.
1103      */
1104     private SSLException shutdownWithError(String operation, int sslError, int error) {
1105         if (logger.isDebugEnabled()) {
1106             String errorString = SSL.getErrorString(error);
1107             logger.debug("{} failed with {}: OpenSSL error: {} {}",
1108                          operation, sslError, error, errorString);
1109         }
1110 
1111         // There was an internal error -- shutdown
1112         shutdown();
1113 
1114         SSLException exception = newSSLExceptionForError(error);
1115         // If we have a pendingException stored already we should include it as well to help the user debug things.
1116         if (pendingException != null) {
1117             exception.initCause(pendingException);
1118             pendingException = null;
1119         }
1120         return exception;
1121     }
1122 
1123     private SSLEngineResult handleUnwrapException(int bytesConsumed, int bytesProduced, SSLException e)
1124             throws SSLException {
1125         int lastError = SSL.getLastErrorNumber();
1126         if (lastError != 0) {
1127             return sslReadErrorResult(SSL.SSL_ERROR_SSL, lastError, bytesConsumed,
1128                     bytesProduced);
1129         }
1130         throw e;
1131     }
1132 
1133     public final SSLEngineResult unwrap(
1134             final ByteBuffer[] srcs, int srcsOffset, final int srcsLength,
1135             final ByteBuffer[] dsts, int dstsOffset, final int dstsLength) throws SSLException {
1136 
1137         // Throw required runtime exceptions
1138         checkNotNullWithIAE(srcs, "srcs");
1139         if (srcsOffset >= srcs.length
1140                 || srcsOffset + srcsLength > srcs.length) {
1141             throw new IndexOutOfBoundsException(
1142                     "offset: " + srcsOffset + ", length: " + srcsLength +
1143                             " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
1144         }
1145         checkNotNullWithIAE(dsts, "dsts");
1146         if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) {
1147             throw new IndexOutOfBoundsException(
1148                     "offset: " + dstsOffset + ", length: " + dstsLength +
1149                             " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))");
1150         }
1151         long capacity = 0;
1152         final int dstsEndOffset = dstsOffset + dstsLength;
1153         for (int i = dstsOffset; i < dstsEndOffset; i ++) {
1154             ByteBuffer dst = checkNotNullArrayParam(dsts[i], i, "dsts");
1155             if (dst.isReadOnly()) {
1156                 throw new ReadOnlyBufferException();
1157             }
1158             capacity += dst.remaining();
1159         }
1160 
1161         final int srcsEndOffset = srcsOffset + srcsLength;
1162         long len = 0;
1163         for (int i = srcsOffset; i < srcsEndOffset; i++) {
1164             ByteBuffer src = checkNotNullArrayParam(srcs[i], i, "srcs");
1165             len += src.remaining();
1166         }
1167 
1168         synchronized (this) {
1169             if (isInboundDone()) {
1170                 return isOutboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_WRAP_CLOSED;
1171             }
1172 
1173             SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
1174             HandshakeState oldHandshakeState = handshakeState;
1175             // Prepare OpenSSL to work in server mode and receive handshake
1176             if (handshakeState != HandshakeState.FINISHED) {
1177                 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
1178                     // Update accepted so we know we triggered the handshake via wrap
1179                     handshakeState = HandshakeState.STARTED_IMPLICITLY;
1180                 }
1181 
1182                 status = handshake();
1183 
1184                 if (status == NEED_TASK) {
1185                     return newResult(status, 0, 0);
1186                 }
1187 
1188                 if (status == NEED_WRAP) {
1189                     return NEED_WRAP_OK;
1190                 }
1191                 // Check if the inbound is considered to be closed if so let us try to wrap again.
1192                 if (isInboundDone) {
1193                     return NEED_WRAP_CLOSED;
1194                 }
1195             }
1196 
1197             int sslPending = sslPending0();
1198             int packetLength;
1199             // The JDK implies that only a single SSL packet should be processed per unwrap call [1]. If we are in
1200             // JDK compatibility mode then we should honor this, but if not we just wrap as much as possible. If there
1201             // are multiple records or partial records this may reduce thrashing events through the pipeline.
1202             // [1] https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html
1203             if (jdkCompatibilityMode ||
1204                     // If the handshake was not finished before we entered the method, we also ensure we only
1205                     // unwrap one record. We do this to ensure we not produce any extra data before the caller
1206                     // of the method is able to observe handshake completion and react on it.
1207                     oldHandshakeState != HandshakeState.FINISHED) {
1208                 if (len < SSL_RECORD_HEADER_LENGTH) {
1209                     return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1210                 }
1211 
1212                 packetLength = SslUtils.getEncryptedPacketLength(srcs, srcsOffset);
1213                 if (packetLength == SslUtils.NOT_ENCRYPTED) {
1214                     throw new NotSslRecordException("not an SSL/TLS record");
1215                 }
1216 
1217                 assert packetLength >= 0;
1218 
1219                 final int packetLengthDataOnly = packetLength - SSL_RECORD_HEADER_LENGTH;
1220                 if (packetLengthDataOnly > capacity) {
1221                     // Not enough space in the destination buffer so signal the caller that the buffer needs to be
1222                     // increased.
1223                     if (packetLengthDataOnly > MAX_RECORD_SIZE) {
1224                         // The packet length MUST NOT exceed 2^14 [1]. However we do accommodate more data to support
1225                         // legacy use cases which may violate this condition (e.g. OpenJDK's SslEngineImpl). If the max
1226                         // length is exceeded we fail fast here to avoid an infinite loop due to the fact that we
1227                         // won't allocate a buffer large enough.
1228                         // [1] https://tools.ietf.org/html/rfc5246#section-6.2.1
1229                         throw new SSLException("Illegal packet length: " + packetLengthDataOnly + " > " +
1230                                                 session.getApplicationBufferSize());
1231                     } else {
1232                         session.tryExpandApplicationBufferSize(packetLengthDataOnly);
1233                     }
1234                     return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
1235                 }
1236 
1237                 if (len < packetLength) {
1238                     // We either don't have enough data to read the packet length or not enough for reading the whole
1239                     // packet.
1240                     return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1241                 }
1242             } else if (len == 0 && sslPending <= 0) {
1243                 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
1244             } else if (capacity == 0) {
1245                 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
1246             } else {
1247                 packetLength = (int) min(MAX_VALUE, len);
1248             }
1249 
1250             // This must always be the case when we reached here as if not we returned BUFFER_UNDERFLOW.
1251             assert srcsOffset < srcsEndOffset;
1252 
1253             // This must always be the case if we reached here.
1254             assert capacity > 0;
1255 
1256             // Number of produced bytes
1257             int bytesProduced = 0;
1258             int bytesConsumed = 0;
1259             try {
1260                 srcLoop:
1261                 for (;;) {
1262                     ByteBuffer src = srcs[srcsOffset];
1263                     int remaining = src.remaining();
1264                     final ByteBuf bioWriteCopyBuf;
1265                     int pendingEncryptedBytes;
1266                     if (remaining == 0) {
1267                         if (sslPending <= 0) {
1268                             // We must skip empty buffers as BIO_write will return 0 if asked to write something
1269                             // with length 0.
1270                             if (++srcsOffset >= srcsEndOffset) {
1271                                 break;
1272                             }
1273                             continue;
1274                         } else {
1275                             bioWriteCopyBuf = null;
1276                             pendingEncryptedBytes = SSL.bioLengthByteBuffer(networkBIO);
1277                         }
1278                     } else {
1279                         // Write more encrypted data into the BIO. Ensure we only read one packet at a time as
1280                         // stated in the SSLEngine javadocs.
1281                         pendingEncryptedBytes = min(packetLength, remaining);
1282                         try {
1283                             bioWriteCopyBuf = writeEncryptedData(src, pendingEncryptedBytes);
1284                         } catch (SSLException e) {
1285                             // Ensure we correctly handle the error stack.
1286                             return handleUnwrapException(bytesConsumed, bytesProduced, e);
1287                         }
1288                     }
1289                     try {
1290                         for (;;) {
1291                             ByteBuffer dst = dsts[dstsOffset];
1292                             if (!dst.hasRemaining()) {
1293                                 // No space left in the destination buffer, skip it.
1294                                 if (++dstsOffset >= dstsEndOffset) {
1295                                     break srcLoop;
1296                                 }
1297                                 continue;
1298                             }
1299 
1300                             int bytesRead;
1301                             try {
1302                                 bytesRead = readPlaintextData(dst);
1303                             } catch (SSLException e) {
1304                                 // Ensure we correctly handle the error stack.
1305                                 return handleUnwrapException(bytesConsumed, bytesProduced, e);
1306                             }
1307                             // We are directly using the ByteBuffer memory for the write, and so we only know what has
1308                             // been consumed after we let SSL decrypt the data. At this point we should update the
1309                             // number of bytes consumed, update the ByteBuffer position, and release temp ByteBuf.
1310                             int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO);
1311                             bytesConsumed += localBytesConsumed;
1312                             packetLength -= localBytesConsumed;
1313                             pendingEncryptedBytes -= localBytesConsumed;
1314                             src.position(src.position() + localBytesConsumed);
1315 
1316                             if (bytesRead > 0) {
1317                                 bytesProduced += bytesRead;
1318 
1319                                 if (!dst.hasRemaining()) {
1320                                     sslPending = sslPending0();
1321                                     // Move to the next dst buffer as this one is full.
1322                                     if (++dstsOffset >= dstsEndOffset) {
1323                                         return sslPending > 0 ?
1324                                                 newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced) :
1325                                                 newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1326                                                         bytesConsumed, bytesProduced);
1327                                     }
1328                                 } else if (packetLength == 0 || jdkCompatibilityMode) {
1329                                     // We either consumed all data or we are in jdkCompatibilityMode and have consumed
1330                                     // a single TLS packet and should stop consuming until this method is called again.
1331                                     break srcLoop;
1332                                 }
1333                             } else {
1334                                 int sslError = SSL.getError(ssl, bytesRead);
1335                                 if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1336                                     // break to the outer loop as we want to read more data which means we need to
1337                                     // write more to the BIO.
1338                                     break;
1339                                 } else if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
1340                                     // This means the connection was shutdown correctly, close inbound and outbound
1341                                     if (!receivedShutdown) {
1342                                         closeAll();
1343                                     }
1344                                     return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1345                                             bytesConsumed, bytesProduced);
1346                                 } else if (sslError == SSL.SSL_ERROR_WANT_X509_LOOKUP ||
1347                                         sslError == SSL.SSL_ERROR_WANT_CERTIFICATE_VERIFY ||
1348                                         sslError == SSL.SSL_ERROR_WANT_PRIVATE_KEY_OPERATION) {
1349                                     return newResult(isInboundDone() ? CLOSED : OK,
1350                                             NEED_TASK, bytesConsumed, bytesProduced);
1351                                 } else {
1352                                     return sslReadErrorResult(sslError, SSL.getLastErrorNumber(), bytesConsumed,
1353                                             bytesProduced);
1354                                 }
1355                             }
1356                         }
1357 
1358                         if (++srcsOffset >= srcsEndOffset) {
1359                             break;
1360                         }
1361                     } finally {
1362                         if (bioWriteCopyBuf != null) {
1363                             bioWriteCopyBuf.release();
1364                         }
1365                     }
1366                 }
1367             } finally {
1368                 SSL.bioClearByteBuffer(networkBIO);
1369                 rejectRemoteInitiatedRenegotiation();
1370             }
1371 
1372             // Check to see if we received a close_notify message from the peer.
1373             if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
1374                 closeAll();
1375             }
1376 
1377             return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced);
1378         }
1379     }
1380 
1381     private boolean needWrapAgain(int stackError) {
1382         // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the
1383         // BIO first or can just shutdown and throw it now.
1384         // This is needed so we ensure close_notify etc is correctly send to the remote peer.
1385         // See https://github.com/netty/netty/issues/3900
1386         if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1387             // we seem to have data left that needs to be transferred and so the user needs
1388             // call wrap(...). Store the error so we can pick it up later.
1389             if (pendingException == null) {
1390                 pendingException = newSSLExceptionForError(stackError);
1391             } else if (shouldAddSuppressed(pendingException, stackError)) {
1392                 ThrowableUtil.addSuppressed(pendingException, newSSLExceptionForError(stackError));
1393             }
1394             // We need to clear all errors so we not pick up anything that was left on the stack on the next
1395             // operation. Note that shutdownWithError(...) will cleanup the stack as well so its only needed here.
1396             SSL.clearError();
1397             return true;
1398         }
1399         return false;
1400     }
1401 
1402     private SSLException newSSLExceptionForError(int stackError) {
1403         String message = SSL.getErrorString(stackError);
1404         return handshakeState == HandshakeState.FINISHED ?
1405                 new OpenSslException(message, stackError) : new OpenSslHandshakeException(message, stackError);
1406     }
1407 
1408     private static boolean shouldAddSuppressed(Throwable target, int errorCode) {
1409         for (Throwable suppressed: ThrowableUtil.getSuppressed(target)) {
1410             if (suppressed instanceof NativeSslException &&
1411                     ((NativeSslException) suppressed).errorCode() == errorCode) {
1412                 /// An exception with this errorCode was already added before.
1413                 return false;
1414             }
1415         }
1416         return true;
1417     }
1418 
1419     private SSLEngineResult sslReadErrorResult(int error, int stackError, int bytesConsumed, int bytesProduced)
1420             throws SSLException {
1421         if (needWrapAgain(stackError)) {
1422             // There is something that needs to be send to the remote peer before we can teardown.
1423             // This is most likely some alert.
1424             return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced);
1425         }
1426         throw shutdownWithError("SSL_read", error, stackError);
1427     }
1428 
1429     private void closeAll() throws SSLException {
1430         receivedShutdown = true;
1431         closeOutbound();
1432         closeInbound();
1433     }
1434 
1435     private void rejectRemoteInitiatedRenegotiation() throws SSLHandshakeException {
1436         // As rejectRemoteInitiatedRenegotiation() is called in a finally block we also need to check if we shutdown
1437         // the engine before as otherwise SSL.getHandshakeCount(ssl) will throw an NPE if the passed in ssl is 0.
1438         // See https://github.com/netty/netty/issues/7353
1439         if (!isDestroyed() && (!clientMode && SSL.getHandshakeCount(ssl) > 1 ||
1440                 // Let's allow to renegotiate once for client auth.
1441                 clientMode && SSL.getHandshakeCount(ssl) > 2) &&
1442             // As we may count multiple handshakes when TLSv1.3 is used we should just ignore this here as
1443             // renegotiation is not supported in TLSv1.3 as per spec.
1444             !SslProtocols.TLS_v1_3.equals(session.getProtocol()) && handshakeState == HandshakeState.FINISHED) {
1445             // TODO: In future versions me may also want to send a fatal_alert to the client and so notify it
1446             // that the renegotiation failed.
1447             shutdown();
1448             throw new SSLHandshakeException("remote-initiated renegotiation not allowed");
1449         }
1450     }
1451 
1452     public final SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException {
1453         return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length);
1454     }
1455 
1456     private ByteBuffer[] singleSrcBuffer(ByteBuffer src) {
1457         singleSrcBuffer[0] = src;
1458         return singleSrcBuffer;
1459     }
1460 
1461     private void resetSingleSrcBuffer() {
1462         singleSrcBuffer[0] = null;
1463     }
1464 
1465     private ByteBuffer[] singleDstBuffer(ByteBuffer src) {
1466         singleDstBuffer[0] = src;
1467         return singleDstBuffer;
1468     }
1469 
1470     private void resetSingleDstBuffer() {
1471         singleDstBuffer[0] = null;
1472     }
1473 
1474     @Override
1475     public final synchronized SSLEngineResult unwrap(
1476             final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException {
1477         try {
1478             return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length);
1479         } finally {
1480             resetSingleSrcBuffer();
1481         }
1482     }
1483 
1484     @Override
1485     public final synchronized SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1486         try {
1487             return wrap(singleSrcBuffer(src), dst);
1488         } finally {
1489             resetSingleSrcBuffer();
1490         }
1491     }
1492 
1493     @Override
1494     public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1495         try {
1496             return unwrap(singleSrcBuffer(src), singleDstBuffer(dst));
1497         } finally {
1498             resetSingleSrcBuffer();
1499             resetSingleDstBuffer();
1500         }
1501     }
1502 
1503     @Override
1504     public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
1505         try {
1506             return unwrap(singleSrcBuffer(src), dsts);
1507         } finally {
1508             resetSingleSrcBuffer();
1509         }
1510     }
1511 
1512     private class TaskDecorator<R extends Runnable> implements Runnable {
1513         protected final R task;
1514         TaskDecorator(R task) {
1515             this.task = task;
1516         }
1517 
1518         @Override
1519         public void run() {
1520             runAndResetNeedTask(task);
1521         }
1522     }
1523 
1524     private final class AsyncTaskDecorator extends TaskDecorator<AsyncTask> implements AsyncRunnable {
1525         AsyncTaskDecorator(AsyncTask task) {
1526             super(task);
1527         }
1528 
1529         @Override
1530         public void run(final Runnable runnable) {
1531             if (isDestroyed()) {
1532                 // The engine was destroyed in the meantime, just return.
1533                 return;
1534             }
1535             task.runAsync(new TaskDecorator<Runnable>(runnable));
1536         }
1537     }
1538 
1539     private void runAndResetNeedTask(Runnable task) {
1540         // We need to synchronize on the ReferenceCountedOpenSslEngine, we are sure the SSL object
1541         // will not be freed by the user calling for example shutdown() concurrently.
1542         synchronized (ReferenceCountedOpenSslEngine.this) {
1543             try {
1544                 if (isDestroyed()) {
1545                     // The engine was destroyed in the meantime, just return.
1546                     return;
1547                 }
1548                 task.run();
1549                 if (handshakeState != HandshakeState.FINISHED && !isDestroyed()) {
1550                     // Call SSL.doHandshake(...) If the handshake was not finished yet. This might be needed
1551                     // to fill the application buffer and so have getHandshakeStatus() return the right value
1552                     // in this case.
1553                     if (SSL.doHandshake(ssl) <= 0) {
1554                         SSL.clearError();
1555                     }
1556                 }
1557             } finally {
1558                 // The task was run, reset needTask to false so getHandshakeStatus() returns the correct value.
1559                 needTask = false;
1560             }
1561         }
1562     }
1563 
1564     @Override
1565     public final synchronized Runnable getDelegatedTask() {
1566         if (isDestroyed()) {
1567             return null;
1568         }
1569         final Runnable task = SSL.getTask(ssl);
1570         if (task == null) {
1571             return null;
1572         }
1573         if (task instanceof AsyncTask) {
1574             return new AsyncTaskDecorator((AsyncTask) task);
1575         }
1576         return new TaskDecorator<Runnable>(task);
1577     }
1578 
1579     @Override
1580     public final synchronized void closeInbound() throws SSLException {
1581         if (isInboundDone) {
1582             return;
1583         }
1584 
1585         isInboundDone = true;
1586 
1587         if (isOutboundDone()) {
1588             // Only call shutdown if there is no outbound data pending.
1589             // See https://github.com/netty/netty/issues/6167
1590             shutdown();
1591         }
1592 
1593         if (handshakeState != HandshakeState.NOT_STARTED && !receivedShutdown) {
1594             throw new SSLException(
1595                     "Inbound closed before receiving peer's close_notify: possible truncation attack?");
1596         }
1597     }
1598 
1599     @Override
1600     public final synchronized boolean isInboundDone() {
1601         return isInboundDone;
1602     }
1603 
1604     @Override
1605     public final synchronized void closeOutbound() {
1606         if (outboundClosed) {
1607             return;
1608         }
1609 
1610         outboundClosed = true;
1611 
1612         if (handshakeState != HandshakeState.NOT_STARTED && !isDestroyed()) {
1613             int mode = SSL.getShutdown(ssl);
1614             if ((mode & SSL.SSL_SENT_SHUTDOWN) != SSL.SSL_SENT_SHUTDOWN) {
1615                 doSSLShutdown();
1616             }
1617         } else {
1618             // engine closing before initial handshake
1619             shutdown();
1620         }
1621     }
1622 
1623     /**
1624      * Attempt to call {@link SSL#shutdownSSL(long)}.
1625      * @return {@code false} if the call to {@link SSL#shutdownSSL(long)} was not attempted or returned an error.
1626      */
1627     private boolean doSSLShutdown() {
1628         if (SSL.isInInit(ssl) != 0) {
1629             // Only try to call SSL_shutdown if we are not in the init state anymore.
1630             // Otherwise we will see 'error:140E0197:SSL routines:SSL_shutdown:shutdown while in init' in our logs.
1631             //
1632             // See also https://hg.nginx.org/nginx/rev/062c189fee20
1633             return false;
1634         }
1635         int err = SSL.shutdownSSL(ssl);
1636         if (err < 0) {
1637             int sslErr = SSL.getError(ssl, err);
1638             if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) {
1639                 if (logger.isDebugEnabled()) {
1640                     int error = SSL.getLastErrorNumber();
1641                     logger.debug("SSL_shutdown failed: OpenSSL error: {} {}", error, SSL.getErrorString(error));
1642                 }
1643                 // There was an internal error -- shutdown
1644                 shutdown();
1645                 return false;
1646             }
1647             SSL.clearError();
1648         }
1649         return true;
1650     }
1651 
1652     @Override
1653     public final synchronized boolean isOutboundDone() {
1654         // Check if there is anything left in the outbound buffer.
1655         // We need to ensure we only call SSL.pendingWrittenBytesInBIO(...) if the engine was not destroyed yet.
1656         return outboundClosed && (networkBIO == 0 || SSL.bioLengthNonApplication(networkBIO) == 0);
1657     }
1658 
1659     @Override
1660     public final String[] getSupportedCipherSuites() {
1661         return OpenSsl.AVAILABLE_CIPHER_SUITES.toArray(EMPTY_STRINGS);
1662     }
1663 
1664     @Override
1665     public final String[] getEnabledCipherSuites() {
1666         final String[] extraCiphers;
1667         final String[] enabled;
1668         final boolean tls13Enabled;
1669         synchronized (this) {
1670             if (!isDestroyed()) {
1671                 enabled = SSL.getCiphers(ssl);
1672                 int opts = SSL.getOptions(ssl);
1673                 if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_3, SslProtocols.TLS_v1_3)) {
1674                     extraCiphers = OpenSsl.EXTRA_SUPPORTED_TLS_1_3_CIPHERS;
1675                     tls13Enabled = true;
1676                 } else {
1677                     extraCiphers = EMPTY_STRINGS;
1678                     tls13Enabled = false;
1679                 }
1680             } else {
1681                 return EMPTY_STRINGS;
1682             }
1683         }
1684         if (enabled == null) {
1685             return EMPTY_STRINGS;
1686         } else {
1687             Set<String> enabledSet = new LinkedHashSet<String>(enabled.length + extraCiphers.length);
1688             synchronized (this) {
1689                 for (int i = 0; i < enabled.length; i++) {
1690                     String mapped = toJavaCipherSuite(enabled[i]);
1691                     final String cipher = mapped == null ? enabled[i] : mapped;
1692                     if ((!tls13Enabled || !OpenSsl.isTlsv13Supported()) && SslUtils.isTLSv13Cipher(cipher)) {
1693                         continue;
1694                     }
1695                     enabledSet.add(cipher);
1696                 }
1697                 Collections.addAll(enabledSet, extraCiphers);
1698             }
1699             return enabledSet.toArray(EMPTY_STRINGS);
1700         }
1701     }
1702 
1703     @Override
1704     public final void setEnabledCipherSuites(String[] cipherSuites) {
1705         checkNotNull(cipherSuites, "cipherSuites");
1706 
1707         final StringBuilder buf = new StringBuilder();
1708         final StringBuilder bufTLSv13 = new StringBuilder();
1709 
1710         CipherSuiteConverter.convertToCipherStrings(Arrays.asList(cipherSuites), buf, bufTLSv13,
1711                 OpenSsl.isBoringSSL());
1712         final String cipherSuiteSpec = buf.toString();
1713         final String cipherSuiteSpecTLSv13 = bufTLSv13.toString();
1714 
1715         if (!OpenSsl.isTlsv13Supported() && !cipherSuiteSpecTLSv13.isEmpty()) {
1716             throw new IllegalArgumentException("TLSv1.3 is not supported by this java version.");
1717         }
1718         synchronized (this) {
1719             hasTLSv13Cipher = !cipherSuiteSpecTLSv13.isEmpty();
1720             if (!isDestroyed()) {
1721                 try {
1722                     // Set non TLSv1.3 ciphers.
1723                     SSL.setCipherSuites(ssl, cipherSuiteSpec, false);
1724                     if (OpenSsl.isTlsv13Supported()) {
1725                         // Set TLSv1.3 ciphers.
1726                         SSL.setCipherSuites(ssl, OpenSsl.checkTls13Ciphers(logger, cipherSuiteSpecTLSv13), true);
1727                     }
1728 
1729                     // We also need to update the enabled protocols to ensure we disable the protocol if there are
1730                     // no compatible ciphers left.
1731                     Set<String> protocols = new HashSet<String>(enabledProtocols);
1732 
1733                     // We have no ciphers that are compatible with none-TLSv1.3, let us explicit disable all other
1734                     // protocols.
1735                     if (cipherSuiteSpec.isEmpty()) {
1736                         protocols.remove(SslProtocols.TLS_v1);
1737                         protocols.remove(SslProtocols.TLS_v1_1);
1738                         protocols.remove(SslProtocols.TLS_v1_2);
1739                         protocols.remove(SslProtocols.SSL_v3);
1740                         protocols.remove(SslProtocols.SSL_v2);
1741                         protocols.remove(SslProtocols.SSL_v2_HELLO);
1742                     }
1743                     // We have no ciphers that are compatible with TLSv1.3, let us explicit disable it.
1744                     if (cipherSuiteSpecTLSv13.isEmpty()) {
1745                         protocols.remove(SslProtocols.TLS_v1_3);
1746                     }
1747                     // Update the protocols but not cache the value. We only cache when we call it from the user
1748                     // code or when we construct the engine.
1749                     setEnabledProtocols0(protocols.toArray(EMPTY_STRINGS), !hasTLSv13Cipher);
1750                 } catch (Exception e) {
1751                     throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e);
1752                 }
1753             } else {
1754                 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec);
1755             }
1756         }
1757     }
1758 
1759     @Override
1760     public final String[] getSupportedProtocols() {
1761         return OpenSsl.SUPPORTED_PROTOCOLS_SET.toArray(EMPTY_STRINGS);
1762     }
1763 
1764     @Override
1765     public final String[] getEnabledProtocols() {
1766         return enabledProtocols.toArray(EMPTY_STRINGS);
1767     }
1768 
1769     private static boolean isProtocolEnabled(int opts, int disableMask, String protocolString) {
1770         // We also need to check if the actual protocolString is supported as depending on the openssl API
1771         // implementations it may use a disableMask of 0 (BoringSSL is doing this for example).
1772         return (opts & disableMask) == 0 && OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(protocolString);
1773     }
1774 
1775     /**
1776      * {@inheritDoc}
1777      * TLS doesn't support a way to advertise non-contiguous versions from the client's perspective, and the client
1778      * just advertises the max supported version. The TLS protocol also doesn't support all different combinations of
1779      * discrete protocols, and instead assumes contiguous ranges. OpenSSL has some unexpected behavior
1780      * (e.g. handshake failures) if non-contiguous protocols are used even where there is a compatible set of protocols
1781      * and ciphers. For these reasons this method will determine the minimum protocol and the maximum protocol and
1782      * enabled a contiguous range from [min protocol, max protocol] in OpenSSL.
1783      */
1784     @Override
1785     public final void setEnabledProtocols(String[] protocols) {
1786         checkNotNullWithIAE(protocols, "protocols");
1787         synchronized (this) {
1788             enabledProtocols.clear();
1789             // Seems like there is no way to explicit disable SSLv2Hello in openssl, so it is always enabled
1790             enabledProtocols.add(SslProtocols.SSL_v2_HELLO);
1791 
1792             Collections.addAll(enabledProtocols, protocols);
1793 
1794             setEnabledProtocols0(protocols, !hasTLSv13Cipher);
1795         }
1796     }
1797 
1798     private void setEnabledProtocols0(String[] protocols, boolean explicitDisableTLSv13) {
1799         assert Thread.holdsLock(this);
1800         // This is correct from the API docs
1801         int minProtocolIndex = OPENSSL_OP_NO_PROTOCOLS.length;
1802         int maxProtocolIndex = 0;
1803         for (String p: protocols) {
1804             if (!OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(p)) {
1805                 throw new IllegalArgumentException("Protocol " + p + " is not supported.");
1806             }
1807             if (p.equals(SslProtocols.SSL_v2)) {
1808                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) {
1809                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1810                 }
1811                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) {
1812                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1813                 }
1814             } else if (p.equals(SslProtocols.SSL_v3)) {
1815                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) {
1816                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1817                 }
1818                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) {
1819                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1820                 }
1821             } else if (p.equals(SslProtocols.TLS_v1)) {
1822                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) {
1823                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1824                 }
1825                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) {
1826                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1827                 }
1828             } else if (p.equals(SslProtocols.TLS_v1_1)) {
1829                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) {
1830                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1831                 }
1832                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) {
1833                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1834                 }
1835             } else if (p.equals(SslProtocols.TLS_v1_2)) {
1836                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
1837                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1838                 }
1839                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
1840                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1841                 }
1842             } else if (!explicitDisableTLSv13 && p.equals(SslProtocols.TLS_v1_3)) {
1843                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3) {
1844                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3;
1845                 }
1846                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3) {
1847                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_3;
1848                 }
1849             }
1850         }
1851         if (!isDestroyed()) {
1852             // Clear out options which disable protocols
1853             SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1 |
1854                     SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2 | SSL.SSL_OP_NO_TLSv1_3);
1855 
1856             int opts = 0;
1857             for (int i = 0; i < minProtocolIndex; ++i) {
1858                 opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1859             }
1860             assert maxProtocolIndex != MAX_VALUE;
1861             for (int i = maxProtocolIndex + 1; i < OPENSSL_OP_NO_PROTOCOLS.length; ++i) {
1862                 opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1863             }
1864 
1865             // Disable protocols we do not want
1866             SSL.setOptions(ssl, opts);
1867         } else {
1868             throw new IllegalStateException("failed to enable protocols: " + Arrays.asList(protocols));
1869         }
1870     }
1871 
1872     @Override
1873     public final SSLSession getSession() {
1874         return session;
1875     }
1876 
1877     @Override
1878     public final synchronized void beginHandshake() throws SSLException {
1879         switch (handshakeState) {
1880             case STARTED_IMPLICITLY:
1881                 checkEngineClosed();
1882 
1883                 // A user did not start handshake by calling this method by him/herself,
1884                 // but handshake has been started already by wrap() or unwrap() implicitly.
1885                 // Because it's the user's first time to call this method, it is unfair to
1886                 // raise an exception.  From the user's standpoint, he or she never asked
1887                 // for renegotiation.
1888 
1889                 handshakeState = HandshakeState.STARTED_EXPLICITLY; // Next time this method is invoked by the user,
1890                 calculateMaxWrapOverhead();
1891                 // we should raise an exception.
1892                 break;
1893             case STARTED_EXPLICITLY:
1894                 // Nothing to do as the handshake is not done yet.
1895                 break;
1896             case FINISHED:
1897                 throw new SSLException("renegotiation unsupported");
1898             case NOT_STARTED:
1899                 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1900                 if (handshake() == NEED_TASK) {
1901                     // Set needTask to true so getHandshakeStatus() will return the correct value.
1902                     needTask = true;
1903                 }
1904                 calculateMaxWrapOverhead();
1905                 break;
1906             default:
1907                 throw new Error();
1908         }
1909     }
1910 
1911     private void checkEngineClosed() throws SSLException {
1912         if (isDestroyed()) {
1913             throw new SSLException("engine closed");
1914         }
1915     }
1916 
1917     private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingStatus) {
1918         // Depending on if there is something left in the BIO we need to WRAP or UNWRAP
1919         return pendingStatus > 0 ? NEED_WRAP : NEED_UNWRAP;
1920     }
1921 
1922     private static boolean isEmpty(Object[] arr) {
1923         return arr == null || arr.length == 0;
1924     }
1925 
1926     private static boolean isEmpty(byte[] cert) {
1927         return cert == null || cert.length == 0;
1928     }
1929 
1930     private SSLEngineResult.HandshakeStatus handshakeException() throws SSLException {
1931         if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1932             // There is something pending, we need to consume it first via a WRAP so we don't loose anything.
1933             return NEED_WRAP;
1934         }
1935 
1936         Throwable exception = pendingException;
1937         assert exception != null;
1938         pendingException = null;
1939         shutdown();
1940         if (exception instanceof SSLHandshakeException) {
1941             throw (SSLHandshakeException) exception;
1942         }
1943         SSLHandshakeException e = new SSLHandshakeException("General OpenSslEngine problem");
1944         e.initCause(exception);
1945         throw e;
1946     }
1947 
1948     /**
1949      * Should be called if the handshake will be failed due a callback that throws an exception.
1950      * This cause will then be used to give more details as part of the {@link SSLHandshakeException}.
1951      */
1952     final void initHandshakeException(Throwable cause) {
1953         if (pendingException == null) {
1954             pendingException = cause;
1955         } else {
1956             ThrowableUtil.addSuppressed(pendingException, cause);
1957         }
1958     }
1959 
1960     private SSLEngineResult.HandshakeStatus handshake() throws SSLException {
1961         if (needTask) {
1962             return NEED_TASK;
1963         }
1964         if (handshakeState == HandshakeState.FINISHED) {
1965             return FINISHED;
1966         }
1967 
1968         checkEngineClosed();
1969 
1970         if (pendingException != null) {
1971             // Let's call SSL.doHandshake(...) again in case there is some async operation pending that would fill the
1972             // outbound buffer.
1973             if (SSL.doHandshake(ssl) <= 0) {
1974                 // Clear any error that was put on the stack by the handshake
1975                 SSL.clearError();
1976             }
1977             return handshakeException();
1978         }
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 }