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