/*
 * Copyright 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.conscrypt;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;

import javax.crypto.SecretKey;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;
import javax.security.auth.x500.X500Principal;

/**
 * Implements the {@link SSLEngine} API using OpenSSL's non-blocking interfaces.
 */
public class OpenSSLEngineImpl extends SSLEngine implements NativeCrypto.SSLHandshakeCallbacks,
        SSLParametersImpl.AliasChooser, SSLParametersImpl.PSKCallbacks {
    private final SSLParametersImpl sslParameters;

    /**
     * Protects handshakeStarted and handshakeCompleted.
     */
    private final Object stateLock = new Object();

    private static enum EngineState {
        /**
         * The {@link OpenSSLSocketImpl} object is constructed, but {@link #beginHandshake()}
         * has not yet been called.
         */
        NEW,
        /**
         * {@link #setUseClientMode(boolean)} has been called at least once.
         */
        MODE_SET,
        /**
         * {@link #beginHandshake()} has been called at least once.
         */
        HANDSHAKE_WANTED,
        /**
         * Handshake task has been started.
         */
        HANDSHAKE_STARTED,
        /**
         * Handshake has been completed, but {@link #beginHandshake()} hasn't returned yet.
         */
        HANDSHAKE_COMPLETED,
        /**
         * {@link #beginHandshake()} has completed but the task hasn't
         * been called. This is expected behaviour in cut-through mode, where SSL_do_handshake
         * returns before the handshake is complete. We can now start writing data to the socket.
         */
        READY_HANDSHAKE_CUT_THROUGH,
        /**
         * {@link #beginHandshake()} has completed and socket is ready to go.
         */
        READY,
        CLOSED_INBOUND,
        CLOSED_OUTBOUND,
        /**
         * Inbound and outbound has been called.
         */
        CLOSED,
    }

    // @GuardedBy("stateLock");
    private EngineState engineState = EngineState.NEW;

    /**
     * Protected by synchronizing on stateLock. Starts as 0, set by
     * startHandshake, reset to 0 on close.
     */
    // @GuardedBy("stateLock");
    private long sslNativePointer;

    /** Used during handshake when {@link #wrap(ByteBuffer, ByteBuffer)} is called. */
    // TODO: make this use something similar to BIO_s_null() in native code
    private static OpenSSLBIOSource nullSource = OpenSSLBIOSource.wrap(ByteBuffer.allocate(0));

    /** A BIO sink written to only during handshakes. */
    private OpenSSLBIOSink handshakeSink;

    /** A BIO sink written to during regular operation. */
    private final OpenSSLBIOSink localToRemoteSink = OpenSSLBIOSink.create();

    /** Set during startHandshake. */
    private OpenSSLSessionImpl sslSession;

    /** Used during handshake callbacks. */
    private OpenSSLSessionImpl handshakeSession;

    /**
     * Private key for the TLS Channel ID extension. This field is client-side
     * only. Set during startHandshake.
     */
    OpenSSLKey channelIdPrivateKey;

    public OpenSSLEngineImpl(SSLParametersImpl sslParameters) {
        this.sslParameters = sslParameters;
    }

    public OpenSSLEngineImpl(String host, int port, SSLParametersImpl sslParameters) {
        super(host, port);
        this.sslParameters = sslParameters;
    }

    @Override
    public void beginHandshake() throws SSLException {
        synchronized (stateLock) {
            if (engineState == EngineState.CLOSED || engineState == EngineState.CLOSED_OUTBOUND
                    || engineState == EngineState.CLOSED_INBOUND) {
                throw new IllegalStateException("Engine has already been closed");
            }
            if (engineState == EngineState.HANDSHAKE_STARTED) {
                throw new IllegalStateException("Handshake has already been started");
            }
            if (engineState != EngineState.MODE_SET) {
                throw new IllegalStateException("Client/server mode must be set before handshake");
            }
            if (getUseClientMode()) {
                engineState = EngineState.HANDSHAKE_WANTED;
            } else {
                engineState = EngineState.HANDSHAKE_STARTED;
            }
        }

        boolean releaseResources = true;
        try {
            final AbstractSessionContext sessionContext = sslParameters.getSessionContext();
            final long sslCtxNativePointer = sessionContext.sslCtxNativePointer;
            sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer);
            sslSession = sslParameters.getSessionToReuse(
                    sslNativePointer, getPeerHost(), getPeerPort());
            sslParameters.setSSLParameters(sslCtxNativePointer, sslNativePointer, this, this,
                    getPeerHost());
            sslParameters.setCertificateValidation(sslNativePointer);
            sslParameters.setTlsChannelId(sslNativePointer, channelIdPrivateKey);
            if (getUseClientMode()) {
                NativeCrypto.SSL_set_connect_state(sslNativePointer);
            } else {
                NativeCrypto.SSL_set_accept_state(sslNativePointer);
            }
            handshakeSink = OpenSSLBIOSink.create();
            releaseResources = false;
        } catch (IOException e) {
            // Write CCS errors to EventLog
            String message = e.getMessage();
            // Must match error reason string of SSL_R_UNEXPECTED_CCS (in ssl/ssl_err.c)
            if (message.contains("unexpected CCS")) {
                String logMessage = String.format("ssl_unexpected_ccs: host=%s", getPeerHost());
                Platform.logEvent(logMessage);
            }
            throw new SSLException(e);
        } finally {
            if (releaseResources) {
                synchronized (stateLock) {
                    engineState = EngineState.CLOSED;
                }
                shutdownAndFreeSslNative();
            }
        }
    }

    @Override
    public void closeInbound() throws SSLException {
        synchronized (stateLock) {
            if (engineState == EngineState.CLOSED) {
                return;
            }
            if (engineState == EngineState.CLOSED_OUTBOUND) {
                engineState = EngineState.CLOSED;
            } else {
                engineState = EngineState.CLOSED_INBOUND;
            }
        }
        // TODO anything else to notify OpenSSL layer?
    }

    @Override
    public void closeOutbound() {
        synchronized (stateLock) {
            if (engineState == EngineState.CLOSED || engineState == EngineState.CLOSED_OUTBOUND) {
                return;
            }
            if (engineState != EngineState.MODE_SET && engineState != EngineState.NEW) {
                shutdownAndFreeSslNative();
            }
            if (engineState == EngineState.CLOSED_INBOUND) {
                engineState = EngineState.CLOSED;
            } else {
                engineState = EngineState.CLOSED_OUTBOUND;
            }
        }
        shutdown();
    }

    @Override
    public Runnable getDelegatedTask() {
        /* This implementation doesn't use any delegated tasks. */
        return null;
    }

    @Override
    public String[] getEnabledCipherSuites() {
        return sslParameters.getEnabledCipherSuites();
    }

    @Override
    public String[] getEnabledProtocols() {
        return sslParameters.getEnabledProtocols();
    }

    @Override
    public boolean getEnableSessionCreation() {
        return sslParameters.getEnableSessionCreation();
    }

    @Override
    public HandshakeStatus getHandshakeStatus() {
        synchronized (stateLock) {
            switch (engineState) {
                case HANDSHAKE_WANTED:
                    if (getUseClientMode()) {
                        return HandshakeStatus.NEED_WRAP;
                    } else {
                        return HandshakeStatus.NEED_UNWRAP;
                    }
                case HANDSHAKE_STARTED:
                    if (handshakeSink.available() > 0) {
                        return HandshakeStatus.NEED_WRAP;
                    } else {
                        return HandshakeStatus.NEED_UNWRAP;
                    }
                case HANDSHAKE_COMPLETED:
                    if (handshakeSink.available() == 0) {
                        handshakeSink = null;
                        engineState = EngineState.READY;
                        return HandshakeStatus.FINISHED;
                    } else {
                        return HandshakeStatus.NEED_WRAP;
                    }
                case NEW:
                case MODE_SET:
                case CLOSED:
                case CLOSED_INBOUND:
                case CLOSED_OUTBOUND:
                case READY:
                case READY_HANDSHAKE_CUT_THROUGH:
                    return HandshakeStatus.NOT_HANDSHAKING;
                default:
                    break;
            }
            throw new IllegalStateException("Unexpected engine state: " + engineState);
        }
    }

    @Override
    public boolean getNeedClientAuth() {
        return sslParameters.getNeedClientAuth();
    }

    @Override
    public SSLSession getSession() {
        if (sslSession == null) {
            return SSLNullSession.getNullSession();
        }
        return sslSession;
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return NativeCrypto.getSupportedCipherSuites();
    }

    @Override
    public String[] getSupportedProtocols() {
        return NativeCrypto.getSupportedProtocols();
    }

    @Override
    public boolean getUseClientMode() {
        return sslParameters.getUseClientMode();
    }

    @Override
    public boolean getWantClientAuth() {
        return sslParameters.getWantClientAuth();
    }

    @Override
    public boolean isInboundDone() {
        if (sslNativePointer == 0) {
            synchronized (stateLock) {
                return engineState == EngineState.CLOSED
                        || engineState == EngineState.CLOSED_INBOUND;
            }
        }
        return (NativeCrypto.SSL_get_shutdown(sslNativePointer)
                & NativeCrypto.SSL_RECEIVED_SHUTDOWN) != 0;
    }

    @Override
    public boolean isOutboundDone() {
        if (sslNativePointer == 0) {
            synchronized (stateLock) {
                return engineState == EngineState.CLOSED
                        || engineState == EngineState.CLOSED_OUTBOUND;
            }
        }
        return (NativeCrypto.SSL_get_shutdown(sslNativePointer)
                & NativeCrypto.SSL_SENT_SHUTDOWN) != 0;
    }

    @Override
    public void setEnabledCipherSuites(String[] suites) {
        sslParameters.setEnabledCipherSuites(suites);
    }

    @Override
    public void setEnabledProtocols(String[] protocols) {
        sslParameters.setEnabledProtocols(protocols);
    }

    @Override
    public void setEnableSessionCreation(boolean flag) {
        sslParameters.setEnableSessionCreation(flag);
    }

    @Override
    public void setNeedClientAuth(boolean need) {
        sslParameters.setNeedClientAuth(need);
    }

    @Override
    public void setUseClientMode(boolean mode) {
        synchronized (stateLock) {
            if (engineState != EngineState.MODE_SET && engineState != EngineState.NEW) {
                throw new IllegalArgumentException(
                        "Can not change mode after handshake: engineState == " + engineState);
            }
            engineState = EngineState.MODE_SET;
        }
        sslParameters.setUseClientMode(mode);
    }

    @Override
    public void setWantClientAuth(boolean want) {
        sslParameters.setWantClientAuth(want);
    }

    private static void checkIndex(int length, int offset, int count) {
        if (offset < 0) {
            throw new IndexOutOfBoundsException("offset < 0");
        } else if (count < 0) {
            throw new IndexOutOfBoundsException("count < 0");
        } else if (offset > length) {
            throw new IndexOutOfBoundsException("offset > length");
        } else if (offset > length - count) {
            throw new IndexOutOfBoundsException("offset + count > length");
        }
    }

    @Override
    public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts, int offset, int length)
            throws SSLException {
        if (src == null) {
            throw new IllegalArgumentException("src == null");
        } else if (dsts == null) {
            throw new IllegalArgumentException("dsts == null");
        }
        checkIndex(dsts.length, offset, length);
        int dstRemaining = 0;
        for (int i = 0; i < dsts.length; i++) {
            ByteBuffer dst = dsts[i];
            if (dst == null) {
                throw new IllegalArgumentException("one of the dst == null");
            } else if (dst.isReadOnly()) {
                throw new ReadOnlyBufferException();
            }
            if (i >= offset && i < offset + length) {
                dstRemaining += dst.remaining();
            }
        }

        synchronized (stateLock) {
            // If the inbound direction is closed. we can't send anymore.
            if (engineState == EngineState.CLOSED || engineState == EngineState.CLOSED_INBOUND) {
                return new SSLEngineResult(Status.CLOSED, getHandshakeStatus(), 0, 0);
            }
            if (engineState == EngineState.NEW || engineState == EngineState.MODE_SET) {
                beginHandshake();
            }
        }

        // If we haven't completed the handshake yet, just let the caller know.
        HandshakeStatus handshakeStatus = getHandshakeStatus();
        if (handshakeStatus == HandshakeStatus.NEED_UNWRAP) {
            int positionBeforeHandshake = src.position();
            OpenSSLBIOSource source = OpenSSLBIOSource.wrap(src);
            long sslSessionCtx = 0L;
            try {
                sslSessionCtx = NativeCrypto.SSL_do_handshake_bio(sslNativePointer,
                        source.getContext(), handshakeSink.getContext(), this, getUseClientMode(),
                        sslParameters.npnProtocols, sslParameters.alpnProtocols);
                if (sslSessionCtx != 0) {
                    if (sslSession != null && engineState == EngineState.HANDSHAKE_STARTED) {
                        engineState = EngineState.READY_HANDSHAKE_CUT_THROUGH;
                    }
                    sslSession = sslParameters.setupSession(sslSessionCtx, sslNativePointer, sslSession,
                            getPeerHost(), getPeerPort(), true);
                }
                int bytesWritten = handshakeSink.position();
                int bytesConsumed = (src.position() - positionBeforeHandshake);
                return new SSLEngineResult((bytesConsumed > 0) ? Status.OK : Status.BUFFER_UNDERFLOW,
                        getHandshakeStatus(), bytesConsumed, bytesWritten);
            } catch (Exception e) {
                throw (SSLHandshakeException) new SSLHandshakeException("Handshake failed")
                        .initCause(e);
            } finally {
                if (sslSession == null && sslSessionCtx != 0) {
                    NativeCrypto.SSL_SESSION_free(sslSessionCtx);
                }
                source.release();
            }
        } else if (handshakeStatus != HandshakeStatus.NOT_HANDSHAKING) {
            return new SSLEngineResult(Status.OK, handshakeStatus, 0, 0);
        }

        if (dstRemaining == 0) {
            return new SSLEngineResult(Status.BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
        }

        ByteBuffer srcDuplicate = src.duplicate();
        OpenSSLBIOSource source = OpenSSLBIOSource.wrap(srcDuplicate);
        try {
            int positionBeforeRead = srcDuplicate.position();
            int produced = 0;
            boolean shouldStop = false;

            while (!shouldStop) {
                ByteBuffer dst = getNextAvailableByteBuffer(dsts, offset, length);
                if (dst == null) {
                    shouldStop = true;
                    continue;
                }
                ByteBuffer arrayDst = dst;
                if (dst.isDirect()) {
                    arrayDst = ByteBuffer.allocate(dst.remaining());
                }

                int dstOffset = arrayDst.arrayOffset() + arrayDst.position();

                int internalProduced = NativeCrypto.SSL_read_BIO(sslNativePointer,
                        arrayDst.array(), dstOffset, dst.remaining(), source.getContext(),
                        localToRemoteSink.getContext(), this);
                if (internalProduced <= 0) {
                    shouldStop = true;
                    continue;
                }
                arrayDst.position(arrayDst.position() + internalProduced);
                produced += internalProduced;
                if (dst != arrayDst) {
                    arrayDst.flip();
                    dst.put(arrayDst);
                }
            }

            int consumed = srcDuplicate.position() - positionBeforeRead;
            src.position(srcDuplicate.position());
            return new SSLEngineResult((consumed > 0) ? Status.OK : Status.BUFFER_UNDERFLOW,
                    getHandshakeStatus(), consumed, produced);
        } catch (IOException e) {
            throw new SSLException(e);
        } finally {
            source.release();
        }
    }

    /** Returns the next non-empty ByteBuffer. */
    private ByteBuffer getNextAvailableByteBuffer(ByteBuffer[] buffers, int offset, int length) {
        for (int i = offset; i < length; ++i) {
            if (buffers[i].remaining() > 0) {
                return buffers[i];
            }
        }
        return null;
    }

    @Override
    public SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int length, ByteBuffer dst)
            throws SSLException {
        if (srcs == null) {
            throw new IllegalArgumentException("srcs == null");
        } else if (dst == null) {
            throw new IllegalArgumentException("dst == null");
        } else if (dst.isReadOnly()) {
            throw new ReadOnlyBufferException();
        }
        for (ByteBuffer src : srcs) {
            if (src == null) {
                throw new IllegalArgumentException("one of the src == null");
            }
        }
        checkIndex(srcs.length, offset, length);

        if (dst.remaining() < NativeCrypto.SSL3_RT_MAX_PACKET_SIZE) {
            return new SSLEngineResult(Status.BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
        }

        synchronized (stateLock) {
            // If the outbound direction is closed. we can't send anymore.
            if (engineState == EngineState.CLOSED || engineState == EngineState.CLOSED_OUTBOUND) {
                return new SSLEngineResult(Status.CLOSED, getHandshakeStatus(), 0, 0);
            }
            if (engineState == EngineState.NEW || engineState == EngineState.MODE_SET) {
                beginHandshake();
            }
        }

        // If we haven't completed the handshake yet, just let the caller know.
        HandshakeStatus handshakeStatus = getHandshakeStatus();
        if (handshakeStatus == HandshakeStatus.NEED_WRAP) {
            if (handshakeSink.available() == 0) {
                long sslSessionCtx = 0L;
                try {
                    sslSessionCtx = NativeCrypto.SSL_do_handshake_bio(sslNativePointer,
                            nullSource.getContext(), handshakeSink.getContext(), this,
                            getUseClientMode(), sslParameters.npnProtocols,
                            sslParameters.alpnProtocols);
                    if (sslSessionCtx != 0) {
                        if (sslSession != null && engineState == EngineState.HANDSHAKE_STARTED) {
                            engineState = EngineState.READY_HANDSHAKE_CUT_THROUGH;
                        }
                        sslSession = sslParameters.setupSession(sslSessionCtx, sslNativePointer, sslSession,
                                getPeerHost(), getPeerPort(), true);
                    }
                } catch (Exception e) {
                    throw (SSLHandshakeException) new SSLHandshakeException("Handshake failed")
                            .initCause(e);
                } finally {
                    if (sslSession == null && sslSessionCtx != 0) {
                        NativeCrypto.SSL_SESSION_free(sslSessionCtx);
                    }
                }
            }
            int bytesWritten = writeSinkToByteBuffer(handshakeSink, dst);
            return new SSLEngineResult(Status.OK, getHandshakeStatus(), 0, bytesWritten);
        } else if (handshakeStatus != HandshakeStatus.NOT_HANDSHAKING) {
            return new SSLEngineResult(Status.OK, handshakeStatus, 0, 0);
        }

        try {
            int totalRead = 0;
            byte[] buffer = null;

            for (ByteBuffer src : srcs) {
                int toRead = src.remaining();
                if (buffer == null || toRead > buffer.length) {
                    buffer = new byte[toRead];
                }
                /*
                 * We can't just use .mark() here because the caller might be
                 * using it.
                 */
                src.duplicate().get(buffer, 0, toRead);
                int numRead = NativeCrypto.SSL_write_BIO(sslNativePointer, buffer, toRead,
                        localToRemoteSink.getContext(), this);
                if (numRead > 0) {
                    src.position(src.position() + numRead);
                    totalRead += numRead;
                }
            }

            return new SSLEngineResult(Status.OK, getHandshakeStatus(), totalRead,
                    writeSinkToByteBuffer(localToRemoteSink, dst));
        } catch (IOException e) {
            throw new SSLException(e);
        }
    }

    /** Writes data available in a BIO sink to a ByteBuffer. */
    private static int writeSinkToByteBuffer(OpenSSLBIOSink sink, ByteBuffer dst) {
        int toWrite = Math.min(sink.available(), dst.remaining());
        dst.put(sink.toByteArray(), sink.position(), toWrite);
        sink.skip(toWrite);
        return toWrite;
    }

    @Override
    public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) {
        return sslParameters.clientPSKKeyRequested(identityHint, identity, key, this);
    }

    @Override
    public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) {
        return sslParameters.serverPSKKeyRequested(identityHint, identity, key, this);
    }

    @Override
    public void onSSLStateChange(long sslSessionNativePtr, int type, int val) {
        synchronized (stateLock) {
            switch (type) {
                case NativeCrypto.SSL_CB_HANDSHAKE_DONE:
                    if (engineState != EngineState.HANDSHAKE_STARTED &&
                        engineState != EngineState.READY_HANDSHAKE_CUT_THROUGH) {
                        throw new IllegalStateException("Completed handshake while in mode "
                                + engineState);
                    }
                    engineState = EngineState.HANDSHAKE_COMPLETED;
                    break;
                case NativeCrypto.SSL_CB_HANDSHAKE_START:
                    // For clients, this will allow the NEED_UNWRAP status to be
                    // returned.
                    engineState = EngineState.HANDSHAKE_STARTED;
                    break;
            }
        }
    }

    @Override
    public void verifyCertificateChain(long sslSessionNativePtr, long[] certRefs,
            String authMethod) throws CertificateException {
        try {
            X509TrustManager x509tm = sslParameters.getX509TrustManager();
            if (x509tm == null) {
                throw new CertificateException("No X.509 TrustManager");
            }
            if (certRefs == null || certRefs.length == 0) {
                throw new SSLException("Peer sent no certificate");
            }
            OpenSSLX509Certificate[] peerCertChain = new OpenSSLX509Certificate[certRefs.length];
            for (int i = 0; i < certRefs.length; i++) {
                peerCertChain[i] = new OpenSSLX509Certificate(certRefs[i]);
            }

            // Used for verifyCertificateChain callback
            handshakeSession = new OpenSSLSessionImpl(sslSessionNativePtr, null, peerCertChain,
                    getPeerHost(), getPeerPort(), null);

            boolean client = sslParameters.getUseClientMode();
            if (client) {
                Platform.checkServerTrusted(x509tm, peerCertChain, authMethod, getPeerHost());
            } else {
                String authType = peerCertChain[0].getPublicKey().getAlgorithm();
                x509tm.checkClientTrusted(peerCertChain, authType);
            }
        } catch (CertificateException e) {
            throw e;
        } catch (Exception e) {
            throw new CertificateException(e);
        } finally {
            // Clear this before notifying handshake completed listeners
            handshakeSession = null;
        }
    }

    @Override
    public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)
            throws CertificateEncodingException, SSLException {
        sslParameters.chooseClientCertificate(keyTypeBytes, asn1DerEncodedPrincipals,
                sslNativePointer, this);
    }

    private void shutdown() {
        try {
            NativeCrypto.SSL_shutdown_BIO(sslNativePointer, nullSource.getContext(),
                    localToRemoteSink.getContext(), this);
        } catch (IOException ignored) {
            /*
             * TODO: The RI ignores close failures in SSLSocket, but need to
             * investigate whether it does for SSLEngine.
             */
        }
    }

    private void shutdownAndFreeSslNative() {
        try {
            shutdown();
        } finally {
            free();
        }
    }

    private void free() {
        if (sslNativePointer == 0) {
            return;
        }
        NativeCrypto.SSL_free(sslNativePointer);
        sslNativePointer = 0;
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            free();
        } finally {
            super.finalize();
        }
    }

    @Override
    public String chooseServerAlias(X509KeyManager keyManager, String keyType) {
        if (keyManager instanceof X509ExtendedKeyManager) {
            X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) keyManager;
            return ekm.chooseEngineServerAlias(keyType, null, this);
        } else {
            return keyManager.chooseServerAlias(keyType, null, null);
        }
    }

    @Override
    public String chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers,
            String[] keyTypes) {
        if (keyManager instanceof X509ExtendedKeyManager) {
            X509ExtendedKeyManager ekm = (X509ExtendedKeyManager) keyManager;
            return ekm.chooseEngineClientAlias(keyTypes, issuers, this);
        } else {
            return keyManager.chooseClientAlias(keyTypes, issuers, null);
        }
    }

    @Override
    public String chooseServerPSKIdentityHint(PSKKeyManager keyManager) {
        return keyManager.chooseServerKeyIdentityHint(this);
    }

    @Override
    public String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint) {
        return keyManager.chooseClientKeyIdentity(identityHint, this);
    }

    @Override
    public SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity) {
        return keyManager.getKey(identityHint, identity, this);
    }
}
