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