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