secure-element to AIDL
Bug: 205762050
Test: atest VtsHalSecureElementTargetTest (8/8 passed)
Test: atest CtsOmapiTestCases
- all tests pass except testStatusWordTransmit,
testTransmitApdu, and testSelectNext. This is because
these tests don't increase coverage of the HAL API
except they call 'transmit' several times. Doing a full
mock OMAPI/APDU implementation for cuttlefish/AOSP is
tracked in b/123254068
Change-Id: I0ec0eb08fbcc4207d8c07427ccdf7ff106995627
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 7110ac0..6a1a426 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -609,6 +609,15 @@
</interface>
</hal>
<hal format="aidl" optional="true">
+ <name>android.hardware.secure_element</name>
+ <version>1</version>
+ <interface>
+ <name>ISecureElement</name>
+ <regex-instance>eSE[1-9][0-9]*</regex-instance>
+ <regex-instance>SIM[1-9][0-9]*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.security.secureclock</name>
<version>1</version>
<interface>
diff --git a/secure_element/aidl/Android.bp b/secure_element/aidl/Android.bp
new file mode 100644
index 0000000..5a529a4
--- /dev/null
+++ b/secure_element/aidl/Android.bp
@@ -0,0 +1,35 @@
+aidl_interface {
+ name: "android.hardware.secure_element",
+ vendor_available: true,
+ host_supported: true,
+ srcs: ["android/hardware/secure_element/*.aidl"],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "system_current",
+ },
+ },
+}
+
+cc_test {
+ name: "VtsHalSecureElementTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["vts/VtsHalSecureElementTargetTest.cpp"],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ static_libs: [
+ "android.hardware.secure_element-V1-ndk",
+ "libgmock",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElement.aidl b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElement.aidl
new file mode 100644
index 0000000..fba29ab
--- /dev/null
+++ b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElement.aidl
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.secure_element;
+@VintfStability
+interface ISecureElement {
+ void closeChannel(in byte channelNumber);
+ byte[] getAtr();
+ void init(in android.hardware.secure_element.ISecureElementCallback clientCallback);
+ boolean isCardPresent();
+ byte[] openBasicChannel(in byte[] aid, in byte p2);
+ android.hardware.secure_element.LogicalChannelResponse openLogicalChannel(in byte[] aid, in byte p2);
+ void reset();
+ byte[] transmit(in byte[] data);
+ const int FAILED = 1;
+ const int CHANNEL_NOT_AVAILABLE = 2;
+ const int NO_SUCH_ELEMENT_ERROR = 3;
+ const int UNSUPPORTED_OPERATION = 4;
+ const int IOERROR = 5;
+}
diff --git a/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElementCallback.aidl b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElementCallback.aidl
new file mode 100644
index 0000000..6c2be2a
--- /dev/null
+++ b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElementCallback.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.secure_element;
+@VintfStability
+interface ISecureElementCallback {
+ void onStateChange(in boolean connected, in String debugReason);
+}
diff --git a/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/LogicalChannelResponse.aidl b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/LogicalChannelResponse.aidl
new file mode 100644
index 0000000..f2e7f04
--- /dev/null
+++ b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/LogicalChannelResponse.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.secure_element;
+@VintfStability
+parcelable LogicalChannelResponse {
+ byte channelNumber;
+ byte[] selectResponse;
+}
diff --git a/secure_element/aidl/android/hardware/secure_element/ISecureElement.aidl b/secure_element/aidl/android/hardware/secure_element/ISecureElement.aidl
new file mode 100644
index 0000000..7c5a704
--- /dev/null
+++ b/secure_element/aidl/android/hardware/secure_element/ISecureElement.aidl
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ */
+
+package android.hardware.secure_element;
+
+import android.hardware.secure_element.ISecureElementCallback;
+import android.hardware.secure_element.LogicalChannelResponse;
+
+@VintfStability
+interface ISecureElement {
+ const int FAILED = 1;
+ const int CHANNEL_NOT_AVAILABLE = 2;
+ const int NO_SUCH_ELEMENT_ERROR = 3;
+ const int UNSUPPORTED_OPERATION = 4;
+ const int IOERROR = 5;
+
+ /**
+ * Closes the channel indicated by the channelNumber.
+ *
+ * @throws ServiceSpecificException Closing a channel must return
+ * FAILED on an error or if a basic channel (i.e. channel 0)
+ * is used.
+ *
+ * @param channelNumber to be closed
+ */
+ void closeChannel(in byte channelNumber);
+
+ /**
+ * Returns Answer to Reset as per ISO/IEC 7816
+ *
+ * @return containing the response. Empty vector if Secure Element
+ * doesn't support ATR.
+ */
+ byte[] getAtr();
+
+ /**
+ * Initializes the Secure Element. This may include updating the applet
+ * and/or vendor-specific initialization.
+ *
+ * HAL service must send onStateChange() with connected equal to true
+ * after all the initialization has been successfully completed.
+ * Clients must wait for a onStateChange(true) before opening channels.
+ *
+ * @param clientCallback callback used to sent status of the SE back to the
+ * client
+ */
+ void init(in ISecureElementCallback clientCallback);
+
+ /**
+ * Returns the current state of the card.
+ *
+ * This is useful for removable Secure Elements like UICC,
+ * Secure Elements on SD cards etc.
+ *
+ * @return true if present, false otherwise
+ */
+ boolean isCardPresent();
+
+ /**
+ * Opens a basic channel with the Secure Element, selecting the applet
+ * represented by the Application ID (AID). A basic channel has channel
+ * number 0.
+ *
+ * @throws ServiceSpecificException with codes
+ * - CHANNEL_NOT_AVAILABLE if secure element has reached the maximum
+ * limit on the number of channels it can support.
+ * - NO_SUCH_ELEMENT_ERROR if AID provided doesn't match any applet
+ * on the secure element.
+ * - UNSUPPORTED_OPERATION if operation provided by the P2 parameter
+ * is not permitted by the applet.
+ * - IOERROR if there was an error communicating with the Secure Element.
+ *
+ * @param aid AID to uniquely identify the applet on the Secure Element
+ * @param p2 P2 parameter of SELECT APDU as per ISO 7816-4
+ *
+ * @return On success, response to SELECT command.
+ */
+ byte[] openBasicChannel(in byte[] aid, in byte p2);
+
+ /**
+ * Opens a logical channel with the Secure Element, selecting the applet
+ * represented by the Application ID (AID).
+ *
+ * @param aid AID to uniquely identify the applet on the Secure Element
+ * @param p2 P2 parameter of SELECT APDU as per ISO 7816-4
+ * @throws ServiceSpecificException on error with the following code:
+ * - CHANNEL_NOT_AVAILABLE if secure element has reached the maximum
+ * limit on the number of channels it can support.
+ * - NO_SUCH_ELEMENT_ERROR if AID provided doesn't match any applet
+ * on the secure element.
+ * - UNSUPPORTED_OPERATION if operation provided by the P2 parameter
+ * is not permitted by the applet.
+ * - IOERROR if there was an error communicating with the Secure Element.
+ *
+ * @return On success, response to SELECT command
+ */
+ LogicalChannelResponse openLogicalChannel(in byte[] aid, in byte p2);
+
+ /**
+ * Reset the Secure Element.
+ *
+ * HAL should trigger reset to the secure element. It could hardware power cycle or
+ * a soft reset depends on the hardware design.
+ * HAL service must send onStateChange() with connected equal to true
+ * after resetting and all the re-initialization has been successfully completed.
+ */
+ void reset();
+
+ /**
+ * Transmits an APDU command (as per ISO/IEC 7816) to the SE.
+ *
+ * @param data APDU command to be sent
+ * @return response to the command
+ */
+ byte[] transmit(in byte[] data);
+}
diff --git a/secure_element/aidl/android/hardware/secure_element/ISecureElementCallback.aidl b/secure_element/aidl/android/hardware/secure_element/ISecureElementCallback.aidl
new file mode 100644
index 0000000..d15a7fb
--- /dev/null
+++ b/secure_element/aidl/android/hardware/secure_element/ISecureElementCallback.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+package android.hardware.secure_element;
+
+@VintfStability
+interface ISecureElementCallback {
+ /**
+ * Used to inform the client about changes in the state of the Secure
+ * Element.
+ *
+ * @param connected indicates the current state of the SE
+ * @param reason provides additional data why there was a change in state
+ * ex. initialization error, SE removed etc
+ * This is used only for debugging purpose to understand
+ * in-field issues.
+ */
+ void onStateChange(in boolean connected, in String debugReason);
+}
diff --git a/secure_element/aidl/android/hardware/secure_element/LogicalChannelResponse.aidl b/secure_element/aidl/android/hardware/secure_element/LogicalChannelResponse.aidl
new file mode 100644
index 0000000..65ea71e
--- /dev/null
+++ b/secure_element/aidl/android/hardware/secure_element/LogicalChannelResponse.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package android.hardware.secure_element;
+
+@VintfStability
+parcelable LogicalChannelResponse {
+ /**
+ * Channel number to uniquely identify the channel
+ */
+ byte channelNumber;
+ /**
+ * Response to SELECT command as per ISO/IEC 7816
+ */
+ byte[] selectResponse;
+}
diff --git a/secure_element/aidl/default/Android.bp b/secure_element/aidl/default/Android.bp
new file mode 100644
index 0000000..c604b68
--- /dev/null
+++ b/secure_element/aidl/default/Android.bp
@@ -0,0 +1,15 @@
+cc_binary {
+ name: "android.hardware.secure_element-service.example",
+ relative_install_path: "hw",
+ vendor: true,
+ init_rc: ["secure_element.rc"],
+ vintf_fragments: ["secure_element.xml"],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "android.hardware.secure_element-V1-ndk",
+ ],
+ srcs: [
+ "main.cpp",
+ ],
+}
diff --git a/secure_element/aidl/default/main.cpp b/secure_element/aidl/default/main.cpp
new file mode 100644
index 0000000..16b8236
--- /dev/null
+++ b/secure_element/aidl/default/main.cpp
@@ -0,0 +1,159 @@
+/*
+ * 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/android/hardware/secure_element/BnSecureElement.h>
+
+#include <android-base/hex.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::secure_element::BnSecureElement;
+using aidl::android::hardware::secure_element::ISecureElementCallback;
+using aidl::android::hardware::secure_element::LogicalChannelResponse;
+using android::base::HexString;
+using ndk::ScopedAStatus;
+
+static const std::vector<uint8_t> kAndroidTestAid = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41,
+ 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64,
+ 0x43, 0x54, 0x53, 0x31};
+static const std::vector<uint8_t> kLongAndroidTestAid = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41,
+ 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64,
+ 0x43, 0x54, 0x53, 0x32};
+
+class MySecureElement : public BnSecureElement {
+ public:
+ ScopedAStatus closeChannel(int8_t channelNumber) override {
+ LOG(INFO) << __func__ << " channel number: " << channelNumber;
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus getAtr(std::vector<uint8_t>* _aidl_return) override {
+ LOG(INFO) << __func__;
+ _aidl_return->clear();
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus init(const std::shared_ptr<ISecureElementCallback>& clientCallback) override {
+ LOG(INFO) << __func__ << " callback: " << clientCallback.get();
+ if (!clientCallback) {
+ return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+ }
+ mCb = clientCallback;
+ mCb->onStateChange(true, "");
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus isCardPresent(bool* _aidl_return) override {
+ LOG(INFO) << __func__;
+ *_aidl_return = true;
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus openBasicChannel(const std::vector<uint8_t>& aid, int8_t p2,
+ std::vector<uint8_t>* _aidl_return) override {
+ LOG(INFO) << __func__ << " aid: " << HexString(aid.data(), aid.size()) << " (" << aid.size()
+ << ") p2 " << p2;
+
+ // TODO(b/123254068) - this is not an implementation of the OMAPI protocol or APDU.
+ // The functionality here is enough to exercise the framework, but actual
+ // calls to the secure element will fail. This implementation does not model
+ // channel isolation or any other aspects important to implementing secure element.
+ *_aidl_return = {0x90, 0x00, 0x00}; // DO NOT COPY
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus openLogicalChannel(
+ const std::vector<uint8_t>& aid, int8_t p2,
+ ::aidl::android::hardware::secure_element::LogicalChannelResponse* _aidl_return)
+ override {
+ LOG(INFO) << __func__ << " aid: " << HexString(aid.data(), aid.size()) << " (" << aid.size()
+ << ") p2 " << p2;
+
+ if (aid != kAndroidTestAid && aid != kLongAndroidTestAid) {
+ return ScopedAStatus::fromServiceSpecificError(NO_SUCH_ELEMENT_ERROR);
+ }
+
+ *_aidl_return = LogicalChannelResponse{.channelNumber = 1, .selectResponse = {}};
+
+ // TODO(b/123254068) - this is not an implementation of the OMAPI protocol or APDU.
+ // The functionality here is enough to exercise the framework, but actual
+ // calls to the secure element will fail. This implementation does not model
+ // channel isolation or any other aspects important to implementing secure element.
+ if (aid == kAndroidTestAid) { // DO NOT COPY
+ size_t size = 2050; // DO NOT COPY
+ _aidl_return->selectResponse.resize(size); // DO NOT COPY
+ _aidl_return->selectResponse[size - 1] = 0x00; // DO NOT COPY
+ _aidl_return->selectResponse[size - 2] = 0x90; // DO NOT COPY
+ } else { // DO NOT COPY
+ _aidl_return->selectResponse = {0x00, 0x00, 0x90, 0x00}; // DO NOT COPY
+ } // DO NOT COPY
+
+ LOG(INFO) << __func__ << " sending response: "
+ << HexString(_aidl_return->selectResponse.data(),
+ _aidl_return->selectResponse.size());
+
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus reset() override {
+ LOG(INFO) << __func__;
+ mCb->onStateChange(false, "reset");
+ mCb->onStateChange(true, "reset");
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus transmit(const std::vector<uint8_t>& data,
+ std::vector<uint8_t>* _aidl_return) override {
+ LOG(INFO) << __func__ << " data: " << HexString(data.data(), data.size()) << " ("
+ << data.size() << ")";
+
+ // TODO(b/123254068) - this is not an implementation of the OMAPI protocol or APDU.
+ // The functionality here is enough to exercise the framework, but actual
+ // calls to the secure element will fail. This implementation does not model
+ // channel isolation or any other aspects important to implementing secure element.
+
+ std::string hex = HexString(data.data(), data.size()); // DO NOT COPY
+ if (hex == "01a4040210a000000476416e64726f696443545331") { // DO NOT COPY
+ *_aidl_return = {0x00, 0x6A, 0x00}; // DO NOT COPY
+ } else if (data == std::vector<uint8_t>{0x00, 0xF4, 0x00, 0x00, 0x00}) { // DO NOT COPY
+ // CHECK_SELECT_P2_APDU w/ channel 1 // DO NOT COPY
+ *_aidl_return = {0x00, 0x90, 0x00}; // DO NOT COPY
+ } else if (data == std::vector<uint8_t>{0x01, 0xF4, 0x00, 0x00, 0x00}) { // DO NOT COPY
+ // CHECK_SELECT_P2_APDU w/ channel 1 // DO NOT COPY
+ *_aidl_return = {0x00, 0x90, 0x00}; // DO NOT COPY
+ } else if (data.size() == 5 || data.size() == 8) { // DO NOT COPY
+ // SEGMENTED_RESP_APDU - happens to use length 5 and 8 // DO NOT COPY
+ size_t size = (data[2] << 8 | data[3]) + 2; // DO NOT COPY
+ _aidl_return->resize(size); // DO NOT COPY
+ (*_aidl_return)[size - 1] = 0x00; // DO NOT COPY
+ (*_aidl_return)[size - 2] = 0x90; // DO NOT COPY
+ if (size >= 3) (*_aidl_return)[size - 3] = 0xFF; // DO NOT COPY
+ } else { // DO NOT COPY
+ *_aidl_return = {0x90, 0x00, 0x00}; // DO NOT COPY
+ } // DO NOT COPY
+
+ return ScopedAStatus::ok();
+ }
+
+ private:
+ std::shared_ptr<ISecureElementCallback> mCb;
+};
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+ auto se = ndk::SharedRefBase::make<MySecureElement>();
+ const std::string name = std::string() + BnSecureElement::descriptor + "/eSE1";
+ binder_status_t status = AServiceManager_addService(se->asBinder().get(), name.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/secure_element/aidl/default/secure_element.rc b/secure_element/aidl/default/secure_element.rc
new file mode 100644
index 0000000..7d21666
--- /dev/null
+++ b/secure_element/aidl/default/secure_element.rc
@@ -0,0 +1,4 @@
+service vendor.secure_element /vendor/bin/hw/android.hardware.secure_element-service.example
+ class hal
+ user nobody
+ group nobody
diff --git a/secure_element/aidl/default/secure_element.xml b/secure_element/aidl/default/secure_element.xml
new file mode 100644
index 0000000..96ab2e7
--- /dev/null
+++ b/secure_element/aidl/default/secure_element.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.secure_element</name>
+ <version>1</version>
+ <fqname>ISecureElement/eSE1</fqname>
+ </hal>
+</manifest>
diff --git a/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp b/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
new file mode 100644
index 0000000..a85a8bc
--- /dev/null
+++ b/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
@@ -0,0 +1,176 @@
+/*
+ * 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/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)
+
+static const std::vector<uint8_t> kDataApdu = {0x00, 0x08, 0x00, 0x00, 0x00};
+static const std::vector<uint8_t> 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<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:
+ virtual void SetUp() override {
+ SpAIBinder binder = SpAIBinder(AServiceManager_waitForService(GetParam().c_str()));
+ se = ISecureElement::fromBinder(binder);
+ ASSERT_NE(se, nullptr);
+
+ cb = SharedRefBase::make<MySecureElementCallback>();
+ EXPECT_OK(se->init(cb));
+
+ cb->expectCallbackHistory({true});
+ }
+
+ std::shared_ptr<ISecureElement> se;
+ std::shared_ptr<MySecureElementCallback> 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<uint8_t> command = kDataApdu;
+ command[0] |= response.channelNumber;
+
+ std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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();
+}