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
This commit is contained in:
parent
3777e1cb44
commit
6fe6954dd4
13 changed files with 722 additions and 0 deletions
|
@ -608,6 +608,15 @@
|
|||
<regex-instance>SIM[1-9][0-9]*</regex-instance>
|
||||
</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>
|
||||
|
|
35
secure_element/aidl/Android.bp
Normal file
35
secure_element/aidl/Android.bp
Normal file
|
@ -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",
|
||||
],
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
15
secure_element/aidl/default/Android.bp
Normal file
15
secure_element/aidl/default/Android.bp
Normal file
|
@ -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",
|
||||
],
|
||||
}
|
159
secure_element/aidl/default/main.cpp
Normal file
159
secure_element/aidl/default/main.cpp
Normal file
|
@ -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
|
||||
}
|
4
secure_element/aidl/default/secure_element.rc
Normal file
4
secure_element/aidl/default/secure_element.rc
Normal file
|
@ -0,0 +1,4 @@
|
|||
service vendor.secure_element /vendor/bin/hw/android.hardware.secure_element-service.example
|
||||
class hal
|
||||
user nobody
|
||||
group nobody
|
7
secure_element/aidl/default/secure_element.xml
Normal file
7
secure_element/aidl/default/secure_element.xml
Normal file
|
@ -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>
|
176
secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
Normal file
176
secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
Normal file
|
@ -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();
|
||||
}
|
Loading…
Reference in a new issue