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