/*
 * Copyright (C) 2014 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 android.security.cts;

import android.content.Context;
import android.test.InstrumentationTestCase;
import android.util.Log;

import com.android.cts.security.R;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.security.KeyFactory;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509KeyManager;
import javax.net.ssl.X509TrustManager;

/**
 * Tests for the OpenSSL Heartbleed vulnerability.
 */
public class OpenSSLHeartbleedTest extends InstrumentationTestCase {

    // IMPLEMENTATION NOTE: This test spawns an SSLSocket client, SSLServerSocket server, and a
    // Man-in-The-Middle (MiTM). The client connects to the MiTM which then connects to the server
    // and starts forwarding all TLS records between the client and the server. In tests that check
    // for the Heartbleed vulnerability, the MiTM also injects a HeartbeatRequest message into the
    // traffic.

    // IMPLEMENTATION NOTE: This test spawns several background threads that perform network I/O
    // on localhost. To ensure that these background threads are cleaned up at the end of the test
    // tearDown() kills the sockets they may be using. To aid this behavior, all Socket and
    // ServerSocket instances are available as fields of this class. These fields should be accessed
    // via setters and getters to avoid memory visibility issues due to concurrency.

    private static final String TAG = OpenSSLHeartbleedTest.class.getSimpleName();

    private SSLServerSocket mServerListeningSocket;
    private SSLSocket mServerSocket;
    private SSLSocket mClientSocket;
    private ServerSocket mMitmListeningSocket;
    private Socket mMitmServerSocket;
    private Socket mMitmClientSocket;
    private ExecutorService mExecutorService;

    private boolean mHeartbeatRequestWasInjected;
    private boolean mHeartbeatResponseWasDetetected;
    private int mFirstDetectedFatalAlertDescription = -1;

    @Override
    protected void tearDown() throws Exception {
        Log.i(TAG, "Tearing down");
        if (mExecutorService != null) {
            mExecutorService.shutdownNow();
        }
        closeQuietly(getServerListeningSocket());
        closeQuietly(getServerSocket());
        closeQuietly(getClientSocket());
        closeQuietly(getMitmListeningSocket());
        closeQuietly(getMitmServerSocket());
        closeQuietly(getMitmClientSocket());
        super.tearDown();
        Log.i(TAG, "Tear down completed");
    }

    /**
     * Tests that TLS handshake succeeds when the MiTM simply forwards all data without tampering
     * with it. This is to catch issues unrelated to TLS heartbeats.
     */
    public void testWithoutHeartbeats() throws Exception {
        handshake(false, false);
    }

    /**
     * Tests whether client sockets are vulnerable to Heartbleed.
     */
    public void testClientHeartbleed() throws Exception {
        checkHeartbleed(true);
    }

    /**
     * Tests whether server sockets are vulnerable to Heartbleed.
     */
    public void testServerHeartbleed() throws Exception {
        checkHeartbleed(false);
    }

    /**
     * Tests for Heartbleed.
     *
     * @param client {@code true} to test the client, {@code false} to test the server.
     */
    private void checkHeartbleed(boolean client) throws Exception {
        // IMPLEMENTATION NOTE: The MiTM is forwarding all TLS records between the client and the
        // server unmodified. Additionally, the MiTM transmits a malformed HeartbeatRequest to
        // server (if "client" argument is false) right after client's ClientKeyExchange or to
        // client (if "client" argument is true) right after server's ServerHello. The peer is
        // expected to either ignore the HeartbeatRequest (if heartbeats are supported) or to abort
        // the handshake with unexpected_message alert (if heartbeats are not supported).
        try {
            handshake(true, client);
        } catch (ExecutionException e) {
            assertFalse(
                    "SSLSocket is vulnerable to Heartbleed in " + ((client) ? "client" : "server")
                            + " mode",
                    wasHeartbeatResponseDetected());
            if (e.getCause() instanceof SSLException) {
                // TLS handshake or data exchange failed. Check whether the error was caused by
                // fatal alert unexpected_message
                int alertDescription = getFirstDetectedFatalAlertDescription();
                if (alertDescription == -1) {
                    fail("Handshake failed without a fatal alert");
                }
                assertEquals(
                        "First fatal alert description received from server",
                        AlertMessage.DESCRIPTION_UNEXPECTED_MESSAGE,
                        alertDescription);
                return;
            } else {
                throw e;
            }
        }

        // TLS handshake succeeded
        assertFalse(
                "SSLSocket is vulnerable to Heartbleed in " + ((client) ? "client" : "server")
                        + " mode",
                wasHeartbeatResponseDetected());
        assertTrue("HeartbeatRequest not injected", wasHeartbeatRequestInjected());
    }

    /**
     * Starts the client, server, and the MiTM. Makes the client and server perform a TLS handshake
     * and exchange application-level data. The MiTM injects a HeartbeatRequest message if requested
     * by {@code heartbeatRequestInjected}. The direction of the injected message is specified by
     * {@code injectedIntoClient}.
     */
    private void handshake(
            final boolean heartbeatRequestInjected,
            final boolean injectedIntoClient) throws Exception {
        mExecutorService = Executors.newFixedThreadPool(4);
        setServerListeningSocket(serverBind());
        final SocketAddress serverAddress = getServerListeningSocket().getLocalSocketAddress();
        Log.i(TAG, "Server bound to " + serverAddress);

        setMitmListeningSocket(mitmBind());
        final SocketAddress mitmAddress = getMitmListeningSocket().getLocalSocketAddress();
        Log.i(TAG, "MiTM bound to " + mitmAddress);

        // Start the MiTM daemon in the background
        mExecutorService.submit(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                mitmAcceptAndForward(
                        serverAddress,
                        heartbeatRequestInjected,
                        injectedIntoClient);
                return null;
            }
        });
        // Start the server in the background
        Future<Void> serverFuture = mExecutorService.submit(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                serverAcceptAndHandshake();
                return null;
            }
        });
        // Start the client in the background
        Future<Void> clientFuture = mExecutorService.submit(new Callable<Void>() {
            @Override
            public Void call() throws Exception {
                clientConnectAndHandshake(mitmAddress);
                return null;
            }
        });

        // Wait for both client and server to terminate, to ensure that we observe all the traffic
        // exchanged between them. Throw an exception if one of them failed.
        Log.i(TAG, "Waiting for client");
        // Wait for the client, but don't yet throw an exception if it failed.
        Exception clientException = null;
        try {
            clientFuture.get(10, TimeUnit.SECONDS);
        } catch (Exception e) {
            clientException = e;
        }
        Log.i(TAG, "Waiting for server");
        // Wait for the server and throw an exception if it failed.
        serverFuture.get(5, TimeUnit.SECONDS);
        // Throw an exception if the client failed.
        if (clientException != null) {
            throw clientException;
        }
        Log.i(TAG, "Handshake completed and application data exchanged");
    }

    private void clientConnectAndHandshake(SocketAddress serverAddress) throws Exception {
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(
                null,
                new TrustManager[] {new TrustAllX509TrustManager()},
                null);
        SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket();
        setClientSocket(socket);
        try {
            Log.i(TAG, "Client connecting to " + serverAddress);
            socket.connect(serverAddress);
            Log.i(TAG, "Client connected to server from " + socket.getLocalSocketAddress());
            // Ensure a TLS handshake is performed and an exception is thrown if it fails.
            socket.getOutputStream().write("client".getBytes());
            socket.getOutputStream().flush();
            Log.i(TAG, "Client sent request. Reading response");
            int b = socket.getInputStream().read();
            Log.i(TAG, "Client read response: " + b);
        } catch (Exception e) {
            Log.w(TAG, "Client failed", e);
            throw e;
          } finally {
            socket.close();
        }
    }

    public SSLServerSocket serverBind() throws Exception {
        // Load the server's private key and cert chain
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(new PKCS8EncodedKeySpec(
                readResource(
                        getInstrumentation().getContext(), R.raw.openssl_heartbleed_test_key)));
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
        X509Certificate[] certChain =  new X509Certificate[] {
                (X509Certificate) certFactory.generateCertificate(
                        new ByteArrayInputStream(readResource(
                                getInstrumentation().getContext(),
                                R.raw.openssl_heartbleed_test_cert)))
        };

        // Initialize TLS context to use the private key and cert chain for server sockets
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(
                new KeyManager[] {new HardcodedCertX509KeyManager(privateKey, certChain)},
                null,
                null);

        Log.i(TAG, "Server binding to local port");
        return (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket(0);
    }

    private void serverAcceptAndHandshake() throws Exception {
        SSLSocket socket = null;
        SSLServerSocket serverSocket = getServerListeningSocket();
        try {
            Log.i(TAG, "Server listening for incoming connection");
            socket = (SSLSocket) serverSocket.accept();
            setServerSocket(socket);
            Log.i(TAG, "Server accepted connection from " + socket.getRemoteSocketAddress());
            // Ensure a TLS handshake is performed and an exception is thrown if it fails.
            socket.getOutputStream().write("server".getBytes());
            socket.getOutputStream().flush();
            Log.i(TAG, "Server sent reply. Reading response");
            int b = socket.getInputStream().read();
            Log.i(TAG, "Server read response: " + b);
        } catch (Exception e) {
          Log.w(TAG, "Server failed", e);
          throw e;
        } finally {
            if (socket != null) {
                socket.close();
            }
        }
    }

    private ServerSocket mitmBind() throws Exception {
        Log.i(TAG, "MiTM binding to local port");
        return ServerSocketFactory.getDefault().createServerSocket(0);
    }

    /**
     * Accepts the connection on the MiTM listening socket, forwards the TLS records between the
     * client and the server, and, if requested, injects a {@code HeartbeatRequest}.
     *
     * @param injectHeartbeat whether to inject a {@code HeartbeatRequest} message.
     * @param injectIntoClient when {@code injectHeartbeat} is {@code true}, whether to inject the
     *        {@code HeartbeatRequest} message into client or into server.
     */
    private void mitmAcceptAndForward(
            SocketAddress serverAddress,
            final boolean injectHeartbeat,
            final boolean injectIntoClient) throws Exception {
        Socket clientSocket = null;
        Socket serverSocket = null;
        ServerSocket listeningSocket = getMitmListeningSocket();
        try {
            Log.i(TAG, "MiTM waiting for incoming connection");
            clientSocket = listeningSocket.accept();
            setMitmClientSocket(clientSocket);
            Log.i(TAG, "MiTM accepted connection from " + clientSocket.getRemoteSocketAddress());
            serverSocket = SocketFactory.getDefault().createSocket();
            setMitmServerSocket(serverSocket);
            Log.i(TAG, "MiTM connecting to server " + serverAddress);
            serverSocket.connect(serverAddress, 10000);
            Log.i(TAG, "MiTM connected to server from " + serverSocket.getLocalSocketAddress());
            final InputStream serverInputStream = serverSocket.getInputStream();
            final OutputStream clientOutputStream = clientSocket.getOutputStream();
            Future<Void> serverToClientTask = mExecutorService.submit(new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                    // Inject HeatbeatRequest after ServerHello, if requested
                    forwardTlsRecords(
                            "MiTM S->C",
                            serverInputStream,
                            clientOutputStream,
                            (injectHeartbeat && injectIntoClient)
                                    ? HandshakeMessage.TYPE_SERVER_HELLO : -1);
                    return null;
                }
            });
            // Inject HeatbeatRequest after ClientKeyExchange, if requested
            forwardTlsRecords(
                    "MiTM C->S",
                    clientSocket.getInputStream(),
                    serverSocket.getOutputStream(),
                    (injectHeartbeat && !injectIntoClient)
                            ? HandshakeMessage.TYPE_CLIENT_KEY_EXCHANGE : -1);
            serverToClientTask.get(10, TimeUnit.SECONDS);
        } catch (Exception e) {
            Log.w(TAG, "MiTM failed", e);
            throw e;
          } finally {
            closeQuietly(clientSocket);
            closeQuietly(serverSocket);
        }
    }

    /**
     * Forwards TLS records from the provided {@code InputStream} to the provided
     * {@code OutputStream}. If requested, injects a {@code HeartbeatMessage}.
     */
    private void forwardTlsRecords(
            String logPrefix,
            InputStream in,
            OutputStream out,
            int handshakeMessageTypeAfterWhichToInjectHeartbeatRequest) throws Exception {
        Log.i(TAG, logPrefix + ": record forwarding started");
        boolean interestingRecordsLogged =
                handshakeMessageTypeAfterWhichToInjectHeartbeatRequest == -1;
        try {
            TlsRecordReader reader = new TlsRecordReader(in);
            byte[] recordBytes;
            // Fragments contained in records may be encrypted after a certain point in the
            // handshake. Once they are encrypted, this MiTM cannot inspect their plaintext which.
            boolean fragmentEncryptionMayBeEnabled = false;
            while ((recordBytes = reader.readRecord()) != null) {
                TlsRecord record = TlsRecord.parse(recordBytes);
                forwardTlsRecord(logPrefix,
                        recordBytes,
                        record,
                        fragmentEncryptionMayBeEnabled,
                        out,
                        interestingRecordsLogged,
                        handshakeMessageTypeAfterWhichToInjectHeartbeatRequest);
                if (record.protocol == TlsProtocols.CHANGE_CIPHER_SPEC) {
                    fragmentEncryptionMayBeEnabled = true;
                }
            }
        } catch (Exception e) {
            Log.w(TAG, logPrefix + ": failed", e);
            throw e;
        } finally {
            Log.d(TAG, logPrefix + ": record forwarding finished");
        }
    }

    private void forwardTlsRecord(
            String logPrefix,
            byte[] recordBytes,
            TlsRecord record,
            boolean fragmentEncryptionMayBeEnabled,
            OutputStream out,
            boolean interestingRecordsLogged,
            int handshakeMessageTypeAfterWhichToInjectHeartbeatRequest) throws IOException {
        // Save information about the records if its of interest to this test
        if (interestingRecordsLogged) {
            switch (record.protocol) {
                case TlsProtocols.ALERT:
                    if (!fragmentEncryptionMayBeEnabled) {
                        AlertMessage alert = AlertMessage.tryParse(record);
                        if ((alert != null) && (alert.level == AlertMessage.LEVEL_FATAL)) {
                            setFatalAlertDetected(alert.description);
                        }
                    }
                    break;
                case TlsProtocols.HEARTBEAT:
                    // When TLS records are encrypted, we cannot determine whether a
                    // heartbeat is a HeartbeatResponse. In our setup, the client and the
                    // server are not expected to sent HeartbeatRequests. Thus, we err on
                    // the side of caution and assume that any heartbeat message sent by
                    // client or server is a HeartbeatResponse.
                    Log.e(TAG, logPrefix
                            + ": heartbeat response detected -- vulnerable to Heartbleed");
                    setHeartbeatResponseWasDetected();
                    break;
            }
        }

        Log.i(TAG, logPrefix + ": Forwarding TLS record. "
                + getRecordInfo(record, fragmentEncryptionMayBeEnabled));
        out.write(recordBytes);
        out.flush();

        // Inject HeartbeatRequest, if necessary, after the specified handshake message type
        if (handshakeMessageTypeAfterWhichToInjectHeartbeatRequest != -1) {
            if ((!fragmentEncryptionMayBeEnabled) && (isHandshakeMessageType(
                    record, handshakeMessageTypeAfterWhichToInjectHeartbeatRequest))) {
                // The Heartbeat Request message below is malformed because its declared
                // length of payload one byte larger than the actual payload. The peer is
                // supposed to reject such messages.
                byte[] payload = "arbitrary".getBytes("US-ASCII");
                byte[] heartbeatRequestRecordBytes = createHeartbeatRequestRecord(
                        record.versionMajor,
                        record.versionMinor,
                        payload.length + 1,
                        payload);
                Log.i(TAG, logPrefix + ": Injecting malformed HeartbeatRequest: "
                        + getRecordInfo(
                                TlsRecord.parse(heartbeatRequestRecordBytes), false));
                setHeartbeatRequestWasInjected();
                out.write(heartbeatRequestRecordBytes);
                out.flush();
            }
        }
    }

    private static String getRecordInfo(TlsRecord record, boolean mayBeEncrypted) {
        StringBuilder result = new StringBuilder();
        result.append(getProtocolName(record.protocol))
                .append(", ")
                .append(getFragmentInfo(record, mayBeEncrypted));
        return result.toString();
    }

    private static String getProtocolName(int protocol) {
        switch (protocol) {
            case TlsProtocols.ALERT:
                return "alert";
            case TlsProtocols.APPLICATION_DATA:
                return "application data";
            case TlsProtocols.CHANGE_CIPHER_SPEC:
                return "change cipher spec";
            case TlsProtocols.HANDSHAKE:
                return "handshake";
            case TlsProtocols.HEARTBEAT:
                return "heatbeat";
            default:
                return String.valueOf(protocol);
        }
    }

    private static String getFragmentInfo(TlsRecord record, boolean mayBeEncrypted) {
        StringBuilder result = new StringBuilder();
        if (mayBeEncrypted) {
            result.append("encrypted?");
        } else {
            switch (record.protocol) {
                case TlsProtocols.ALERT:
                    result.append("level: " + ((record.fragment.length > 0)
                            ? String.valueOf(record.fragment[0] & 0xff) : "n/a")
                    + ", description: "
                    + ((record.fragment.length > 1)
                            ? String.valueOf(record.fragment[1] & 0xff) : "n/a"));
                    break;
                case TlsProtocols.APPLICATION_DATA:
                    break;
                case TlsProtocols.CHANGE_CIPHER_SPEC:
                    result.append("payload: " + ((record.fragment.length > 0)
                            ? String.valueOf(record.fragment[0] & 0xff) : "n/a"));
                    break;
                case TlsProtocols.HANDSHAKE:
                    result.append("type: " + ((record.fragment.length > 0)
                            ? String.valueOf(record.fragment[0] & 0xff) : "n/a"));
                    break;
                case TlsProtocols.HEARTBEAT:
                    result.append("type: " + ((record.fragment.length > 0)
                            ? String.valueOf(record.fragment[0] & 0xff) : "n/a")
                            + ", payload length: "
                            + ((record.fragment.length >= 3)
                                    ? String.valueOf(
                                            getUnsignedShortBigEndian(record.fragment, 1))
                                    : "n/a"));
                    break;
            }
        }
        result.append(", ").append("fragment length: " + record.fragment.length);
        return result.toString();
    }

    private synchronized void setServerListeningSocket(SSLServerSocket socket) {
        mServerListeningSocket = socket;
    }

    private synchronized SSLServerSocket getServerListeningSocket() {
        return mServerListeningSocket;
    }

    private synchronized void setServerSocket(SSLSocket socket) {
        mServerSocket = socket;
    }

    private synchronized SSLSocket getServerSocket() {
        return mServerSocket;
    }

    private synchronized void setClientSocket(SSLSocket socket) {
        mClientSocket = socket;
    }

    private synchronized SSLSocket getClientSocket() {
        return mClientSocket;
    }

    private synchronized void setMitmListeningSocket(ServerSocket socket) {
        mMitmListeningSocket = socket;
    }

    private synchronized ServerSocket getMitmListeningSocket() {
        return mMitmListeningSocket;
    }

    private synchronized void setMitmServerSocket(Socket socket) {
        mMitmServerSocket = socket;
    }

    private synchronized Socket getMitmServerSocket() {
        return mMitmServerSocket;
    }

    private synchronized void setMitmClientSocket(Socket socket) {
        mMitmClientSocket = socket;
    }

    private synchronized Socket getMitmClientSocket() {
        return mMitmClientSocket;
    }

    private synchronized void setHeartbeatRequestWasInjected() {
        mHeartbeatRequestWasInjected = true;
    }

    private synchronized boolean wasHeartbeatRequestInjected() {
        return mHeartbeatRequestWasInjected;
    }

    private synchronized void setHeartbeatResponseWasDetected() {
        mHeartbeatResponseWasDetetected = true;
    }

    private synchronized boolean wasHeartbeatResponseDetected() {
        return mHeartbeatResponseWasDetetected;
    }

    private synchronized void setFatalAlertDetected(int description) {
        if (mFirstDetectedFatalAlertDescription == -1) {
            mFirstDetectedFatalAlertDescription = description;
        }
    }

    private synchronized int getFirstDetectedFatalAlertDescription() {
        return mFirstDetectedFatalAlertDescription;
    }

    public static abstract class TlsProtocols {
        public static final int CHANGE_CIPHER_SPEC = 20;
        public static final int ALERT = 21;
        public static final int HANDSHAKE = 22;
        public static final int APPLICATION_DATA = 23;
        public static final int HEARTBEAT = 24;
        private TlsProtocols() {}
    }

    public static class TlsRecord {
        public int protocol;
        public int versionMajor;
        public int versionMinor;
        public byte[] fragment;

        public static TlsRecord parse(byte[] record) throws IOException {
            TlsRecord result = new TlsRecord();
            if (record.length < TlsRecordReader.RECORD_HEADER_LENGTH) {
                throw new IOException("Record too short: " + record.length);
            }
            result.protocol = record[0] & 0xff;
            result.versionMajor = record[1] & 0xff;
            result.versionMinor = record[2] & 0xff;
            int fragmentLength = getUnsignedShortBigEndian(record, 3);
            int actualFragmentLength = record.length - TlsRecordReader.RECORD_HEADER_LENGTH;
            if (fragmentLength != actualFragmentLength) {
                throw new IOException("Fragment length mismatch. Expected: " + fragmentLength
                        + ", actual: " + actualFragmentLength);
            }
            result.fragment = new byte[fragmentLength];
            System.arraycopy(
                    record, TlsRecordReader.RECORD_HEADER_LENGTH,
                    result.fragment, 0,
                    fragmentLength);
            return result;
        }

        public static byte[] unparse(TlsRecord record) {
            byte[] result = new byte[TlsRecordReader.RECORD_HEADER_LENGTH + record.fragment.length];
            result[0] = (byte) record.protocol;
            result[1] = (byte) record.versionMajor;
            result[2] = (byte) record.versionMinor;
            putUnsignedShortBigEndian(result, 3, record.fragment.length);
            System.arraycopy(
                    record.fragment, 0,
                    result, TlsRecordReader.RECORD_HEADER_LENGTH,
                    record.fragment.length);
            return result;
        }
    }

    public static final boolean isHandshakeMessageType(TlsRecord record, int type) {
        HandshakeMessage handshake = HandshakeMessage.tryParse(record);
        if (handshake == null) {
            return false;
        }
        return handshake.type == type;
    }

    public static class HandshakeMessage {
        public static final int TYPE_SERVER_HELLO = 2;
        public static final int TYPE_CERTIFICATE = 11;
        public static final int TYPE_CLIENT_KEY_EXCHANGE = 16;

        public int type;

        /**
         * Parses the provided TLS record as a handshake message.
         *
         * @return alert message or {@code null} if the record does not contain a handshake message.
         */
        public static HandshakeMessage tryParse(TlsRecord record) {
            if (record.protocol != TlsProtocols.HANDSHAKE) {
                return null;
            }
            if (record.fragment.length < 1) {
                return null;
            }
            HandshakeMessage result = new HandshakeMessage();
            result.type = record.fragment[0] & 0xff;
            return result;
        }
    }

    public static class AlertMessage {
        public static final int LEVEL_FATAL = 2;
        public static final int DESCRIPTION_UNEXPECTED_MESSAGE = 10;

        public int level;
        public int description;

        /**
         * Parses the provided TLS record as an alert message.
         *
         * @return alert message or {@code null} if the record does not contain an alert message.
         */
        public static AlertMessage tryParse(TlsRecord record) {
            if (record.protocol != TlsProtocols.ALERT) {
                return null;
            }
            if (record.fragment.length < 2) {
                return null;
            }
            AlertMessage result = new AlertMessage();
            result.level = record.fragment[0] & 0xff;
            result.description = record.fragment[1] & 0xff;
            return result;
        }
    }

    private static abstract class HeartbeatProtocol {
        private HeartbeatProtocol() {}

        private static final int MESSAGE_TYPE_REQUEST = 1;
        @SuppressWarnings("unused")
        private static final int MESSAGE_TYPE_RESPONSE = 2;

        private static final int MESSAGE_HEADER_LENGTH = 3;
        private static final int MESSAGE_PADDING_LENGTH = 16;
    }

    private static byte[] createHeartbeatRequestRecord(
            int versionMajor, int versionMinor,
            int declaredPayloadLength, byte[] payload) {

        byte[] fragment = new byte[HeartbeatProtocol.MESSAGE_HEADER_LENGTH
                + payload.length + HeartbeatProtocol.MESSAGE_PADDING_LENGTH];
        fragment[0] = HeartbeatProtocol.MESSAGE_TYPE_REQUEST;
        putUnsignedShortBigEndian(fragment, 1, declaredPayloadLength); // payload_length
        TlsRecord record = new TlsRecord();
        record.protocol = TlsProtocols.HEARTBEAT;
        record.versionMajor = versionMajor;
        record.versionMinor = versionMinor;
        record.fragment = fragment;
        return TlsRecord.unparse(record);
    }

    /**
     * Reader of TLS records.
     */
    public static class TlsRecordReader {
        private static final int MAX_RECORD_LENGTH = 16384;
        public static final int RECORD_HEADER_LENGTH = 5;

        private final InputStream in;
        private final byte[] buffer;
        private int firstBufferedByteOffset;
        private int bufferedByteCount;

        public TlsRecordReader(InputStream in) {
            this.in = in;
            buffer = new byte[MAX_RECORD_LENGTH];
        }

        /**
         * Reads the next TLS record.
         *
         * @return TLS record or {@code null} if EOF was encountered before any bytes of a record
         *         could be read.
         */
        public byte[] readRecord() throws IOException {
            // Ensure that a TLS record header (or more) is in the buffer.
            if (bufferedByteCount < RECORD_HEADER_LENGTH) {
                boolean eofPermittedInstead = (bufferedByteCount == 0);
                boolean eofEncounteredInstead =
                        !readAtLeast(RECORD_HEADER_LENGTH, eofPermittedInstead);
                if (eofEncounteredInstead) {
                    // End of stream reached exactly before a TLS record start.
                    return null;
                }
            }

            // TLS record header (or more) is in the buffer.
            // Ensure that the rest of the record is in the buffer.
            int fragmentLength = getUnsignedShortBigEndian(buffer, firstBufferedByteOffset + 3);
            int recordLength = RECORD_HEADER_LENGTH + fragmentLength;
            if (recordLength > MAX_RECORD_LENGTH) {
                throw new IOException("TLS record too long: " + recordLength);
            }
            if (bufferedByteCount < recordLength) {
                readAtLeast(recordLength - bufferedByteCount, false);
            }

            // TLS record (or more) is in the buffer.
            byte[] record = new byte[recordLength];
            System.arraycopy(buffer, firstBufferedByteOffset, record, 0, recordLength);
            firstBufferedByteOffset += recordLength;
            bufferedByteCount -= recordLength;
            return record;
        }

        /**
         * Reads at least the specified number of bytes from the underlying {@code InputStream} into
         * the {@code buffer}.
         *
         * <p>Bytes buffered but not yet returned to the client in the {@code buffer} are relocated
         * to the start of the buffer to make space if necessary.
         *
         * @param eofPermittedInstead {@code true} if it's permitted for an EOF to be encountered
         *        without any bytes having been read.
         *
         * @return {@code true} if the requested number of bytes (or more) has been read,
         *         {@code false} if {@code eofPermittedInstead} was {@code true} and EOF was
         *         encountered when no bytes have yet been read.
         */
        private boolean readAtLeast(int size, boolean eofPermittedInstead) throws IOException {
            ensureRemainingBufferCapacityAtLeast(size);
            boolean firstAttempt = true;
            while (size > 0) {
                int chunkSize = in.read(
                        buffer,
                        firstBufferedByteOffset + bufferedByteCount,
                        buffer.length - (firstBufferedByteOffset + bufferedByteCount));
                if (chunkSize == -1) {
                    if ((firstAttempt) && (eofPermittedInstead)) {
                        return false;
                    } else {
                        throw new EOFException("Premature EOF");
                    }
                }
                firstAttempt = false;
                bufferedByteCount += chunkSize;
                size -= chunkSize;
            }
            return true;
        }

        /**
         * Ensures that there is enough capacity in the buffer to store the specified number of
         * bytes at the {@code firstBufferedByteOffset + bufferedByteCount} offset.
         */
        private void ensureRemainingBufferCapacityAtLeast(int size) throws IOException {
            int bufferCapacityRemaining =
                    buffer.length - (firstBufferedByteOffset + bufferedByteCount);
            if (bufferCapacityRemaining >= size) {
                return;
            }
            // Insufficient capacity at the end of the buffer.
            if (firstBufferedByteOffset > 0) {
                // Some of the bytes at the start of the buffer have already been returned to the
                // client of this reader. Check if moving the remaining buffered bytes to the start
                // of the buffer will make enough space at the end of the buffer.
                bufferCapacityRemaining += firstBufferedByteOffset;
                if (bufferCapacityRemaining >= size) {
                    System.arraycopy(buffer, firstBufferedByteOffset, buffer, 0, bufferedByteCount);
                    firstBufferedByteOffset = 0;
                    return;
                }
            }

            throw new IOException("Insuffucient remaining capacity in the buffer. Requested: "
                    + size + ", remaining: " + bufferCapacityRemaining);
        }
    }

    private static int getUnsignedShortBigEndian(byte[] buf, int offset) {
        return ((buf[offset] & 0xff) << 8) | (buf[offset + 1] & 0xff);
    }

    private static void putUnsignedShortBigEndian(byte[] buf, int offset, int value) {
        buf[offset] = (byte) ((value >>> 8) & 0xff);
        buf[offset + 1] = (byte) (value & 0xff);
    }

    // IMPLEMENTATION NOTE: We can't implement just one closeQueietly(Closeable) because on some
    // older Android platforms Socket did not implement these interfaces. To make this patch easy to
    // apply to these older platforms, we declare all the variants of closeQuietly that are needed
    // without relying on the Closeable interface.

    private static void closeQuietly(InputStream in) {
        if (in != null) {
            try {
                in.close();
            } catch (IOException ignored) {}
        }
    }

    public static void closeQuietly(ServerSocket socket) {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException ignored) {}
        }
    }

    public static void closeQuietly(Socket socket) {
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException ignored) {}
        }
    }

    public static byte[] readResource(Context context, int resId) throws IOException {
        ByteArrayOutputStream result = new ByteArrayOutputStream();
        InputStream in = null;
        byte[] buf = new byte[16 * 1024];
        try {
            in = context.getResources().openRawResource(resId);
            int chunkSize;
            while ((chunkSize = in.read(buf)) != -1) {
                result.write(buf, 0, chunkSize);
            }
            return result.toByteArray();
        } finally {
            closeQuietly(in);
        }
    }

    /**
     * {@link X509TrustManager} which trusts all certificate chains.
     */
    public static class TrustAllX509TrustManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }

    /**
     * {@link X509KeyManager} which uses the provided private key and cert chain for all sockets.
     */
    public static class HardcodedCertX509KeyManager implements X509KeyManager {

        private final PrivateKey mPrivateKey;
        private final X509Certificate[] mCertChain;

        HardcodedCertX509KeyManager(PrivateKey privateKey, X509Certificate[] certChain) {
            mPrivateKey = privateKey;
            mCertChain = certChain;
        }

        @Override
        public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
            return null;
        }

        @Override
        public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
            return "singleton";
        }

        @Override
        public X509Certificate[] getCertificateChain(String alias) {
            return mCertChain;
        }

        @Override
        public String[] getClientAliases(String keyType, Principal[] issuers) {
            return null;
        }

        @Override
        public PrivateKey getPrivateKey(String alias) {
            return mPrivateKey;
        }

        @Override
        public String[] getServerAliases(String keyType, Principal[] issuers) {
            return new String[] {"singleton"};
        }
    }
}
