/* * 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 #include #include #include #include #include #include #include #include #include #include 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) static const std::vector kDataApdu = {0x00, 0x08, 0x00, 0x00, 0x00}; static const std::vector kAndroidTestAid = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x31}; class MySecureElementCallback : public BnSecureElementCallback { public: ScopedAStatus onStateChange(bool state, const std::string& debugReason) override { { std::unique_lock l(m); (void)debugReason; history.push_back(state); } cv.notify_one(); return ScopedAStatus::ok(); }; void expectCallbackHistory(std::vector&& want) { std::unique_lock 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 history; }; class SecureElementAidl : public ::testing::TestWithParam { public: virtual void SetUp() override { SpAIBinder binder = SpAIBinder(AServiceManager_waitForService(GetParam().c_str())); se = ISecureElement::fromBinder(binder); ASSERT_NE(se, nullptr); cb = SharedRefBase::make(); EXPECT_OK(se->init(cb)); cb->expectCallbackHistory({true}); } std::shared_ptr se; std::shared_ptr cb; }; TEST_P(SecureElementAidl, isCardPresent) { bool res = false; EXPECT_OK(se->isCardPresent(&res)); EXPECT_TRUE(res); } TEST_P(SecureElementAidl, transmit) { LogicalChannelResponse response; EXPECT_OK(se->openLogicalChannel(kAndroidTestAid, 0x00, &response)); EXPECT_GE(response.selectResponse.size(), 2u); EXPECT_GE(response.channelNumber, 1); std::vector command = kDataApdu; command[0] |= response.channelNumber; std::vector transmitResponse; EXPECT_OK(se->transmit(command, &transmitResponse)); EXPECT_LE(transmitResponse.size(), 3); EXPECT_GE(transmitResponse.size(), 2); EXPECT_EQ(transmitResponse[transmitResponse.size() - 1], 0x00); EXPECT_EQ(transmitResponse[transmitResponse.size() - 2], 0x90); EXPECT_OK(se->closeChannel(response.channelNumber)); } TEST_P(SecureElementAidl, openBasicChannel) { std::vector response; auto status = se->openBasicChannel(kAndroidTestAid, 0x00, &response); if (!status.isOk()) { EXPECT_EQ(status.getServiceSpecificError(), ISecureElement::CHANNEL_NOT_AVAILABLE) << status.getDescription(); return; } EXPECT_GE(response.size(), 2u); EXPECT_OK(se->closeChannel(0)); } TEST_P(SecureElementAidl, getAtr) { std::vector atr; EXPECT_OK(se->getAtr(&atr)); if (atr.size() == 0) { return; } EXPECT_LE(atr.size(), 32u); EXPECT_GE(atr.size(), 1u); } TEST_P(SecureElementAidl, openCloseLogicalChannel) { LogicalChannelResponse response; EXPECT_OK(se->openLogicalChannel(kAndroidTestAid, 0x00, &response)); EXPECT_GE(response.selectResponse.size(), 2u); EXPECT_GE(response.channelNumber, 1); EXPECT_OK(se->closeChannel(response.channelNumber)); } TEST_P(SecureElementAidl, openInvalidAid) { LogicalChannelResponse response; auto status = se->openLogicalChannel({0x42}, 0x00, &response); EXPECT_EQ(status.getServiceSpecificError(), ISecureElement::NO_SUCH_ELEMENT_ERROR) << status.getDescription(); } TEST_P(SecureElementAidl, Reset) { cb->expectCallbackHistory({true}); EXPECT_OK(se->reset()); cb->expectCallbackHistory({true, false, true}); } 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(); }