You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
717 lines
27 KiB
717 lines
27 KiB
/*
|
|
* Copyright (C) 2019 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.
|
|
*/
|
|
|
|
#define LOG_TAG "keymaster_benchmark"
|
|
|
|
#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
|
|
#include <android/hardware/keymaster/4.0/types.h>
|
|
#include <keymaster/keymaster_configuration.h>
|
|
#include <keymasterV4_0/authorization_set.h>
|
|
|
|
#include <android/hidl/manager/1.0/IServiceManager.h>
|
|
#include <binder/IServiceManager.h>
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include <log/log.h>
|
|
#include <utils/StrongPointer.h>
|
|
|
|
#include <benchmark/benchmark.h>
|
|
#include <hidl/Status.h>
|
|
|
|
#include <base/command_line.h>
|
|
|
|
namespace android {
|
|
namespace hardware {
|
|
namespace keymaster {
|
|
namespace V4_0 {
|
|
namespace test {
|
|
|
|
// libutils:
|
|
using android::OK;
|
|
using android::sp;
|
|
using android::status_t;
|
|
|
|
// libhidl:
|
|
using android::hardware::hidl_vec;
|
|
using android::hardware::Return;
|
|
using android::hardware::Void;
|
|
|
|
// IKeymaster:
|
|
using android::IServiceManager;
|
|
using android::hardware::hidl_string;
|
|
using android::hardware::keymaster::V4_0::AuthorizationSet;
|
|
using android::hardware::keymaster::V4_0::AuthorizationSetBuilder;
|
|
using android::hardware::keymaster::V4_0::BlockMode;
|
|
using android::hardware::keymaster::V4_0::ErrorCode;
|
|
using android::hardware::keymaster::V4_0::IKeymasterDevice;
|
|
using android::hardware::keymaster::V4_0::KeyCharacteristics;
|
|
using android::hardware::keymaster::V4_0::SecurityLevel;
|
|
|
|
// Standard library:
|
|
using std::cerr;
|
|
using std::cout;
|
|
using std::endl;
|
|
using std::optional;
|
|
using std::string;
|
|
using std::unique_ptr;
|
|
using std::vector;
|
|
|
|
class HidlBuf : public hidl_vec<uint8_t> {
|
|
typedef hidl_vec<uint8_t> super;
|
|
|
|
public:
|
|
HidlBuf() {}
|
|
HidlBuf(const super& other) : super(other) {}
|
|
HidlBuf(super&& other) : super(std::move(other)) {}
|
|
explicit HidlBuf(const std::string& other) : HidlBuf() { *this = other; }
|
|
|
|
HidlBuf& operator=(const super& other) {
|
|
super::operator=(other);
|
|
return *this;
|
|
}
|
|
|
|
HidlBuf& operator=(super&& other) {
|
|
super::operator=(std::move(other));
|
|
return *this;
|
|
}
|
|
|
|
HidlBuf& operator=(const string& other) {
|
|
resize(other.size());
|
|
std::copy(other.begin(), other.end(), begin());
|
|
return *this;
|
|
}
|
|
|
|
string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
|
|
};
|
|
|
|
#define SMALL_MESSAGE_SIZE 64
|
|
#define MEDIUM_MESSAGE_SIZE 1024
|
|
#define LARGE_MESSAGE_SIZE 131072
|
|
|
|
class KeymasterWrapper {
|
|
private:
|
|
sp<IKeymasterDevice> keymaster_;
|
|
SecurityLevel securityLevel_;
|
|
hidl_string name_;
|
|
hidl_string author_;
|
|
HidlBuf key_blob_;
|
|
KeyCharacteristics key_characteristics_;
|
|
ErrorCode error_;
|
|
string key_transform_;
|
|
string keymaster_name_;
|
|
uint32_t os_version_;
|
|
uint32_t os_patch_level_;
|
|
std::vector<string> message_cache_;
|
|
|
|
bool GenerateKey(const AuthorizationSet& authSet) {
|
|
return (keymaster_
|
|
->generateKey(
|
|
authSet.hidl_data(),
|
|
[&](ErrorCode hidl_error, const hidl_vec<uint8_t>& hidl_key_blob,
|
|
const KeyCharacteristics& hidl_key_characteristics) {
|
|
error_ = hidl_error;
|
|
key_blob_ = hidl_key_blob;
|
|
key_characteristics_ = std::move(hidl_key_characteristics);
|
|
})
|
|
.isOk() &&
|
|
error_ == ErrorCode::OK);
|
|
}
|
|
|
|
bool GenerateKey(Algorithm algorithm, int keySize, Digest digest = Digest::NONE,
|
|
PaddingMode padding = PaddingMode::NONE, optional<BlockMode> blockMode = {}) {
|
|
AuthorizationSetBuilder authSet = AuthorizationSetBuilder()
|
|
.Authorization(TAG_NO_AUTH_REQUIRED)
|
|
.Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT)
|
|
.Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT)
|
|
.Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
|
|
.Authorization(TAG_PURPOSE, KeyPurpose::VERIFY)
|
|
.Authorization(TAG_KEY_SIZE, keySize)
|
|
.Authorization(TAG_ALGORITHM, algorithm)
|
|
.Digest(digest)
|
|
.Authorization(TAG_MIN_MAC_LENGTH, 128)
|
|
.Padding(padding);
|
|
if (blockMode) {
|
|
authSet.BlockMode(*blockMode);
|
|
}
|
|
if (algorithm == Algorithm::RSA) {
|
|
authSet.Authorization(TAG_RSA_PUBLIC_EXPONENT, 65537U);
|
|
}
|
|
return GenerateKey(authSet);
|
|
}
|
|
|
|
KeymasterWrapper(const sp<IKeymasterDevice> keymaster) {
|
|
os_version_ = ::keymaster::GetOsVersion();
|
|
os_patch_level_ = ::keymaster::GetOsPatchlevel();
|
|
keymaster_ = keymaster;
|
|
keymaster_->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
|
|
const hidl_string& author) {
|
|
securityLevel_ = securityLevel;
|
|
name_ = name;
|
|
author_ = author;
|
|
});
|
|
|
|
message_cache_.push_back(string(SMALL_MESSAGE_SIZE, 'x'));
|
|
message_cache_.push_back(string(MEDIUM_MESSAGE_SIZE, 'x'));
|
|
message_cache_.push_back(string(LARGE_MESSAGE_SIZE, 'x'));
|
|
}
|
|
|
|
public:
|
|
static KeymasterWrapper* newInstance(const std::string& keymaster_name) {
|
|
auto keymaster = IKeymasterDevice::getService(keymaster_name);
|
|
if (!keymaster) {
|
|
std::cerr << "Error: unable to find keymaster service named " << keymaster_name
|
|
<< std::endl;
|
|
return nullptr;
|
|
}
|
|
return new KeymasterWrapper(keymaster);
|
|
}
|
|
|
|
bool GenerateKey(string transform, int keySize, bool sign = false) {
|
|
if (transform == key_transform_) {
|
|
return true;
|
|
} else if (key_transform_ != "") {
|
|
// Deleting old key first
|
|
if (!DeleteKey()) {
|
|
return false;
|
|
}
|
|
}
|
|
optional<Algorithm> algorithm = getAlgorithm(transform);
|
|
if (!algorithm) {
|
|
cerr << "Error: invalid algorithm " << transform << endl;
|
|
return false;
|
|
}
|
|
key_transform_ = transform;
|
|
return GenerateKey(*algorithm, keySize, getDigest(transform), getPadding(transform, sign),
|
|
getBlockMode(transform));
|
|
}
|
|
|
|
bool DeleteKey() {
|
|
key_blob_ = HidlBuf();
|
|
key_transform_ = "";
|
|
return keymaster_->deleteKey(key_blob_).isOk();
|
|
}
|
|
|
|
AuthorizationSet getOperationParams(string transform, bool sign = false) {
|
|
AuthorizationSetBuilder builder = AuthorizationSetBuilder()
|
|
.Padding(getPadding(transform, sign))
|
|
.Authorization(TAG_MAC_LENGTH, 128)
|
|
.Digest(getDigest(transform));
|
|
optional<BlockMode> blockMode = getBlockMode(transform);
|
|
if (blockMode) {
|
|
builder.BlockMode(*blockMode);
|
|
}
|
|
return std::move(builder);
|
|
}
|
|
|
|
optional<OperationHandle> EncryptBegin(AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params = new AuthorizationSet) {
|
|
return Begin(KeyPurpose::ENCRYPT, in_params, out_params);
|
|
}
|
|
|
|
optional<OperationHandle> DecryptBegin(AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params = new AuthorizationSet) {
|
|
return Begin(KeyPurpose::DECRYPT, in_params, out_params);
|
|
}
|
|
|
|
optional<OperationHandle> SignBegin(AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params = new AuthorizationSet) {
|
|
return Begin(KeyPurpose::SIGN, in_params, out_params);
|
|
}
|
|
|
|
optional<OperationHandle> VerifyBegin(AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params = new AuthorizationSet) {
|
|
return Begin(KeyPurpose::VERIFY, in_params, out_params);
|
|
}
|
|
|
|
optional<OperationHandle> Begin(KeyPurpose operation, const AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params) {
|
|
OperationHandle op_handle;
|
|
if (!keymaster_
|
|
->begin(operation, key_blob_, in_params.hidl_data(), HardwareAuthToken(),
|
|
[&](ErrorCode hidl_error,
|
|
const hidl_vec<KeyParameter>& hidl_out_params,
|
|
uint64_t hidl_op_handle) {
|
|
error_ = hidl_error;
|
|
out_params->push_back(AuthorizationSet(hidl_out_params));
|
|
op_handle = hidl_op_handle;
|
|
})
|
|
.isOk() ||
|
|
error_ != ErrorCode::OK) {
|
|
keymaster_->abort(op_handle);
|
|
return {};
|
|
}
|
|
return op_handle;
|
|
}
|
|
|
|
optional<string> ProcessMessage(const OperationHandle& op_handle, const string& message,
|
|
const AuthorizationSet& in_params,
|
|
AuthorizationSet* out_params = new AuthorizationSet,
|
|
const string& signature = "") {
|
|
static const int HIDL_BUFFER_LIMIT = 1 << 14; // 16KB
|
|
|
|
string output;
|
|
size_t input_consumed = 0;
|
|
while (message.length() - input_consumed > 0) {
|
|
if (!keymaster_
|
|
->update(op_handle, in_params.hidl_data(),
|
|
HidlBuf(message.substr(input_consumed, HIDL_BUFFER_LIMIT)),
|
|
HardwareAuthToken(), VerificationToken(),
|
|
[&](ErrorCode hidl_error, uint32_t hidl_input_consumed,
|
|
const hidl_vec<KeyParameter>& hidl_out_params,
|
|
const HidlBuf& hidl_output) {
|
|
error_ = hidl_error;
|
|
out_params->push_back(AuthorizationSet(hidl_out_params));
|
|
output.append(hidl_output.to_string());
|
|
input_consumed += hidl_input_consumed;
|
|
})
|
|
.isOk() ||
|
|
error_ != ErrorCode::OK) {
|
|
keymaster_->abort(op_handle);
|
|
return {};
|
|
}
|
|
}
|
|
|
|
if (!keymaster_
|
|
->finish(op_handle, in_params.hidl_data(),
|
|
HidlBuf(message.substr(input_consumed)), HidlBuf(signature),
|
|
HardwareAuthToken(), VerificationToken(),
|
|
[&](ErrorCode hidl_error,
|
|
const hidl_vec<KeyParameter>& hidl_out_params,
|
|
const HidlBuf& hidl_output) {
|
|
error_ = hidl_error;
|
|
out_params->push_back(AuthorizationSet(hidl_out_params));
|
|
output.append(hidl_output.to_string());
|
|
})
|
|
.isOk() ||
|
|
error_ != ErrorCode::OK) {
|
|
keymaster_->abort(op_handle);
|
|
return {};
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
int getError() { return static_cast<int>(error_); }
|
|
|
|
const string getHardwareName() { return name_; }
|
|
|
|
SecurityLevel getSecurityLevel() { return securityLevel_; }
|
|
|
|
const string& GenerateMessage(int size) {
|
|
for (const string& message : message_cache_) {
|
|
if (message.size() == size) {
|
|
return message;
|
|
}
|
|
}
|
|
string message = string(size, 'x');
|
|
message_cache_.push_back(message);
|
|
return std::move(message);
|
|
}
|
|
|
|
optional<BlockMode> getBlockMode(string transform) {
|
|
if (transform.find("/ECB") != string::npos) {
|
|
return BlockMode::ECB;
|
|
} else if (transform.find("/CBC") != string::npos) {
|
|
return BlockMode::CBC;
|
|
} else if (transform.find("/CTR") != string::npos) {
|
|
return BlockMode::CTR;
|
|
} else if (transform.find("/GCM") != string::npos) {
|
|
return BlockMode::GCM;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
PaddingMode getPadding(string transform, bool sign) {
|
|
if (transform.find("/PKCS7") != string::npos) {
|
|
return PaddingMode::PKCS7;
|
|
} else if (transform.find("/PSS") != string::npos) {
|
|
return PaddingMode::RSA_PSS;
|
|
} else if (transform.find("/OAEP") != string::npos) {
|
|
return PaddingMode::RSA_OAEP;
|
|
} else if (transform.find("/PKCS1") != string::npos) {
|
|
return sign ? PaddingMode::RSA_PKCS1_1_5_SIGN : PaddingMode::RSA_PKCS1_1_5_ENCRYPT;
|
|
} else if (sign && transform.find("RSA") != string::npos) {
|
|
// RSA defaults to PKCS1 for sign
|
|
return PaddingMode::RSA_PKCS1_1_5_SIGN;
|
|
}
|
|
return PaddingMode::NONE;
|
|
}
|
|
|
|
optional<Algorithm> getAlgorithm(string transform) {
|
|
if (transform.find("AES") != string::npos) {
|
|
return Algorithm::AES;
|
|
} else if (transform.find("Hmac") != string::npos) {
|
|
return Algorithm::HMAC;
|
|
} else if (transform.find("DESede") != string::npos) {
|
|
return Algorithm::TRIPLE_DES;
|
|
} else if (transform.find("RSA") != string::npos) {
|
|
return Algorithm::RSA;
|
|
} else if (transform.find("EC") != string::npos) {
|
|
return Algorithm::EC;
|
|
}
|
|
cerr << "Can't find algorithm for " << transform << endl;
|
|
return {};
|
|
}
|
|
|
|
Digest getDigest(string transform) {
|
|
if (transform.find("MD5") != string::npos) {
|
|
return Digest::MD5;
|
|
} else if (transform.find("SHA1") != string::npos ||
|
|
transform.find("SHA-1") != string::npos) {
|
|
return Digest::SHA1;
|
|
} else if (transform.find("SHA224") != string::npos) {
|
|
return Digest::SHA_2_224;
|
|
} else if (transform.find("SHA256") != string::npos) {
|
|
return Digest::SHA_2_256;
|
|
} else if (transform.find("SHA384") != string::npos) {
|
|
return Digest::SHA_2_384;
|
|
} else if (transform.find("SHA512") != string::npos) {
|
|
return Digest::SHA_2_512;
|
|
} else if (transform.find("RSA") != string::npos &&
|
|
transform.find("OAEP") != string::npos) {
|
|
return Digest::SHA1;
|
|
}
|
|
return Digest::NONE;
|
|
}
|
|
};
|
|
|
|
KeymasterWrapper* keymaster;
|
|
|
|
static void settings(benchmark::internal::Benchmark* benchmark) {
|
|
benchmark->Unit(benchmark::kMillisecond);
|
|
}
|
|
|
|
static void addDefaultLabel(benchmark::State& state) {
|
|
string secLevel;
|
|
switch (keymaster->getSecurityLevel()) {
|
|
case SecurityLevel::STRONGBOX:
|
|
secLevel = "STRONGBOX";
|
|
break;
|
|
case SecurityLevel::SOFTWARE:
|
|
secLevel = "SOFTWARE";
|
|
break;
|
|
case SecurityLevel::TRUSTED_ENVIRONMENT:
|
|
secLevel = "TEE";
|
|
break;
|
|
}
|
|
state.SetLabel("hardware_name:" + keymaster->getHardwareName() + " sec_level:" + secLevel);
|
|
}
|
|
|
|
// clang-format off
|
|
#define BENCHMARK_KM(func, transform, keySize) \
|
|
BENCHMARK_CAPTURE(func, transform/keySize, #transform "/" #keySize, keySize)->Apply(settings);
|
|
#define BENCHMARK_KM_MSG(func, transform, keySize, msgSize) \
|
|
BENCHMARK_CAPTURE(func, transform/keySize/msgSize, #transform "/" #keySize "/" #msgSize, \
|
|
keySize, msgSize) \
|
|
->Apply(settings);
|
|
|
|
#define BENCHMARK_KM_ALL_MSGS(func, transform, keySize) \
|
|
BENCHMARK_KM_MSG(func, transform, keySize, SMALL_MESSAGE_SIZE) \
|
|
BENCHMARK_KM_MSG(func, transform, keySize, MEDIUM_MESSAGE_SIZE) \
|
|
BENCHMARK_KM_MSG(func, transform, keySize, LARGE_MESSAGE_SIZE)
|
|
|
|
#define BENCHMARK_KM_CIPHER(transform, keySize, msgSize) \
|
|
BENCHMARK_KM_MSG(encrypt, transform, keySize, msgSize) \
|
|
BENCHMARK_KM_MSG(decrypt, transform, keySize, msgSize)
|
|
|
|
#define BENCHMARK_KM_CIPHER_ALL_MSGS(transform, keySize) \
|
|
BENCHMARK_KM_ALL_MSGS(encrypt, transform, keySize) \
|
|
BENCHMARK_KM_ALL_MSGS(decrypt, transform, keySize)
|
|
|
|
#define BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, keySize) \
|
|
BENCHMARK_KM_ALL_MSGS(sign, transform, keySize) \
|
|
BENCHMARK_KM_ALL_MSGS(verify, transform, keySize)
|
|
// clang-format on
|
|
|
|
/*
|
|
* ============= KeyGen TESTS ==================
|
|
*/
|
|
static void keygen(benchmark::State& state, string transform, int keySize) {
|
|
addDefaultLabel(state);
|
|
for (auto _ : state) {
|
|
keymaster->GenerateKey(transform, keySize);
|
|
state.PauseTiming();
|
|
keymaster->DeleteKey();
|
|
state.ResumeTiming();
|
|
}
|
|
}
|
|
|
|
BENCHMARK_KM(keygen, AES, 128);
|
|
BENCHMARK_KM(keygen, AES, 256);
|
|
|
|
BENCHMARK_KM(keygen, RSA, 2048);
|
|
BENCHMARK_KM(keygen, RSA, 3072);
|
|
BENCHMARK_KM(keygen, RSA, 4096);
|
|
|
|
BENCHMARK_KM(keygen, EC, 224);
|
|
BENCHMARK_KM(keygen, EC, 256);
|
|
BENCHMARK_KM(keygen, EC, 384);
|
|
BENCHMARK_KM(keygen, EC, 521);
|
|
|
|
BENCHMARK_KM(keygen, DESede, 168);
|
|
|
|
BENCHMARK_KM(keygen, Hmac, 64);
|
|
BENCHMARK_KM(keygen, Hmac, 128);
|
|
BENCHMARK_KM(keygen, Hmac, 256);
|
|
BENCHMARK_KM(keygen, Hmac, 512);
|
|
BENCHMARK_KM(keygen, Hmac, 1024);
|
|
BENCHMARK_KM(keygen, Hmac, 2048);
|
|
BENCHMARK_KM(keygen, Hmac, 4096);
|
|
BENCHMARK_KM(keygen, Hmac, 8192);
|
|
|
|
/*
|
|
* ============= SIGNATURE TESTS ==================
|
|
*/
|
|
|
|
static void sign(benchmark::State& state, string transform, int keySize, int msgSize) {
|
|
addDefaultLabel(state);
|
|
if (!keymaster->GenerateKey(transform, keySize, true)) {
|
|
state.SkipWithError(
|
|
("Key generation error, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
auto params = keymaster->getOperationParams(transform, true);
|
|
string message = keymaster->GenerateMessage(msgSize);
|
|
|
|
for (auto _ : state) {
|
|
state.PauseTiming();
|
|
auto opHandle = keymaster->SignBegin(params);
|
|
if (!opHandle) {
|
|
state.SkipWithError(
|
|
("Error beginning sign, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
state.ResumeTiming();
|
|
if (!keymaster->ProcessMessage(*opHandle, message, params)) {
|
|
state.SkipWithError(("Sign error, " + std::to_string(keymaster->getError())).c_str());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void verify(benchmark::State& state, string transform, int keySize, int msgSize) {
|
|
addDefaultLabel(state);
|
|
if (!keymaster->GenerateKey(transform, keySize, true)) {
|
|
state.SkipWithError(
|
|
("Key generation error, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
AuthorizationSet out_params;
|
|
AuthorizationSet in_params = keymaster->getOperationParams(transform, true);
|
|
string message = keymaster->GenerateMessage(msgSize);
|
|
auto opHandle = keymaster->SignBegin(in_params, &out_params);
|
|
if (!opHandle) {
|
|
state.SkipWithError(
|
|
("Error beginning sign, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
optional<string> signature =
|
|
keymaster->ProcessMessage(*opHandle, message, in_params, &out_params);
|
|
if (!signature) {
|
|
state.SkipWithError(("Sign error, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
in_params.push_back(out_params);
|
|
for (auto _ : state) {
|
|
state.PauseTiming();
|
|
opHandle = keymaster->VerifyBegin(in_params);
|
|
if (!opHandle) {
|
|
state.SkipWithError(
|
|
("Verify begin error, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
state.ResumeTiming();
|
|
if (!keymaster->ProcessMessage(*opHandle, message, in_params, &out_params, *signature)) {
|
|
state.SkipWithError(("Verify error, " + std::to_string(keymaster->getError())).c_str());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// clang-format off
|
|
#define BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(transform) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 64) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 128) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 256) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 512) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 1024) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 2024) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 4096) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 8192)
|
|
|
|
BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA1)
|
|
BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA256)
|
|
BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA224)
|
|
BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA256)
|
|
BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA384)
|
|
BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA512)
|
|
|
|
#define BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(transform) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 224) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 256) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 384) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 521)
|
|
|
|
BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(NONEwithECDSA);
|
|
BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA1withECDSA);
|
|
BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA224withECDSA);
|
|
BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA256withECDSA);
|
|
BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA384withECDSA);
|
|
BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA512withECDSA);
|
|
|
|
#define BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(transform) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 2048) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 3072) \
|
|
BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 4096)
|
|
|
|
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(MD5withRSA);
|
|
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA1withRSA);
|
|
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA224withRSA);
|
|
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA384withRSA);
|
|
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA512withRSA);
|
|
|
|
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(MD5withRSA/PSS);
|
|
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA1withRSA/PSS);
|
|
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA224withRSA/PSS);
|
|
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA384withRSA/PSS);
|
|
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA512withRSA/PSS);
|
|
// clang-format on
|
|
|
|
/*
|
|
* ============= CIPHER TESTS ==================
|
|
*/
|
|
|
|
static void encrypt(benchmark::State& state, string transform, int keySize, int msgSize) {
|
|
addDefaultLabel(state);
|
|
if (!keymaster->GenerateKey(transform, keySize)) {
|
|
state.SkipWithError(
|
|
("Key generation error, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
auto params = keymaster->getOperationParams(transform);
|
|
string message = keymaster->GenerateMessage(msgSize);
|
|
|
|
for (auto _ : state) {
|
|
state.PauseTiming();
|
|
auto opHandle = keymaster->EncryptBegin(params);
|
|
if (!opHandle) {
|
|
state.SkipWithError(
|
|
("Encryption begin error, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
state.ResumeTiming();
|
|
if (!keymaster->ProcessMessage(*opHandle, message, params)) {
|
|
state.SkipWithError(
|
|
("Encryption error, " + std::to_string(keymaster->getError())).c_str());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void decrypt(benchmark::State& state, string transform, int keySize, int msgSize) {
|
|
addDefaultLabel(state);
|
|
if (!keymaster->GenerateKey(transform, keySize)) {
|
|
state.SkipWithError(
|
|
("Key generation error, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
AuthorizationSet out_params;
|
|
AuthorizationSet in_params = keymaster->getOperationParams(transform);
|
|
string message = keymaster->GenerateMessage(msgSize);
|
|
auto opHandle = keymaster->EncryptBegin(in_params, &out_params);
|
|
if (!opHandle) {
|
|
state.SkipWithError(
|
|
("Encryption begin error, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
auto encryptedMessage = keymaster->ProcessMessage(*opHandle, message, in_params, &out_params);
|
|
if (!encryptedMessage) {
|
|
state.SkipWithError(("Encryption error, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
in_params.push_back(out_params);
|
|
for (auto _ : state) {
|
|
state.PauseTiming();
|
|
opHandle = keymaster->DecryptBegin(in_params);
|
|
if (!opHandle) {
|
|
state.SkipWithError(
|
|
("Decryption begin error, " + std::to_string(keymaster->getError())).c_str());
|
|
return;
|
|
}
|
|
state.ResumeTiming();
|
|
if (!keymaster->ProcessMessage(*opHandle, *encryptedMessage, in_params)) {
|
|
state.SkipWithError(
|
|
("Decryption error, " + std::to_string(keymaster->getError())).c_str());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// clang-format off
|
|
// AES
|
|
#define BENCHMARK_KM_CIPHER_ALL_AES_KEYS(transform) \
|
|
BENCHMARK_KM_CIPHER_ALL_MSGS(transform, 128) \
|
|
BENCHMARK_KM_CIPHER_ALL_MSGS(transform, 256)
|
|
|
|
BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/CBC/NoPadding);
|
|
BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/CBC/PKCS7Padding);
|
|
BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/CTR/NoPadding);
|
|
BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/ECB/NoPadding);
|
|
BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/ECB/PKCS7Padding);
|
|
BENCHMARK_KM_CIPHER_ALL_AES_KEYS(AES/GCM/NoPadding);
|
|
|
|
// Triple DES
|
|
BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/CBC/NoPadding, 168);
|
|
BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/CBC/PKCS7Padding, 168);
|
|
BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/ECB/NoPadding, 168);
|
|
BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/ECB/PKCS7Padding, 168);
|
|
|
|
#define BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(transform, msgSize) \
|
|
BENCHMARK_KM_CIPHER(transform, 2048, msgSize) \
|
|
BENCHMARK_KM_CIPHER(transform, 3072, msgSize) \
|
|
BENCHMARK_KM_CIPHER(transform, 4096, msgSize)
|
|
|
|
BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/NoPadding, SMALL_MESSAGE_SIZE);
|
|
BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/PKCS1Padding, SMALL_MESSAGE_SIZE);
|
|
BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/OAEPPadding, SMALL_MESSAGE_SIZE);
|
|
// clang-format on
|
|
|
|
} // namespace test
|
|
} // namespace V4_0
|
|
} // namespace keymaster
|
|
} // namespace hardware
|
|
} // namespace android
|
|
|
|
int main(int argc, char** argv) {
|
|
::benchmark::Initialize(&argc, argv);
|
|
base::CommandLine::Init(argc, argv);
|
|
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
|
auto service_name = command_line->GetSwitchValueASCII("service_name");
|
|
if (service_name.empty()) {
|
|
service_name = "default";
|
|
}
|
|
android::hardware::keymaster::V4_0::test::keymaster =
|
|
android::hardware::keymaster::V4_0::test::KeymasterWrapper::newInstance(service_name);
|
|
if (!android::hardware::keymaster::V4_0::test::keymaster) {
|
|
return 1;
|
|
}
|
|
::benchmark::RunSpecifiedBenchmarks();
|
|
} |