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