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