1/*
2 * Copyright 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * 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,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 * Copyright 2016 The Netty Project
19 *
20 * The Netty Project licenses this file to you under the Apache License,
21 * version 2.0 (the "License"); you may not use this file except in compliance
22 * with the License. You may obtain a copy of the License at:
23 *
24 *   http://www.apache.org/licenses/LICENSE-2.0
25 *
26 * Unless required by applicable law or agreed to in writing, software
27 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
28 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
29 * License for the specific language governing permissions and limitations
30 * under the License.
31 */
32
33package org.conscrypt;
34
35import static javax.net.ssl.SSLEngineResult.HandshakeStatus.FINISHED;
36import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
37import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NEED_WRAP;
38import static javax.net.ssl.SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
39import static javax.net.ssl.SSLEngineResult.Status.BUFFER_OVERFLOW;
40import static javax.net.ssl.SSLEngineResult.Status.BUFFER_UNDERFLOW;
41import static javax.net.ssl.SSLEngineResult.Status.CLOSED;
42import static javax.net.ssl.SSLEngineResult.Status.OK;
43import static org.conscrypt.NativeConstants.SSL3_RT_HEADER_LENGTH;
44import static org.conscrypt.NativeConstants.SSL3_RT_MAX_PACKET_SIZE;
45import static org.conscrypt.NativeConstants.SSL3_RT_MAX_PLAIN_LENGTH;
46import static org.conscrypt.NativeConstants.SSL_CB_HANDSHAKE_DONE;
47import static org.conscrypt.NativeConstants.SSL_CB_HANDSHAKE_START;
48import static org.conscrypt.NativeConstants.SSL_ERROR_NONE;
49import static org.conscrypt.NativeConstants.SSL_ERROR_WANT_READ;
50import static org.conscrypt.NativeConstants.SSL_ERROR_WANT_WRITE;
51import static org.conscrypt.NativeConstants.SSL_ERROR_ZERO_RETURN;
52import static org.conscrypt.NativeConstants.SSL_RECEIVED_SHUTDOWN;
53import static org.conscrypt.NativeConstants.SSL_SENT_SHUTDOWN;
54import static org.conscrypt.SSLUtils.calculateOutNetBufSize;
55import static org.conscrypt.SSLUtils.toSSLHandshakeException;
56
57import java.io.IOException;
58import java.nio.ByteBuffer;
59import java.nio.ReadOnlyBufferException;
60import java.security.InvalidKeyException;
61import java.security.PrivateKey;
62import java.security.cert.CertificateEncodingException;
63import java.security.cert.CertificateException;
64import java.security.interfaces.ECKey;
65import java.security.spec.ECParameterSpec;
66import javax.crypto.SecretKey;
67import javax.net.ssl.SSLEngine;
68import javax.net.ssl.SSLEngineResult;
69import javax.net.ssl.SSLEngineResult.HandshakeStatus;
70import javax.net.ssl.SSLEngineResult.Status;
71import javax.net.ssl.SSLException;
72import javax.net.ssl.SSLHandshakeException;
73import javax.net.ssl.SSLParameters;
74import javax.net.ssl.SSLSession;
75import javax.net.ssl.X509ExtendedKeyManager;
76import javax.net.ssl.X509KeyManager;
77import javax.net.ssl.X509TrustManager;
78import javax.security.auth.x500.X500Principal;
79
80/**
81 * Implements the {@link SSLEngine} API using OpenSSL's non-blocking interfaces.
82 *
83 * @hide
84 */
85final class OpenSSLEngineImpl extends SSLEngine implements NativeCrypto.SSLHandshakeCallbacks,
86                                                           SSLParametersImpl.AliasChooser,
87                                                           SSLParametersImpl.PSKCallbacks {
88    private static final SSLEngineResult NEED_UNWRAP_OK =
89            new SSLEngineResult(OK, NEED_UNWRAP, 0, 0);
90    private static final SSLEngineResult NEED_UNWRAP_CLOSED =
91            new SSLEngineResult(CLOSED, NEED_UNWRAP, 0, 0);
92    private static final SSLEngineResult NEED_WRAP_OK = new SSLEngineResult(OK, NEED_WRAP, 0, 0);
93    private static final SSLEngineResult NEED_WRAP_CLOSED =
94            new SSLEngineResult(CLOSED, NEED_WRAP, 0, 0);
95    private static final SSLEngineResult CLOSED_NOT_HANDSHAKING =
96            new SSLEngineResult(CLOSED, NOT_HANDSHAKING, 0, 0);
97    private static final ByteBuffer EMPTY = ByteBuffer.allocateDirect(0);
98    private static final long EMPTY_ADDR = NativeCrypto.getDirectBufferAddress(EMPTY);
99
100    /**
101     * Hostname used with the TLS extension SNI hostname. {@link #getPeerHost()} is used if this is
102     * not set.
103     */
104    private String sniHostname;
105
106    private final SSLParametersImpl sslParameters;
107
108    /**
109     * Protects {@link #engineState} and {@link #handshakeFinished}.
110     */
111    private final Object stateLock = new Object();
112
113    private enum EngineState {
114        /**
115         * The {@link OpenSSLSocketImpl} object is constructed, but {@link #beginHandshake()} has
116         * not yet been called.
117         */
118        NEW,
119        /**
120         * {@link #setUseClientMode(boolean)} has been called at least once.
121         */
122        MODE_SET,
123        /**
124         * Handshake task has been started.
125         */
126        HANDSHAKE_STARTED,
127        /**
128         * Handshake has been completed, but {@link #beginHandshake()} hasn't returned yet.
129         */
130        HANDSHAKE_COMPLETED,
131        /**
132         * {@link #beginHandshake()} has completed but the task hasn't been called. This is expected
133         * behaviour in cut-through mode, where SSL_do_handshake returns before the handshake is
134         * complete. We can now start writing data to the socket.
135         */
136        READY_HANDSHAKE_CUT_THROUGH,
137        /**
138         * {@link #beginHandshake()} has completed and socket is ready to go.
139         */
140        READY,
141        CLOSED_INBOUND,
142        CLOSED_OUTBOUND,
143        /**
144         * Inbound and outbound has been called.
145         */
146        CLOSED,
147    }
148
149    // @GuardedBy("stateLock");
150    private EngineState engineState = EngineState.NEW;
151    private boolean handshakeFinished;
152
153    /**
154     * Protected by synchronizing on stateLock. Starts as 0, set by startHandshake, reset to 0 on
155     * close.
156     */
157    // @GuardedBy("stateLock");
158    private long sslNativePointer;
159
160    /**
161     * Protected by synchronizing on stateLock. Starts as 0, set by startHandshake, reset to 0 on
162     * close.
163     */
164    // @GuardedBy("stateLock");
165    private long networkBio;
166
167    /**
168     * Set during startHandshake.
169     */
170    private AbstractOpenSSLSession sslSession;
171
172    /**
173     * Used during handshake callbacks.
174     */
175    private AbstractOpenSSLSession handshakeSession;
176
177    /**
178     * Private key for the TLS Channel ID extension. This field is client-side only. Set during
179     * startHandshake.
180     */
181    private OpenSSLKey channelIdPrivateKey;
182
183    private int maxSealOverhead;
184
185    private HandshakeListener handshakeListener;
186
187    private final ByteBuffer[] singleSrcBuffer = new ByteBuffer[1];
188    private final ByteBuffer[] singleDstBuffer = new ByteBuffer[1];
189
190    OpenSSLEngineImpl(SSLParametersImpl sslParameters) {
191        this.sslParameters = sslParameters;
192    }
193
194    OpenSSLEngineImpl(String host, int port, SSLParametersImpl sslParameters) {
195        super(host, port);
196        this.sslParameters = sslParameters;
197    }
198
199    /**
200     * Returns the maximum overhead, in bytes, of sealing a record with SSL.
201     */
202    int maxSealOverhead() {
203        return maxSealOverhead;
204    }
205
206    /**
207     * Enables/disables TLS Channel ID for this server engine.
208     *
209     * <p>This method needs to be invoked before the handshake starts.
210     *
211     * @throws IllegalStateException if this is a client engine or if the handshake has already
212     *         started.
213     */
214    void setChannelIdEnabled(boolean enabled) {
215        synchronized (stateLock) {
216            if (getUseClientMode()) {
217                throw new IllegalStateException("Not allowed in client mode");
218            }
219            if (isHandshakeStarted()) {
220                throw new IllegalStateException(
221                        "Could not enable/disable Channel ID after the initial handshake has begun.");
222            }
223            sslParameters.channelIdEnabled = enabled;
224        }
225    }
226
227    /**
228     * Gets the TLS Channel ID for this server engine. Channel ID is only available once the
229     * handshake completes.
230     *
231     * @return channel ID or {@code null} if not available.
232     *
233     * @throws IllegalStateException if this is a client engine or if the handshake has not yet
234     * completed.
235     * @throws SSLException if channel ID is available but could not be obtained.
236     */
237    byte[] getChannelId() throws SSLException {
238        synchronized (stateLock) {
239            if (getUseClientMode()) {
240                throw new IllegalStateException("Not allowed in client mode");
241            }
242
243            if (isHandshakeStarted()) {
244                throw new IllegalStateException(
245                        "Channel ID is only available after handshake completes");
246            }
247            return NativeCrypto.SSL_get_tls_channel_id(sslNativePointer);
248        }
249    }
250
251    /**
252     * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client engine.
253     *
254     * <p>This method needs to be invoked before the handshake starts.
255     *
256     * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables
257     *        TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST
258     *        P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1).
259     *
260     * @throws IllegalStateException if this is a server engine or if the handshake has already
261     *         started.
262     */
263    void setChannelIdPrivateKey(PrivateKey privateKey) {
264        if (!getUseClientMode()) {
265            throw new IllegalStateException("Not allowed in server mode");
266        }
267
268        synchronized (stateLock) {
269            if (isHandshakeStarted()) {
270                throw new IllegalStateException("Could not change Channel ID private key "
271                        + "after the initial handshake has begun.");
272            }
273
274            if (privateKey == null) {
275                sslParameters.channelIdEnabled = false;
276                channelIdPrivateKey = null;
277                return;
278            }
279
280            sslParameters.channelIdEnabled = true;
281            try {
282                ECParameterSpec ecParams = null;
283                if (privateKey instanceof ECKey) {
284                    ecParams = ((ECKey) privateKey).getParams();
285                }
286                if (ecParams == null) {
287                    // Assume this is a P-256 key, as specified in the contract of this method.
288                    ecParams =
289                            OpenSSLECGroupContext.getCurveByName("prime256v1").getECParameterSpec();
290                }
291                channelIdPrivateKey =
292                        OpenSSLKey.fromECPrivateKeyForTLSStackOnly(privateKey, ecParams);
293            } catch (InvalidKeyException e) {
294                // Will have error in startHandshake
295            }
296        }
297    }
298
299    /**
300     * Sets the listener for the completion of the TLS handshake.
301     */
302    void setHandshakeListener(HandshakeListener handshakeListener) {
303        synchronized (stateLock) {
304            if (isHandshakeStarted()) {
305                throw new IllegalStateException(
306                        "Handshake listener must be set before starting the handshake.");
307            }
308            this.handshakeListener = handshakeListener;
309        }
310    }
311
312    private boolean isHandshakeStarted() {
313        switch (engineState) {
314            case NEW:
315            case MODE_SET:
316                return false;
317            default:
318                return true;
319        }
320    }
321
322    @Override
323    public void beginHandshake() throws SSLException {
324        synchronized (stateLock) {
325            beginHandshakeInternal();
326        }
327    }
328
329    private void beginHandshakeInternal() throws SSLException {
330        switch (engineState) {
331            case MODE_SET:
332                // This is the only allowed state.
333                break;
334            case HANDSHAKE_STARTED:
335                throw new IllegalStateException("Handshake has already been started");
336            case CLOSED_INBOUND:
337            case CLOSED_OUTBOUND:
338            case CLOSED:
339                throw new IllegalStateException("Engine has already been closed");
340            default:
341                throw new IllegalStateException("Client/server mode must be set before handshake");
342        }
343
344        engineState = EngineState.HANDSHAKE_STARTED;
345
346        boolean releaseResources = true;
347        try {
348            final AbstractSessionContext sessionContext = sslParameters.getSessionContext();
349            sslNativePointer = NativeCrypto.SSL_new(sessionContext.sslCtxNativePointer);
350            networkBio = NativeCrypto.SSL_BIO_new(sslNativePointer);
351            sslSession = sslParameters.getSessionToReuse(
352                    sslNativePointer, getSniHostname(), getPeerPort());
353            sslParameters.setSSLParameters(sslNativePointer, this, this, getSniHostname());
354            sslParameters.setCertificateValidation(sslNativePointer);
355            sslParameters.setTlsChannelId(sslNativePointer, channelIdPrivateKey);
356            if (getUseClientMode()) {
357                NativeCrypto.SSL_set_connect_state(sslNativePointer);
358            } else {
359                NativeCrypto.SSL_set_accept_state(sslNativePointer);
360            }
361            maxSealOverhead = NativeCrypto.SSL_max_seal_overhead(sslNativePointer);
362            handshake();
363            releaseResources = false;
364        } catch (IOException e) {
365            // Write CCS errors to EventLog
366            String message = e.getMessage();
367            // Must match error reason string of SSL_R_UNEXPECTED_CCS (in ssl/ssl_err.c)
368            if (message.contains("unexpected CCS")) {
369                String logMessage = String.format("ssl_unexpected_ccs: host=%s", getSniHostname());
370                Platform.logEvent(logMessage);
371            }
372            throw new SSLException(e);
373        } finally {
374            if (releaseResources) {
375                engineState = EngineState.CLOSED;
376                shutdownAndFreeSslNative();
377            }
378        }
379    }
380
381    @Override
382    public void closeInbound() throws SSLException {
383        synchronized (stateLock) {
384            if (engineState == EngineState.CLOSED) {
385                return;
386            }
387            if (engineState == EngineState.CLOSED_OUTBOUND) {
388                engineState = EngineState.CLOSED;
389            } else {
390                engineState = EngineState.CLOSED_INBOUND;
391            }
392        }
393        // TODO anything else to notify OpenSSL layer?
394    }
395
396    @Override
397    public void closeOutbound() {
398        synchronized (stateLock) {
399            if (engineState == EngineState.CLOSED || engineState == EngineState.CLOSED_OUTBOUND) {
400                return;
401            }
402            if (engineState != EngineState.MODE_SET && engineState != EngineState.NEW) {
403                shutdownAndFreeSslNative();
404            }
405            if (engineState == EngineState.CLOSED_INBOUND) {
406                engineState = EngineState.CLOSED;
407            } else {
408                engineState = EngineState.CLOSED_OUTBOUND;
409            }
410        }
411        shutdown();
412    }
413
414    @Override
415    public Runnable getDelegatedTask() {
416        // This implementation doesn't use any delegated tasks.
417        return null;
418    }
419
420    @Override
421    public String[] getEnabledCipherSuites() {
422        return sslParameters.getEnabledCipherSuites();
423    }
424
425    @Override
426    public String[] getEnabledProtocols() {
427        return sslParameters.getEnabledProtocols();
428    }
429
430    @Override
431    public boolean getEnableSessionCreation() {
432        return sslParameters.getEnableSessionCreation();
433    }
434
435    @Override
436    public SSLParameters getSSLParameters() {
437        SSLParameters params = super.getSSLParameters();
438        Platform.getSSLParameters(params, sslParameters, this);
439        return params;
440    }
441
442    public void setSniHostname(String sniHostname) {
443        this.sniHostname = sniHostname;
444    }
445
446    public String getSniHostname() {
447        return sniHostname != null ? sniHostname : getPeerHost();
448    }
449
450    @Override
451    public void setSSLParameters(SSLParameters p) {
452        super.setSSLParameters(p);
453        Platform.setSSLParameters(p, sslParameters, this);
454    }
455
456    @Override
457    public HandshakeStatus getHandshakeStatus() {
458        synchronized (stateLock) {
459            return getHandshakeStatusInternal();
460        }
461    }
462
463    private HandshakeStatus getHandshakeStatusInternal() {
464        if (handshakeFinished) {
465            return HandshakeStatus.NOT_HANDSHAKING;
466        }
467        switch (engineState) {
468            case HANDSHAKE_STARTED:
469                return pendingStatus(pendingOutboundEncryptedBytes());
470            case HANDSHAKE_COMPLETED:
471                return HandshakeStatus.NEED_WRAP;
472            case NEW:
473            case MODE_SET:
474            case CLOSED:
475            case CLOSED_INBOUND:
476            case CLOSED_OUTBOUND:
477            case READY:
478            case READY_HANDSHAKE_CUT_THROUGH:
479                return HandshakeStatus.NOT_HANDSHAKING;
480            default:
481                break;
482        }
483        throw new IllegalStateException("Unexpected engine state: " + engineState);
484    }
485
486    private int pendingOutboundEncryptedBytes() {
487        return NativeCrypto.SSL_pending_written_bytes_in_BIO(networkBio);
488    }
489
490    private int pendingInboundCleartextBytes() {
491        return NativeCrypto.SSL_pending_readable_bytes(sslNativePointer);
492    }
493
494    private static SSLEngineResult.HandshakeStatus pendingStatus(int pendingOutboundBytes) {
495        // Depending on if there is something left in the BIO we need to WRAP or UNWRAP
496        return pendingOutboundBytes > 0 ? NEED_WRAP : NEED_UNWRAP;
497    }
498
499    @Override
500    public boolean getNeedClientAuth() {
501        return sslParameters.getNeedClientAuth();
502    }
503
504    @Override
505    public SSLSession getSession() {
506        if (sslSession == null) {
507            return handshakeSession != null ? Platform.wrapSSLSession(handshakeSession)
508                                            : SSLNullSession.getNullSession();
509        }
510        return Platform.wrapSSLSession(sslSession);
511    }
512
513    @Override
514    public String[] getSupportedCipherSuites() {
515        return NativeCrypto.getSupportedCipherSuites();
516    }
517
518    @Override
519    public String[] getSupportedProtocols() {
520        return NativeCrypto.getSupportedProtocols();
521    }
522
523    @Override
524    public boolean getUseClientMode() {
525        return sslParameters.getUseClientMode();
526    }
527
528    @Override
529    public boolean getWantClientAuth() {
530        return sslParameters.getWantClientAuth();
531    }
532
533    @Override
534    public boolean isInboundDone() {
535        if (sslNativePointer == 0) {
536            synchronized (stateLock) {
537                return engineState == EngineState.CLOSED
538                        || engineState == EngineState.CLOSED_INBOUND;
539            }
540        }
541        return (NativeCrypto.SSL_get_shutdown(sslNativePointer) & SSL_RECEIVED_SHUTDOWN) != 0;
542    }
543
544    @Override
545    public boolean isOutboundDone() {
546        if (sslNativePointer == 0) {
547            synchronized (stateLock) {
548                return engineState == EngineState.CLOSED
549                        || engineState == EngineState.CLOSED_OUTBOUND;
550            }
551        }
552        return (NativeCrypto.SSL_get_shutdown(sslNativePointer) & SSL_SENT_SHUTDOWN) != 0;
553    }
554
555    @Override
556    public void setEnabledCipherSuites(String[] suites) {
557        sslParameters.setEnabledCipherSuites(suites);
558    }
559
560    @Override
561    public void setEnabledProtocols(String[] protocols) {
562        sslParameters.setEnabledProtocols(protocols);
563    }
564
565    @Override
566    public void setEnableSessionCreation(boolean flag) {
567        sslParameters.setEnableSessionCreation(flag);
568    }
569
570    @Override
571    public void setNeedClientAuth(boolean need) {
572        sslParameters.setNeedClientAuth(need);
573    }
574
575    @Override
576    public void setUseClientMode(boolean mode) {
577        synchronized (stateLock) {
578            if (engineState != EngineState.MODE_SET && engineState != EngineState.NEW) {
579                throw new IllegalArgumentException(
580                        "Can not change mode after handshake: engineState == " + engineState);
581            }
582            engineState = EngineState.MODE_SET;
583        }
584        sslParameters.setUseClientMode(mode);
585    }
586
587    @Override
588    public void setWantClientAuth(boolean want) {
589        sslParameters.setWantClientAuth(want);
590    }
591
592    @Override
593    public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
594        synchronized (stateLock) {
595            try {
596                return unwrap(singleSrcBuffer(src), singleDstBuffer(dst));
597            } finally {
598                resetSingleSrcBuffer();
599                resetSingleDstBuffer();
600            }
601        }
602    }
603
604    @Override
605    public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts) throws SSLException {
606        synchronized (stateLock) {
607            try {
608                return unwrap(singleSrcBuffer(src), dsts);
609            } finally {
610                resetSingleSrcBuffer();
611            }
612        }
613    }
614
615    @Override
616    public SSLEngineResult unwrap(final ByteBuffer src, final ByteBuffer[] dsts, final int offset,
617            final int length) throws SSLException {
618        synchronized (stateLock) {
619            try {
620                return unwrap(singleSrcBuffer(src), 0, 1, dsts, offset, length);
621            } finally {
622                resetSingleSrcBuffer();
623            }
624        }
625    }
626
627    SSLEngineResult unwrap(final ByteBuffer[] srcs, final ByteBuffer[] dsts) throws SSLException {
628        checkNotNull(srcs, "srcs");
629        checkNotNull(dsts, "dsts");
630        return unwrap(srcs, 0, srcs.length, dsts, 0, dsts.length);
631    }
632
633    SSLEngineResult unwrap(final ByteBuffer[] srcs, int srcsOffset, final int srcsLength,
634            final ByteBuffer[] dsts, final int dstsOffset, final int dstsLength)
635            throws SSLException {
636        checkNotNull(srcs, "srcs");
637        checkNotNull(dsts, "dsts");
638
639        checkIndex(srcs.length, srcsOffset, srcsLength, "srcs");
640        checkIndex(dsts.length, dstsOffset, dstsLength, "dsts");
641
642        // Determine the output capacity.
643        final int dstLength = calcDstsLength(dsts, dstsOffset, dstsLength);
644        final int endOffset = dstsOffset + dstsLength;
645
646        final int srcsEndOffset = srcsOffset + srcsLength;
647        final long srcLength = calcSrcsLength(srcs, srcsOffset, srcsEndOffset);
648
649        synchronized (stateLock) {
650            switch (engineState) {
651                case MODE_SET:
652                    // Begin the handshake implicitly.
653                    beginHandshakeInternal();
654                    break;
655                case CLOSED_INBOUND:
656                case CLOSED:
657                    // If the inbound direction is closed. we can't send anymore.
658                    return new SSLEngineResult(Status.CLOSED, getHandshakeStatusInternal(), 0, 0);
659                case NEW:
660                    throw new IllegalStateException(
661                            "Client/server mode must be set before calling unwrap");
662                default:
663                    break;
664            }
665
666            HandshakeStatus handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
667            if (!handshakeFinished) {
668                handshakeStatus = handshake();
669                if (handshakeStatus == NEED_WRAP) {
670                    return NEED_WRAP_OK;
671                }
672                if (engineState == EngineState.CLOSED) {
673                    return NEED_WRAP_CLOSED;
674                }
675                // NEED_UNWRAP - just fall through to perform the unwrap.
676            }
677
678            // Consume any source data. Skip this if there are unread cleartext data.
679            boolean noCleartextDataAvailable = pendingInboundCleartextBytes() <= 0;
680            int lenRemaining = 0;
681            if (srcLength > 0 && noCleartextDataAvailable) {
682                if (srcLength < SSL3_RT_HEADER_LENGTH) {
683                    // Need to be able to read a full TLS header.
684                    return new SSLEngineResult(BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0);
685                }
686
687                int packetLength = SSLUtils.getEncryptedPacketLength(srcs, srcsOffset);
688                if (packetLength < 0) {
689                    throw new SSLException("Unable to parse TLS packet header");
690                }
691
692                if (srcLength < packetLength) {
693                    // We either have not enough data to read the packet header or not enough for
694                    // reading the whole packet.
695                    return new SSLEngineResult(BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0);
696                }
697
698                // Limit the amount of data to be read to a single packet.
699                lenRemaining = packetLength;
700            } else if (noCleartextDataAvailable) {
701                // No pending data and nothing provided as input.  Need more data.
702                return new SSLEngineResult(BUFFER_UNDERFLOW, getHandshakeStatus(), 0, 0);
703            }
704
705            // Write all of the encrypted source data to the networkBio
706            int bytesConsumed = 0;
707            if (lenRemaining > 0 && srcsOffset < srcsEndOffset) {
708                do {
709                    ByteBuffer src = srcs[srcsOffset];
710                    int remaining = src.remaining();
711                    if (remaining == 0) {
712                        // We must skip empty buffers as BIO_write will return 0 if asked to
713                        // write something with length 0.
714                        srcsOffset++;
715                        continue;
716                    }
717                    // Write the source encrypted data to the networkBio.
718                    int written = writeEncryptedData(src, Math.min(lenRemaining, remaining));
719                    if (written > 0) {
720                        bytesConsumed += written;
721                        lenRemaining -= written;
722                        if (lenRemaining == 0) {
723                            // A whole packet has been consumed.
724                            break;
725                        }
726
727                        if (written == remaining) {
728                            srcsOffset++;
729                        } else {
730                            // We were not able to write everything into the BIO so break the
731                            // write loop as otherwise we will produce an error on the next
732                            // write attempt, which will trigger a SSL.clearError() later.
733                            break;
734                        }
735                    } else {
736                        // BIO_write returned a negative or zero number, this means we could not
737                        // complete the write operation and should retry later.
738                        // We ignore BIO_* errors here as we use in memory BIO anyway and will
739                        // do another SSL_* call later on in which we will produce an exception
740                        // in case of an error
741                        NativeCrypto.SSL_clear_error();
742                        break;
743                    }
744                } while (srcsOffset < srcsEndOffset);
745            }
746
747            // Now read any available plaintext data.
748            int bytesProduced = 0;
749            if (dstLength > 0) {
750                // Write decrypted data to dsts buffers
751                for (int idx = dstsOffset; idx < endOffset; ++idx) {
752                    ByteBuffer dst = dsts[idx];
753                    if (!dst.hasRemaining()) {
754                        continue;
755                    }
756
757                    int bytesRead = readPlaintextData(dst);
758                    if (bytesRead > 0) {
759                        bytesProduced += bytesRead;
760                        if (dst.hasRemaining()) {
761                            // We haven't filled this buffer fully, break out of the loop
762                            // and determine the correct response status below.
763                            break;
764                        }
765                    } else {
766                        // Return an appropriate result based on the error code.
767                        int sslError = NativeCrypto.SSL_get_error(sslNativePointer, bytesRead);
768                        switch (sslError) {
769                            case SSL_ERROR_ZERO_RETURN:
770                                // This means the connection was shutdown correctly, close inbound
771                                // and outbound
772                                closeAll();
773                                return newResult(bytesConsumed, bytesProduced, handshakeStatus);
774                            case SSL_ERROR_WANT_READ:
775                            case SSL_ERROR_WANT_WRITE:
776                                return newResult(bytesConsumed, bytesProduced, handshakeStatus);
777                            default:
778                                return sslReadErrorResult(NativeCrypto.SSL_get_last_error_number(),
779                                        bytesConsumed, bytesProduced);
780                        }
781                    }
782                }
783            } else {
784                // If the capacity of all destination buffers is 0 we need to trigger a SSL_read
785                // anyway to ensure everything is flushed in the BIO pair and so we can detect it
786                // in the pendingInboundCleartextBytes() call.
787                try {
788                    if (NativeCrypto.ENGINE_SSL_read_direct(sslNativePointer, EMPTY_ADDR, 0, this)
789                            <= 0) {
790                        // We do not check SSL_get_error as we are not interested in any error that
791                        // is not fatal.
792                        int err = NativeCrypto.SSL_get_last_error_number();
793                        if (err != SSL_ERROR_NONE) {
794                            return sslReadErrorResult(err, bytesConsumed, bytesProduced);
795                        }
796                    }
797                } catch (IOException e) {
798                    throw new SSLException(e);
799                }
800            }
801
802            // There won't be any application data until we're done handshaking.
803            // We first check handshakeFinished to eliminate the overhead of extra JNI call if
804            // possible.
805            int pendingCleartextBytes = handshakeFinished ? pendingInboundCleartextBytes() : 0;
806            if (pendingCleartextBytes > 0) {
807                // We filled all buffers but there is still some data pending in the BIO buffer,
808                // return BUFFER_OVERFLOW.
809                return new SSLEngineResult(BUFFER_OVERFLOW,
810                        mayFinishHandshake(handshakeStatus == FINISHED
811                                        ? handshakeStatus
812                                        : getHandshakeStatusInternal()),
813                        bytesConsumed, bytesProduced);
814            }
815
816            return newResult(bytesConsumed, bytesProduced, handshakeStatus);
817        }
818    }
819
820    private static int calcDstsLength(ByteBuffer[] dsts, int dstsOffset, int dstsLength) {
821        int capacity = 0;
822        for (int i = 0; i < dsts.length; i++) {
823            ByteBuffer dst = dsts[i];
824            checkNotNull(dst, "one of the dst");
825            if (dst.isReadOnly()) {
826                throw new ReadOnlyBufferException();
827            }
828            if (i >= dstsOffset && i < dstsOffset + dstsLength) {
829                capacity += dst.remaining();
830            }
831        }
832        return capacity;
833    }
834
835    private static long calcSrcsLength(ByteBuffer[] srcs, int srcsOffset, int srcsEndOffset) {
836        long len = 0;
837        for (int i = srcsOffset; i < srcsEndOffset; i++) {
838            ByteBuffer src = srcs[i];
839            if (src == null) {
840                throw new IllegalArgumentException("srcs[" + i + "] is null");
841            }
842            len += src.remaining();
843        }
844        return len;
845    }
846
847    private SSLEngineResult.HandshakeStatus handshake() throws SSLException {
848        long sslSessionCtx = 0L;
849        try {
850            // Only actually perform the handshake if we haven't already just completed it
851            // via BIO operations.
852            int code = NativeCrypto.ENGINE_SSL_do_handshake(sslNativePointer, this);
853            if (code <= 0) {
854                int sslError = NativeCrypto.SSL_get_error(sslNativePointer, code);
855                switch (sslError) {
856                    case SSL_ERROR_WANT_READ:
857                    case SSL_ERROR_WANT_WRITE:
858                        return pendingStatus(pendingOutboundEncryptedBytes());
859                    default:
860                        // Everything else is considered as error
861                        throw shutdownWithError("SSL_do_handshake");
862                }
863            }
864
865            // Handshake is finished!
866            sslSessionCtx = NativeCrypto.SSL_get1_session(sslNativePointer);
867            if (sslSessionCtx == 0) {
868                // TODO(nathanmittler): Should we throw here?
869                // return pendingStatus(pendingOutboundBytes());
870                throw shutdownWithError("Failed to obtain session after handshake completed");
871            }
872            sslSession = sslParameters.setupSession(sslSessionCtx, sslNativePointer, sslSession,
873                    getSniHostname(), getPeerPort(), true);
874            if (sslSession != null && engineState == EngineState.HANDSHAKE_STARTED) {
875                engineState = EngineState.READY_HANDSHAKE_CUT_THROUGH;
876            } else {
877                engineState = EngineState.READY;
878            }
879            finishHandshake();
880            return FINISHED;
881        } catch (Exception e) {
882            throw toSSLHandshakeException(e);
883        } finally {
884            if (sslSession == null && sslSessionCtx != 0) {
885                NativeCrypto.SSL_SESSION_free(sslSessionCtx);
886            }
887        }
888    }
889
890    private void finishHandshake() throws SSLException {
891        handshakeFinished = true;
892        // Notify the listener, if provided.
893        if (handshakeListener != null) {
894            handshakeListener.onHandshakeFinished();
895        }
896    }
897    /**
898     * Write plaintext data to the OpenSSL internal BIO
899     *
900     * Calling this function with src.remaining == 0 is undefined.
901     */
902    private int writePlaintextData(final ByteBuffer src, int len) throws SSLException {
903        try {
904            final int pos = src.position();
905            final int sslWrote;
906
907            if (src.isDirect()) {
908                long addr = NativeCrypto.getDirectBufferAddress(src) + pos;
909                sslWrote = NativeCrypto.ENGINE_SSL_write_direct(sslNativePointer, addr, len, this);
910            } else {
911                ByteBuffer heapSrc = toHeapBuffer(src, len);
912                sslWrote = NativeCrypto.ENGINE_SSL_write_heap(sslNativePointer, heapSrc.array(),
913                        heapSrc.arrayOffset() + heapSrc.position(), len, this);
914            }
915            if (sslWrote > 0) {
916                src.position(pos + sslWrote);
917            }
918            return sslWrote;
919        } catch (Exception e) {
920            throw convertException(e);
921        }
922    }
923
924    /**
925     * Read plaintext data from the OpenSSL internal BIO
926     */
927    private int readPlaintextData(final ByteBuffer dst) throws SSLException {
928        try {
929            final int sslRead;
930            final int pos = dst.position();
931            final int limit = dst.limit();
932            final int len = Math.min(SSL3_RT_MAX_PACKET_SIZE, limit - pos);
933            if (dst.isDirect()) {
934                long addr = NativeCrypto.getDirectBufferAddress(dst) + pos;
935                sslRead = NativeCrypto.ENGINE_SSL_read_direct(sslNativePointer, addr, len, this);
936                if (sslRead > 0) {
937                    dst.position(pos + sslRead);
938                }
939            } else if (dst.hasArray()) {
940                sslRead = NativeCrypto.ENGINE_SSL_read_heap(
941                        sslNativePointer, dst.array(), dst.arrayOffset() + pos, len, this);
942                if (sslRead > 0) {
943                    dst.position(pos + sslRead);
944                }
945            } else {
946                byte[] data = new byte[len];
947                sslRead = NativeCrypto.ENGINE_SSL_read_heap(sslNativePointer, data, 0, len, this);
948                if (sslRead > 0) {
949                    dst.put(data, 0, sslRead);
950                }
951            }
952            return sslRead;
953        } catch (Exception e) {
954            throw convertException(e);
955        }
956    }
957
958    private SSLException convertException(Throwable e) {
959        if (e instanceof SSLHandshakeException || !handshakeFinished) {
960            return SSLUtils.toSSLHandshakeException(e);
961        }
962        return SSLUtils.toSSLException(e);
963    }
964
965    /**
966     * Write encrypted data to the OpenSSL network BIO.
967     */
968    private int writeEncryptedData(final ByteBuffer src, int len) throws SSLException {
969        try {
970            final int pos = src.position();
971            final int netWrote;
972            if (src.isDirect()) {
973                long addr = NativeCrypto.getDirectBufferAddress(src) + pos;
974                netWrote = NativeCrypto.ENGINE_SSL_write_BIO_direct(
975                        sslNativePointer, networkBio, addr, len, this);
976            } else {
977                ByteBuffer heapSrc = toHeapBuffer(src, len);
978                netWrote = NativeCrypto.ENGINE_SSL_write_BIO_heap(sslNativePointer, networkBio,
979                        heapSrc.array(), heapSrc.arrayOffset() + heapSrc.position(), len, this);
980            }
981
982            if (netWrote >= 0) {
983                src.position(pos + netWrote);
984            }
985
986            return netWrote;
987        } catch (IOException e) {
988            throw new SSLException(e);
989        }
990    }
991
992    private SSLEngineResult readPendingBytesFromBIO(ByteBuffer dst, int bytesConsumed,
993            int bytesProduced, SSLEngineResult.HandshakeStatus status) throws SSLException {
994        try {
995            // Check to see if the engine wrote data into the network BIO
996            int pendingNet = pendingOutboundEncryptedBytes();
997            if (pendingNet > 0) {
998                // Do we have enough room in dst to write encrypted data?
999                int capacity = dst.remaining();
1000                if (capacity < pendingNet) {
1001                    return new SSLEngineResult(BUFFER_OVERFLOW,
1002                            mayFinishHandshake(
1003                                    status == FINISHED ? status : getHandshakeStatus(pendingNet)),
1004                            bytesConsumed, bytesProduced);
1005                }
1006
1007                // Write the pending data from the network BIO into the dst buffer
1008                int produced = readEncryptedData(dst, pendingNet);
1009
1010                if (produced <= 0) {
1011                    // We ignore BIO_* errors here as we use in memory BIO anyway and will do
1012                    // another SSL_* call later on in which we will produce an exception in
1013                    // case of an error
1014                    NativeCrypto.SSL_clear_error();
1015                } else {
1016                    bytesProduced += produced;
1017                    pendingNet -= produced;
1018                }
1019
1020                return new SSLEngineResult(getEngineStatus(),
1021                        mayFinishHandshake(
1022                                status == FINISHED ? status : getHandshakeStatus(pendingNet)),
1023                        bytesConsumed, bytesProduced);
1024            }
1025            return null;
1026        } catch (Exception e) {
1027            throw convertException(e);
1028        }
1029    }
1030
1031    /**
1032     * Read encrypted data from the OpenSSL network BIO
1033     */
1034    private int readEncryptedData(final ByteBuffer dst, final int pending) throws SSLException {
1035        try {
1036            int bioRead = 0;
1037            if (dst.remaining() >= pending) {
1038                final int pos = dst.position();
1039                final int limit = dst.limit();
1040                final int len = Math.min(pending, limit - pos);
1041                if (dst.isDirect()) {
1042                    long addr = NativeCrypto.getDirectBufferAddress(dst) + pos;
1043                    bioRead = NativeCrypto.ENGINE_SSL_read_BIO_direct(
1044                            sslNativePointer, networkBio, addr, len, this);
1045                    if (bioRead > 0) {
1046                        dst.position(pos + bioRead);
1047                        return bioRead;
1048                    }
1049                } else if (dst.hasArray()) {
1050                    bioRead = NativeCrypto.ENGINE_SSL_read_BIO_heap(sslNativePointer, networkBio,
1051                            dst.array(), dst.arrayOffset() + pos, pending, this);
1052                    if (bioRead > 0) {
1053                        dst.position(pos + bioRead);
1054                        return bioRead;
1055                    }
1056                } else {
1057                    byte[] data = new byte[len];
1058                    bioRead = NativeCrypto.ENGINE_SSL_read_BIO_heap(
1059                            sslNativePointer, networkBio, data, 0, pending, this);
1060                    if (bioRead > 0) {
1061                        dst.put(data, 0, bioRead);
1062                        return bioRead;
1063                    }
1064                }
1065            }
1066            return bioRead;
1067        } catch (Exception e) {
1068            throw convertException(e);
1069        }
1070    }
1071
1072    private SSLEngineResult.HandshakeStatus mayFinishHandshake(
1073            SSLEngineResult.HandshakeStatus status) throws SSLException {
1074        if (!handshakeFinished
1075                && status
1076                        == NOT_HANDSHAKING /*|| engineState == EngineState.HANDSHAKE_COMPLETED)*/) {
1077            // If the status was NOT_HANDSHAKING and we not finished the handshake we need to call
1078            // SSL_do_handshake() again
1079            return handshake();
1080        }
1081        return status;
1082    }
1083
1084    private SSLEngineResult.HandshakeStatus getHandshakeStatus(int pending) {
1085        // Check if we are in the initial handshake phase or shutdown phase
1086        return !handshakeFinished ? pendingStatus(pending) : NOT_HANDSHAKING;
1087    }
1088
1089    private SSLEngineResult.Status getEngineStatus() {
1090        switch (engineState) {
1091            case CLOSED_INBOUND:
1092            case CLOSED_OUTBOUND:
1093            case CLOSED:
1094                return CLOSED;
1095            default:
1096                return OK;
1097        }
1098    }
1099
1100    private void closeAll() throws SSLException {
1101        closeOutbound();
1102        closeInbound();
1103    }
1104
1105    private SSLEngineResult sslReadErrorResult(int err, int bytesConsumed, int bytesProduced)
1106            throws SSLException {
1107        if (!handshakeFinished && pendingOutboundEncryptedBytes() > 0) {
1108            return new SSLEngineResult(OK, NEED_WRAP, bytesConsumed, bytesProduced);
1109        }
1110        throw shutdownWithError(NativeCrypto.SSL_get_error_string(err));
1111    }
1112
1113    private SSLException shutdownWithError(String err) {
1114        // There was an internal error -- shutdown
1115        shutdown();
1116        if (getHandshakeStatusInternal() == HandshakeStatus.FINISHED) {
1117            return new SSLException(err);
1118        }
1119        return new SSLHandshakeException(err);
1120    }
1121
1122    private SSLEngineResult newResult(int bytesConsumed, int bytesProduced,
1123            SSLEngineResult.HandshakeStatus status) throws SSLException {
1124        return new SSLEngineResult(getEngineStatus(),
1125                mayFinishHandshake(status == FINISHED ? status : getHandshakeStatusInternal()),
1126                bytesConsumed, bytesProduced);
1127    }
1128
1129    @Override
1130    public final SSLEngineResult wrap(ByteBuffer src, ByteBuffer dst) throws SSLException {
1131        synchronized (stateLock) {
1132            try {
1133                return wrap(singleSrcBuffer(src), dst);
1134            } finally {
1135                resetSingleSrcBuffer();
1136            }
1137        }
1138    }
1139
1140    @Override
1141    public SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst)
1142            throws SSLException {
1143        checkNotNull(srcs, "srcs");
1144        checkNotNull(dst, "dst");
1145        checkIndex(srcs.length, offset, length, "srcs");
1146        if (dst.isReadOnly()) {
1147            throw new ReadOnlyBufferException();
1148        }
1149
1150        synchronized (stateLock) {
1151            switch (engineState) {
1152                case MODE_SET:
1153                    // Begin the handshake implicitly.
1154                    beginHandshakeInternal();
1155                    break;
1156                case CLOSED_OUTBOUND:
1157                case CLOSED:
1158                    return new SSLEngineResult(Status.CLOSED, getHandshakeStatusInternal(), 0, 0);
1159                case NEW:
1160                    throw new IllegalStateException(
1161                            "Client/server mode must be set before calling wrap");
1162                default:
1163                    break;
1164            }
1165
1166            // If we haven't completed the handshake yet, just let the caller know.
1167            HandshakeStatus handshakeStatus = HandshakeStatus.NOT_HANDSHAKING;
1168            // Prepare OpenSSL to work in server mode and receive handshake
1169            if (!handshakeFinished) {
1170                handshakeStatus = handshake();
1171                if (handshakeStatus == NEED_UNWRAP) {
1172                    return NEED_UNWRAP_OK;
1173                }
1174
1175                if (engineState == EngineState.CLOSED) {
1176                    return NEED_UNWRAP_CLOSED;
1177                }
1178                // NEED_WRAP - just fall through to perform the wrap.
1179            }
1180
1181            int srcsLen = 0;
1182            final int endOffset = offset + length;
1183            for (int i = offset; i < endOffset; ++i) {
1184                final ByteBuffer src = srcs[i];
1185                if (src == null) {
1186                    throw new IllegalArgumentException("srcs[" + i + "] is null");
1187                }
1188                if (srcsLen == SSL3_RT_MAX_PLAIN_LENGTH) {
1189                    continue;
1190                }
1191
1192                srcsLen += src.remaining();
1193                if (srcsLen > SSL3_RT_MAX_PLAIN_LENGTH || srcsLen < 0) {
1194                    // If srcLen > MAX_PLAINTEXT_LENGTH or secLen < 0 just set it to
1195                    // MAX_PLAINTEXT_LENGTH.
1196                    // This also help us to guard against overflow.
1197                    // We not break out here as we still need to check for null entries in srcs[].
1198                    srcsLen = SSL3_RT_MAX_PLAIN_LENGTH;
1199                }
1200            }
1201
1202            if (dst.remaining() < calculateOutNetBufSize(srcsLen)) {
1203                return new SSLEngineResult(
1204                        Status.BUFFER_OVERFLOW, getHandshakeStatusInternal(), 0, 0);
1205            }
1206
1207            int bytesProduced = 0;
1208            int bytesConsumed = 0;
1209        loop:
1210            for (int i = offset; i < endOffset; ++i) {
1211                final ByteBuffer src = srcs[i];
1212                checkNotNull(src, "srcs[%d] is null", i);
1213                while (src.hasRemaining()) {
1214                    final SSLEngineResult pendingNetResult;
1215                    // Write plaintext application data to the SSL engine
1216                    int result = writePlaintextData(src,
1217                            Math.min(src.remaining(), SSL3_RT_MAX_PLAIN_LENGTH - bytesConsumed));
1218                    if (result > 0) {
1219                        bytesConsumed += result;
1220
1221                        pendingNetResult = readPendingBytesFromBIO(
1222                                dst, bytesConsumed, bytesProduced, handshakeStatus);
1223                        if (pendingNetResult != null) {
1224                            if (pendingNetResult.getStatus() != OK) {
1225                                return pendingNetResult;
1226                            }
1227                            bytesProduced = pendingNetResult.bytesProduced();
1228                        }
1229                        if (bytesConsumed == SSL3_RT_MAX_PLAIN_LENGTH) {
1230                            // If we consumed the maximum amount of bytes for the plaintext length
1231                            // break out of the loop and start to fill the dst buffer.
1232                            break loop;
1233                        }
1234                    } else {
1235                        int sslError = NativeCrypto.SSL_get_error(sslNativePointer, result);
1236                        switch (sslError) {
1237                            case SSL_ERROR_ZERO_RETURN:
1238                                // This means the connection was shutdown correctly, close inbound
1239                                // and outbound
1240                                closeAll();
1241                                pendingNetResult = readPendingBytesFromBIO(
1242                                        dst, bytesConsumed, bytesProduced, handshakeStatus);
1243                                return pendingNetResult != null ? pendingNetResult
1244                                                                : CLOSED_NOT_HANDSHAKING;
1245                            case SSL_ERROR_WANT_READ:
1246                                // If there is no pending data to read from BIO we should go back to
1247                                // event loop and try
1248                                // to read more data [1]. It is also possible that event loop will
1249                                // detect the socket
1250                                // has been closed. [1]
1251                                // https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
1252                                pendingNetResult = readPendingBytesFromBIO(
1253                                        dst, bytesConsumed, bytesProduced, handshakeStatus);
1254                                return pendingNetResult != null
1255                                        ? pendingNetResult
1256                                        : new SSLEngineResult(getEngineStatus(), NEED_UNWRAP,
1257                                                  bytesConsumed, bytesProduced);
1258                            case SSL_ERROR_WANT_WRITE:
1259                                // SSL_ERROR_WANT_WRITE typically means that the underlying
1260                                // transport is not writable
1261                                // and we should set the "want write" flag on the selector and try
1262                                // again when the
1263                                // underlying transport is writable [1]. However we are not directly
1264                                // writing to the
1265                                // underlying transport and instead writing to a BIO buffer. The
1266                                // OpenSsl documentation
1267                                // says we should do the following [1]:
1268                                //
1269                                // "When using a buffering BIO, like a BIO pair, data must be
1270                                // written into or retrieved
1271                                // out of the BIO before being able to continue."
1272                                //
1273                                // So we attempt to drain the BIO buffer below, but if there is no
1274                                // data this condition
1275                                // is undefined and we assume their is a fatal error with the
1276                                // openssl engine and close.
1277                                // [1] https://www.openssl.org/docs/manmaster/ssl/SSL_write.html
1278                                pendingNetResult = readPendingBytesFromBIO(
1279                                        dst, bytesConsumed, bytesProduced, handshakeStatus);
1280                                return pendingNetResult != null ? pendingNetResult
1281                                                                : NEED_WRAP_CLOSED;
1282                            default:
1283                                // Everything else is considered as error
1284                                throw shutdownWithError("SSL_write");
1285                        }
1286                    }
1287                }
1288            }
1289            // We need to check if pendingWrittenBytesInBIO was checked yet, as we may not checked
1290            // if the srcs was
1291            // empty, or only contained empty buffers.
1292            if (bytesConsumed == 0) {
1293                SSLEngineResult pendingNetResult =
1294                        readPendingBytesFromBIO(dst, 0, bytesProduced, handshakeStatus);
1295                if (pendingNetResult != null) {
1296                    return pendingNetResult;
1297                }
1298            }
1299
1300            // return new SSLEngineResult(OK, getHandshakeStatusInternal(), bytesConsumed,
1301            // bytesProduced);
1302            return newResult(bytesConsumed, bytesProduced, handshakeStatus);
1303        }
1304    }
1305
1306    @Override
1307    public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) {
1308        return sslParameters.clientPSKKeyRequested(identityHint, identity, key, this);
1309    }
1310
1311    @Override
1312    public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) {
1313        return sslParameters.serverPSKKeyRequested(identityHint, identity, key, this);
1314    }
1315
1316    @Override
1317    public void onSSLStateChange(int type, int val) {
1318        synchronized (stateLock) {
1319            switch (type) {
1320                case SSL_CB_HANDSHAKE_DONE:
1321                    if (engineState != EngineState.HANDSHAKE_STARTED
1322                            && engineState != EngineState.READY_HANDSHAKE_CUT_THROUGH) {
1323                        throw new IllegalStateException(
1324                                "Completed handshake while in mode " + engineState);
1325                    }
1326                    engineState = EngineState.HANDSHAKE_COMPLETED;
1327                    break;
1328                case SSL_CB_HANDSHAKE_START:
1329                    // For clients, this will allow the NEED_UNWRAP status to be
1330                    // returned.
1331                    engineState = EngineState.HANDSHAKE_STARTED;
1332                    break;
1333            }
1334        }
1335    }
1336
1337    @Override
1338    public void verifyCertificateChain(long[] certRefs, String authMethod)
1339            throws CertificateException {
1340        try {
1341            X509TrustManager x509tm = sslParameters.getX509TrustManager();
1342            if (x509tm == null) {
1343                throw new CertificateException("No X.509 TrustManager");
1344            }
1345            if (certRefs == null || certRefs.length == 0) {
1346                throw new SSLException("Peer sent no certificate");
1347            }
1348            OpenSSLX509Certificate[] peerCertChain =
1349                    OpenSSLX509Certificate.createCertChain(certRefs);
1350
1351            byte[] ocspData = NativeCrypto.SSL_get_ocsp_response(sslNativePointer);
1352            byte[] tlsSctData = NativeCrypto.SSL_get_signed_cert_timestamp_list(sslNativePointer);
1353
1354            // Used for verifyCertificateChain callback
1355            handshakeSession = new OpenSSLSessionImpl(
1356                    NativeCrypto.SSL_get1_session(sslNativePointer), null, peerCertChain, ocspData,
1357                    tlsSctData, getSniHostname(), getPeerPort(), null);
1358
1359            boolean client = sslParameters.getUseClientMode();
1360            if (client) {
1361                Platform.checkServerTrusted(x509tm, peerCertChain, authMethod, this);
1362            } else {
1363                String authType = peerCertChain[0].getPublicKey().getAlgorithm();
1364                Platform.checkClientTrusted(x509tm, peerCertChain, authType, this);
1365            }
1366        } catch (CertificateException e) {
1367            throw e;
1368        } catch (Exception e) {
1369            throw new CertificateException(e);
1370        } finally {
1371            handshakeSession = null;
1372        }
1373    }
1374
1375    @Override
1376    public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)
1377            throws CertificateEncodingException, SSLException {
1378        sslParameters.chooseClientCertificate(
1379                keyTypeBytes, asn1DerEncodedPrincipals, sslNativePointer, this);
1380    }
1381
1382    private void shutdown() {
1383        try {
1384            NativeCrypto.ENGINE_SSL_shutdown(sslNativePointer, this);
1385        } catch (IOException ignored) {
1386            // TODO: The RI ignores close failures in SSLSocket, but need to
1387            // investigate whether it does for SSLEngine.
1388        }
1389    }
1390
1391    private void shutdownAndFreeSslNative() {
1392        try {
1393            shutdown();
1394        } finally {
1395            free();
1396        }
1397    }
1398
1399    private void free() {
1400        if (sslNativePointer == 0) {
1401            return;
1402        }
1403        NativeCrypto.SSL_free(sslNativePointer);
1404        NativeCrypto.BIO_free_all(networkBio);
1405        sslNativePointer = 0;
1406        networkBio = 0;
1407    }
1408
1409    @Override
1410    protected void finalize() throws Throwable {
1411        try {
1412            free();
1413        } finally {
1414            super.finalize();
1415        }
1416    }
1417
1418    /* @Override */
1419    @SuppressWarnings("MissingOverride") // For compilation with Java 6.
1420    public SSLSession getHandshakeSession() {
1421        return handshakeSession;
1422    }
1423
1424    @Override
1425    public String chooseServerAlias(X509KeyManager keyManager, String keyType) {
1426        if (keyManager instanceof X509ExtendedKeyManager) {
1427            X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) keyManager;
1428            return ekm.chooseEngineServerAlias(keyType, null, this);
1429        } else {
1430            return keyManager.chooseServerAlias(keyType, null, null);
1431        }
1432    }
1433
1434    @Override
1435    public String chooseClientAlias(
1436            X509KeyManager keyManager, X500Principal[] issuers, String[] keyTypes) {
1437        if (keyManager instanceof X509ExtendedKeyManager) {
1438            X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) keyManager;
1439            return ekm.chooseEngineClientAlias(keyTypes, issuers, this);
1440        } else {
1441            return keyManager.chooseClientAlias(keyTypes, issuers, null);
1442        }
1443    }
1444
1445    @Override
1446    @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package
1447    public String chooseServerPSKIdentityHint(PSKKeyManager keyManager) {
1448        return keyManager.chooseServerKeyIdentityHint(this);
1449    }
1450
1451    @Override
1452    @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package
1453    public String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint) {
1454        return keyManager.chooseClientKeyIdentity(identityHint, this);
1455    }
1456
1457    @Override
1458    @SuppressWarnings("deprecation") // PSKKeyManager is deprecated, but in our own package
1459    public SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity) {
1460        return keyManager.getKey(identityHint, identity, this);
1461    }
1462
1463    /**
1464     * This method enables session ticket support.
1465     *
1466     * @param useSessionTickets True to enable session tickets
1467     */
1468    void setUseSessionTickets(boolean useSessionTickets) {
1469        sslParameters.setUseSessionTickets(useSessionTickets);
1470    }
1471
1472    /**
1473     * Sets the list of ALPN protocols.
1474     *
1475     * @param alpnProtocols the list of ALPN protocols
1476     */
1477    void setAlpnProtocols(String[] alpnProtocols) {
1478        sslParameters.setAlpnProtocols(alpnProtocols);
1479    }
1480
1481    /**
1482     * Returns the protocol agreed upon by client and server, or {@code null} if no protocol was
1483     * agreed upon.
1484     */
1485    byte[] getAlpnSelectedProtocol() {
1486        return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer);
1487    }
1488
1489    private ByteBuffer toHeapBuffer(ByteBuffer buffer, int len) {
1490        if (buffer.hasArray()) {
1491            return buffer;
1492        }
1493
1494        // Need to copy to a heap buffer.
1495        final ByteBuffer heapBuffer = ByteBuffer.allocate(len);
1496        final int pos = buffer.position();
1497        final int limit = buffer.limit();
1498        buffer.limit(pos + len);
1499        try {
1500            heapBuffer.put(buffer);
1501            heapBuffer.flip();
1502            return heapBuffer;
1503        } finally {
1504            buffer.limit(limit);
1505            buffer.position(pos);
1506        }
1507    }
1508
1509    private ByteBuffer[] singleSrcBuffer(ByteBuffer src) {
1510        singleSrcBuffer[0] = src;
1511        return singleSrcBuffer;
1512    }
1513
1514    private void resetSingleSrcBuffer() {
1515        singleSrcBuffer[0] = null;
1516    }
1517
1518    private ByteBuffer[] singleDstBuffer(ByteBuffer src) {
1519        singleDstBuffer[0] = src;
1520        return singleDstBuffer;
1521    }
1522
1523    private void resetSingleDstBuffer() {
1524        singleDstBuffer[0] = null;
1525    }
1526
1527    private static void checkIndex(int arrayLength, int offset, int length, String arrayName) {
1528        if ((offset | length) < 0 || offset + length > arrayLength) {
1529            throw new IndexOutOfBoundsException("offset: " + offset + ", length: " + length
1530                    + " (expected: offset <= offset + length <= " + arrayName + ".length ("
1531                    + arrayLength + "))");
1532        }
1533    }
1534
1535    private static <T> T checkNotNull(T obj, String fmt, Object... args) {
1536        if (obj == null) {
1537            throw new IllegalArgumentException(String.format(fmt, args));
1538        }
1539        return obj;
1540    }
1541}
1542