Files
hardware_interfaces/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp
Prashant Patil 10f81a7ed2 Screen wakeup is added in VTS tests setup
VtsHalConfirmationUITargetTest need screen to be on in order to pass.
Hence device wakeup command is executed from VTS tests setup.

Bug: 332827323
Test: atest VtsHalConfirmationUITargetTest
Change-Id: I354cd33c6b48f7cf94433a4959ecfcb96f4a9da2
2024-04-16 17:06:42 +00:00

542 lines
23 KiB
C++

/*
* Copyright (C) 2022 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 "ConfirmationIOAidlHalTest"
#include <algorithm>
#include <condition_variable>
#include <future>
#include <iostream>
#include <memory>
#include <mutex>
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/confirmationui/BnConfirmationResultCallback.h>
#include <aidl/android/hardware/confirmationui/IConfirmationUI.h>
#include <aidl/android/hardware/confirmationui/TestModeCommands.h>
#include <aidl/android/hardware/confirmationui/UIOption.h>
#include <android-base/thread_annotations.h>
#include <android/hardware/confirmationui/support/confirmationui_utils.h>
#include <cutils/log.h>
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <cn-cbor/cn-cbor.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <android/binder_status.h>
static constexpr int TIMEOUT_PERIOD = 10;
namespace aidl::android::hardware::confirmationui::test {
using ::aidl::android::hardware::security::keymint::HardwareAuthenticatorType;
using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
using ::android::hardware::confirmationui::support::auth_token_key_t;
using ::android::hardware::confirmationui::support::ByteBufferProxy;
using ::android::hardware::confirmationui::support::HMac;
using ::android::hardware::confirmationui::support::hmac_t;
using ::android::hardware::confirmationui::support::hton;
using ::android::hardware::confirmationui::support::NullOr;
using std::shared_ptr;
using std::string;
using std::vector;
namespace {
const auth_token_key_t testKey(static_cast<uint8_t>(IConfirmationUI::TEST_KEY_BYTE));
class HMacImplementation {
public:
static NullOr<hmac_t> hmac256(const auth_token_key_t& key,
std::initializer_list<ByteBufferProxy> buffers) {
HMAC_CTX hmacCtx;
HMAC_CTX_init(&hmacCtx);
if (!HMAC_Init_ex(&hmacCtx, key.data(), key.size(), EVP_sha256(), nullptr)) {
return {};
}
for (auto& buffer : buffers) {
if (!HMAC_Update(&hmacCtx, buffer.data(), buffer.size())) {
return {};
}
}
hmac_t result;
if (!HMAC_Final(&hmacCtx, result.data(), nullptr)) {
return {};
}
return result;
}
};
using HMacer = HMac<HMacImplementation>;
template <typename... Data>
vector<uint8_t> testHMAC(const Data&... data) {
auto hmac = HMacer::hmac256(testKey, data...);
if (!hmac.isOk()) {
ADD_FAILURE() << "Failed to compute test hmac. This is a self-test error.";
return {};
}
vector<uint8_t> result(hmac.value().size());
std::copy(hmac.value().data(), hmac.value().data() + hmac.value().size(), result.data());
return result;
}
template <typename T>
auto toBytes(const T& v) -> const uint8_t (&)[sizeof(T)] {
return *reinterpret_cast<const uint8_t(*)[sizeof(T)]>(&v);
}
HardwareAuthToken makeTestToken(const TestModeCommands command, uint64_t timestamp = 0) {
HardwareAuthToken auth_token;
auth_token.challenge = static_cast<uint64_t>(command);
auth_token.userId = 0;
auth_token.authenticatorId = 0;
auth_token.authenticatorType = HardwareAuthenticatorType::NONE;
auth_token.timestamp = {static_cast<int64_t>(timestamp)};
// Canonical form of auth-token v0
// version (1 byte)
// challenge (8 bytes)
// user_id (8 bytes)
// authenticator_id (8 bytes)
// authenticator_type (4 bytes)
// timestamp (8 bytes)
// total 37 bytes
auth_token.mac = testHMAC("\0",
toBytes(auth_token.challenge), //
toBytes(auth_token.userId), //
toBytes(auth_token.authenticatorId), //
toBytes(hton(auth_token.authenticatorType)), //
toBytes(hton(auth_token.timestamp))); //
return auth_token;
}
#define DEBUG_CONFRIMATIONUI_UTILS_TEST
#ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST
std::ostream& hexdump(std::ostream& out, const uint8_t* data, size_t size) {
for (size_t i = 0; i < size; ++i) {
uint8_t byte = data[i];
out << std::hex << std::setw(2) << std::setfill('0') << (unsigned)byte;
switch (i & 0xf) {
case 0xf:
out << "\n";
break;
case 7:
out << " ";
break;
default:
out << " ";
break;
}
}
return out;
}
#endif
constexpr char hex_value[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9'
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F'
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f'
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
std::string hex2str(std::string a) {
std::string b;
size_t num = a.size() / 2;
b.resize(num);
for (size_t i = 0; i < num; i++) {
b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]);
}
return b;
}
int getReturnCode(const ::ndk::ScopedAStatus& result) {
if (result.isOk()) return IConfirmationUI::OK;
if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
return static_cast<int>(result.getServiceSpecificError());
}
return result.getStatus();
}
} // namespace
class ConfirmationUIAidlTest : public ::testing::TestWithParam<std::string> {
public:
void TearDown() override { confirmator_->abort(); }
void SetUp() override {
// Wake up the device in-case screen is off. b/332827323
int ret = system("input keyevent KEYCODE_WAKEUP");
if (ret != 0) {
ALOGE("Failed to run keyevent KEYCODE_WAKEUP command");
}
usleep(100000); // wait for 100ms to wake up the screen.
std::string name = GetParam();
ASSERT_TRUE(AServiceManager_isDeclared(name.c_str())) << name;
ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
ASSERT_NE(binder, nullptr);
confirmator_ = IConfirmationUI::fromBinder(binder);
ASSERT_NE(confirmator_, nullptr);
}
// Used as a mechanism to inform the test about data/event callback
inline void notify() {
std::unique_lock<std::mutex> lock(mtx_);
cv_.notify_one();
}
// Test code calls this function to wait for data/event callback
inline std::cv_status wait() {
std::unique_lock<std::mutex> lock(mtx_);
auto now = std::chrono::system_clock::now();
std::cv_status status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
return status;
}
protected:
shared_ptr<IConfirmationUI> confirmator_;
private:
// synchronization objects
std::mutex mtx_;
std::condition_variable cv_;
};
class ConfirmationTestCallback
: public ::aidl::android::hardware::confirmationui::BnConfirmationResultCallback {
public:
ConfirmationTestCallback(ConfirmationUIAidlTest& parent) : parent_(parent){};
virtual ~ConfirmationTestCallback() = default;
::ndk::ScopedAStatus result(int32_t err, const vector<uint8_t>& msg,
const vector<uint8_t>& confToken) override {
error_ = err;
formattedMessage_ = msg;
confirmationToken_ = confToken;
parent_.notify();
return ndk::ScopedAStatus::ok();
}
bool verifyConfirmationToken() {
static constexpr char confirmationPrefix[] = "confirmation token";
EXPECT_EQ(32U, confirmationToken_.size());
return 32U == confirmationToken_.size() &&
!memcmp(confirmationToken_.data(),
testHMAC(confirmationPrefix, formattedMessage_).data(), 32);
}
int error_;
vector<uint8_t> formattedMessage_;
vector<uint8_t> confirmationToken_;
private:
ConfirmationUIAidlTest& parent_;
};
struct CnCborDeleter {
void operator()(cn_cbor* ptr) { cn_cbor_free(ptr); }
};
typedef std::unique_ptr<cn_cbor, CnCborDeleter> CnCborPtr;
// Simulates the User taping Ok
TEST_P(ConfirmationUIAidlTest, UserOkTest) {
static constexpr char test_prompt[] = "Me first, gimme gimme!";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
// Simulate the user taping ok.
ASSERT_TRUE(confirmator_->deliverSecureInputEvent(makeTestToken(TestModeCommands::OK_EVENT))
.isOk());
// Wait for the callback.
EXPECT_EQ(std::cv_status::no_timeout, wait());
ASSERT_EQ(IConfirmationUI::OK, conf_cb->error_);
ASSERT_TRUE(conf_cb->verifyConfirmationToken());
cn_cbor_errback cn_cbor_error;
auto parsed_message = CnCborPtr(cn_cbor_decode(
conf_cb->formattedMessage_.data(), conf_cb->formattedMessage_.size(), &cn_cbor_error));
// is parsable CBOR
ASSERT_TRUE(parsed_message.get());
// is a map
ASSERT_EQ(CN_CBOR_MAP, parsed_message->type);
// the message must have exactly 2 key value pairs.
// cn_cbor holds 2*<no_of_pairs> in the length field
ASSERT_EQ(4, parsed_message->length);
// map has key "prompt"
auto prompt = cn_cbor_mapget_string(parsed_message.get(), "prompt");
ASSERT_TRUE(prompt);
ASSERT_EQ(CN_CBOR_TEXT, prompt->type);
ASSERT_EQ(22, prompt->length);
ASSERT_EQ(0, memcmp(test_prompt, prompt->v.str, 22));
// map has key "extra"
auto extra_out = cn_cbor_mapget_string(parsed_message.get(), "extra");
ASSERT_TRUE(extra_out);
ASSERT_EQ(CN_CBOR_BYTES, extra_out->type);
ASSERT_EQ(3, extra_out->length);
ASSERT_EQ(0, memcmp(test_extra, extra_out->v.bytes, 3));
}
// Initiates a confirmation prompt with a message that is too long
TEST_P(ConfirmationUIAidlTest, MessageTooLongTest) {
static constexpr uint8_t test_extra[IConfirmationUI::MAX_MESSAGE_SIZE] = {};
static constexpr char test_prompt[] = "D\'oh!";
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
ASSERT_EQ(IConfirmationUI::UI_ERROR_MESSAGE_TOO_LONG, getReturnCode(result));
}
// If the message gets very long some HAL implementations might fail even before the message
// reaches the trusted app implementation. But the HAL must still diagnose the correct error.
TEST_P(ConfirmationUIAidlTest, MessageWayTooLongTest) {
static constexpr uint8_t test_extra[(IConfirmationUI::MAX_MESSAGE_SIZE)*10] = {};
static constexpr char test_prompt[] = "D\'oh!";
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
ASSERT_EQ(IConfirmationUI::UI_ERROR_MESSAGE_TOO_LONG, getReturnCode(result));
}
// Simulates the User tapping the Cancel
TEST_P(ConfirmationUIAidlTest, UserCancelTest) {
static constexpr char test_prompt[] = "Me first, gimme gimme!";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
// Simulate the user taping ok.
ASSERT_TRUE(confirmator_->deliverSecureInputEvent(makeTestToken(TestModeCommands::CANCEL_EVENT))
.isOk());
// Wait for the callback.
EXPECT_EQ(std::cv_status::no_timeout, wait());
ASSERT_EQ(IConfirmationUI::CANCELED, conf_cb->error_);
ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
}
// Simulates the framework cancelling an ongoing prompt
TEST_P(ConfirmationUIAidlTest, AbortTest) {
static constexpr char test_prompt[] = "Me first, gimme gimme!";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
confirmator_->abort();
// Wait for the callback.
EXPECT_EQ(std::cv_status::no_timeout, wait());
ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
}
// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
// the design guidelines.
TEST_P(ConfirmationUIAidlTest, PortableMessageTest1) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
"WWWWWWWWWWWWWW";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
confirmator_->abort();
// Wait for the callback.
EXPECT_EQ(std::cv_status::no_timeout, wait());
ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
}
// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
// the design guidelines in magnified mode.
TEST_P(ConfirmationUIAidlTest, PortableMessageTest1Magnified) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
"WWWWWWWWWWWWWW";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_
->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
{UIOption::ACCESSIBILITY_MAGNIFIED})
.isOk());
confirmator_->abort();
// Wait for the callback.
EXPECT_EQ(std::cv_status::no_timeout, wait());
ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
}
// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
// required by the design guidelines.
TEST_P(ConfirmationUIAidlTest, PortableMessageTest2) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
"WWWWWWWWWWWW WWWWWWWWWWWW";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
confirmator_->abort();
// Wait for the callback.
EXPECT_EQ(std::cv_status::no_timeout, wait());
ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
}
// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
// required by the design guidelines in magnified mode.
TEST_P(ConfirmationUIAidlTest, PortableMessageTest2Magnified) {
static constexpr char test_prompt[] =
"WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
"WWWWWWWWWWWW WWWWWWWWWWWW";
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
ASSERT_TRUE(confirmator_
->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
{UIOption::ACCESSIBILITY_MAGNIFIED})
.isOk());
confirmator_->abort();
// Wait for the callback.
EXPECT_EQ(std::cv_status::no_timeout, wait());
ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
}
// Passing malformed UTF-8 to the confirmation UI
// This test passes a string that ends in the middle of a multibyte character
TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test1) {
static constexpr char test_prompt[] = {char(0xc0), 0};
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
}
// Passing malformed UTF-8 to the confirmation UI
// This test passes a string with a 5-byte character.
TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test2) {
static constexpr char test_prompt[] = {char(0xf8), char(0x82), char(0x82),
char(0x82), char(0x82), 0};
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
}
// Passing malformed UTF-8 to the confirmation UI
// This test passes a string with a 2-byte character followed by a stray non UTF-8 character.
TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test3) {
static constexpr char test_prompt[] = {char(0xc0), char(0x82), char(0x83), 0};
static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
shared_ptr<ConfirmationTestCallback> conf_cb =
::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
vector<uint8_t> extra(test_extra, test_extra + 3);
auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
}
// Test the implementation of HMAC SHA 256 against a golden blob.
TEST(ConfirmationUITestSelfTest, HMAC256SelfTest) {
const char key_str[32] = "keykeykeykeykeykeykeykeykeykeyk";
const uint8_t(&key)[32] = *reinterpret_cast<const uint8_t(*)[32]>(key_str);
auto expected = hex2str("2377fbcaa7fb3f6c20cfa1d9ebc60e9922cf58c909e25e300f3cb57f7805c886");
auto result = HMacer::hmac256(key, "value1", "value2", "value3");
#ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST
hexdump(std::cout, reinterpret_cast<const uint8_t*>(expected.data()), 32) << std::endl;
hexdump(std::cout, result.value().data(), 32) << std::endl;
#endif
ByteBufferProxy expected_bytes(expected);
ASSERT_TRUE(result.isOk());
ASSERT_EQ(expected, result.value());
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ConfirmationUIAidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, ConfirmationUIAidlTest,
testing::ValuesIn(::android::getAidlHalInstanceNames(IConfirmationUI::descriptor)),
::android::PrintInstanceNameToString);
} // namespace aidl::android::hardware::confirmationui::test
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
ABinderProcess_setThreadPoolMaxThreadCount(1);
ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
}