diff --git a/tests/tests/security/res/raw/openssl_heartbleed_test_cert.pem b/tests/tests/security/res/raw/openssl_heartbleed_test_cert.pem
new file mode 100644
index 0000000..553339c
--- /dev/null
+++ b/tests/tests/security/res/raw/openssl_heartbleed_test_cert.pem
@@ -0,0 +1,84 @@
+-----BEGIN CERTIFICATE-----
+MIIEJTCCAw2gAwIBAgIJAIyWCjpFJYdnMA0GCSqGSIb3DQEBBQUAMIGoMQswCQYD
+VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxFDAS
+BgNVBAoMC0dvb2dsZSBJbmMuMR4wHAYDVQQLDBVBbmRyb2lkIFNlY3VyaXR5IFRl
+YW0xPjA8BgNVBAMMNUFuZHJvaWQgQ1RTIHRlc3QgZm9yIE9wZW5TU0wgSGVhcnRi
+bGVlZCB2dWxuZXJhYmlsaXR5MB4XDTE0MDQxNDE5MjExNFoXDTI0MDQxMTE5MjEx
+NFowgagxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRh
+aW4gVmlldzEUMBIGA1UECgwLR29vZ2xlIEluYy4xHjAcBgNVBAsMFUFuZHJvaWQg
+U2VjdXJpdHkgVGVhbTE+MDwGA1UEAww1QW5kcm9pZCBDVFMgdGVzdCBmb3IgT3Bl
+blNTTCBIZWFydGJsZWVkIHZ1bG5lcmFiaWxpdHkwggEiMA0GCSqGSIb3DQEBAQUA
+A4IBDwAwggEKAoIBAQC3hfx9exE0EGokpMyNj6CAaSAdYL5bCCafZwpr5/U9GnKC
+5i5spopmqaQKUj3KsaLEBs9k1LsYqgVGeobOb/IonYrnNsRwqBawGLhhksz0/R5H
+2lOYDibsHd8igJkwWCxhhQLnT/h62x67B9/2mduV3nHcjjQ/+g4umVySKcoO79+4
+5rX4dX/dX3vrfKE5ootDLvTycavAPSUfCKlBG4+DQYI0Q2bfjLWSHYdhFwkCTaYs
+uTJPdDfzD8gRd/2egjYE/sNoKiNb3NiyHynZ849VDB1H/Y9ojO/3wAWpcDnP+9b9
+JDq4eszjYrmCc0PiDWXBMbqpCei4jaJLmUDymCRXAgMBAAGjUDBOMB0GA1UdDgQW
+BBR8Zq0HoE1D2c6/MLtWRXI2JWUcqjAfBgNVHSMEGDAWgBR8Zq0HoE1D2c6/MLtW
+RXI2JWUcqjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQB7ceFMrL8I
+4why5v2M272EAay2o0AdKsZFlUpM3qJ3XvosLqcKEu9NVdVxiI4QJOh5Rgm7e48e
+7WXgDcZM5F6/1e8X2PjgtbhwCpq1yTtIEhMLpu0IbVsNfvIT/IemfGAQqWBjZByE
+jUoTW2AeuA7ZpzzmrNI+98Y2MocX9LcveK7Fnfsb7Y8LKVOvnRZ34VzC+py+w9p2
+K8tOZU22mIBdZtdXe1cEdb5FszU8XMp7nzgZn5QDDWIoipNiL9m226kwEPf3EoXz
+bcNhn6KrPah86kVwpeOsX2fM4xHUg7Zv2IcX66r9WzchyB7HrDyTjfzDQRt1fJCO
+s0xyq4f1EHH2
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            8c:96:0a:3a:45:25:87:67
+    Signature Algorithm: sha1WithRSAEncryption
+        Issuer: C=US, ST=CA, L=Mountain View, O=Google Inc., OU=Android Security Team, CN=Android CTS test for OpenSSL Heartbleed vulnerability
+        Validity
+            Not Before: Apr 14 19:21:14 2014 GMT
+            Not After : Apr 11 19:21:14 2024 GMT
+        Subject: C=US, ST=CA, L=Mountain View, O=Google Inc., OU=Android Security Team, CN=Android CTS test for OpenSSL Heartbleed vulnerability
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (2048 bit)
+                Modulus:
+                    00:b7:85:fc:7d:7b:11:34:10:6a:24:a4:cc:8d:8f:
+                    a0:80:69:20:1d:60:be:5b:08:26:9f:67:0a:6b:e7:
+                    f5:3d:1a:72:82:e6:2e:6c:a6:8a:66:a9:a4:0a:52:
+                    3d:ca:b1:a2:c4:06:cf:64:d4:bb:18:aa:05:46:7a:
+                    86:ce:6f:f2:28:9d:8a:e7:36:c4:70:a8:16:b0:18:
+                    b8:61:92:cc:f4:fd:1e:47:da:53:98:0e:26:ec:1d:
+                    df:22:80:99:30:58:2c:61:85:02:e7:4f:f8:7a:db:
+                    1e:bb:07:df:f6:99:db:95:de:71:dc:8e:34:3f:fa:
+                    0e:2e:99:5c:92:29:ca:0e:ef:df:b8:e6:b5:f8:75:
+                    7f:dd:5f:7b:eb:7c:a1:39:a2:8b:43:2e:f4:f2:71:
+                    ab:c0:3d:25:1f:08:a9:41:1b:8f:83:41:82:34:43:
+                    66:df:8c:b5:92:1d:87:61:17:09:02:4d:a6:2c:b9:
+                    32:4f:74:37:f3:0f:c8:11:77:fd:9e:82:36:04:fe:
+                    c3:68:2a:23:5b:dc:d8:b2:1f:29:d9:f3:8f:55:0c:
+                    1d:47:fd:8f:68:8c:ef:f7:c0:05:a9:70:39:cf:fb:
+                    d6:fd:24:3a:b8:7a:cc:e3:62:b9:82:73:43:e2:0d:
+                    65:c1:31:ba:a9:09:e8:b8:8d:a2:4b:99:40:f2:98:
+                    24:57
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                7C:66:AD:07:A0:4D:43:D9:CE:BF:30:BB:56:45:72:36:25:65:1C:AA
+            X509v3 Authority Key Identifier: 
+                keyid:7C:66:AD:07:A0:4D:43:D9:CE:BF:30:BB:56:45:72:36:25:65:1C:AA
+
+            X509v3 Basic Constraints: 
+                CA:TRUE
+    Signature Algorithm: sha1WithRSAEncryption
+         7b:71:e1:4c:ac:bf:08:e3:08:72:e6:fd:8c:db:bd:84:01:ac:
+         b6:a3:40:1d:2a:c6:45:95:4a:4c:de:a2:77:5e:fa:2c:2e:a7:
+         0a:12:ef:4d:55:d5:71:88:8e:10:24:e8:79:46:09:bb:7b:8f:
+         1e:ed:65:e0:0d:c6:4c:e4:5e:bf:d5:ef:17:d8:f8:e0:b5:b8:
+         70:0a:9a:b5:c9:3b:48:12:13:0b:a6:ed:08:6d:5b:0d:7e:f2:
+         13:fc:87:a6:7c:60:10:a9:60:63:64:1c:84:8d:4a:13:5b:60:
+         1e:b8:0e:d9:a7:3c:e6:ac:d2:3e:f7:c6:36:32:87:17:f4:b7:
+         2f:78:ae:c5:9d:fb:1b:ed:8f:0b:29:53:af:9d:16:77:e1:5c:
+         c2:fa:9c:be:c3:da:76:2b:cb:4e:65:4d:b6:98:80:5d:66:d7:
+         57:7b:57:04:75:be:45:b3:35:3c:5c:ca:7b:9f:38:19:9f:94:
+         03:0d:62:28:8a:93:62:2f:d9:b6:db:a9:30:10:f7:f7:12:85:
+         f3:6d:c3:61:9f:a2:ab:3d:a8:7c:ea:45:70:a5:e3:ac:5f:67:
+         cc:e3:11:d4:83:b6:6f:d8:87:17:eb:aa:fd:5b:37:21:c8:1e:
+         c7:ac:3c:93:8d:fc:c3:41:1b:75:7c:90:8e:b3:4c:72:ab:87:
+         f5:10:71:f6
+SHA1 Fingerprint=01:E1:C6:46:02:BE:8F:F7:F6:82:22:C8:1C:AE:A2:85:0D:3E:D0:98
diff --git a/tests/tests/security/res/raw/openssl_heartbleed_test_key.der b/tests/tests/security/res/raw/openssl_heartbleed_test_key.der
new file mode 100644
index 0000000..c925724
--- /dev/null
+++ b/tests/tests/security/res/raw/openssl_heartbleed_test_key.der
Binary files differ
diff --git a/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java b/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java
new file mode 100644
index 0000000..86957a8
--- /dev/null
+++ b/tests/tests/security/src/android/security/cts/OpenSSLHeartbleedTest.java
@@ -0,0 +1,969 @@
+/*
+ * 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;
+            }
+        });
+
+        Log.i(TAG, "Waiting for client");
+        clientFuture.get(10, TimeUnit.SECONDS);
+        Log.i(TAG, "Waiting for server");
+        serverFuture.get(1, TimeUnit.SECONDS);
+        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();
+        }
+    }
+
+    private 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;
+    }
+
+    private 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() {}
+    }
+
+    private static class TlsRecord {
+        private int protocol;
+        private int versionMajor;
+        private int versionMinor;
+        private byte[] fragment;
+
+        private 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;
+        }
+
+        private 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;
+        }
+    }
+
+    private static final boolean isHandshakeMessageType(TlsRecord record, int type) {
+        HandshakeMessage handshake = HandshakeMessage.tryParse(record);
+        if (handshake == null) {
+            return false;
+        }
+        return handshake.type == type;
+    }
+
+    private static class HandshakeMessage {
+        private static final int TYPE_SERVER_HELLO = 2;
+        private static final int TYPE_CLIENT_KEY_EXCHANGE = 16;
+
+        private 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.
+         */
+        private 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;
+        }
+    }
+
+    private static class AlertMessage {
+        private static final int LEVEL_FATAL = 2;
+        private static final int DESCRIPTION_UNEXPECTED_MESSAGE = 10;
+
+        private int level;
+        private 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.
+         */
+        private 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.
+     */
+    private 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) {}
+        }
+    }
+
+    private static void closeQuietly(ServerSocket socket) {
+        if (socket != null) {
+            try {
+                socket.close();
+            } catch (IOException ignored) {}
+        }
+    }
+
+    private static void closeQuietly(Socket socket) {
+        if (socket != null) {
+            try {
+                socket.close();
+            } catch (IOException ignored) {}
+        }
+    }
+
+    private 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.
+     */
+    private 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.
+     */
+    private static class HardcodedCertX509KeyManager implements X509KeyManager {
+
+        private final PrivateKey mPrivateKey;
+        private final X509Certificate[] mCertChain;
+
+        private 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"};
+        }
+    }
+}
