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    *   http://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.internal.tcnative.Buffer;
21  import io.netty.internal.tcnative.SSL;
22  import io.netty.util.AbstractReferenceCounted;
23  import io.netty.util.ReferenceCounted;
24  import io.netty.util.ResourceLeakDetector;
25  import io.netty.util.ResourceLeakDetectorFactory;
26  import io.netty.util.ResourceLeakTracker;
27  import io.netty.util.internal.EmptyArrays;
28  import io.netty.util.internal.PlatformDependent;
29  import io.netty.util.internal.StringUtil;
30  import io.netty.util.internal.ThrowableUtil;
31  import io.netty.util.internal.UnstableApi;
32  import io.netty.util.internal.logging.InternalLogger;
33  import io.netty.util.internal.logging.InternalLoggerFactory;
34  
35  import java.nio.ByteBuffer;
36  import java.nio.ReadOnlyBufferException;
37  import java.security.Principal;
38  import java.security.cert.Certificate;
39  import java.util.ArrayList;
40  import java.util.Arrays;
41  import java.util.Collection;
42  import java.util.HashMap;
43  import java.util.List;
44  import java.util.Map;
45  import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
46  import java.util.concurrent.locks.Lock;
47  
48  import javax.net.ssl.SSLEngine;
49  import javax.net.ssl.SSLEngineResult;
50  import javax.net.ssl.SSLException;
51  import javax.net.ssl.SSLHandshakeException;
52  import javax.net.ssl.SSLParameters;
53  import javax.net.ssl.SSLPeerUnverifiedException;
54  import javax.net.ssl.SSLSession;
55  import javax.net.ssl.SSLSessionBindingEvent;
56  import javax.net.ssl.SSLSessionBindingListener;
57  import javax.net.ssl.SSLSessionContext;
58  import javax.security.cert.X509Certificate;
59  
60  import static io.netty.handler.ssl.OpenSsl.memoryAddress;
61  import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V2;
62  import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V2_HELLO;
63  import static io.netty.handler.ssl.SslUtils.PROTOCOL_SSL_V3;
64  import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1;
65  import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_1;
66  import static io.netty.handler.ssl.SslUtils.PROTOCOL_TLS_V1_2;
67  import static io.netty.handler.ssl.SslUtils.SSL_RECORD_HEADER_LENGTH;
68  import static io.netty.internal.tcnative.SSL.SSL_MAX_PLAINTEXT_LENGTH;
69  import static io.netty.internal.tcnative.SSL.SSL_MAX_RECORD_LENGTH;
70  import static io.netty.util.internal.EmptyArrays.EMPTY_CERTIFICATES;
71  import static io.netty.util.internal.EmptyArrays.EMPTY_JAVAX_X509_CERTIFICATES;
72  import static io.netty.util.internal.ObjectUtil.checkNotNull;
73  import static java.lang.Integer.MAX_VALUE;
74  import static java.lang.Math.min;
75  import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED;
76  import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
77  import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_WRAP;
78  import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
79  import static javax.net.ssl.SSLEngineResult.Status.BUFFER_OVERFLOW;
80  import static javax.net.ssl.SSLEngineResult.Status.BUFFER_UNDERFLOW;
81  import static javax.net.ssl.SSLEngineResult.Status.CLOSED;
82  import static javax.net.ssl.SSLEngineResult.Status.OK;
83  
84  /**
85   * Implements a {@link SSLEngine} using
86   * <a href="https://www.openssl.org/docs/crypto/BIO_s_bio.html#EXAMPLE">OpenSSL BIO abstractions</a>.
87   * <p>Instances of this class must be {@link #release() released} or else native memory will leak!
88   *
89   * <p>Instances of this class <strong>must</strong> be released before the {@link ReferenceCountedOpenSslContext}
90   * the instance depends upon are released. Otherwise if any method of this class is called which uses the
91   * the {@link ReferenceCountedOpenSslContext} JNI resources the JVM may crash.
92   */
93  public class ReferenceCountedOpenSslEngine extends SSLEngine implements ReferenceCounted, ApplicationProtocolAccessor {
94  
95      private static final InternalLogger logger = InternalLoggerFactory.getInstance(ReferenceCountedOpenSslEngine.class);
96  
97      private static final SSLException BEGIN_HANDSHAKE_ENGINE_CLOSED = ThrowableUtil.unknownStackTrace(
98              new SSLException("engine closed"), ReferenceCountedOpenSslEngine.class, "beginHandshake()");
99      private static final SSLException HANDSHAKE_ENGINE_CLOSED = ThrowableUtil.unknownStackTrace(
100             new SSLException("engine closed"), ReferenceCountedOpenSslEngine.class, "handshake()");
101     private static final SSLException RENEGOTIATION_UNSUPPORTED =  ThrowableUtil.unknownStackTrace(
102             new SSLException("renegotiation unsupported"), ReferenceCountedOpenSslEngine.class, "beginHandshake()");
103     private static final ResourceLeakDetector<ReferenceCountedOpenSslEngine> leakDetector =
104             ResourceLeakDetectorFactory.instance().newResourceLeakDetector(ReferenceCountedOpenSslEngine.class);
105     private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2 = 0;
106     private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3 = 1;
107     private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1 = 2;
108     private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1 = 3;
109     private static final int OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2 = 4;
110     private static final int[] OPENSSL_OP_NO_PROTOCOLS = {
111             SSL.SSL_OP_NO_SSLv2,
112             SSL.SSL_OP_NO_SSLv3,
113             SSL.SSL_OP_NO_TLSv1,
114             SSL.SSL_OP_NO_TLSv1_1,
115             SSL.SSL_OP_NO_TLSv1_2
116     };
117     /**
118      * <a href="https://www.openssl.org/docs/man1.0.2/crypto/X509_check_host.html">The flags argument is usually 0</a>.
119      */
120     private static final int DEFAULT_HOSTNAME_VALIDATION_FLAGS = 0;
121 
122     /**
123      * Depends upon tcnative ... only use if tcnative is available!
124      */
125     static final int MAX_PLAINTEXT_LENGTH = SSL_MAX_PLAINTEXT_LENGTH;
126     /**
127      * Depends upon tcnative ... only use if tcnative is available!
128      */
129     private static final int MAX_RECORD_SIZE = SSL_MAX_RECORD_LENGTH;
130 
131     private static final AtomicIntegerFieldUpdater<ReferenceCountedOpenSslEngine> DESTROYED_UPDATER =
132             AtomicIntegerFieldUpdater.newUpdater(ReferenceCountedOpenSslEngine.class, "destroyed");
133 
134     private static final String INVALID_CIPHER = "SSL_NULL_WITH_NULL_NULL";
135     private static final SSLEngineResult NEED_UNWRAP_OK = new SSLEngineResult(OK, NEED_UNWRAP, 0, 0);
136     private static final SSLEngineResult NEED_UNWRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_UNWRAP, 0, 0);
137     private static final SSLEngineResult NEED_WRAP_OK = new SSLEngineResult(OK, NEED_WRAP, 0, 0);
138     private static final SSLEngineResult NEED_WRAP_CLOSED = new SSLEngineResult(CLOSED, NEED_WRAP, 0, 0);
139     private static final SSLEngineResult CLOSED_NOT_HANDSHAKING = new SSLEngineResult(CLOSED, NOT_HANDSHAKING, 0, 0);
140 
141     // OpenSSL state
142     private long ssl;
143     private long networkBIO;
144     private boolean certificateSet;
145 
146     private enum HandshakeState {
147         /**
148          * Not started yet.
149          */
150         NOT_STARTED,
151         /**
152          * Started via unwrap/wrap.
153          */
154         STARTED_IMPLICITLY,
155         /**
156          * Started via {@link #beginHandshake()}.
157          */
158         STARTED_EXPLICITLY,
159         /**
160          * Handshake is finished.
161          */
162         FINISHED
163     }
164 
165     private HandshakeState handshakeState = HandshakeState.NOT_STARTED;
166     private boolean receivedShutdown;
167     private volatile int destroyed;
168     private volatile String applicationProtocol;
169 
170     // Reference Counting
171     private final ResourceLeakTracker<ReferenceCountedOpenSslEngine> leak;
172     private final AbstractReferenceCounted refCnt = new AbstractReferenceCounted() {
173         @Override
174         protected void deallocate() {
175             shutdown();
176             if (leak != null) {
177                 boolean closed = leak.close(ReferenceCountedOpenSslEngine.this);
178                 assert closed;
179             }
180         }
181     };
182 
183     private volatile ClientAuth clientAuth = ClientAuth.NONE;
184 
185     // Updated once a new handshake is started and so the SSLSession reused.
186     private volatile long lastAccessed = -1;
187 
188     private String endPointIdentificationAlgorithm;
189     // Store as object as AlgorithmConstraints only exists since java 7.
190     private Object algorithmConstraints;
191     private List<String> sniHostNames;
192 
193     // Mark as volatile as accessed by checkSniHostnameMatch(...) and also not specify the SNIMatcher type to allow us
194     // using it with java7.
195     private volatile Collection<?> matchers;
196 
197     // SSL Engine status variables
198     private boolean isInboundDone;
199     private boolean outboundClosed;
200 
201     final boolean jdkCompatibilityMode;
202     private final boolean clientMode;
203     private final ByteBufAllocator alloc;
204     private final OpenSslEngineMap engineMap;
205     private final OpenSslApplicationProtocolNegotiator apn;
206     private final OpenSslSession session;
207     private final Certificate[] localCerts;
208     private final ByteBuffer[] singleSrcBuffer = new ByteBuffer[1];
209     private final ByteBuffer[] singleDstBuffer = new ByteBuffer[1];
210     private final OpenSslKeyMaterialManager keyMaterialManager;
211     private final boolean enableOcsp;
212     private int maxWrapOverhead;
213     private int maxWrapBufferSize;
214 
215     // This is package-private as we set it from OpenSslContext if an exception is thrown during
216     // the verification step.
217     SSLHandshakeException handshakeException;
218 
219     /**
220      * Create a new instance.
221      * @param context Reference count release responsibility is not transferred! The callee still owns this object.
222      * @param alloc The allocator to use.
223      * @param peerHost The peer host name.
224      * @param peerPort The peer port.
225      * @param jdkCompatibilityMode {@code true} to behave like described in
226      *                             https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html.
227      *                             {@code false} allows for partial and/or multiple packets to be process in a single
228      *                             wrap or unwrap call.
229      * @param leakDetection {@code true} to enable leak detection of this object.
230      */
231     ReferenceCountedOpenSslEngine(ReferenceCountedOpenSslContext context, ByteBufAllocator alloc, String peerHost,
232                                   int peerPort, boolean jdkCompatibilityMode, boolean leakDetection) {
233         super(peerHost, peerPort);
234         OpenSsl.ensureAvailability();
235         this.alloc = checkNotNull(alloc, "alloc");
236         apn = (OpenSslApplicationProtocolNegotiator) context.applicationProtocolNegotiator();
237         session = new OpenSslSession(context.sessionContext());
238         clientMode = context.isClient();
239         engineMap = context.engineMap;
240         localCerts = context.keyCertChain;
241         keyMaterialManager = context.keyMaterialManager();
242         enableOcsp = context.enableOcsp;
243         this.jdkCompatibilityMode = jdkCompatibilityMode;
244         Lock readerLock = context.ctxLock.readLock();
245         readerLock.lock();
246         final long finalSsl;
247         try {
248             finalSsl = SSL.newSSL(context.ctx, !context.isClient());
249         } finally {
250             readerLock.unlock();
251         }
252         synchronized (this) {
253             ssl = finalSsl;
254             try {
255                 networkBIO = SSL.bioNewByteBuffer(ssl, context.getBioNonApplicationBufferSize());
256 
257                 // Set the client auth mode, this needs to be done via setClientAuth(...) method so we actually call the
258                 // needed JNI methods.
259                 setClientAuth(clientMode ? ClientAuth.NONE : context.clientAuth);
260 
261                 if (context.protocols != null) {
262                     setEnabledProtocols(context.protocols);
263                 }
264 
265                 // Use SNI if peerHost was specified
266                 // See https://github.com/netty/netty/issues/4746
267                 if (clientMode && peerHost != null) {
268                     SSL.setTlsExtHostName(ssl, peerHost);
269                 }
270 
271                 if (enableOcsp) {
272                     SSL.enableOcsp(ssl);
273                 }
274 
275                 if (!jdkCompatibilityMode) {
276                     SSL.setMode(ssl, SSL.getMode(ssl) | SSL.SSL_MODE_ENABLE_PARTIAL_WRITE);
277                 }
278 
279                 // setMode may impact the overhead.
280                 calculateMaxWrapOverhead();
281             } catch (Throwable cause) {
282                 SSL.freeSSL(ssl);
283                 PlatformDependent.throwException(cause);
284             }
285         }
286 
287         // Only create the leak after everything else was executed and so ensure we don't produce a false-positive for
288         // the ResourceLeakDetector.
289         leak = leakDetection ? leakDetector.track(this) : null;
290     }
291 
292     /**
293      * Sets the OCSP response.
294      */
295     @UnstableApi
296     public void setOcspResponse(byte[] response) {
297         if (!enableOcsp) {
298             throw new IllegalStateException("OCSP stapling is not enabled");
299         }
300 
301         if (clientMode) {
302             throw new IllegalStateException("Not a server SSLEngine");
303         }
304 
305         synchronized (this) {
306             SSL.setOcspResponse(ssl, response);
307         }
308     }
309 
310     /**
311      * Returns the OCSP response or {@code null} if the server didn't provide a stapled OCSP response.
312      */
313     @UnstableApi
314     public byte[] getOcspResponse() {
315         if (!enableOcsp) {
316             throw new IllegalStateException("OCSP stapling is not enabled");
317         }
318 
319         if (!clientMode) {
320             throw new IllegalStateException("Not a client SSLEngine");
321         }
322 
323         synchronized (this) {
324             return SSL.getOcspResponse(ssl);
325         }
326     }
327 
328     @Override
329     public final int refCnt() {
330         return refCnt.refCnt();
331     }
332 
333     @Override
334     public final ReferenceCounted retain() {
335         refCnt.retain();
336         return this;
337     }
338 
339     @Override
340     public final ReferenceCounted retain(int increment) {
341         refCnt.retain(increment);
342         return this;
343     }
344 
345     @Override
346     public final boolean release() {
347         return refCnt.release();
348     }
349 
350     @Override
351     public final boolean release(int decrement) {
352         return refCnt.release(decrement);
353     }
354 
355     @Override
356     public final synchronized SSLSession getHandshakeSession() {
357         // Javadocs state return value should be:
358         // null if this instance is not currently handshaking, or if the current handshake has not
359         // progressed far enough to create a basic SSLSession. Otherwise, this method returns the
360         // SSLSession currently being negotiated.
361         switch(handshakeState) {
362             case NOT_STARTED:
363             case FINISHED:
364                 return null;
365             default:
366                 return session;
367         }
368     }
369 
370     /**
371      * Returns the pointer to the {@code SSL} object for this {@link ReferenceCountedOpenSslEngine}.
372      * Be aware that it is freed as soon as the {@link #release()} or {@link #shutdown()} methods are called.
373      * At this point {@code 0} will be returned.
374      */
375     public final synchronized long sslPointer() {
376         return ssl;
377     }
378 
379     /**
380      * Destroys this engine.
381      */
382     public final synchronized void shutdown() {
383         if (DESTROYED_UPDATER.compareAndSet(this, 0, 1)) {
384             engineMap.remove(ssl);
385             SSL.freeSSL(ssl);
386             ssl = networkBIO = 0;
387 
388             isInboundDone = outboundClosed = true;
389         }
390 
391         // On shutdown clear all errors
392         SSL.clearError();
393     }
394 
395     /**
396      * Write plaintext data to the OpenSSL internal BIO
397      *
398      * Calling this function with src.remaining == 0 is undefined.
399      */
400     private int writePlaintextData(final ByteBuffer src, int len) {
401         final int pos = src.position();
402         final int limit = src.limit();
403         final int sslWrote;
404 
405         if (src.isDirect()) {
406             sslWrote = SSL.writeToSSL(ssl, Buffer.address(src) + pos, len);
407             if (sslWrote > 0) {
408                 src.position(pos + sslWrote);
409             }
410         } else {
411             ByteBuf buf = alloc.directBuffer(len);
412             try {
413                 src.limit(pos + len);
414 
415                 buf.setBytes(0, src);
416                 src.limit(limit);
417 
418                 sslWrote = SSL.writeToSSL(ssl, memoryAddress(buf), len);
419                 if (sslWrote > 0) {
420                     src.position(pos + sslWrote);
421                 } else {
422                     src.position(pos);
423                 }
424             } finally {
425                 buf.release();
426             }
427         }
428         return sslWrote;
429     }
430 
431     /**
432      * Write encrypted data to the OpenSSL network BIO.
433      */
434     private ByteBuf writeEncryptedData(final ByteBuffer src, int len) {
435         final int pos = src.position();
436         if (src.isDirect()) {
437             SSL.bioSetByteBuffer(networkBIO, Buffer.address(src) + pos, len, false);
438         } else {
439             final ByteBuf buf = alloc.directBuffer(len);
440             try {
441                 final int limit = src.limit();
442                 src.limit(pos + len);
443                 buf.writeBytes(src);
444                 // Restore the original position and limit because we don't want to consume from `src`.
445                 src.position(pos);
446                 src.limit(limit);
447 
448                 SSL.bioSetByteBuffer(networkBIO, memoryAddress(buf), len, false);
449                 return buf;
450             } catch (Throwable cause) {
451                 buf.release();
452                 PlatformDependent.throwException(cause);
453             }
454         }
455         return null;
456     }
457 
458     /**
459      * Read plaintext data from the OpenSSL internal BIO
460      */
461     private int readPlaintextData(final ByteBuffer dst) {
462         final int sslRead;
463         final int pos = dst.position();
464         if (dst.isDirect()) {
465             sslRead = SSL.readFromSSL(ssl, Buffer.address(dst) + pos, dst.limit() - pos);
466             if (sslRead > 0) {
467                 dst.position(pos + sslRead);
468             }
469         } else {
470             final int limit = dst.limit();
471             final int len = min(maxEncryptedPacketLength0(), limit - pos);
472             final ByteBuf buf = alloc.directBuffer(len);
473             try {
474                 sslRead = SSL.readFromSSL(ssl, memoryAddress(buf), len);
475                 if (sslRead > 0) {
476                     dst.limit(pos + sslRead);
477                     buf.getBytes(buf.readerIndex(), dst);
478                     dst.limit(limit);
479                 }
480             } finally {
481                 buf.release();
482             }
483         }
484 
485         return sslRead;
486     }
487 
488     /**
489      * Visible only for testing!
490      */
491     final synchronized int maxWrapOverhead() {
492         return maxWrapOverhead;
493     }
494 
495     /**
496      * Visible only for testing!
497      */
498     final synchronized int maxEncryptedPacketLength() {
499         return maxEncryptedPacketLength0();
500     }
501 
502     /**
503      * This method is intentionally not synchronized, only use if you know you are in the EventLoop
504      * thread and visibility on {@link #maxWrapOverhead} is achieved via other synchronized blocks.
505      */
506     final int maxEncryptedPacketLength0() {
507         return maxWrapOverhead + MAX_PLAINTEXT_LENGTH;
508     }
509 
510     /**
511      * This method is intentionally not synchronized, only use if you know you are in the EventLoop
512      * thread and visibility on {@link #maxWrapBufferSize} and {@link #maxWrapOverhead} is achieved
513      * via other synchronized blocks.
514      */
515     final int calculateMaxLengthForWrap(int plaintextLength, int numComponents) {
516         return (int) min(maxWrapBufferSize, plaintextLength + (long) maxWrapOverhead * numComponents);
517     }
518 
519     final synchronized int sslPending() {
520         return sslPending0();
521     }
522 
523     /**
524      * It is assumed this method is called in a synchronized block (or the constructor)!
525      */
526     private void calculateMaxWrapOverhead() {
527         maxWrapOverhead = SSL.getMaxWrapOverhead(ssl);
528 
529         // maxWrapBufferSize must be set after maxWrapOverhead because there is a dependency on this value.
530         // If jdkCompatibility mode is off we allow enough space to encrypt 16 buffers at a time. This could be
531         // configurable in the future if necessary.
532         maxWrapBufferSize = jdkCompatibilityMode ? maxEncryptedPacketLength0() : maxEncryptedPacketLength0() << 4;
533     }
534 
535     private int sslPending0() {
536         // OpenSSL has a limitation where if you call SSL_pending before the handshake is complete OpenSSL will throw a
537         // "called a function you should not call" error. Using the TLS_method instead of SSLv23_method may solve this
538         // issue but this API is only available in 1.1.0+ [1].
539         // [1] https://www.openssl.org/docs/man1.1.0/ssl/SSL_CTX_new.html
540         return handshakeState != HandshakeState.FINISHED ? 0 : SSL.sslPending(ssl);
541     }
542 
543     private boolean isBytesAvailableEnoughForWrap(int bytesAvailable, int plaintextLength, int numComponents) {
544         return bytesAvailable - (long) maxWrapOverhead * numComponents >= plaintextLength;
545     }
546 
547     @Override
548     public final SSLEngineResult wrap(
549             final ByteBuffer[] srcs, int offset, final int length, final ByteBuffer dst) throws SSLException {
550         // Throw required runtime exceptions
551         if (srcs == null) {
552             throw new IllegalArgumentException("srcs is null");
553         }
554         if (dst == null) {
555             throw new IllegalArgumentException("dst is null");
556         }
557 
558         if (offset >= srcs.length || offset + length > srcs.length) {
559             throw new IndexOutOfBoundsException(
560                     "offset: " + offset + ", length: " + length +
561                             " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
562         }
563 
564         if (dst.isReadOnly()) {
565             throw new ReadOnlyBufferException();
566         }
567 
568         synchronized (this) {
569             if (isOutboundDone()) {
570                 // All drained in the outbound buffer
571                 return isInboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_UNWRAP_CLOSED;
572             }
573 
574             int bytesProduced = 0;
575             ByteBuf bioReadCopyBuf = null;
576             try {
577                 // Setup the BIO buffer so that we directly write the encryption results into dst.
578                 if (dst.isDirect()) {
579                     SSL.bioSetByteBuffer(networkBIO, Buffer.address(dst) + dst.position(), dst.remaining(),
580                             true);
581                 } else {
582                     bioReadCopyBuf = alloc.directBuffer(dst.remaining());
583                     SSL.bioSetByteBuffer(networkBIO, memoryAddress(bioReadCopyBuf), bioReadCopyBuf.writableBytes(),
584                             true);
585                 }
586 
587                 int bioLengthBefore = SSL.bioLengthByteBuffer(networkBIO);
588 
589                 // Explicit use outboundClosed as we want to drain any bytes that are still present.
590                 if (outboundClosed) {
591                     // There is something left to drain.
592                     // See https://github.com/netty/netty/issues/6260
593                     bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
594                     if (bytesProduced <= 0) {
595                         return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, 0);
596                     }
597                     // It is possible when the outbound was closed there was not enough room in the non-application
598                     // buffers to hold the close_notify. We should keep trying to close until we consume all the data
599                     // OpenSSL can give us.
600                     if (!doSSLShutdown()) {
601                         return newResultMayFinishHandshake(NOT_HANDSHAKING, 0, bytesProduced);
602                     }
603                     bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
604                     return newResultMayFinishHandshake(NEED_WRAP, 0, bytesProduced);
605                 }
606 
607                 // Flush any data that may be implicitly generated by OpenSSL (handshake, close, etc..).
608                 SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
609                 // Prepare OpenSSL to work in server mode and receive handshake
610                 if (handshakeState != HandshakeState.FINISHED) {
611                     if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
612                         // Update accepted so we know we triggered the handshake via wrap
613                         handshakeState = HandshakeState.STARTED_IMPLICITLY;
614                     }
615 
616                     // Flush any data that may have been written implicitly during the handshake by OpenSSL.
617                     bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
618 
619                     if (bytesProduced > 0 && handshakeException != null) {
620                         // TODO(scott): It is possible that when the handshake failed there was not enough room in the
621                         // non-application buffers to hold the alert. We should get all the data before progressing on.
622                         // However I'm not aware of a way to do this with the OpenSSL APIs.
623                         // See https://github.com/netty/netty/issues/6385.
624 
625                         // We produced / consumed some data during the handshake, signal back to the caller.
626                         // If there is a handshake exception and we have produced data, we should send the data before
627                         // we allow handshake() to throw the handshake exception.
628                         return newResult(NEED_WRAP, 0, bytesProduced);
629                     }
630 
631                     status = handshake();
632 
633                     // Handshake may have generated more data, for example if the internal SSL buffer is small
634                     // we may have freed up space by flushing above.
635                     bytesProduced = bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
636 
637                     if (bytesProduced > 0) {
638                         // If we have filled up the dst buffer and we have not finished the handshake we should try to
639                         // wrap again. Otherwise we should only try to wrap again if there is still data pending in
640                         // SSL buffers.
641                         return newResult(mayFinishHandshake(status != FINISHED ?
642                                          bytesProduced == bioLengthBefore ? NEED_WRAP :
643                                          getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO)) : FINISHED),
644                                          0, bytesProduced);
645                     }
646 
647                     if (status == NEED_UNWRAP) {
648                         // Signal if the outbound is done or not.
649                         return isOutboundDone() ? NEED_UNWRAP_CLOSED : NEED_UNWRAP_OK;
650                     }
651 
652                     // Explicit use outboundClosed and not outboundClosed() as we want to drain any bytes that are
653                     // still present.
654                     if (outboundClosed) {
655                         bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
656                         return newResultMayFinishHandshake(status, 0, bytesProduced);
657                     }
658                 }
659 
660                 final int endOffset = offset + length;
661                 if (jdkCompatibilityMode) {
662                     int srcsLen = 0;
663                     for (int i = offset; i < endOffset; ++i) {
664                         final ByteBuffer src = srcs[i];
665                         if (src == null) {
666                             throw new IllegalArgumentException("srcs[" + i + "] is null");
667                         }
668                         if (srcsLen == MAX_PLAINTEXT_LENGTH) {
669                             continue;
670                         }
671 
672                         srcsLen += src.remaining();
673                         if (srcsLen > MAX_PLAINTEXT_LENGTH || srcsLen < 0) {
674                             // If srcLen > MAX_PLAINTEXT_LENGTH or secLen < 0 just set it to MAX_PLAINTEXT_LENGTH.
675                             // This also help us to guard against overflow.
676                             // We not break out here as we still need to check for null entries in srcs[].
677                             srcsLen = MAX_PLAINTEXT_LENGTH;
678                         }
679                     }
680 
681                     // jdkCompatibilityMode will only produce a single TLS packet, and we don't aggregate src buffers,
682                     // so we always fix the number of buffers to 1 when checking if the dst buffer is large enough.
683                     if (!isBytesAvailableEnoughForWrap(dst.remaining(), srcsLen, 1)) {
684                         return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
685                     }
686                 }
687 
688                 // There was no pending data in the network BIO -- encrypt any application data
689                 int bytesConsumed = 0;
690                 // Flush any data that may have been written implicitly by OpenSSL in case a shutdown/alert occurs.
691                 bytesProduced = SSL.bioFlushByteBuffer(networkBIO);
692                 for (; offset < endOffset; ++offset) {
693                     final ByteBuffer src = srcs[offset];
694                     final int remaining = src.remaining();
695                     if (remaining == 0) {
696                         continue;
697                     }
698 
699                     final int bytesWritten;
700                     if (jdkCompatibilityMode) {
701                         // Write plaintext application data to the SSL engine. We don't have to worry about checking
702                         // if there is enough space if jdkCompatibilityMode because we only wrap at most
703                         // MAX_PLAINTEXT_LENGTH and we loop over the input before hand and check if there is space.
704                         bytesWritten = writePlaintextData(src, min(remaining, MAX_PLAINTEXT_LENGTH - bytesConsumed));
705                     } else {
706                         // OpenSSL's SSL_write keeps state between calls. We should make sure the amount we attempt to
707                         // write is guaranteed to succeed so we don't have to worry about keeping state consistent
708                         // between calls.
709                         final int availableCapacityForWrap = dst.remaining() - bytesProduced - maxWrapOverhead;
710                         if (availableCapacityForWrap <= 0) {
711                             return new SSLEngineResult(BUFFER_OVERFLOW, getHandshakeStatus(), bytesConsumed,
712                                     bytesProduced);
713                         }
714                         bytesWritten = writePlaintextData(src, min(remaining, availableCapacityForWrap));
715                     }
716 
717                     if (bytesWritten > 0) {
718                         bytesConsumed += bytesWritten;
719 
720                         // Determine how much encrypted data was generated:
721                         final int pendingNow = SSL.bioLengthByteBuffer(networkBIO);
722                         bytesProduced += bioLengthBefore - pendingNow;
723                         bioLengthBefore = pendingNow;
724 
725                         if (jdkCompatibilityMode || bytesProduced == dst.remaining()) {
726                             return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
727                         }
728                     } else {
729                         int sslError = SSL.getError(ssl, bytesWritten);
730                         if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
731                             // This means the connection was shutdown correctly, close inbound and outbound
732                             if (!receivedShutdown) {
733                                 closeAll();
734 
735                                 bytesProduced += bioLengthBefore - SSL.bioLengthByteBuffer(networkBIO);
736 
737                                 // If we have filled up the dst buffer and we have not finished the handshake we should
738                                 // try to wrap again. Otherwise we should only try to wrap again if there is still data
739                                 // pending in SSL buffers.
740                                 SSLEngineResult.HandshakeStatus hs = mayFinishHandshake(
741                                         status != FINISHED ? bytesProduced == dst.remaining() ? NEED_WRAP
742                                                 : getHandshakeStatus(SSL.bioLengthNonApplication(networkBIO))
743                                                 : FINISHED);
744                                 return newResult(hs, bytesConsumed, bytesProduced);
745                             }
746 
747                             return newResult(NOT_HANDSHAKING, bytesConsumed, bytesProduced);
748                         } else if (sslError == SSL.SSL_ERROR_WANT_READ) {
749                             // If there is no pending data to read from BIO we should go back to event loop and try
750                             // to read more data [1]. It is also possible that event loop will detect the socket has
751                             // been closed. [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
752                             return newResult(NEED_UNWRAP, bytesConsumed, bytesProduced);
753                         } else if (sslError == SSL.SSL_ERROR_WANT_WRITE) {
754                             // SSL_ERROR_WANT_WRITE typically means that the underlying transport is not writable
755                             // and we should set the "want write" flag on the selector and try again when the
756                             // underlying transport is writable [1]. However we are not directly writing to the
757                             // underlying transport and instead writing to a BIO buffer. The OpenSsl documentation
758                             // says we should do the following [1]:
759                             //
760                             // "When using a buffering BIO, like a BIO pair, data must be written into or retrieved
761                             // out of the BIO before being able to continue."
762                             //
763                             // In practice this means the destination buffer doesn't have enough space for OpenSSL
764                             // to write encrypted data to. This is an OVERFLOW condition.
765                             // [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
766                             return newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced);
767                         } else {
768                             // Everything else is considered as error
769                             throw shutdownWithError("SSL_write");
770                         }
771                     }
772                 }
773                 return newResultMayFinishHandshake(status, bytesConsumed, bytesProduced);
774             } finally {
775                 SSL.bioClearByteBuffer(networkBIO);
776                 if (bioReadCopyBuf == null) {
777                     dst.position(dst.position() + bytesProduced);
778                 } else {
779                     assert bioReadCopyBuf.readableBytes() <= dst.remaining() : "The destination buffer " + dst +
780                             " didn't have enough remaining space to hold the encrypted content in " + bioReadCopyBuf;
781                     dst.put(bioReadCopyBuf.internalNioBuffer(bioReadCopyBuf.readerIndex(), bytesProduced));
782                     bioReadCopyBuf.release();
783                 }
784             }
785         }
786     }
787 
788     private SSLEngineResult newResult(SSLEngineResult.HandshakeStatus hs, int bytesConsumed, int bytesProduced) {
789         return newResult(OK, hs, bytesConsumed, bytesProduced);
790     }
791 
792     private SSLEngineResult newResult(SSLEngineResult.Status status, SSLEngineResult.HandshakeStatus hs,
793                                       int bytesConsumed, int bytesProduced) {
794         // If isOutboundDone, then the data from the network BIO
795         // was the close_notify message and all was consumed we are not required to wait
796         // for the receipt the peer's close_notify message -- shutdown.
797         if (isOutboundDone()) {
798             if (isInboundDone()) {
799                 // If the inbound was done as well, we need to ensure we return NOT_HANDSHAKING to signal we are done.
800                 hs = NOT_HANDSHAKING;
801 
802                 // As the inbound and the outbound is done we can shutdown the engine now.
803                 shutdown();
804             }
805             return new SSLEngineResult(CLOSED, hs, bytesConsumed, bytesProduced);
806         }
807         return new SSLEngineResult(status, hs, bytesConsumed, bytesProduced);
808     }
809 
810     private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.HandshakeStatus hs,
811                                                         int bytesConsumed, int bytesProduced) throws SSLException {
812         return newResult(mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED),
813                          bytesConsumed, bytesProduced);
814     }
815 
816     private SSLEngineResult newResultMayFinishHandshake(SSLEngineResult.Status status,
817                                                         SSLEngineResult.HandshakeStatus hs,
818                                                         int bytesConsumed, int bytesProduced) throws SSLException {
819         return newResult(status, mayFinishHandshake(hs != FINISHED ? getHandshakeStatus() : FINISHED),
820                          bytesConsumed, bytesProduced);
821     }
822 
823     /**
824      * Log the error, shutdown the engine and throw an exception.
825      */
826     private SSLException shutdownWithError(String operations) {
827         String err = SSL.getLastError();
828         return shutdownWithError(operations, err);
829     }
830 
831     private SSLException shutdownWithError(String operation, String err) {
832         if (logger.isDebugEnabled()) {
833             logger.debug("{} failed: OpenSSL error: {}", operation, err);
834         }
835 
836         // There was an internal error -- shutdown
837         shutdown();
838         if (handshakeState == HandshakeState.FINISHED) {
839             return new SSLException(err);
840         }
841         return new SSLHandshakeException(err);
842     }
843 
844     public final SSLEngineResult unwrap(
845             final ByteBuffer[] srcs, int srcsOffset, final int srcsLength,
846             final ByteBuffer[] dsts, int dstsOffset, final int dstsLength) throws SSLException {
847 
848         // Throw required runtime exceptions
849         if (srcs == null) {
850             throw new NullPointerException("srcs");
851         }
852         if (srcsOffset >= srcs.length
853                 || srcsOffset + srcsLength > srcs.length) {
854             throw new IndexOutOfBoundsException(
855                     "offset: " + srcsOffset + ", length: " + srcsLength +
856                             " (expected: offset <= offset + length <= srcs.length (" + srcs.length + "))");
857         }
858         if (dsts == null) {
859             throw new IllegalArgumentException("dsts is null");
860         }
861         if (dstsOffset >= dsts.length || dstsOffset + dstsLength > dsts.length) {
862             throw new IndexOutOfBoundsException(
863                     "offset: " + dstsOffset + ", length: " + dstsLength +
864                             " (expected: offset <= offset + length <= dsts.length (" + dsts.length + "))");
865         }
866         long capacity = 0;
867         final int dstsEndOffset = dstsOffset + dstsLength;
868         for (int i = dstsOffset; i < dstsEndOffset; i ++) {
869             ByteBuffer dst = dsts[i];
870             if (dst == null) {
871                 throw new IllegalArgumentException("dsts[" + i + "] is null");
872             }
873             if (dst.isReadOnly()) {
874                 throw new ReadOnlyBufferException();
875             }
876             capacity += dst.remaining();
877         }
878 
879         final int srcsEndOffset = srcsOffset + srcsLength;
880         long len = 0;
881         for (int i = srcsOffset; i < srcsEndOffset; i++) {
882             ByteBuffer src = srcs[i];
883             if (src == null) {
884                 throw new IllegalArgumentException("srcs[" + i + "] is null");
885             }
886             len += src.remaining();
887         }
888 
889         synchronized (this) {
890             if (isInboundDone()) {
891                 return isOutboundDone() || isDestroyed() ? CLOSED_NOT_HANDSHAKING : NEED_WRAP_CLOSED;
892             }
893 
894             SSLEngineResult.HandshakeStatus status = NOT_HANDSHAKING;
895             // Prepare OpenSSL to work in server mode and receive handshake
896             if (handshakeState != HandshakeState.FINISHED) {
897                 if (handshakeState != HandshakeState.STARTED_EXPLICITLY) {
898                     // Update accepted so we know we triggered the handshake via wrap
899                     handshakeState = HandshakeState.STARTED_IMPLICITLY;
900                 }
901 
902                 status = handshake();
903                 if (status == NEED_WRAP) {
904                     return NEED_WRAP_OK;
905                 }
906                 // Check if the inbound is considered to be closed if so let us try to wrap again.
907                 if (isInboundDone) {
908                     return NEED_WRAP_CLOSED;
909                 }
910             }
911 
912             int sslPending = sslPending0();
913             int packetLength;
914             // The JDK implies that only a single SSL packet should be processed per unwrap call [1]. If we are in
915             // JDK compatibility mode then we should honor this, but if not we just wrap as much as possible. If there
916             // are multiple records or partial records this may reduce thrashing events through the pipeline.
917             // [1] https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html
918             if (jdkCompatibilityMode) {
919                 if (len < SSL_RECORD_HEADER_LENGTH) {
920                     return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
921                 }
922 
923                 packetLength = SslUtils.getEncryptedPacketLength(srcs, srcsOffset);
924                 if (packetLength == SslUtils.NOT_ENCRYPTED) {
925                     throw new NotSslRecordException("not an SSL/TLS record");
926                 }
927 
928                 final int packetLengthDataOnly = packetLength - SSL_RECORD_HEADER_LENGTH;
929                 if (packetLengthDataOnly > capacity) {
930                     // Not enough space in the destination buffer so signal the caller that the buffer needs to be
931                     // increased.
932                     if (packetLengthDataOnly > MAX_RECORD_SIZE) {
933                         // The packet length MUST NOT exceed 2^14 [1]. However we do accommodate more data to support
934                         // legacy use cases which may violate this condition (e.g. OpenJDK's SslEngineImpl). If the max
935                         // length is exceeded we fail fast here to avoid an infinite loop due to the fact that we
936                         // won't allocate a buffer large enough.
937                         // [1] https://tools.ietf.org/html/rfc5246#section-6.2.1
938                         throw new SSLException("Illegal packet length: " + packetLengthDataOnly + " > " +
939                                                 session.getApplicationBufferSize());
940                     } else {
941                         session.tryExpandApplicationBufferSize(packetLengthDataOnly);
942                     }
943                     return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
944                 }
945 
946                 if (len < packetLength) {
947                     // We either don't have enough data to read the packet length or not enough for reading the whole
948                     // packet.
949                     return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
950                 }
951             } else if (len == 0 && sslPending <= 0) {
952                 return newResultMayFinishHandshake(BUFFER_UNDERFLOW, status, 0, 0);
953             } else if (capacity == 0) {
954                 return newResultMayFinishHandshake(BUFFER_OVERFLOW, status, 0, 0);
955             } else {
956                 packetLength = (int) min(MAX_VALUE, len);
957             }
958 
959             // This must always be the case when we reached here as if not we returned BUFFER_UNDERFLOW.
960             assert srcsOffset < srcsEndOffset;
961 
962             // This must always be the case if we reached here.
963             assert capacity > 0;
964 
965             // Number of produced bytes
966             int bytesProduced = 0;
967             int bytesConsumed = 0;
968             try {
969                 srcLoop:
970                 for (;;) {
971                     ByteBuffer src = srcs[srcsOffset];
972                     int remaining = src.remaining();
973                     final ByteBuf bioWriteCopyBuf;
974                     int pendingEncryptedBytes;
975                     if (remaining == 0) {
976                         if (sslPending <= 0) {
977                             // We must skip empty buffers as BIO_write will return 0 if asked to write something
978                             // with length 0.
979                             if (++srcsOffset >= srcsEndOffset) {
980                                 break;
981                             }
982                             continue;
983                         } else {
984                             bioWriteCopyBuf = null;
985                             pendingEncryptedBytes = SSL.bioLengthByteBuffer(networkBIO);
986                         }
987                     } else {
988                         // Write more encrypted data into the BIO. Ensure we only read one packet at a time as
989                         // stated in the SSLEngine javadocs.
990                         pendingEncryptedBytes = min(packetLength, remaining);
991                         bioWriteCopyBuf = writeEncryptedData(src, pendingEncryptedBytes);
992                     }
993                     try {
994                         for (;;) {
995                             ByteBuffer dst = dsts[dstsOffset];
996                             if (!dst.hasRemaining()) {
997                                 // No space left in the destination buffer, skip it.
998                                 if (++dstsOffset >= dstsEndOffset) {
999                                     break srcLoop;
1000                                 }
1001                                 continue;
1002                             }
1003 
1004                             int bytesRead = readPlaintextData(dst);
1005                             // We are directly using the ByteBuffer memory for the write, and so we only know what has
1006                             // been consumed after we let SSL decrypt the data. At this point we should update the
1007                             // number of bytes consumed, update the ByteBuffer position, and release temp ByteBuf.
1008                             int localBytesConsumed = pendingEncryptedBytes - SSL.bioLengthByteBuffer(networkBIO);
1009                             bytesConsumed += localBytesConsumed;
1010                             packetLength -= localBytesConsumed;
1011                             pendingEncryptedBytes -= localBytesConsumed;
1012                             src.position(src.position() + localBytesConsumed);
1013 
1014                             if (bytesRead > 0) {
1015                                 bytesProduced += bytesRead;
1016 
1017                                 if (!dst.hasRemaining()) {
1018                                     sslPending = sslPending0();
1019                                     // Move to the next dst buffer as this one is full.
1020                                     if (++dstsOffset >= dstsEndOffset) {
1021                                         return sslPending > 0 ?
1022                                                 newResult(BUFFER_OVERFLOW, status, bytesConsumed, bytesProduced) :
1023                                                 newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1024                                                                             bytesConsumed, bytesProduced);
1025                                     }
1026                                 } else if (packetLength == 0 || jdkCompatibilityMode) {
1027                                     // We either consumed all data or we are in jdkCompatibilityMode and have consumed
1028                                     // a single TLS packet and should stop consuming until this method is called again.
1029                                     break srcLoop;
1030                                 }
1031                             } else {
1032                                 int sslError = SSL.getError(ssl, bytesRead);
1033                                 if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1034                                     // break to the outer loop as we want to read more data which means we need to
1035                                     // write more to the BIO.
1036                                     break;
1037                                 } else if (sslError == SSL.SSL_ERROR_ZERO_RETURN) {
1038                                     // This means the connection was shutdown correctly, close inbound and outbound
1039                                     if (!receivedShutdown) {
1040                                         closeAll();
1041                                     }
1042                                     return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status,
1043                                                                        bytesConsumed, bytesProduced);
1044                                 } else {
1045                                     return sslReadErrorResult(SSL.getLastErrorNumber(), bytesConsumed,
1046                                                               bytesProduced);
1047                                 }
1048                             }
1049                         }
1050 
1051                         if (++srcsOffset >= srcsEndOffset) {
1052                             break;
1053                         }
1054                     } finally {
1055                         if (bioWriteCopyBuf != null) {
1056                             bioWriteCopyBuf.release();
1057                         }
1058                     }
1059                 }
1060             } finally {
1061                 SSL.bioClearByteBuffer(networkBIO);
1062                 rejectRemoteInitiatedRenegotiation();
1063             }
1064 
1065             // Check to see if we received a close_notify message from the peer.
1066             if (!receivedShutdown && (SSL.getShutdown(ssl) & SSL.SSL_RECEIVED_SHUTDOWN) == SSL.SSL_RECEIVED_SHUTDOWN) {
1067                 closeAll();
1068             }
1069 
1070             return newResultMayFinishHandshake(isInboundDone() ? CLOSED : OK, status, bytesConsumed, bytesProduced);
1071         }
1072     }
1073 
1074     private SSLEngineResult sslReadErrorResult(int err, int bytesConsumed, int bytesProduced) throws SSLException {
1075         String errStr = SSL.getErrorString(err);
1076 
1077         // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the
1078         // BIO first or can just shutdown and throw it now.
1079         // This is needed so we ensure close_notify etc is correctly send to the remote peer.
1080         // See https://github.com/netty/netty/issues/3900
1081         if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1082             if (handshakeException == null && handshakeState != HandshakeState.FINISHED) {
1083                 // we seems to have data left that needs to be transfered and so the user needs
1084                 // call wrap(...). Store the error so we can pick it up later.
1085                 handshakeException = new SSLHandshakeException(errStr);
1086             }
1087             return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced);
1088         }
1089         throw shutdownWithError("SSL_read", errStr);
1090     }
1091 
1092     private void closeAll() throws SSLException {
1093         receivedShutdown = true;
1094         closeOutbound();
1095         closeInbound();
1096     }
1097 
1098     private void rejectRemoteInitiatedRenegotiation() throws SSLHandshakeException {
1099         // As rejectRemoteInitiatedRenegotiation() is called in a finally block we also need to check if we shutdown
1100         // the engine before as otherwise SSL.getHandshakeCount(ssl) will throw an NPE if the passed in ssl is 0.
1101         // See https://github.com/netty/netty/issues/7353
1102         if (!isDestroyed() && SSL.getHandshakeCount(ssl) > 1) {
1103             // TODO: In future versions me may also want to send a fatal_alert to the client and so notify it
1104             // that the renegotiation failed.
1105             shutdown();
1106             throw new SSLHandshakeException("remote-initiated renegotiation not allowed");
1107         }
1108     }
1109 
1110     public final SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException {
1111         return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length);
1112     }
1113 
1114     private ByteBuffer[] singleSrcBuffer(ByteBuffer src) {
1115         singleSrcBuffer[0] = src;
1116         return singleSrcBuffer;
1117     }
1118 
1119     private void resetSingleSrcBuffer() {
1120         singleSrcBuffer[0] = null;
1121     }
1122 
1123     private ByteBuffer[] singleDstBuffer(ByteBuffer src) {
1124         singleDstBuffer[0] = src;
1125         return singleDstBuffer;
1126     }
1127 
1128     private void resetSingleDstBuffer() {
1129         singleDstBuffer[0] = null;
1130     }
1131 
1132     @Override
1133     public final synchronized SSLEngineResult unwrap(
1134             final ByteBuffer src, final ByteBuffer[] dsts, final int offset, final int length) throws SSLException {
1135         try {
1136             return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length);
1137         } finally {
1138             resetSingleSrcBuffer();
1139         }
1140     }
1141 
1142     @Override
1143     public final synchronized SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1144         try {
1145             return wrap(singleSrcBuffer(src), dst);
1146         } finally {
1147             resetSingleSrcBuffer();
1148         }
1149     }
1150 
1151     @Override
1152     public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1153         try {
1154             return unwrap(singleSrcBuffer(src), singleDstBuffer(dst));
1155         } finally {
1156             resetSingleSrcBuffer();
1157             resetSingleDstBuffer();
1158         }
1159     }
1160 
1161     @Override
1162     public final synchronized SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
1163         try {
1164             return unwrap(singleSrcBuffer(src), dsts);
1165         } finally {
1166             resetSingleSrcBuffer();
1167         }
1168     }
1169 
1170     @Override
1171     public final Runnable getDelegatedTask() {
1172         // Currently, we do not delegate SSL computation tasks
1173         // TODO: in the future, possibly create tasks to do encrypt / decrypt async
1174         return null;
1175     }
1176 
1177     @Override
1178     public final synchronized void closeInbound() throws SSLException {
1179         if (isInboundDone) {
1180             return;
1181         }
1182 
1183         isInboundDone = true;
1184 
1185         if (isOutboundDone()) {
1186             // Only call shutdown if there is no outbound data pending.
1187             // See https://github.com/netty/netty/issues/6167
1188             shutdown();
1189         }
1190 
1191         if (handshakeState != HandshakeState.NOT_STARTED && !receivedShutdown) {
1192             throw new SSLException(
1193                     "Inbound closed before receiving peer's close_notify: possible truncation attack?");
1194         }
1195     }
1196 
1197     @Override
1198     public final synchronized boolean isInboundDone() {
1199         return isInboundDone;
1200     }
1201 
1202     @Override
1203     public final synchronized void closeOutbound() {
1204         if (outboundClosed) {
1205             return;
1206         }
1207 
1208         outboundClosed = true;
1209 
1210         if (handshakeState != HandshakeState.NOT_STARTED && !isDestroyed()) {
1211             int mode = SSL.getShutdown(ssl);
1212             if ((mode & SSL.SSL_SENT_SHUTDOWN) != SSL.SSL_SENT_SHUTDOWN) {
1213                 doSSLShutdown();
1214             }
1215         } else {
1216             // engine closing before initial handshake
1217             shutdown();
1218         }
1219     }
1220 
1221     /**
1222      * Attempt to call {@link SSL#shutdownSSL(long)}.
1223      * @return {@code false} if the call to {@link SSL#shutdownSSL(long)} was not attempted or returned an error.
1224      */
1225     private boolean doSSLShutdown() {
1226         if (SSL.isInInit(ssl) != 0) {
1227             // Only try to call SSL_shutdown if we are not in the init state anymore.
1228             // Otherwise we will see 'error:140E0197:SSL routines:SSL_shutdown:shutdown while in init' in our logs.
1229             //
1230             // See also http://hg.nginx.org/nginx/rev/062c189fee20
1231             return false;
1232         }
1233         int err = SSL.shutdownSSL(ssl);
1234         if (err < 0) {
1235             int sslErr = SSL.getError(ssl, err);
1236             if (sslErr == SSL.SSL_ERROR_SYSCALL || sslErr == SSL.SSL_ERROR_SSL) {
1237                 if (logger.isDebugEnabled()) {
1238                     logger.debug("SSL_shutdown failed: OpenSSL error: {}", SSL.getLastError());
1239                 }
1240                 // There was an internal error -- shutdown
1241                 shutdown();
1242                 return false;
1243             }
1244             SSL.clearError();
1245         }
1246         return true;
1247     }
1248 
1249     @Override
1250     public final synchronized boolean isOutboundDone() {
1251         // Check if there is anything left in the outbound buffer.
1252         // We need to ensure we only call SSL.pendingWrittenBytesInBIO(...) if the engine was not destroyed yet.
1253         return outboundClosed && (networkBIO == 0 || SSL.bioLengthNonApplication(networkBIO) == 0);
1254     }
1255 
1256     @Override
1257     public final String[] getSupportedCipherSuites() {
1258         return OpenSsl.AVAILABLE_CIPHER_SUITES.toArray(new String[OpenSsl.AVAILABLE_CIPHER_SUITES.size()]);
1259     }
1260 
1261     @Override
1262     public final String[] getEnabledCipherSuites() {
1263         final String[] enabled;
1264         synchronized (this) {
1265             if (!isDestroyed()) {
1266                 enabled = SSL.getCiphers(ssl);
1267             } else {
1268                 return EmptyArrays.EMPTY_STRINGS;
1269             }
1270         }
1271         if (enabled == null) {
1272             return EmptyArrays.EMPTY_STRINGS;
1273         } else {
1274             synchronized (this) {
1275                 for (int i = 0; i < enabled.length; i++) {
1276                     String mapped = toJavaCipherSuite(enabled[i]);
1277                     if (mapped != null) {
1278                         enabled[i] = mapped;
1279                     }
1280                 }
1281             }
1282             return enabled;
1283         }
1284     }
1285 
1286     @Override
1287     public final void setEnabledCipherSuites(String[] cipherSuites) {
1288         checkNotNull(cipherSuites, "cipherSuites");
1289 
1290         final StringBuilder buf = new StringBuilder();
1291         for (String c: cipherSuites) {
1292             if (c == null) {
1293                 break;
1294             }
1295 
1296             String converted = CipherSuiteConverter.toOpenSsl(c);
1297             if (converted == null) {
1298                 converted = c;
1299             }
1300 
1301             if (!OpenSsl.isCipherSuiteAvailable(converted)) {
1302                 throw new IllegalArgumentException("unsupported cipher suite: " + c + '(' + converted + ')');
1303             }
1304 
1305             buf.append(converted);
1306             buf.append(':');
1307         }
1308 
1309         if (buf.length() == 0) {
1310             throw new IllegalArgumentException("empty cipher suites");
1311         }
1312         buf.setLength(buf.length() - 1);
1313 
1314         final String cipherSuiteSpec = buf.toString();
1315 
1316         synchronized (this) {
1317             if (!isDestroyed()) {
1318                 try {
1319                     SSL.setCipherSuites(ssl, cipherSuiteSpec);
1320                 } catch (Exception e) {
1321                     throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec, e);
1322                 }
1323             } else {
1324                 throw new IllegalStateException("failed to enable cipher suites: " + cipherSuiteSpec);
1325             }
1326         }
1327     }
1328 
1329     @Override
1330     public final String[] getSupportedProtocols() {
1331         return OpenSsl.SUPPORTED_PROTOCOLS_SET.toArray(new String[OpenSsl.SUPPORTED_PROTOCOLS_SET.size()]);
1332     }
1333 
1334     @Override
1335     public final String[] getEnabledProtocols() {
1336         List<String> enabled = new ArrayList<String>(6);
1337         // Seems like there is no way to explicit disable SSLv2Hello in openssl so it is always enabled
1338         enabled.add(PROTOCOL_SSL_V2_HELLO);
1339 
1340         int opts;
1341         synchronized (this) {
1342             if (!isDestroyed()) {
1343                 opts = SSL.getOptions(ssl);
1344             } else {
1345                 return enabled.toArray(new String[1]);
1346             }
1347         }
1348         if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1, PROTOCOL_TLS_V1)) {
1349             enabled.add(PROTOCOL_TLS_V1);
1350         }
1351         if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_1, PROTOCOL_TLS_V1_1)) {
1352             enabled.add(PROTOCOL_TLS_V1_1);
1353         }
1354         if (isProtocolEnabled(opts, SSL.SSL_OP_NO_TLSv1_2, PROTOCOL_TLS_V1_2)) {
1355             enabled.add(PROTOCOL_TLS_V1_2);
1356         }
1357         if (isProtocolEnabled(opts, SSL.SSL_OP_NO_SSLv2, PROTOCOL_SSL_V2)) {
1358             enabled.add(PROTOCOL_SSL_V2);
1359         }
1360         if (isProtocolEnabled(opts, SSL.SSL_OP_NO_SSLv3, PROTOCOL_SSL_V3)) {
1361             enabled.add(PROTOCOL_SSL_V3);
1362         }
1363         return enabled.toArray(new String[enabled.size()]);
1364     }
1365 
1366     private static boolean isProtocolEnabled(int opts, int disableMask, String protocolString) {
1367         // We also need to check if the actual protocolString is supported as depending on the openssl API
1368         // implementations it may use a disableMask of 0 (BoringSSL is doing this for example).
1369         return (opts & disableMask) == 0 && OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(protocolString);
1370     }
1371 
1372     /**
1373      * {@inheritDoc}
1374      * TLS doesn't support a way to advertise non-contiguous versions from the client's perspective, and the client
1375      * just advertises the max supported version. The TLS protocol also doesn't support all different combinations of
1376      * discrete protocols, and instead assumes contiguous ranges. OpenSSL has some unexpected behavior
1377      * (e.g. handshake failures) if non-contiguous protocols are used even where there is a compatible set of protocols
1378      * and ciphers. For these reasons this method will determine the minimum protocol and the maximum protocol and
1379      * enabled a contiguous range from [min protocol, max protocol] in OpenSSL.
1380      */
1381     @Override
1382     public final void setEnabledProtocols(String[] protocols) {
1383         if (protocols == null) {
1384             // This is correct from the API docs
1385             throw new IllegalArgumentException();
1386         }
1387         int minProtocolIndex = OPENSSL_OP_NO_PROTOCOLS.length;
1388         int maxProtocolIndex = 0;
1389         for (String p: protocols) {
1390             if (!OpenSsl.SUPPORTED_PROTOCOLS_SET.contains(p)) {
1391                 throw new IllegalArgumentException("Protocol " + p + " is not supported.");
1392             }
1393             if (p.equals(PROTOCOL_SSL_V2)) {
1394                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) {
1395                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1396                 }
1397                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2) {
1398                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV2;
1399                 }
1400             } else if (p.equals(PROTOCOL_SSL_V3)) {
1401                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) {
1402                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1403                 }
1404                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3) {
1405                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_SSLV3;
1406                 }
1407             } else if (p.equals(PROTOCOL_TLS_V1)) {
1408                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) {
1409                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1410                 }
1411                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1) {
1412                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1;
1413                 }
1414             } else if (p.equals(PROTOCOL_TLS_V1_1)) {
1415                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) {
1416                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1417                 }
1418                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1) {
1419                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_1;
1420                 }
1421             } else if (p.equals(PROTOCOL_TLS_V1_2)) {
1422                 if (minProtocolIndex > OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
1423                     minProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1424                 }
1425                 if (maxProtocolIndex < OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2) {
1426                     maxProtocolIndex = OPENSSL_OP_NO_PROTOCOL_INDEX_TLSv1_2;
1427                 }
1428             }
1429         }
1430         synchronized (this) {
1431             if (!isDestroyed()) {
1432                 // Clear out options which disable protocols
1433                 SSL.clearOptions(ssl, SSL.SSL_OP_NO_SSLv2 | SSL.SSL_OP_NO_SSLv3 | SSL.SSL_OP_NO_TLSv1 |
1434                                       SSL.SSL_OP_NO_TLSv1_1 | SSL.SSL_OP_NO_TLSv1_2);
1435 
1436                 int opts = 0;
1437                 for (int i = 0; i < minProtocolIndex; ++i) {
1438                     opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1439                 }
1440                 assert maxProtocolIndex != MAX_VALUE;
1441                 for (int i = maxProtocolIndex + 1; i < OPENSSL_OP_NO_PROTOCOLS.length; ++i) {
1442                     opts |= OPENSSL_OP_NO_PROTOCOLS[i];
1443                 }
1444 
1445                 // Disable protocols we do not want
1446                 SSL.setOptions(ssl, opts);
1447             } else {
1448                 throw new IllegalStateException("failed to enable protocols: " + Arrays.asList(protocols));
1449             }
1450         }
1451     }
1452 
1453     @Override
1454     public final SSLSession getSession() {
1455         return session;
1456     }
1457 
1458     @Override
1459     public final synchronized void beginHandshake() throws SSLException {
1460         switch (handshakeState) {
1461             case STARTED_IMPLICITLY:
1462                 checkEngineClosed(BEGIN_HANDSHAKE_ENGINE_CLOSED);
1463 
1464                 // A user did not start handshake by calling this method by him/herself,
1465                 // but handshake has been started already by wrap() or unwrap() implicitly.
1466                 // Because it's the user's first time to call this method, it is unfair to
1467                 // raise an exception.  From the user's standpoint, he or she never asked
1468                 // for renegotiation.
1469 
1470                 handshakeState = HandshakeState.STARTED_EXPLICITLY; // Next time this method is invoked by the user,
1471                 calculateMaxWrapOverhead();
1472                 // we should raise an exception.
1473                 break;
1474             case STARTED_EXPLICITLY:
1475                 // Nothing to do as the handshake is not done yet.
1476                 break;
1477             case FINISHED:
1478                 throw RENEGOTIATION_UNSUPPORTED;
1479             case NOT_STARTED:
1480                 handshakeState = HandshakeState.STARTED_EXPLICITLY;
1481                 handshake();
1482                 calculateMaxWrapOverhead();
1483                 break;
1484             default:
1485                 throw new Error();
1486         }
1487     }
1488 
1489     private void checkEngineClosed(SSLException cause) throws SSLException {
1490         if (isDestroyed()) {
1491             throw cause;
1492         }
1493     }
1494 
1495     private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingStatus) {
1496         // Depending on if there is something left in the BIO we need to WRAP or UNWRAP
1497         return pendingStatus > 0 ? NEED_WRAP : NEED_UNWRAP;
1498     }
1499 
1500     private static boolean isEmpty(Object[] arr) {
1501         return arr == null || arr.length == 0;
1502     }
1503 
1504     private static boolean isEmpty(byte[] cert) {
1505         return cert == null || cert.length == 0;
1506     }
1507 
1508     private SSLEngineResult.HandshakeStatus handshake() throws SSLException {
1509         if (handshakeState == HandshakeState.FINISHED) {
1510             return FINISHED;
1511         }
1512         checkEngineClosed(HANDSHAKE_ENGINE_CLOSED);
1513 
1514         // Check if we have a pending handshakeException and if so see if we need to consume all pending data from the
1515         // BIO first or can just shutdown and throw it now.
1516         // This is needed so we ensure close_notify etc is correctly send to the remote peer.
1517         // See https://github.com/netty/netty/issues/3900
1518         SSLHandshakeException exception = handshakeException;
1519         if (exception != null) {
1520             if (SSL.bioLengthNonApplication(networkBIO) > 0) {
1521                 // There is something pending, we need to consume it first via a WRAP so we don't loose anything.
1522                 return NEED_WRAP;
1523             }
1524             // No more data left to send to the remote peer, so null out the exception field, shutdown and throw
1525             // the exception.
1526             handshakeException = null;
1527             shutdown();
1528             throw exception;
1529         }
1530 
1531         // Adding the OpenSslEngine to the OpenSslEngineMap so it can be used in the AbstractCertificateVerifier.
1532         engineMap.add(this);
1533         if (lastAccessed == -1) {
1534             lastAccessed = System.currentTimeMillis();
1535         }
1536 
1537         if (!certificateSet && keyMaterialManager != null) {
1538             certificateSet = true;
1539             keyMaterialManager.setKeyMaterial(this);
1540         }
1541 
1542         int code = SSL.doHandshake(ssl);
1543         if (code <= 0) {
1544             // Check if we have a pending exception that was created during the handshake and if so throw it after
1545             // shutdown the connection.
1546             if (handshakeException != null) {
1547                 exception = handshakeException;
1548                 handshakeException = null;
1549                 shutdown();
1550                 throw exception;
1551             }
1552 
1553             int sslError = SSL.getError(ssl, code);
1554             if (sslError == SSL.SSL_ERROR_WANT_READ || sslError == SSL.SSL_ERROR_WANT_WRITE) {
1555                 return pendingStatus(SSL.bioLengthNonApplication(networkBIO));
1556             } else {
1557                 // Everything else is considered as error
1558                 throw shutdownWithError("SSL_do_handshake");
1559             }
1560         }
1561         // if SSL_do_handshake returns > 0 or sslError == SSL.SSL_ERROR_NAME it means the handshake was finished.
1562         session.handshakeFinished();
1563         engineMap.remove(ssl);
1564         return FINISHED;
1565     }
1566 
1567     private SSLEngineResult.HandshakeStatus mayFinishHandshake(SSLEngineResult.HandshakeStatus status)
1568             throws SSLException {
1569         if (status == NOT_HANDSHAKING && handshakeState != HandshakeState.FINISHED) {
1570             // If the status was NOT_HANDSHAKING and we not finished the handshake we need to call
1571             // SSL_do_handshake() again
1572             return handshake();
1573         }
1574         return status;
1575     }
1576 
1577     @Override
1578     public final synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
1579         // Check if we are in the initial handshake phase or shutdown phase
1580         return needPendingStatus() ? pendingStatus(SSL.bioLengthNonApplication(networkBIO)) : NOT_HANDSHAKING;
1581     }
1582 
1583     private SSLEngineResult.HandshakeStatus getHandshakeStatus(int pending) {
1584         // Check if we are in the initial handshake phase or shutdown phase
1585         return needPendingStatus() ? pendingStatus(pending) : NOT_HANDSHAKING;
1586     }
1587 
1588     private boolean needPendingStatus() {
1589         return handshakeState != HandshakeState.NOT_STARTED && !isDestroyed()
1590                 && (handshakeState != HandshakeState.FINISHED || isInboundDone() || isOutboundDone());
1591     }
1592 
1593     /**
1594      * Converts the specified OpenSSL cipher suite to the Java cipher suite.
1595      */
1596     private String toJavaCipherSuite(String openSslCipherSuite) {
1597         if (openSslCipherSuite == null) {
1598             return null;
1599         }
1600 
1601         String prefix = toJavaCipherSuitePrefix(SSL.getVersion(ssl));
1602         return CipherSuiteConverter.toJava(openSslCipherSuite, prefix);
1603     }
1604 
1605     /**
1606      * Converts the protocol version string returned by {@link SSL#getVersion(long)} to protocol family string.
1607      */
1608     private static String toJavaCipherSuitePrefix(String protocolVersion) {
1609         final char c;
1610         if (protocolVersion == null || protocolVersion.isEmpty()) {
1611             c = 0;
1612         } else {
1613             c = protocolVersion.charAt(0);
1614         }
1615 
1616         switch (c) {
1617             case 'T':
1618                 return "TLS";
1619             case 'S':
1620                 return "SSL";
1621             default:
1622                 return "UNKNOWN";
1623         }
1624     }
1625 
1626     @Override
1627     public final void setUseClientMode(boolean clientMode) {
1628         if (clientMode != this.clientMode) {
1629             throw new UnsupportedOperationException();
1630         }
1631     }
1632 
1633     @Override
1634     public final boolean getUseClientMode() {
1635         return clientMode;
1636     }
1637 
1638     @Override
1639     public final void setNeedClientAuth(boolean b) {
1640         setClientAuth(b ? ClientAuth.REQUIRE : ClientAuth.NONE);
1641     }
1642 
1643     @Override
1644     public final boolean getNeedClientAuth() {
1645         return clientAuth == ClientAuth.REQUIRE;
1646     }
1647 
1648     @Override
1649     public final void setWantClientAuth(boolean b) {
1650         setClientAuth(b ? ClientAuth.OPTIONAL : ClientAuth.NONE);
1651     }
1652 
1653     @Override
1654     public final boolean getWantClientAuth() {
1655         return clientAuth == ClientAuth.OPTIONAL;
1656     }
1657 
1658     /**
1659      * See <a href="https://www.openssl.org/docs/man1.0.2/ssl/SSL_set_verify.html">SSL_set_verify</a> and
1660      * {@link SSL#setVerify(long, int, int)}.
1661      */
1662     @UnstableApi
1663     public final synchronized void setVerify(int verifyMode, int depth) {
1664         SSL.setVerify(ssl, verifyMode, depth);
1665     }
1666 
1667     private void setClientAuth(ClientAuth mode) {
1668         if (clientMode) {
1669             return;
1670         }
1671         synchronized (this) {
1672             if (clientAuth == mode) {
1673                 // No need to issue any JNI calls if the mode is the same
1674                 return;
1675             }
1676             switch (mode) {
1677                 case NONE:
1678                     SSL.setVerify(ssl, SSL.SSL_CVERIFY_NONE, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
1679                     break;
1680                 case REQUIRE:
1681                     SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
1682                     break;
1683                 case OPTIONAL:
1684                     SSL.setVerify(ssl, SSL.SSL_CVERIFY_OPTIONAL, ReferenceCountedOpenSslContext.VERIFY_DEPTH);
1685                     break;
1686                 default:
1687                     throw new Error(mode.toString());
1688             }
1689             clientAuth = mode;
1690         }
1691     }
1692 
1693     @Override
1694     public final void setEnableSessionCreation(boolean b) {
1695         if (b) {
1696             throw new UnsupportedOperationException();
1697         }
1698     }
1699 
1700     @Override
1701     public final boolean getEnableSessionCreation() {
1702         return false;
1703     }
1704 
1705     @Override
1706     public final synchronized SSLParameters getSSLParameters() {
1707         SSLParameters sslParameters = super.getSSLParameters();
1708 
1709         int version = PlatformDependent.javaVersion();
1710         if (version >= 7) {
1711             sslParameters.setEndpointIdentificationAlgorithm(endPointIdentificationAlgorithm);
1712             Java7SslParametersUtils.setAlgorithmConstraints(sslParameters, algorithmConstraints);
1713             if (version >= 8) {
1714                 if (sniHostNames != null) {
1715                     Java8SslUtils.setSniHostNames(sslParameters, sniHostNames);
1716                 }
1717                 if (!isDestroyed()) {
1718                     Java8SslUtils.setUseCipherSuitesOrder(
1719                             sslParameters, (SSL.getOptions(ssl) & SSL.SSL_OP_CIPHER_SERVER_PREFERENCE) != 0);
1720                 }
1721 
1722                 Java8SslUtils.setSNIMatchers(sslParameters, matchers);
1723             }
1724         }
1725         return sslParameters;
1726     }
1727 
1728     @Override
1729     public final synchronized void setSSLParameters(SSLParameters sslParameters) {
1730         int version = PlatformDependent.javaVersion();
1731         if (version >= 7) {
1732             if (sslParameters.getAlgorithmConstraints() != null) {
1733                 throw new IllegalArgumentException("AlgorithmConstraints are not supported.");
1734             }
1735 
1736             if (version >= 8) {
1737                 if (!isDestroyed()) {
1738                     if (clientMode) {
1739                         final List<String> sniHostNames = Java8SslUtils.getSniHostNames(sslParameters);
1740                         for (String name: sniHostNames) {
1741                             SSL.setTlsExtHostName(ssl, name);
1742                         }
1743                         this.sniHostNames = sniHostNames;
1744                     }
1745                     if (Java8SslUtils.getUseCipherSuitesOrder(sslParameters)) {
1746                         SSL.setOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
1747                     } else {
1748                         SSL.clearOptions(ssl, SSL.SSL_OP_CIPHER_SERVER_PREFERENCE);
1749                     }
1750                 }
1751                 matchers = sslParameters.getSNIMatchers();
1752             }
1753 
1754             final String endPointIdentificationAlgorithm = sslParameters.getEndpointIdentificationAlgorithm();
1755             final boolean endPointVerificationEnabled = endPointIdentificationAlgorithm != null &&
1756                     !endPointIdentificationAlgorithm.isEmpty();
1757             SSL.setHostNameValidation(ssl, DEFAULT_HOSTNAME_VALIDATION_FLAGS,
1758                     endPointVerificationEnabled ? getPeerHost() : null);
1759             // If the user asks for hostname verification we must ensure we verify the peer.
1760             // If the user disables hostname verification we leave it up to the user to change the mode manually.
1761             if (clientMode && endPointVerificationEnabled) {
1762                 SSL.setVerify(ssl, SSL.SSL_CVERIFY_REQUIRED, -1);
1763             }
1764 
1765             this.endPointIdentificationAlgorithm = endPointIdentificationAlgorithm;
1766             algorithmConstraints = sslParameters.getAlgorithmConstraints();
1767         }
1768         super.setSSLParameters(sslParameters);
1769     }
1770 
1771     private boolean isDestroyed() {
1772         return destroyed != 0;
1773     }
1774 
1775     final boolean checkSniHostnameMatch(String hostname) {
1776         return Java8SslUtils.checkSniHostnameMatch(matchers, hostname);
1777     }
1778 
1779     @Override
1780     public String getNegotiatedApplicationProtocol() {
1781         return applicationProtocol;
1782     }
1783 
1784     private final class OpenSslSession implements SSLSession {
1785         private final OpenSslSessionContext sessionContext;
1786 
1787         // These are guarded by synchronized(OpenSslEngine.this) as handshakeFinished() may be triggered by any
1788         // thread.
1789         private X509Certificate[] x509PeerCerts;
1790         private Certificate[] peerCerts;
1791         private String protocol;
1792         private String cipher;
1793         private byte[] id;
1794         private long creationTime;
1795         private volatile int applicationBufferSize = MAX_PLAINTEXT_LENGTH;
1796 
1797         // lazy init for memory reasons
1798         private Map<String, Object> values;
1799 
1800         OpenSslSession(OpenSslSessionContext sessionContext) {
1801             this.sessionContext = sessionContext;
1802         }
1803 
1804         @Override
1805         public byte[] getId() {
1806             synchronized (ReferenceCountedOpenSslEngine.this) {
1807                 if (id == null) {
1808                     return EmptyArrays.EMPTY_BYTES;
1809                 }
1810                 return id.clone();
1811             }
1812         }
1813 
1814         @Override
1815         public SSLSessionContext getSessionContext() {
1816             return sessionContext;
1817         }
1818 
1819         @Override
1820         public long getCreationTime() {
1821             synchronized (ReferenceCountedOpenSslEngine.this) {
1822                 if (creationTime == 0 && !isDestroyed()) {
1823                     creationTime = SSL.getTime(ssl) * 1000L;
1824                 }
1825             }
1826             return creationTime;
1827         }
1828 
1829         @Override
1830         public long getLastAccessedTime() {
1831             long lastAccessed = ReferenceCountedOpenSslEngine.this.lastAccessed;
1832             // if lastAccessed is -1 we will just return the creation time as the handshake was not started yet.
1833             return lastAccessed == -1 ? getCreationTime() : lastAccessed;
1834         }
1835 
1836         @Override
1837         public void invalidate() {
1838             synchronized (ReferenceCountedOpenSslEngine.this) {
1839                 if (!isDestroyed()) {
1840                     SSL.setTimeout(ssl, 0);
1841                 }
1842             }
1843         }
1844 
1845         @Override
1846         public boolean isValid() {
1847             synchronized (ReferenceCountedOpenSslEngine.this) {
1848                 if (!isDestroyed()) {
1849                     return System.currentTimeMillis() - (SSL.getTimeout(ssl) * 1000L) < (SSL.getTime(ssl) * 1000L);
1850                 }
1851             }
1852             return false;
1853         }
1854 
1855         @Override
1856         public void putValue(String name, Object value) {
1857             if (name == null) {
1858                 throw new NullPointerException("name");
1859             }
1860             if (value == null) {
1861                 throw new NullPointerException("value");
1862             }
1863             Map<String, Object> values = this.values;
1864             if (values == null) {
1865                 // Use size of 2 to keep the memory overhead small
1866                 values = this.values = new HashMap<String, Object>(2);
1867             }
1868             Object old = values.put(name, value);
1869             if (value instanceof SSLSessionBindingListener) {
1870                 ((SSLSessionBindingListener) value).valueBound(new SSLSessionBindingEvent(this, name));
1871             }
1872             notifyUnbound(old, name);
1873         }
1874 
1875         @Override
1876         public Object getValue(String name) {
1877             if (name == null) {
1878                 throw new NullPointerException("name");
1879             }
1880             if (values == null) {
1881                 return null;
1882             }
1883             return values.get(name);
1884         }
1885 
1886         @Override
1887         public void removeValue(String name) {
1888             if (name == null) {
1889                 throw new NullPointerException("name");
1890             }
1891             Map<String, Object> values = this.values;
1892             if (values == null) {
1893                 return;
1894             }
1895             Object old = values.remove(name);
1896             notifyUnbound(old, name);
1897         }
1898 
1899         @Override
1900         public String[] getValueNames() {
1901             Map<String, Object> values = this.values;
1902             if (values == null || values.isEmpty()) {
1903                 return EmptyArrays.EMPTY_STRINGS;
1904             }
1905             return values.keySet().toArray(new String[values.size()]);
1906         }
1907 
1908         private void notifyUnbound(Object value, String name) {
1909             if (value instanceof SSLSessionBindingListener) {
1910                 ((SSLSessionBindingListener) value).valueUnbound(new SSLSessionBindingEvent(this, name));
1911             }
1912         }
1913 
1914         /**
1915          * Finish the handshake and so init everything in the {@link OpenSslSession} that should be accessible by
1916          * the user.
1917          */
1918         void handshakeFinished() throws SSLException {
1919             synchronized (ReferenceCountedOpenSslEngine.this) {
1920                 if (!isDestroyed()) {
1921                     id = SSL.getSessionId(ssl);
1922                     cipher = toJavaCipherSuite(SSL.getCipherForSSL(ssl));
1923                     protocol = SSL.getVersion(ssl);
1924 
1925                     initPeerCerts();
1926                     selectApplicationProtocol();
1927                     calculateMaxWrapOverhead();
1928 
1929                     handshakeState = HandshakeState.FINISHED;
1930                 } else {
1931                     throw new SSLException("Already closed");
1932                 }
1933             }
1934         }
1935 
1936         /**
1937          * Init peer certificates that can be obtained via {@link #getPeerCertificateChain()}
1938          * and {@link #getPeerCertificates()}.
1939          */
1940         private void initPeerCerts() {
1941             // Return the full chain from the JNI layer.
1942             byte[][] chain = SSL.getPeerCertChain(ssl);
1943             if (clientMode) {
1944                 if (isEmpty(chain)) {
1945                     peerCerts = EMPTY_CERTIFICATES;
1946                     x509PeerCerts = EMPTY_JAVAX_X509_CERTIFICATES;
1947                 } else {
1948                     peerCerts = new Certificate[chain.length];
1949                     x509PeerCerts = new X509Certificate[chain.length];
1950                     initCerts(chain, 0);
1951                 }
1952             } else {
1953                 // if used on the server side SSL_get_peer_cert_chain(...) will not include the remote peer
1954                 // certificate. We use SSL_get_peer_certificate to get it in this case and add it to our
1955                 // array later.
1956                 //
1957                 // See https://www.openssl.org/docs/ssl/SSL_get_peer_cert_chain.html
1958                 byte[] clientCert = SSL.getPeerCertificate(ssl);
1959                 if (isEmpty(clientCert)) {
1960                     peerCerts = EMPTY_CERTIFICATES;
1961                     x509PeerCerts = EMPTY_JAVAX_X509_CERTIFICATES;
1962                 } else {
1963                     if (isEmpty(chain)) {
1964                         peerCerts = new Certificate[] {new OpenSslX509Certificate(clientCert)};
1965                         x509PeerCerts = new X509Certificate[] {new OpenSslJavaxX509Certificate(clientCert)};
1966                     } else {
1967                         peerCerts = new Certificate[chain.length + 1];
1968                         x509PeerCerts = new X509Certificate[chain.length + 1];
1969                         peerCerts[0] = new OpenSslX509Certificate(clientCert);
1970                         x509PeerCerts[0] = new OpenSslJavaxX509Certificate(clientCert);
1971                         initCerts(chain, 1);
1972                     }
1973                 }
1974             }
1975         }
1976 
1977         private void initCerts(byte[][] chain, int startPos) {
1978             for (int i = 0; i < chain.length; i++) {
1979                 int certPos = startPos + i;
1980                 peerCerts[certPos] = new OpenSslX509Certificate(chain[i]);
1981                 x509PeerCerts[certPos] = new OpenSslJavaxX509Certificate(chain[i]);
1982             }
1983         }
1984 
1985         /**
1986          * Select the application protocol used.
1987          */
1988         private void selectApplicationProtocol() throws SSLException {
1989             ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior = apn.selectedListenerFailureBehavior();
1990             List<String> protocols = apn.protocols();
1991             String applicationProtocol;
1992             switch (apn.protocol()) {
1993                 case NONE:
1994                     break;
1995                 // We always need to check for applicationProtocol == null as the remote peer may not support
1996                 // the TLS extension or may have returned an empty selection.
1997                 case ALPN:
1998                     applicationProtocol = SSL.getAlpnSelected(ssl);
1999                     if (applicationProtocol != null) {
2000                         ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2001                                 protocols, behavior, applicationProtocol);
2002                     }
2003                     break;
2004                 case NPN:
2005                     applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2006                     if (applicationProtocol != null) {
2007                         ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2008                                 protocols, behavior, applicationProtocol);
2009                     }
2010                     break;
2011                 case NPN_AND_ALPN:
2012                     applicationProtocol = SSL.getAlpnSelected(ssl);
2013                     if (applicationProtocol == null) {
2014                         applicationProtocol = SSL.getNextProtoNegotiated(ssl);
2015                     }
2016                     if (applicationProtocol != null) {
2017                         ReferenceCountedOpenSslEngine.this.applicationProtocol = selectApplicationProtocol(
2018                                 protocols, behavior, applicationProtocol);
2019                     }
2020                     break;
2021                 default:
2022                     throw new Error();
2023             }
2024         }
2025 
2026         private String selectApplicationProtocol(List<String> protocols,
2027                                                  ApplicationProtocolConfig.SelectedListenerFailureBehavior behavior,
2028                                                  String applicationProtocol) throws SSLException {
2029             if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.ACCEPT) {
2030                 return applicationProtocol;
2031             } else {
2032                 int size = protocols.size();
2033                 assert size > 0;
2034                 if (protocols.contains(applicationProtocol)) {
2035                     return applicationProtocol;
2036                 } else {
2037                     if (behavior == ApplicationProtocolConfig.SelectedListenerFailureBehavior.CHOOSE_MY_LAST_PROTOCOL) {
2038                         return protocols.get(size - 1);
2039                     } else {
2040                         throw new SSLException("unknown protocol " + applicationProtocol);
2041                     }
2042                 }
2043             }
2044         }
2045 
2046         @Override
2047         public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException {
2048             synchronized (ReferenceCountedOpenSslEngine.this) {
2049                 if (isEmpty(peerCerts)) {
2050                     throw new SSLPeerUnverifiedException("peer not verified");
2051                 }
2052                 return peerCerts.clone();
2053             }
2054         }
2055 
2056         @Override
2057         public Certificate[] getLocalCertificates() {
2058             if (localCerts == null) {
2059                 return null;
2060             }
2061             return localCerts.clone();
2062         }
2063 
2064         @Override
2065         public X509Certificate[] getPeerCertificateChain() throws SSLPeerUnverifiedException {
2066             synchronized (ReferenceCountedOpenSslEngine.this) {
2067                 if (isEmpty(x509PeerCerts)) {
2068                     throw new SSLPeerUnverifiedException("peer not verified");
2069                 }
2070                 return x509PeerCerts.clone();
2071             }
2072         }
2073 
2074         @Override
2075         public Principal getPeerPrincipal() throws SSLPeerUnverifiedException {
2076             Certificate[] peer = getPeerCertificates();
2077             // No need for null or length > 0 is needed as this is done in getPeerCertificates()
2078             // already.
2079             return ((java.security.cert.X509Certificate) peer[0]).getSubjectX500Principal();
2080         }
2081 
2082         @Override
2083         public Principal getLocalPrincipal() {
2084             Certificate[] local = localCerts;
2085             if (local == null || local.length == 0) {
2086                 return null;
2087             }
2088             return ((java.security.cert.X509Certificate) local[0]).getIssuerX500Principal();
2089         }
2090 
2091         @Override
2092         public String getCipherSuite() {
2093             synchronized (ReferenceCountedOpenSslEngine.this) {
2094                 if (cipher == null) {
2095                     return INVALID_CIPHER;
2096                 }
2097                 return cipher;
2098             }
2099         }
2100 
2101         @Override
2102         public String getProtocol() {
2103             String protocol = this.protocol;
2104             if (protocol == null) {
2105                 synchronized (ReferenceCountedOpenSslEngine.this) {
2106                     if (!isDestroyed()) {
2107                         protocol = SSL.getVersion(ssl);
2108                     } else {
2109                         protocol = StringUtil.EMPTY_STRING;
2110                     }
2111                 }
2112             }
2113             return protocol;
2114         }
2115 
2116         @Override
2117         public String getPeerHost() {
2118             return ReferenceCountedOpenSslEngine.this.getPeerHost();
2119         }
2120 
2121         @Override
2122         public int getPeerPort() {
2123             return ReferenceCountedOpenSslEngine.this.getPeerPort();
2124         }
2125 
2126         @Override
2127         public int getPacketBufferSize() {
2128             return maxEncryptedPacketLength();
2129         }
2130 
2131         @Override
2132         public int getApplicationBufferSize() {
2133             return applicationBufferSize;
2134         }
2135 
2136         /**
2137          * Expand (or increase) the value returned by {@link #getApplicationBufferSize()} if necessary.
2138          * <p>
2139          * This is only called in a synchronized block, so no need to use atomic operations.
2140          * @param packetLengthDataOnly The packet size which exceeds the current {@link #getApplicationBufferSize()}.
2141          */
2142         void tryExpandApplicationBufferSize(int packetLengthDataOnly) {
2143             if (packetLengthDataOnly > MAX_PLAINTEXT_LENGTH && applicationBufferSize != MAX_RECORD_SIZE) {
2144                 applicationBufferSize = MAX_RECORD_SIZE;
2145             }
2146         }
2147     }
2148 }