1da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian/*
2da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * Copyright 2017 The Android Open Source Project
3da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian *
4da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * Licensed under the Apache License, Version 2.0 (the "License");
5da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * you may not use this file except in compliance with the License.
6da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * You may obtain a copy of the License at
7da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian *
8da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian *      http://www.apache.org/licenses/LICENSE-2.0
9da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian *
10da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * Unless required by applicable law or agreed to in writing, software
11da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * distributed under the License is distributed on an "AS IS" BASIS,
12da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * See the License for the specific language governing permissions and
14da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian * limitations under the License.
15da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian */
16da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
17da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianpackage org.conscrypt;
18da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
19da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport static org.conscrypt.TestUtils.LOCALHOST;
20da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport static org.conscrypt.TestUtils.getConscryptServerSocketFactory;
21da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport static org.conscrypt.TestUtils.getJdkSocketFactory;
22da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport static org.conscrypt.TestUtils.getProtocols;
23da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport static org.conscrypt.TestUtils.newTextMessage;
24da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport static org.conscrypt.TestUtils.pickUnusedPort;
25da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport static org.junit.Assert.assertArrayEquals;
26da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
27da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport java.io.IOException;
28da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport java.util.Arrays;
29da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport java.util.concurrent.Future;
30da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport java.util.concurrent.TimeUnit;
31da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport javax.net.ssl.SSLServerSocket;
32da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport javax.net.ssl.SSLServerSocketFactory;
33da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport javax.net.ssl.SSLSocket;
34da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport javax.net.ssl.SSLSocketFactory;
35da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport org.junit.After;
36da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport org.junit.Before;
37da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport org.junit.Test;
38da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport org.junit.runner.RunWith;
39da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport org.junit.runners.Parameterized;
40da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport org.junit.runners.Parameterized.Parameter;
41da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianimport org.junit.runners.Parameterized.Parameters;
42da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
43da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian@RunWith(Parameterized.class)
44da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianpublic class OpenSSLServerSocketImplTest {
45da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    private static final String CIPHER = "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256";
467bc9febe8749e98a3812a0dc4380ceae75c29450Johann    private static final int MESSAGE_SIZE = 4096;
477bc9febe8749e98a3812a0dc4380ceae75c29450Johann
487bc9febe8749e98a3812a0dc4380ceae75c29450Johann    /**
497bc9febe8749e98a3812a0dc4380ceae75c29450Johann     * Various factories for SSL server sockets.
507bc9febe8749e98a3812a0dc4380ceae75c29450Johann     */
517bc9febe8749e98a3812a0dc4380ceae75c29450Johann    public enum SocketType {
527bc9febe8749e98a3812a0dc4380ceae75c29450Johann        DEFAULT(getConscryptServerSocketFactory(false)),
537bc9febe8749e98a3812a0dc4380ceae75c29450Johann        ENGINE(getConscryptServerSocketFactory(true));
547bc9febe8749e98a3812a0dc4380ceae75c29450Johann
557bc9febe8749e98a3812a0dc4380ceae75c29450Johann        @SuppressWarnings("ImmutableEnumChecker")
567bc9febe8749e98a3812a0dc4380ceae75c29450Johann        private final SSLServerSocketFactory serverSocketFactory;
577bc9febe8749e98a3812a0dc4380ceae75c29450Johann
587bc9febe8749e98a3812a0dc4380ceae75c29450Johann        SocketType(SSLServerSocketFactory serverSocketFactory) {
597bc9febe8749e98a3812a0dc4380ceae75c29450Johann            this.serverSocketFactory = serverSocketFactory;
607bc9febe8749e98a3812a0dc4380ceae75c29450Johann        }
617bc9febe8749e98a3812a0dc4380ceae75c29450Johann
627bc9febe8749e98a3812a0dc4380ceae75c29450Johann        final SSLServerSocket newServerSocket(String cipher) {
637bc9febe8749e98a3812a0dc4380ceae75c29450Johann            try {
647bc9febe8749e98a3812a0dc4380ceae75c29450Johann                int port = pickUnusedPort();
657bc9febe8749e98a3812a0dc4380ceae75c29450Johann                SSLServerSocket sslSocket =
667bc9febe8749e98a3812a0dc4380ceae75c29450Johann                        (SSLServerSocket) serverSocketFactory.createServerSocket(port);
677bc9febe8749e98a3812a0dc4380ceae75c29450Johann                sslSocket.setEnabledProtocols(getProtocols());
687bc9febe8749e98a3812a0dc4380ceae75c29450Johann                sslSocket.setEnabledCipherSuites(new String[] {cipher});
697bc9febe8749e98a3812a0dc4380ceae75c29450Johann                return sslSocket;
70da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian            } catch (IOException e) {
71da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                throw new RuntimeException(e);
72da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian            }
737bc9febe8749e98a3812a0dc4380ceae75c29450Johann        }
747bc9febe8749e98a3812a0dc4380ceae75c29450Johann    }
757bc9febe8749e98a3812a0dc4380ceae75c29450Johann
76da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    @Parameters(name = "{0}")
77da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    public static Iterable<SocketType> data() {
78da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        // Android-changed: Temporarily (2017 Q2) disable ENGINE tests. http://b/37271061#comment9
79da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        // This experimental (unused by default) implementation is unstable and causing test
80da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        // failures on Android.
81da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        // return Arrays.asList(SocketType.DEFAULT, SocketType.ENGINE);
82da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        return Arrays.asList(SocketType.DEFAULT);
83da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
84da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
857bc9febe8749e98a3812a0dc4380ceae75c29450Johann    @Parameter public SocketType socketType;
867bc9febe8749e98a3812a0dc4380ceae75c29450Johann
877bc9febe8749e98a3812a0dc4380ceae75c29450Johann    private TestClient client;
887bc9febe8749e98a3812a0dc4380ceae75c29450Johann    private TestServer server;
897bc9febe8749e98a3812a0dc4380ceae75c29450Johann
907bc9febe8749e98a3812a0dc4380ceae75c29450Johann    @Before
917bc9febe8749e98a3812a0dc4380ceae75c29450Johann    public void setup() throws Exception {
927bc9febe8749e98a3812a0dc4380ceae75c29450Johann        // Create and start the server.
93da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        server = new TestServer(socketType.newServerSocket(CIPHER), MESSAGE_SIZE);
94da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        Future<?> connectedFuture = server.start();
95da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
96da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        // Create and start the client.
97da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        SSLSocketFactory socketFactory = getJdkSocketFactory();
98da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        SSLSocket socket = (SSLSocket) socketFactory.createSocket(LOCALHOST, server.port());
99da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        socket.setEnabledProtocols(getProtocols());
100da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        socket.setEnabledCipherSuites(new String[] {CIPHER});
101da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        client = new TestClient(socket);
102da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        client.start();
103da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
104da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        // Wait for the initial connection to complete.
105da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        connectedFuture.get(5, TimeUnit.SECONDS);
106da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
107da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
108da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    @After
109da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    public void teardown() throws Exception {
110da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        client.stop();
111da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        server.stop();
112da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
113da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
114da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    @Test
115da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    public void pingPong() throws IOException {
116da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        byte[] request = newTextMessage(MESSAGE_SIZE);
117da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        byte[] responseBuffer = new byte[MESSAGE_SIZE];
118da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        client.sendMessage(request);
119da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        client.flush();
120da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        int numBytes = client.readMessage(responseBuffer);
121da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        byte[] response = Arrays.copyOfRange(responseBuffer, 0, numBytes);
122da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        assertArrayEquals(request, response);
123da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
124da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian}
125da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian