/* * Copyright (C) 2018 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 "secure_element_hidl_hal_test" #include #include #include #include #include #include #include #include using ::android::hardware::secure_element::V1_0::ISecureElement; using ::android::hardware::secure_element::V1_0::ISecureElementHalCallback; using ::android::hardware::secure_element::V1_0::SecureElementStatus; using ::android::hardware::secure_element::V1_0::LogicalChannelResponse; using ::android::hardware::Return; using ::android::hardware::Void; using ::android::sp; #define DATA_APDU \ { 0x00, 0x08, 0x00, 0x00, 0x00 } #define ANDROID_TEST_AID \ { \ 0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, \ 0x31 \ } constexpr char kCallbackNameOnStateChange[] = "onStateChange"; class SecureElementCallbackArgs { public: bool state_; }; class SecureElementHalCallback : public ::testing::VtsHalHidlTargetCallbackBase, public ISecureElementHalCallback { public: virtual ~SecureElementHalCallback() = default; Return onStateChange(bool state) override { SecureElementCallbackArgs args; args.state_ = state; NotifyFromCallback(kCallbackNameOnStateChange, args); return Void(); }; }; class SecureElementHidlTest : public ::testing::TestWithParam { public: virtual void SetUp() override { LOG(INFO) << "get service with name:" << GetParam(); se_ = ISecureElement::getService(GetParam()); ASSERT_NE(se_, nullptr); se_cb_ = new SecureElementHalCallback(); ASSERT_NE(se_cb_, nullptr); se_->init(se_cb_); auto res = se_cb_->WaitForCallback(kCallbackNameOnStateChange); EXPECT_TRUE(res.no_timeout); EXPECT_TRUE(res.args->state_); } sp se_; sp se_cb_; }; /* * isCardPresent: * Expects the card to be present */ TEST_P(SecureElementHidlTest, isCardPresent) { EXPECT_TRUE(se_->isCardPresent()); } /* * transmit: * Check status word in the response */ TEST_P(SecureElementHidlTest, transmit) { std::vector aid = ANDROID_TEST_AID; SecureElementStatus statusReturned; LogicalChannelResponse response; se_->openLogicalChannel( aid, 0x00, [&statusReturned, &response](LogicalChannelResponse channelResponse, SecureElementStatus status) { statusReturned = status; if (status == SecureElementStatus::SUCCESS) { response.channelNumber = channelResponse.channelNumber; response.selectResponse.resize(channelResponse.selectResponse.size()); for (size_t i = 0; i < channelResponse.selectResponse.size(); i++) { response.selectResponse[i] = channelResponse.selectResponse[i]; } } }); EXPECT_EQ(SecureElementStatus::SUCCESS, statusReturned); EXPECT_LE((unsigned int)2, response.selectResponse.size()); EXPECT_LE(1, response.channelNumber); std::vector command = DATA_APDU; command[0] |= response.channelNumber; std::vector transmitResponse; se_->transmit(command, [&transmitResponse](std::vector res) { transmitResponse.resize(res.size()); for (size_t i = 0; i < res.size(); i++) { transmitResponse[i] = res[i]; } }); EXPECT_LE((unsigned int)3, transmitResponse.size()); EXPECT_EQ(0x90, transmitResponse[transmitResponse.size() - 2]); EXPECT_EQ(0x00, transmitResponse[transmitResponse.size() - 1]); EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber)); } /* * OpenCloseBasicChannel: * If the secure element allows opening of basic channel: * open channel, check the length of selectResponse and close the channel */ TEST_P(SecureElementHidlTest, openBasicChannel) { std::vector aid = ANDROID_TEST_AID; SecureElementStatus statusReturned; std::vector response; se_->openBasicChannel(aid, 0x00, [&statusReturned, &response](std::vector selectResponse, SecureElementStatus status) { statusReturned = status; if (status == SecureElementStatus::SUCCESS) { response.resize(selectResponse.size()); for (size_t i = 0; i < selectResponse.size(); i++) { response[i] = selectResponse[i]; } } }); if (statusReturned == SecureElementStatus::SUCCESS) { EXPECT_LE((unsigned int)2, response.size()); se_->closeChannel(0); return; } EXPECT_EQ(SecureElementStatus::CHANNEL_NOT_AVAILABLE, statusReturned); } /* * GetATR */ TEST_P(SecureElementHidlTest, getAtr) { std::vector atr; se_->getAtr([&atr](std::vector atrReturned) { atr.resize(atrReturned.size()); for (size_t i = 0; i < atrReturned.size(); i++) { atr[i] = atrReturned[i]; } }); if (atr.size() == 0) { return; } EXPECT_GE((unsigned int)32, atr.size()); EXPECT_LE((unsigned int)1, atr.size()); } /* * OpenCloseLogicalChannel: * Open Channel * Check status * Close Channel */ TEST_P(SecureElementHidlTest, openCloseLogicalChannel) { std::vector aid = ANDROID_TEST_AID; SecureElementStatus statusReturned; LogicalChannelResponse response; se_->openLogicalChannel( aid, 0x00, [&statusReturned, &response](LogicalChannelResponse channelResponse, SecureElementStatus status) { statusReturned = status; if (status == SecureElementStatus::SUCCESS) { response.channelNumber = channelResponse.channelNumber; response.selectResponse.resize(channelResponse.selectResponse.size()); for (size_t i = 0; i < channelResponse.selectResponse.size(); i++) { response.selectResponse[i] = channelResponse.selectResponse[i]; } } }); EXPECT_EQ(SecureElementStatus::SUCCESS, statusReturned); EXPECT_LE((unsigned int)2, response.selectResponse.size()); EXPECT_LE(1, response.channelNumber); EXPECT_EQ(SecureElementStatus::SUCCESS, se_->closeChannel(response.channelNumber)); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SecureElementHidlTest); INSTANTIATE_TEST_SUITE_P( PerInstance, SecureElementHidlTest, testing::ValuesIn(android::hardware::getAllHalInstanceNames(ISecureElement::descriptor)), android::hardware::PrintInstanceNameToString);