Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aefca840 authored by Miguel Aranda's avatar Miguel Aranda Committed by Automerger Merge Worker
Browse files

Merge "Add first set of conscrypt benchmarks within frameworks." into main am:...

Merge "Add first set of conscrypt benchmarks within frameworks." into main am: fcb4947d am: fe45014c

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/3138575



Change-Id: Id448d898221a0e580cf183d59dc32779d6fc7aaa
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 1260ee8f fe45014c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ android_test {
        "apct-perftests-resources-manager-apps",
        "apct-perftests-utils",
        "collector-device-lib",
        "conscrypt-test-support",
        "compatibility-device-util-axt",
        "junit",
        "junit-params",
+48 −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 java.nio.ByteBuffer;
import javax.net.ssl.SSLEngine;

/**
 * Enumeration that provides allocation of direct or heap buffers.
 */
@SuppressWarnings("unused")
public enum BufferType {
    HEAP {
        @Override
        ByteBuffer newBuffer(int size) {
            return ByteBuffer.allocate(size);
        }
    },
    DIRECT {
        @Override
        ByteBuffer newBuffer(int size) {
            return ByteBuffer.allocateDirect(size);
        }
    };

    abstract ByteBuffer newBuffer(int size);

    ByteBuffer newApplicationBuffer(SSLEngine engine) {
        return newBuffer(engine.getSession().getApplicationBufferSize());
    }

    ByteBuffer newPacketBuffer(SSLEngine engine) {
        return newBuffer(engine.getSession().getPacketBufferSize());
    }
}
 No newline at end of file
+228 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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 android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import androidx.test.filters.LargeTest;

import org.conscrypt.TestUtils;

import java.nio.ByteBuffer;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;

import junitparams.JUnitParamsRunner;
import junitparams.Parameters;

import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * Benchmark for comparing cipher encrypt performance.
 */
@RunWith(JUnitParamsRunner.class)
@LargeTest
public final class CipherEncryptPerfTest {

    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();

    public enum BufferType {
        ARRAY,
        HEAP_HEAP,
        HEAP_DIRECT,
        DIRECT_DIRECT,
        DIRECT_HEAP
    }

    private enum MyCipherFactory implements CipherFactory {
        JDK {
            @Override
            public Cipher newCipher(String transformation)
                throws NoSuchPaddingException, NoSuchAlgorithmException {
                return Cipher.getInstance(transformation);
            }
        },
        CONSCRYPT {
            @Override
            public Cipher newCipher(String transformation)
                throws NoSuchPaddingException, NoSuchAlgorithmException {
                return Cipher.getInstance(transformation, TestUtils.getConscryptProvider());
            }
        };
    }

    private class Config {
        BufferType b_bufferType;
        CipherFactory c_provider;
        Transformation a_tx;
        Config(BufferType bufferType, CipherFactory cipherFactory, Transformation transformation) {
          b_bufferType = bufferType;
          c_provider = cipherFactory;
          a_tx = transformation;
        }
        public BufferType bufferType() {
            return b_bufferType;
        }

        public CipherFactory cipherFactory() {
            return c_provider;
        }

        public Transformation transformation() {
            return a_tx;
        }
    }

    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)},
        };
    }

    private EncryptStrategy encryptStrategy;

    @Test
    @Parameters(method = "getParams")
    public void encrypt(Config config) throws Exception {
        switch (config.bufferType()) {
            case ARRAY:
                encryptStrategy = new ArrayStrategy(config);
                break;
            default:
                encryptStrategy = new ByteBufferStrategy(config);
                break;
        }
        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
        while (state.keepRunning()) {
          encryptStrategy.encrypt();
        }
    }

    private static abstract class EncryptStrategy {
        private final Key key;
        final Cipher cipher;
        final int outputSize;

        EncryptStrategy(Config config) throws Exception {
            Transformation tx = config.transformation();
            key = tx.newEncryptKey();
            cipher = config.cipherFactory().newCipher(tx.toFormattedString());
            initCipher();

            int messageSize = messageSize(tx.toFormattedString());
            outputSize = cipher.getOutputSize(messageSize);
        }

        final void initCipher() throws Exception {
            cipher.init(Cipher.ENCRYPT_MODE, key);
        }

        final int messageSize(String transformation) throws Exception {
            Cipher conscryptCipher = Cipher.getInstance(
                transformation, TestUtils.getConscryptProvider());
            conscryptCipher.init(Cipher.ENCRYPT_MODE, key);
            return conscryptCipher.getBlockSize() > 0 ?
                conscryptCipher.getBlockSize() : 128;
        }

        final byte[] newMessage() {
            return TestUtils.newTextMessage(cipher.getBlockSize());
        }

        abstract int encrypt() throws Exception;
    }

    private static final class ArrayStrategy extends EncryptStrategy {
        private final byte[] plainBytes;
        private final byte[] cipherBytes;

        ArrayStrategy(Config config) throws Exception {
            super(config);

            plainBytes = newMessage();
            cipherBytes = new byte[outputSize];
        }

        @Override
        int encrypt() throws Exception {
            initCipher();
            return cipher.doFinal(plainBytes, 0, plainBytes.length, cipherBytes, 0);
        }
    }

    private static final class ByteBufferStrategy extends EncryptStrategy {
        private final ByteBuffer input;
        private final ByteBuffer output;

        ByteBufferStrategy(Config config) throws Exception {
            super(config);

            switch (config.bufferType()) {
                case HEAP_HEAP:
                    input = ByteBuffer.wrap(newMessage());
                    output = ByteBuffer.allocate(outputSize);
                    break;
                case HEAP_DIRECT:
                    input = ByteBuffer.wrap(newMessage());
                    output = ByteBuffer.allocateDirect(outputSize);
                    break;
                case DIRECT_DIRECT:
                    input = toDirect(newMessage());
                    output = ByteBuffer.allocateDirect(outputSize);
                    break;
                case DIRECT_HEAP:
                    input = toDirect(newMessage());
                    output = ByteBuffer.allocate(outputSize);
                    break;
                default: {
                    throw new IllegalStateException(
                            "Unexpected buffertype: " + config.bufferType());
                }
            }
        }

        @Override
        int encrypt() throws Exception {
            initCipher();
            input.position(0);
            output.clear();
            return cipher.doFinal(input, output);
        }

        private static ByteBuffer toDirect(byte[] data) {
            ByteBuffer buffer = ByteBuffer.allocateDirect(data.length);
            buffer.put(data);
            buffer.flip();
            return buffer;
        }
    }
}
 No newline at end of file
+27 −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 java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;

/**
 * Factory for {@link Cipher} instances.
 */
public interface CipherFactory {
  Cipher newCipher(String transformation) throws NoSuchPaddingException, NoSuchAlgorithmException;
}
 No newline at end of file
+110 −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 java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.SocketException;
import java.nio.channels.ClosedChannelException;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

import org.conscrypt.ChannelType;

/**
 * Client-side endpoint. Provides basic services for sending/receiving messages from the client
 * socket.
 */
final class ClientEndpoint {
    private final SSLSocket socket;
    private InputStream input;
    private OutputStream output;

    ClientEndpoint(SSLSocketFactory socketFactory, ChannelType channelType, int port,
            String[] protocols, String[] ciphers) throws IOException {
        socket = channelType.newClientSocket(socketFactory, InetAddress.getLoopbackAddress(), port);
        socket.setEnabledProtocols(protocols);
        socket.setEnabledCipherSuites(ciphers);
    }

    void start() {
        try {
            socket.startHandshake();
            input = socket.getInputStream();
            output = socket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    void stop() {
        try {
            socket.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    int readMessage(byte[] buffer) {
        try {
            int totalBytesRead = 0;
            while (totalBytesRead < buffer.length) {
                int remaining = buffer.length - totalBytesRead;
                int bytesRead = input.read(buffer, totalBytesRead, remaining);
                if (bytesRead == -1) {
                    break;
                }
                totalBytesRead += bytesRead;
            }
            return totalBytesRead;
        } catch (SSLException e) {
            if (e.getCause() instanceof EOFException) {
                return -1;
            }
            throw new RuntimeException(e);
        } catch (ClosedChannelException e) {
            // Thrown for channel-based sockets. Just treat like EOF.
            return -1;
        }  catch (SocketException e) {
            // The socket was broken. Just treat like EOF.
            return -1;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    void sendMessage(byte[] data) {
        try {
            output.write(data);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    void flush() {
        try {
            output.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
 No newline at end of file
Loading