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