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