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