Files
hardware_interfaces/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
Henri Chataing 4b780ebe46 secure_element: Fix the expectation for closeChannel in VTS tests
The AIDL interface states that closeChannel must return FAILED
if the channel is not opened. The default AIDL implementation
did not respect this requirement either.

Bug: 266384111
Test: m VtsHalSecureElementTargetTest
Change-Id: I3e7142e6bbeb9d79cea2c109689da59c0615167a
2023-02-02 16:20:42 +00:00

280 lines
10 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.
*/
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/secure_element/BnSecureElementCallback.h>
#include <aidl/android/hardware/secure_element/ISecureElement.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <chrono>
#include <condition_variable>
#include <mutex>
using namespace std::chrono_literals;
using aidl::android::hardware::secure_element::BnSecureElementCallback;
using aidl::android::hardware::secure_element::ISecureElement;
using aidl::android::hardware::secure_element::LogicalChannelResponse;
using ndk::ScopedAStatus;
using ndk::SharedRefBase;
using ndk::SpAIBinder;
using testing::ElementsAre;
using testing::ElementsAreArray;
#define EXPECT_OK(status) \
do { \
auto status_impl = (status); \
EXPECT_TRUE(status_impl.isOk()) << status_impl.getDescription(); \
} while (false)
#define EXPECT_ERR(status) \
do { \
auto status_impl = (status); \
EXPECT_FALSE(status_impl.isOk()) << status_impl.getDescription(); \
} while (false)
// APDU defined in CTS tests.
// The applet selected with kSelectableAid will return 256 bytes of data
// in response.
static const std::vector<uint8_t> kDataApdu = {
0x00, 0x08, 0x00, 0x00, 0x00,
};
// Selectable test AID defined in CTS tests.
static const std::vector<uint8_t> kSelectableAid = {
0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x31,
};
// Non-selectable test AID defined in CTS tests.
static const std::vector<uint8_t> kNonSelectableAid = {
0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0xFF,
};
class MySecureElementCallback : public BnSecureElementCallback {
public:
ScopedAStatus onStateChange(bool state, const std::string& debugReason) override {
{
std::unique_lock<std::mutex> l(m);
(void)debugReason;
history.push_back(state);
}
cv.notify_one();
return ScopedAStatus::ok();
};
void expectCallbackHistory(std::vector<bool>&& want) {
std::unique_lock<std::mutex> l(m);
cv.wait_for(l, 2s, [&]() { return history.size() >= want.size(); });
EXPECT_THAT(history, ElementsAreArray(want));
}
private:
std::mutex m; // guards history
std::condition_variable cv;
std::vector<bool> history;
};
class SecureElementAidl : public ::testing::TestWithParam<std::string> {
public:
void SetUp() override {
SpAIBinder binder = SpAIBinder(AServiceManager_waitForService(GetParam().c_str()));
secure_element_ = ISecureElement::fromBinder(binder);
ASSERT_NE(secure_element_, nullptr);
secure_element_callback_ = SharedRefBase::make<MySecureElementCallback>();
ASSERT_NE(secure_element_callback_, nullptr);
EXPECT_OK(secure_element_->init(secure_element_callback_));
secure_element_callback_->expectCallbackHistory({true});
}
void TearDown() override {
EXPECT_OK(secure_element_->reset());
secure_element_ = nullptr;
secure_element_callback_ = nullptr;
}
// Call transmit with kDataApdu and the selected channel number.
// Return the response sstatus code.
uint16_t transmit(uint8_t channel_number) {
std::vector<uint8_t> apdu = kDataApdu;
std::vector<uint8_t> response;
// Edit the channel number into the CLA header byte.
if (channel_number < 4) {
apdu[0] |= channel_number;
} else {
apdu[0] |= (channel_number - 4) | 0x40;
}
EXPECT_OK(secure_element_->transmit(apdu, &response));
EXPECT_GE(response.size(), 2u);
uint16_t status =
(response[response.size() - 2] << 8) | (response[response.size() - 1] << 0);
// When the command is successful the response
// must contain 256 bytes of data.
if (status == 0x9000) {
EXPECT_EQ(response.size(), 258);
}
return status;
}
std::shared_ptr<ISecureElement> secure_element_;
std::shared_ptr<MySecureElementCallback> secure_element_callback_;
};
TEST_P(SecureElementAidl, init) {
// init(nullptr) shall fail.
EXPECT_ERR(secure_element_->init(nullptr));
// init with a valid callback pointer shall succeed.
EXPECT_OK(secure_element_->init(secure_element_callback_));
secure_element_callback_->expectCallbackHistory({true, true});
}
TEST_P(SecureElementAidl, reset) {
std::vector<uint8_t> basic_channel_response;
LogicalChannelResponse logical_channel_response;
// reset called after init shall succeed.
EXPECT_OK(secure_element_->openBasicChannel(kSelectableAid, 0x00, &basic_channel_response));
EXPECT_OK(secure_element_->openLogicalChannel(kSelectableAid, 0x00, &logical_channel_response));
EXPECT_OK(secure_element_->reset());
secure_element_callback_->expectCallbackHistory({true, false, true});
// All opened channels must be closed.
EXPECT_NE(transmit(0), 0x9000);
EXPECT_NE(transmit(logical_channel_response.channelNumber), 0x9000);
}
TEST_P(SecureElementAidl, isCardPresent) {
bool res = false;
// isCardPresent called after init shall succeed.
EXPECT_OK(secure_element_->isCardPresent(&res));
EXPECT_TRUE(res);
}
TEST_P(SecureElementAidl, getAtr) {
std::vector<uint8_t> atr;
// getAtr called after init shall succeed.
// The ATR has size between 0 and 32 bytes.
EXPECT_OK(secure_element_->getAtr(&atr));
EXPECT_LE(atr.size(), 32u);
}
TEST_P(SecureElementAidl, openBasicChannel) {
std::vector<uint8_t> response;
// openBasicChannel called with an invalid AID shall fail.
EXPECT_ERR(secure_element_->openBasicChannel(kNonSelectableAid, 0x00, &response));
// openBasicChannel called after init shall succeed.
// The response size must be larger than 2 bytes as it includes the
// status code.
EXPECT_OK(secure_element_->openBasicChannel(kSelectableAid, 0x00, &response));
EXPECT_GE(response.size(), 2u);
// tramsmit called on the basic channel should succeed.
EXPECT_EQ(transmit(0), 0x9000);
// openBasicChannel called a second time shall fail.
// The basic channel can only be opened once.
EXPECT_ERR(secure_element_->openBasicChannel(kSelectableAid, 0x00, &response));
// openBasicChannel called after closing the basic channel shall succeed.
EXPECT_OK(secure_element_->closeChannel(0));
EXPECT_OK(secure_element_->openBasicChannel(kSelectableAid, 0x00, &response));
}
TEST_P(SecureElementAidl, openLogicalChannel) {
LogicalChannelResponse response;
// openLogicalChannel called with an invalid AID shall fail.
EXPECT_ERR(secure_element_->openLogicalChannel(kNonSelectableAid, 0x00, &response));
// openLogicalChannel called after init shall succeed.
// The response size must be larger than 2 bytes as it includes the
// status code. The channel number must be in the range 1-19.
EXPECT_OK(secure_element_->openLogicalChannel(kSelectableAid, 0x00, &response));
EXPECT_GE(response.selectResponse.size(), 2u);
EXPECT_GE(response.channelNumber, 1u);
EXPECT_LE(response.channelNumber, 19u);
// tramsmit called on the logical channel should succeed.
EXPECT_EQ(transmit(response.channelNumber), 0x9000);
}
TEST_P(SecureElementAidl, closeChannel) {
std::vector<uint8_t> basic_channel_response;
LogicalChannelResponse logical_channel_response;
// closeChannel called on non-existing basic or logical channel
// shall fail.
EXPECT_ERR(secure_element_->closeChannel(0));
EXPECT_ERR(secure_element_->closeChannel(1));
// closeChannel called on basic channel closes the basic channel.
EXPECT_OK(secure_element_->openBasicChannel(kSelectableAid, 0x00, &basic_channel_response));
EXPECT_OK(secure_element_->closeChannel(0));
// tramsmit called on the basic channel should fail.
EXPECT_NE(transmit(0), 0x9000);
// closeChannel called on logical channel closes the logical channel.
EXPECT_OK(secure_element_->openLogicalChannel(kSelectableAid, 0x00, &logical_channel_response));
EXPECT_OK(secure_element_->closeChannel(logical_channel_response.channelNumber));
// tramsmit called on the basic channel should fail.
EXPECT_NE(transmit(logical_channel_response.channelNumber), 0x9000);
}
TEST_P(SecureElementAidl, transmit) {
std::vector<uint8_t> response;
// transmit called after init shall succeed.
// Note: no channel is opened for this test and the transmit
// response will have the status SW_LOGICAL_CHANNEL_NOT_SUPPORTED.
// The transmit response shall be larger than 2 bytes as it includes the
// status code.
EXPECT_OK(secure_element_->transmit(kDataApdu, &response));
EXPECT_GE(response.size(), 2u);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SecureElementAidl);
INSTANTIATE_TEST_SUITE_P(
SecureElement, SecureElementAidl,
testing::ValuesIn(android::getAidlHalInstanceNames(ISecureElement::descriptor)),
android::PrintInstanceNameToString);
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
ABinderProcess_setThreadPoolMaxThreadCount(1);
ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
}