Loading apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherEncryptPerfTest.java +14 −15 Original line number Diff line number Diff line Loading @@ -23,6 +23,9 @@ import androidx.test.filters.LargeTest; import org.conscrypt.TestUtils; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.security.Key; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; Loading Loading @@ -91,21 +94,17 @@ public final class CipherEncryptPerfTest { } } private Object[] getParams() { return new Object[][] { new Object[] {new Config(BufferType.ARRAY, MyCipherFactory.CONSCRYPT, Transformation.AES_CBC_PKCS5)}, new Object[] {new Config(BufferType.ARRAY, MyCipherFactory.CONSCRYPT, Transformation.AES_ECB_PKCS5)}, new Object[] {new Config(BufferType.ARRAY, MyCipherFactory.CONSCRYPT, Transformation.AES_GCM_NO)}, new Object[] {new Config(BufferType.ARRAY, MyCipherFactory.CONSCRYPT, Transformation.AES_GCM_SIV)}, }; public Collection <Object[]> getParams() { final List<Object[]> params = new ArrayList<>(); for (BufferType bufferType : BufferType.values()) { for (CipherFactory cipherFactory : MyCipherFactory.values()) { for (Transformation transformation : Transformation.values()) { params.add(new Object[] {new Config( bufferType, cipherFactory, transformation)}); } } } return params; } private EncryptStrategy encryptStrategy; Loading apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java +21 −11 Original line number Diff line number Diff line Loading @@ -30,6 +30,9 @@ import java.io.IOException; import java.io.OutputStream; import java.net.SocketException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; Loading Loading @@ -104,18 +107,25 @@ public final class ClientSocketPerfTest { } } private Object[] getParams() { return new Object[][] { new Object[] {new Config( EndpointFactory.CONSCRYPT, EndpointFactory.CONSCRYPT, 64, "AES128-GCM", ChannelType.CHANNEL, PerfTestProtocol.TLSv13)}, }; public Collection getParams() { final List<Object[]> params = new ArrayList<>(); for (EndpointFactory endpointFactory : EndpointFactory.values()) { for (ChannelType channelType : ChannelType.values()) { for (PerfTestProtocol protocol : PerfTestProtocol.values()) { params.add(new Object[] {new Config(endpointFactory, endpointFactory, 64, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", channelType, protocol)}); params.add(new Object[] {new Config(endpointFactory, endpointFactory, 512, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", channelType, protocol)}); params.add(new Object[] {new Config(endpointFactory, endpointFactory, 4096, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", channelType, protocol)}); } } } return params; } private ClientEndpoint client; private ServerEndpoint server; Loading apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineFactory.java 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * Copyright 2017 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.conscrypt; import org.conscrypt.TestUtils; import java.security.Security; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; /** * Factory for {@link SSLEngine} instances. */ public class EngineFactory { public EngineFactory() { this(newConscryptClientContext(), newConscryptServerContext()); } private EngineFactory(SSLContext clientContext, SSLContext serverContext) { this.clientContext = clientContext; this.serverContext = serverContext; } private final SSLContext clientContext; private final SSLContext serverContext; public SSLEngine newClientEngine(String cipher) { SSLEngine engine = initEngine(clientContext.createSSLEngine(), cipher, true); return engine; } public SSLEngine newServerEngine(String cipher) { SSLEngine engine = initEngine(serverContext.createSSLEngine(), cipher, false); return engine; } public void dispose(SSLEngine engine) { engine.closeOutbound(); } private static SSLContext newConscryptClientContext() { return TestUtils.newClientSslContext(TestUtils.getConscryptProvider()); } private static SSLContext newConscryptServerContext() { return TestUtils.newServerSslContext(TestUtils.getConscryptProvider()); } static SSLEngine initEngine(SSLEngine engine, String cipher, boolean client) { engine.setEnabledProtocols(new String[]{"TLSv1.2", "TLSv1.3"}); engine.setEnabledCipherSuites(new String[] {cipher}); engine.setUseClientMode(client); return engine; } } No newline at end of file apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineHandshakePerfTest.java 0 → 100644 +207 −0 Original line number Diff line number Diff line /* * Copyright 2017 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. */ /* * Copyright 2017 The Netty Project * * The Netty Project licenses this file to you 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.conscrypt; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLException; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import androidx.test.filters.LargeTest; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; /** * Benchmark comparing handshake performance of various engine implementations to conscrypt. */ @RunWith(JUnitParamsRunner.class) @LargeTest public final class EngineHandshakePerfTest { @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); /** * Provider for the test configuration */ private class Config { BufferType a_bufferType; String c_cipher; int d_rttMillis; Config(BufferType bufferType, String cipher, int rttMillis) { a_bufferType = bufferType; c_cipher = cipher; d_rttMillis = rttMillis; } public BufferType bufferType() { return a_bufferType; } public String cipher() { return c_cipher; } public int rttMillis() { return d_rttMillis; } } public Collection getParams() { final List<Object[]> params = new ArrayList<>(); for (BufferType bufferType : BufferType.values()) { params.add(new Object[] {new Config(bufferType, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 100)}); } return params; } private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocateDirect(0); private EngineFactory engineFactory = new EngineFactory(); private String cipher; private int rttMillis; private ByteBuffer clientApplicationBuffer; private ByteBuffer clientPacketBuffer; private ByteBuffer serverApplicationBuffer; private ByteBuffer serverPacketBuffer; private void setup(Config config) throws Exception { cipher = config.cipher(); rttMillis = config.rttMillis(); BufferType bufferType = config.bufferType(); SSLEngine clientEngine = engineFactory.newClientEngine(cipher); SSLEngine serverEngine = engineFactory.newServerEngine(cipher); // Create the application and packet buffers for both endpoints. clientApplicationBuffer = bufferType.newApplicationBuffer(clientEngine); serverApplicationBuffer = bufferType.newApplicationBuffer(serverEngine); clientPacketBuffer = bufferType.newPacketBuffer(clientEngine); serverPacketBuffer = bufferType.newPacketBuffer(serverEngine); engineFactory.dispose(clientEngine); engineFactory.dispose(serverEngine); } @Test @Parameters(method = "getParams") public void handshake(Config config) throws Exception { setup(config); SSLEngine client = engineFactory.newClientEngine(cipher); SSLEngine server = engineFactory.newServerEngine(cipher); clientApplicationBuffer.clear(); clientPacketBuffer.clear(); serverApplicationBuffer.clear(); serverPacketBuffer.clear(); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { client.beginHandshake(); server.beginHandshake(); doHandshake(client, server); } engineFactory.dispose(client); engineFactory.dispose(server); } private void doHandshake(SSLEngine client, SSLEngine server) throws SSLException { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { // Send as many client-to-server messages as possible doHalfHandshake(client, server, clientPacketBuffer, serverApplicationBuffer); if (client.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING && server.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) { return; } // Do the same with server-to-client messages doHalfHandshake(server, client, serverPacketBuffer, clientApplicationBuffer); if (client.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING && server.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) { return; } } } private void doHalfHandshake(SSLEngine sender, SSLEngine receiver, ByteBuffer senderPacketBuffer, ByteBuffer receiverApplicationBuffer) throws SSLException { SSLEngineResult senderResult; SSLEngineResult receiverResult; do { senderResult = sender.wrap(EMPTY_BUFFER, senderPacketBuffer); runDelegatedTasks(senderResult, sender); senderPacketBuffer.flip(); receiverResult = receiver.unwrap(senderPacketBuffer, receiverApplicationBuffer); runDelegatedTasks(receiverResult, receiver); senderPacketBuffer.compact(); } while (senderResult.getHandshakeStatus() == HandshakeStatus.NEED_WRAP); if (rttMillis > 0) { try { Thread.sleep(rttMillis / 2); } catch (InterruptedException e) { throw new RuntimeException(e); } } } private static void runDelegatedTasks(SSLEngineResult result, SSLEngine engine) { if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) { for (;;) { Runnable task = engine.getDelegatedTask(); if (task == null) { break; } task.run(); } } } } No newline at end of file apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineWrapPerfTest.java 0 → 100644 +221 −0 Original line number Diff line number Diff line /* * Copyright 2017 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. */ /* * Copyright 2017 The Netty Project * * The Netty Project licenses this file to you 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.conscrypt; import static org.conscrypt.TestUtils.doEngineHandshake; import static org.conscrypt.TestUtils.newTextMessage; import static org.junit.Assert.assertEquals; import java.nio.ByteBuffer; import java.util.Locale; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLException; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import androidx.test.filters.LargeTest; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; /** * Benchmark comparing performance of various engine implementations to conscrypt. */ @RunWith(JUnitParamsRunner.class) @LargeTest public final class EngineWrapPerfTest { @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); /** * Provider for the benchmark configuration */ private class Config { BufferType a_bufferType; int c_messageSize; String d_cipher; Config(BufferType bufferType, int messageSize, String cipher) { a_bufferType = bufferType; c_messageSize = messageSize; d_cipher = cipher; } public BufferType bufferType() { return a_bufferType; } public int messageSize() { return c_messageSize; } public String cipher() { return d_cipher; } } public Collection getParams() { final List<Object[]> params = new ArrayList<>(); for (BufferType bufferType : BufferType.values()) { params.add(new Object[] {new Config(bufferType, 64, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")}); params.add(new Object[] {new Config(bufferType, 512, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")}); params.add(new Object[] {new Config(bufferType, 4096, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")}); } return params; } private EngineFactory engineFactory = new EngineFactory(); private String cipher; private SSLEngine clientEngine; private SSLEngine serverEngine; private ByteBuffer messageBuffer; private ByteBuffer clientApplicationBuffer; private ByteBuffer clientPacketBuffer; private ByteBuffer serverApplicationBuffer; private ByteBuffer serverPacketBuffer; private ByteBuffer preEncryptedBuffer; private void setup(Config config) throws Exception { cipher = config.cipher(); BufferType bufferType = config.bufferType(); clientEngine = engineFactory.newClientEngine(cipher); serverEngine = engineFactory.newServerEngine(cipher); // Create the application and packet buffers for both endpoints. clientApplicationBuffer = bufferType.newApplicationBuffer(clientEngine); serverApplicationBuffer = bufferType.newApplicationBuffer(serverEngine); clientPacketBuffer = bufferType.newPacketBuffer(clientEngine); serverPacketBuffer = bufferType.newPacketBuffer(serverEngine); // Generate the message to be sent from the client. int messageSize = config.messageSize(); messageBuffer = bufferType.newBuffer(messageSize); messageBuffer.put(newTextMessage(messageSize)); messageBuffer.flip(); // Complete the initial TLS handshake. doEngineHandshake(clientEngine, serverEngine, clientApplicationBuffer, clientPacketBuffer, serverApplicationBuffer, serverPacketBuffer, true); // Populate the pre-encrypted buffer for use with the unwrap benchmark. preEncryptedBuffer = bufferType.newBuffer(clientEngine.getSession().getPacketBufferSize()); doWrap(messageBuffer, preEncryptedBuffer); doUnwrap(preEncryptedBuffer, serverApplicationBuffer); } void teardown() { engineFactory.dispose(clientEngine); engineFactory.dispose(serverEngine); } @Test @Parameters(method = "getParams") public void wrap(Config config) throws Exception { setup(config); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { // Reset the buffers. messageBuffer.position(0); clientPacketBuffer.clear(); // Wrap the original message and create the encrypted data. doWrap(messageBuffer, clientPacketBuffer); // Lightweight comparison - just make sure the data length is correct. assertEquals(preEncryptedBuffer.limit(), clientPacketBuffer.limit()); } teardown(); } /** * Simple benchmark that sends a single message from client to server. */ @Test @Parameters(method = "getParams") public void wrapAndUnwrap(Config config) throws Exception { setup(config); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { // Reset the buffers. messageBuffer.position(0); clientPacketBuffer.clear(); serverApplicationBuffer.clear(); // Wrap the original message and create the encrypted data. doWrap(messageBuffer, clientPacketBuffer); // Unwrap the encrypted data and get back the original result. doUnwrap(clientPacketBuffer, serverApplicationBuffer); // Lightweight comparison - just make sure the unencrypted data length is correct. assertEquals(messageBuffer.limit(), serverApplicationBuffer.limit()); } teardown(); } private void doWrap(ByteBuffer src, ByteBuffer dst) throws SSLException { // Wrap the original message and create the encrypted data. verifyResult(src, clientEngine.wrap(src, dst)); dst.flip(); } private void doUnwrap(ByteBuffer src, ByteBuffer dst) throws SSLException { verifyResult(src, serverEngine.unwrap(src, dst)); dst.flip(); } private void verifyResult(ByteBuffer src, SSLEngineResult result) { if (result.getStatus() != SSLEngineResult.Status.OK) { throw new RuntimeException("Operation returned unexpected result " + result); } if (result.bytesConsumed() != src.limit()) { throw new RuntimeException( String.format(Locale.US, "Operation didn't consume all bytes. Expected %d, consumed %d.", src.limit(), result.bytesConsumed())); } } } No newline at end of file Loading
apct-tests/perftests/core/src/android/conscrypt/conscrypt/CipherEncryptPerfTest.java +14 −15 Original line number Diff line number Diff line Loading @@ -23,6 +23,9 @@ import androidx.test.filters.LargeTest; import org.conscrypt.TestUtils; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.security.Key; import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; Loading Loading @@ -91,21 +94,17 @@ public final class CipherEncryptPerfTest { } } private Object[] getParams() { return new Object[][] { new Object[] {new Config(BufferType.ARRAY, MyCipherFactory.CONSCRYPT, Transformation.AES_CBC_PKCS5)}, new Object[] {new Config(BufferType.ARRAY, MyCipherFactory.CONSCRYPT, Transformation.AES_ECB_PKCS5)}, new Object[] {new Config(BufferType.ARRAY, MyCipherFactory.CONSCRYPT, Transformation.AES_GCM_NO)}, new Object[] {new Config(BufferType.ARRAY, MyCipherFactory.CONSCRYPT, Transformation.AES_GCM_SIV)}, }; public Collection <Object[]> getParams() { final List<Object[]> params = new ArrayList<>(); for (BufferType bufferType : BufferType.values()) { for (CipherFactory cipherFactory : MyCipherFactory.values()) { for (Transformation transformation : Transformation.values()) { params.add(new Object[] {new Config( bufferType, cipherFactory, transformation)}); } } } return params; } private EncryptStrategy encryptStrategy; Loading
apct-tests/perftests/core/src/android/conscrypt/conscrypt/ClientSocketPerfTest.java +21 −11 Original line number Diff line number Diff line Loading @@ -30,6 +30,9 @@ import java.io.IOException; import java.io.OutputStream; import java.net.SocketException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; Loading Loading @@ -104,18 +107,25 @@ public final class ClientSocketPerfTest { } } private Object[] getParams() { return new Object[][] { new Object[] {new Config( EndpointFactory.CONSCRYPT, EndpointFactory.CONSCRYPT, 64, "AES128-GCM", ChannelType.CHANNEL, PerfTestProtocol.TLSv13)}, }; public Collection getParams() { final List<Object[]> params = new ArrayList<>(); for (EndpointFactory endpointFactory : EndpointFactory.values()) { for (ChannelType channelType : ChannelType.values()) { for (PerfTestProtocol protocol : PerfTestProtocol.values()) { params.add(new Object[] {new Config(endpointFactory, endpointFactory, 64, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", channelType, protocol)}); params.add(new Object[] {new Config(endpointFactory, endpointFactory, 512, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", channelType, protocol)}); params.add(new Object[] {new Config(endpointFactory, endpointFactory, 4096, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", channelType, protocol)}); } } } return params; } private ClientEndpoint client; private ServerEndpoint server; Loading
apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineFactory.java 0 → 100644 +68 −0 Original line number Diff line number Diff line /* * Copyright 2017 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.conscrypt; import org.conscrypt.TestUtils; import java.security.Security; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; /** * Factory for {@link SSLEngine} instances. */ public class EngineFactory { public EngineFactory() { this(newConscryptClientContext(), newConscryptServerContext()); } private EngineFactory(SSLContext clientContext, SSLContext serverContext) { this.clientContext = clientContext; this.serverContext = serverContext; } private final SSLContext clientContext; private final SSLContext serverContext; public SSLEngine newClientEngine(String cipher) { SSLEngine engine = initEngine(clientContext.createSSLEngine(), cipher, true); return engine; } public SSLEngine newServerEngine(String cipher) { SSLEngine engine = initEngine(serverContext.createSSLEngine(), cipher, false); return engine; } public void dispose(SSLEngine engine) { engine.closeOutbound(); } private static SSLContext newConscryptClientContext() { return TestUtils.newClientSslContext(TestUtils.getConscryptProvider()); } private static SSLContext newConscryptServerContext() { return TestUtils.newServerSslContext(TestUtils.getConscryptProvider()); } static SSLEngine initEngine(SSLEngine engine, String cipher, boolean client) { engine.setEnabledProtocols(new String[]{"TLSv1.2", "TLSv1.3"}); engine.setEnabledCipherSuites(new String[] {cipher}); engine.setUseClientMode(client); return engine; } } No newline at end of file
apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineHandshakePerfTest.java 0 → 100644 +207 −0 Original line number Diff line number Diff line /* * Copyright 2017 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. */ /* * Copyright 2017 The Netty Project * * The Netty Project licenses this file to you 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.conscrypt; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLException; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import androidx.test.filters.LargeTest; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; /** * Benchmark comparing handshake performance of various engine implementations to conscrypt. */ @RunWith(JUnitParamsRunner.class) @LargeTest public final class EngineHandshakePerfTest { @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); /** * Provider for the test configuration */ private class Config { BufferType a_bufferType; String c_cipher; int d_rttMillis; Config(BufferType bufferType, String cipher, int rttMillis) { a_bufferType = bufferType; c_cipher = cipher; d_rttMillis = rttMillis; } public BufferType bufferType() { return a_bufferType; } public String cipher() { return c_cipher; } public int rttMillis() { return d_rttMillis; } } public Collection getParams() { final List<Object[]> params = new ArrayList<>(); for (BufferType bufferType : BufferType.values()) { params.add(new Object[] {new Config(bufferType, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", 100)}); } return params; } private static final ByteBuffer EMPTY_BUFFER = ByteBuffer.allocateDirect(0); private EngineFactory engineFactory = new EngineFactory(); private String cipher; private int rttMillis; private ByteBuffer clientApplicationBuffer; private ByteBuffer clientPacketBuffer; private ByteBuffer serverApplicationBuffer; private ByteBuffer serverPacketBuffer; private void setup(Config config) throws Exception { cipher = config.cipher(); rttMillis = config.rttMillis(); BufferType bufferType = config.bufferType(); SSLEngine clientEngine = engineFactory.newClientEngine(cipher); SSLEngine serverEngine = engineFactory.newServerEngine(cipher); // Create the application and packet buffers for both endpoints. clientApplicationBuffer = bufferType.newApplicationBuffer(clientEngine); serverApplicationBuffer = bufferType.newApplicationBuffer(serverEngine); clientPacketBuffer = bufferType.newPacketBuffer(clientEngine); serverPacketBuffer = bufferType.newPacketBuffer(serverEngine); engineFactory.dispose(clientEngine); engineFactory.dispose(serverEngine); } @Test @Parameters(method = "getParams") public void handshake(Config config) throws Exception { setup(config); SSLEngine client = engineFactory.newClientEngine(cipher); SSLEngine server = engineFactory.newServerEngine(cipher); clientApplicationBuffer.clear(); clientPacketBuffer.clear(); serverApplicationBuffer.clear(); serverPacketBuffer.clear(); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { client.beginHandshake(); server.beginHandshake(); doHandshake(client, server); } engineFactory.dispose(client); engineFactory.dispose(server); } private void doHandshake(SSLEngine client, SSLEngine server) throws SSLException { BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { // Send as many client-to-server messages as possible doHalfHandshake(client, server, clientPacketBuffer, serverApplicationBuffer); if (client.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING && server.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) { return; } // Do the same with server-to-client messages doHalfHandshake(server, client, serverPacketBuffer, clientApplicationBuffer); if (client.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING && server.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) { return; } } } private void doHalfHandshake(SSLEngine sender, SSLEngine receiver, ByteBuffer senderPacketBuffer, ByteBuffer receiverApplicationBuffer) throws SSLException { SSLEngineResult senderResult; SSLEngineResult receiverResult; do { senderResult = sender.wrap(EMPTY_BUFFER, senderPacketBuffer); runDelegatedTasks(senderResult, sender); senderPacketBuffer.flip(); receiverResult = receiver.unwrap(senderPacketBuffer, receiverApplicationBuffer); runDelegatedTasks(receiverResult, receiver); senderPacketBuffer.compact(); } while (senderResult.getHandshakeStatus() == HandshakeStatus.NEED_WRAP); if (rttMillis > 0) { try { Thread.sleep(rttMillis / 2); } catch (InterruptedException e) { throw new RuntimeException(e); } } } private static void runDelegatedTasks(SSLEngineResult result, SSLEngine engine) { if (result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK) { for (;;) { Runnable task = engine.getDelegatedTask(); if (task == null) { break; } task.run(); } } } } No newline at end of file
apct-tests/perftests/core/src/android/conscrypt/conscrypt/EngineWrapPerfTest.java 0 → 100644 +221 −0 Original line number Diff line number Diff line /* * Copyright 2017 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. */ /* * Copyright 2017 The Netty Project * * The Netty Project licenses this file to you 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.conscrypt; import static org.conscrypt.TestUtils.doEngineHandshake; import static org.conscrypt.TestUtils.newTextMessage; import static org.junit.Assert.assertEquals; import java.nio.ByteBuffer; import java.util.Locale; import java.util.ArrayList; import java.util.Collection; import java.util.List; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLException; import android.perftests.utils.BenchmarkState; import android.perftests.utils.PerfStatusReporter; import androidx.test.filters.LargeTest; import junitparams.JUnitParamsRunner; import junitparams.Parameters; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; /** * Benchmark comparing performance of various engine implementations to conscrypt. */ @RunWith(JUnitParamsRunner.class) @LargeTest public final class EngineWrapPerfTest { @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter(); /** * Provider for the benchmark configuration */ private class Config { BufferType a_bufferType; int c_messageSize; String d_cipher; Config(BufferType bufferType, int messageSize, String cipher) { a_bufferType = bufferType; c_messageSize = messageSize; d_cipher = cipher; } public BufferType bufferType() { return a_bufferType; } public int messageSize() { return c_messageSize; } public String cipher() { return d_cipher; } } public Collection getParams() { final List<Object[]> params = new ArrayList<>(); for (BufferType bufferType : BufferType.values()) { params.add(new Object[] {new Config(bufferType, 64, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")}); params.add(new Object[] {new Config(bufferType, 512, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")}); params.add(new Object[] {new Config(bufferType, 4096, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256")}); } return params; } private EngineFactory engineFactory = new EngineFactory(); private String cipher; private SSLEngine clientEngine; private SSLEngine serverEngine; private ByteBuffer messageBuffer; private ByteBuffer clientApplicationBuffer; private ByteBuffer clientPacketBuffer; private ByteBuffer serverApplicationBuffer; private ByteBuffer serverPacketBuffer; private ByteBuffer preEncryptedBuffer; private void setup(Config config) throws Exception { cipher = config.cipher(); BufferType bufferType = config.bufferType(); clientEngine = engineFactory.newClientEngine(cipher); serverEngine = engineFactory.newServerEngine(cipher); // Create the application and packet buffers for both endpoints. clientApplicationBuffer = bufferType.newApplicationBuffer(clientEngine); serverApplicationBuffer = bufferType.newApplicationBuffer(serverEngine); clientPacketBuffer = bufferType.newPacketBuffer(clientEngine); serverPacketBuffer = bufferType.newPacketBuffer(serverEngine); // Generate the message to be sent from the client. int messageSize = config.messageSize(); messageBuffer = bufferType.newBuffer(messageSize); messageBuffer.put(newTextMessage(messageSize)); messageBuffer.flip(); // Complete the initial TLS handshake. doEngineHandshake(clientEngine, serverEngine, clientApplicationBuffer, clientPacketBuffer, serverApplicationBuffer, serverPacketBuffer, true); // Populate the pre-encrypted buffer for use with the unwrap benchmark. preEncryptedBuffer = bufferType.newBuffer(clientEngine.getSession().getPacketBufferSize()); doWrap(messageBuffer, preEncryptedBuffer); doUnwrap(preEncryptedBuffer, serverApplicationBuffer); } void teardown() { engineFactory.dispose(clientEngine); engineFactory.dispose(serverEngine); } @Test @Parameters(method = "getParams") public void wrap(Config config) throws Exception { setup(config); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { // Reset the buffers. messageBuffer.position(0); clientPacketBuffer.clear(); // Wrap the original message and create the encrypted data. doWrap(messageBuffer, clientPacketBuffer); // Lightweight comparison - just make sure the data length is correct. assertEquals(preEncryptedBuffer.limit(), clientPacketBuffer.limit()); } teardown(); } /** * Simple benchmark that sends a single message from client to server. */ @Test @Parameters(method = "getParams") public void wrapAndUnwrap(Config config) throws Exception { setup(config); BenchmarkState state = mPerfStatusReporter.getBenchmarkState(); while (state.keepRunning()) { // Reset the buffers. messageBuffer.position(0); clientPacketBuffer.clear(); serverApplicationBuffer.clear(); // Wrap the original message and create the encrypted data. doWrap(messageBuffer, clientPacketBuffer); // Unwrap the encrypted data and get back the original result. doUnwrap(clientPacketBuffer, serverApplicationBuffer); // Lightweight comparison - just make sure the unencrypted data length is correct. assertEquals(messageBuffer.limit(), serverApplicationBuffer.limit()); } teardown(); } private void doWrap(ByteBuffer src, ByteBuffer dst) throws SSLException { // Wrap the original message and create the encrypted data. verifyResult(src, clientEngine.wrap(src, dst)); dst.flip(); } private void doUnwrap(ByteBuffer src, ByteBuffer dst) throws SSLException { verifyResult(src, serverEngine.unwrap(src, dst)); dst.flip(); } private void verifyResult(ByteBuffer src, SSLEngineResult result) { if (result.getStatus() != SSLEngineResult.Status.OK) { throw new RuntimeException("Operation returned unexpected result " + result); } if (result.bytesConsumed() != src.limit()) { throw new RuntimeException( String.format(Locale.US, "Operation didn't consume all bytes. Expected %d, consumed %d.", src.limit(), result.bytesConsumed())); } } } No newline at end of file