summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2019-03-16 23:16:32 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2019-03-16 23:16:32 +0000
commitbfa84fa484d566a3a32751186d714748d5631e17 (patch)
tree1359627649e9e6060c7c97dc315aee10227a5598
parentf2580ed3eda8bcb9f5852631fba0c33da7d1a754 (diff)
parent52caef057413dca49b49c243ca9f6c9db5123673 (diff)
downloadsecure_element-bfa84fa484d566a3a32751186d714748d5631e17.tar.gz
Snap for 5381581 from 52caef057413dca49b49c243ca9f6c9db5123673 to qt-release
Change-Id: I13d34321d91b1df0dd3634575954055db9c143bd
-rwxr-xr-x1.0/SecureElement.cpp11
-rwxr-xr-x1.0/SecureElement.h3
-rwxr-xr-x1.1/NxpEseService.cpp60
-rwxr-xr-x1.1/SecureElement.cpp503
-rwxr-xr-x1.1/SecureElement.h89
-rw-r--r--1.1/android.hardware.secure_element@1.1-service-disabled.rc5
-rw-r--r--1.1/android.hardware.secure_element@1.1-service.rc5
-rwxr-xr-xAndroid.bp43
-rwxr-xr-xls_client/inc/LsClient.h25
-rwxr-xr-xls_client/inc/LsLib.h11
-rwxr-xr-xls_client/src/LsClient.cpp197
-rwxr-xr-xls_client/src/LsLib.cpp54
12 files changed, 982 insertions, 24 deletions
diff --git a/1.0/SecureElement.cpp b/1.0/SecureElement.cpp
index 2ca4e7f..6a38a25 100755
--- a/1.0/SecureElement.cpp
+++ b/1.0/SecureElement.cpp
@@ -32,6 +32,10 @@ namespace implementation {
sp<V1_0::ISecureElementHalCallback> SecureElement::mCallbackV1_0 = nullptr;
+static void onLSCompleted(bool result, std::string reason, void* arg) {
+ ((SecureElement*)arg)->onStateChange(result, reason);
+}
+
SecureElement::SecureElement()
: mOpenedchannelCount(0),
mOpenedChannels{false, false, false, false} {}
@@ -61,7 +65,7 @@ Return<void> SecureElement::init(
return Void();
}
- LSCSTATUS lsStatus = LSC_doDownload(clientCallback);
+ LSCSTATUS lsStatus = LSC_doDownload(onLSCompleted, (void*)this);
/*
* LSC_doDownload returns LSCSTATUS_FAILED in case thread creation fails.
* So return callback as false.
@@ -439,6 +443,11 @@ SecureElement::seHalDeInit() {
return sestatus;
}
+void SecureElement::onStateChange(bool result, std::string reason) {
+ ALOGD("%s: result: %d, reaon= %s", __func__, result, reason.c_str());
+ mCallbackV1_0->onStateChange(result);
+}
+
} // namespace implementation
} // namespace V1_0
} // namespace secure_element
diff --git a/1.0/SecureElement.h b/1.0/SecureElement.h
index 6e5c4a7..a15028a 100755
--- a/1.0/SecureElement.h
+++ b/1.0/SecureElement.h
@@ -21,6 +21,8 @@
#include <android/hardware/secure_element/1.0/ISecureElement.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>
+#include <string>
+
#include "phNxpEse_Api.h"
namespace android {
@@ -61,6 +63,7 @@ struct SecureElement : public ISecureElement, public hidl_death_recipient {
Return<::android::hardware::secure_element::V1_0::SecureElementStatus>
closeChannel(uint8_t channelNumber) override;
void serviceDied(uint64_t /*cookie*/, const wp<IBase>& /*who*/) override;
+ void onStateChange(bool result, std::string reason);
private:
uint8_t mOpenedchannelCount = 0;
diff --git a/1.1/NxpEseService.cpp b/1.1/NxpEseService.cpp
new file mode 100755
index 0000000..595f11e
--- /dev/null
+++ b/1.1/NxpEseService.cpp
@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * Copyright 2018 NXP
+ *
+ * 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 "nxpese@1.0-service"
+#include <android/hardware/secure_element/1.1/ISecureElement.h>
+#include <hidl/LegacySupport.h>
+#include <log/log.h>
+#include <vendor/nxp/nxpese/1.0/INxpEse.h>
+
+#include "NxpEse.h"
+#include "SecureElement.h"
+
+// Generated HIDL files
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::secure_element::V1_1::ISecureElement;
+using android::hardware::secure_element::V1_1::implementation::SecureElement;
+using vendor::nxp::nxpese::V1_0::INxpEse;
+using vendor::nxp::nxpese::V1_0::implementation::NxpEse;
+
+int main() {
+ ALOGD("Secure Element HAL Service 1.1 is starting.");
+ sp<ISecureElement> se_service = new SecureElement();
+ configureRpcThreadpool(1, true /*callerWillJoin*/);
+ status_t status = se_service->registerAsService("eSE1");
+ if (status != OK) {
+ LOG_ALWAYS_FATAL(
+ "Could not register service for Secure Element HAL Iface (%d).",
+ status);
+ return -1;
+ }
+ sp<INxpEse> nxp_se_service = new NxpEse();
+ status = nxp_se_service->registerAsService();
+ if (status != OK) {
+ LOG_ALWAYS_FATAL(
+ "Could not register service for Power Secure Element Extn Iface (%d).",
+ status);
+ return -1;
+ }
+ ALOGD("Secure Element Service is ready");
+ joinRpcThreadpool();
+ return 1;
+}
diff --git a/1.1/SecureElement.cpp b/1.1/SecureElement.cpp
new file mode 100755
index 0000000..e04b8ba
--- /dev/null
+++ b/1.1/SecureElement.cpp
@@ -0,0 +1,503 @@
+/******************************************************************************
+ *
+ * Copyright 2018 NXP
+ *
+ * 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 "NxpEseHal"
+#include <log/log.h>
+
+#include "LsClient.h"
+#include "SecureElement.h"
+#include "phNxpEse_Api.h"
+
+extern bool ese_debug_enabled;
+
+namespace android {
+namespace hardware {
+namespace secure_element {
+namespace V1_1 {
+namespace implementation {
+
+sp<V1_0::ISecureElementHalCallback> SecureElement::mCallbackV1_0 = nullptr;
+sp<V1_1::ISecureElementHalCallback> SecureElement::mCallbackV1_1 = nullptr;
+
+static void onLSCompleted(bool result, std::string reason, void* arg) {
+ ((SecureElement*)arg)->onStateChange(result, reason);
+}
+
+SecureElement::SecureElement()
+ : mOpenedchannelCount(0), mOpenedChannels{false, false, false, false} {}
+
+Return<void> SecureElement::init(
+ const sp<V1_0::ISecureElementHalCallback>& clientCallback) {
+ ESESTATUS status = ESESTATUS_SUCCESS;
+
+ if (clientCallback == nullptr) {
+ return Void();
+ } else {
+ mCallbackV1_0 = clientCallback;
+ mCallbackV1_1 = nullptr;
+ if (!mCallbackV1_0->linkToDeath(this, 0 /*cookie*/)) {
+ ALOGE("%s: Failed to register death notification", __func__);
+ }
+ }
+ if (isSeInitialized()) {
+ clientCallback->onStateChange(true);
+ return Void();
+ }
+
+ status = seHalInit();
+ if (status != ESESTATUS_SUCCESS) {
+ clientCallback->onStateChange(false);
+ return Void();
+ }
+
+ LSCSTATUS lsStatus = LSC_doDownload(onLSCompleted, (void*)this);
+ /*
+ * LSC_doDownload returns LSCSTATUS_FAILED in case thread creation fails.
+ * So return callback as false.
+ * Otherwise callback will be called in LSDownload module.
+ */
+ if (lsStatus != LSCSTATUS_SUCCESS) {
+ ALOGE("%s: LSDownload thread creation failed!!!", __func__);
+ SecureElementStatus sestatus = seHalDeInit();
+ if (sestatus != SecureElementStatus::SUCCESS) {
+ ALOGE("%s: seHalDeInit failed!!!", __func__);
+ }
+ clientCallback->onStateChange(false);
+ }
+ return Void();
+}
+
+Return<void> SecureElement::init_1_1(
+ const sp<V1_1::ISecureElementHalCallback>& clientCallback) {
+ ESESTATUS status = ESESTATUS_SUCCESS;
+
+ if (clientCallback == nullptr) {
+ return Void();
+ } else {
+ mCallbackV1_1 = clientCallback;
+ mCallbackV1_0 = nullptr;
+ if (!mCallbackV1_1->linkToDeath(this, 0 /*cookie*/)) {
+ ALOGE("%s: Failed to register death notification", __func__);
+ }
+ }
+ if (isSeInitialized()) {
+ clientCallback->onStateChange_1_1(true, "NXP SE HAL init ok");
+ return Void();
+ }
+
+ status = seHalInit();
+ if (status != ESESTATUS_SUCCESS) {
+ clientCallback->onStateChange_1_1(false, "NXP SE HAL init failed");
+ return Void();
+ }
+
+ LSCSTATUS lsStatus = LSC_doDownload(onLSCompleted, (void*)this);
+ /*
+ * LSC_doDownload returns LSCSTATUS_FAILED in case thread creation fails.
+ * So return callback as false.
+ * Otherwise callback will be called in LSDownload module.
+ */
+ if (lsStatus != LSCSTATUS_SUCCESS) {
+ ALOGE("%s: LSDownload thread creation failed!!!", __func__);
+ SecureElementStatus sestatus = seHalDeInit();
+ if (sestatus != SecureElementStatus::SUCCESS) {
+ ALOGE("%s: seHalDeInit failed!!!", __func__);
+ }
+ clientCallback->onStateChange_1_1(false,
+ "Failed to create LS download thread");
+ }
+ return Void();
+}
+
+Return<void> SecureElement::getAtr(getAtr_cb _hidl_cb) {
+ hidl_vec<uint8_t> response;
+ _hidl_cb(response);
+ return Void();
+}
+
+Return<bool> SecureElement::isCardPresent() { return true; }
+
+Return<void> SecureElement::transmit(const hidl_vec<uint8_t>& data,
+ transmit_cb _hidl_cb) {
+ ESESTATUS status = ESESTATUS_FAILED;
+ phNxpEse_data cmdApdu;
+ phNxpEse_data rspApdu;
+ phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+ phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+
+ cmdApdu.len = data.size();
+ if (cmdApdu.len >= MIN_APDU_LENGTH) {
+ cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(data.size() * sizeof(uint8_t));
+ memcpy(cmdApdu.p_data, data.data(), cmdApdu.len);
+ status = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+ }
+
+ hidl_vec<uint8_t> result;
+ if (status != ESESTATUS_SUCCESS) {
+ ALOGE("%s: transmit failed!!!", __func__);
+ } else {
+ result.resize(rspApdu.len);
+ memcpy(&result[0], rspApdu.p_data, rspApdu.len);
+ }
+ _hidl_cb(result);
+ phNxpEse_free(cmdApdu.p_data);
+ phNxpEse_free(rspApdu.p_data);
+ return Void();
+}
+
+Return<void> SecureElement::openLogicalChannel(const hidl_vec<uint8_t>& aid,
+ uint8_t p2,
+ openLogicalChannel_cb _hidl_cb) {
+ hidl_vec<uint8_t> manageChannelCommand = {0x00, 0x70, 0x00, 0x00, 0x01};
+
+ LogicalChannelResponse resApduBuff;
+ resApduBuff.channelNumber = 0xff;
+ memset(&resApduBuff, 0x00, sizeof(resApduBuff));
+
+ if (!isSeInitialized()) {
+ ESESTATUS status = seHalInit();
+ if (status != ESESTATUS_SUCCESS) {
+ ALOGE("%s: seHalInit Failed!!!", __func__);
+ _hidl_cb(resApduBuff, SecureElementStatus::IOERROR);
+ return Void();
+ }
+ }
+
+ SecureElementStatus sestatus = SecureElementStatus::IOERROR;
+ ESESTATUS status = ESESTATUS_FAILED;
+ phNxpEse_data cmdApdu;
+ phNxpEse_data rspApdu;
+
+ phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+ phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+
+ cmdApdu.len = manageChannelCommand.size();
+ cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(manageChannelCommand.size() *
+ sizeof(uint8_t));
+ if (cmdApdu.p_data != NULL) {
+ memcpy(cmdApdu.p_data, manageChannelCommand.data(), cmdApdu.len);
+ status = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+ }
+ if (status != ESESTATUS_SUCCESS) {
+ /*Transceive failed*/
+ sestatus = SecureElementStatus::IOERROR;
+ } else if (rspApdu.p_data[rspApdu.len - 2] == 0x90 &&
+ rspApdu.p_data[rspApdu.len - 1] == 0x00) {
+ /*ManageChannel successful*/
+ resApduBuff.channelNumber = rspApdu.p_data[0];
+ mOpenedchannelCount++;
+ mOpenedChannels[resApduBuff.channelNumber] = true;
+ sestatus = SecureElementStatus::SUCCESS;
+ } else if (rspApdu.p_data[rspApdu.len - 2] == 0x6A &&
+ rspApdu.p_data[rspApdu.len - 1] == 0x81) {
+ sestatus = SecureElementStatus::CHANNEL_NOT_AVAILABLE;
+ } else if (((rspApdu.p_data[rspApdu.len - 2] == 0x6E) ||
+ (rspApdu.p_data[rspApdu.len - 2] == 0x6D)) &&
+ rspApdu.p_data[rspApdu.len - 1] == 0x00) {
+ sestatus = SecureElementStatus::UNSUPPORTED_OPERATION;
+ }
+
+ /*Free the allocations*/
+ phNxpEse_free(cmdApdu.p_data);
+ phNxpEse_free(rspApdu.p_data);
+
+ if (sestatus != SecureElementStatus::SUCCESS) {
+ /*If first logical channel open fails, DeInit SE*/
+ if (isSeInitialized() && (mOpenedchannelCount == 0)) {
+ SecureElementStatus deInitStatus = seHalDeInit();
+ if (deInitStatus != SecureElementStatus::SUCCESS) {
+ ALOGE("%s: seDeInit Failed", __func__);
+ }
+ }
+ /*If manageChanle is failed in any of above cases
+ send the callback and return*/
+ _hidl_cb(resApduBuff, sestatus);
+ return Void();
+ }
+
+ ALOGD_IF(ese_debug_enabled, "%s: Sending selectApdu", __func__);
+ /*Reset variables if manageChannel is success*/
+ sestatus = SecureElementStatus::IOERROR;
+ status = ESESTATUS_FAILED;
+
+ phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+ phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+
+ cmdApdu.len = (int32_t)(5 + aid.size());
+ cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
+ if (cmdApdu.p_data != NULL) {
+ uint8_t xx = 0;
+ cmdApdu.p_data[xx++] = resApduBuff.channelNumber;
+ cmdApdu.p_data[xx++] = 0xA4; // INS
+ cmdApdu.p_data[xx++] = 0x04; // P1
+ cmdApdu.p_data[xx++] = p2; // P2
+ cmdApdu.p_data[xx++] = aid.size(); // Lc
+ memcpy(&cmdApdu.p_data[xx], aid.data(), aid.size());
+
+ status = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+ }
+
+ if (status != ESESTATUS_SUCCESS) {
+ /*Transceive failed*/
+ sestatus = SecureElementStatus::IOERROR;
+ } else {
+ uint8_t sw1 = rspApdu.p_data[rspApdu.len - 2];
+ uint8_t sw2 = rspApdu.p_data[rspApdu.len - 1];
+ /*Return response on success, empty vector on failure*/
+ /*Status is success*/
+ if (sw1 == 0x90 && sw2 == 0x00) {
+ /*Copy the response including status word*/
+ resApduBuff.selectResponse.resize(rspApdu.len);
+ memcpy(&resApduBuff.selectResponse[0], rspApdu.p_data, rspApdu.len);
+ sestatus = SecureElementStatus::SUCCESS;
+ }
+ /*AID provided doesn't match any applet on the secure element*/
+ else if (sw1 == 0x6A && sw2 == 0x82) {
+ sestatus = SecureElementStatus::NO_SUCH_ELEMENT_ERROR;
+ }
+ /*Operation provided by the P2 parameter is not permitted by the applet.*/
+ else if (sw1 == 0x6A && sw2 == 0x86) {
+ sestatus = SecureElementStatus::UNSUPPORTED_OPERATION;
+ }
+ }
+
+ if (sestatus != SecureElementStatus::SUCCESS) {
+ SecureElementStatus closeChannelStatus =
+ closeChannel(resApduBuff.channelNumber);
+ if (closeChannelStatus != SecureElementStatus::SUCCESS) {
+ ALOGE("%s: closeChannel Failed", __func__);
+ } else {
+ resApduBuff.channelNumber = 0xff;
+ }
+ }
+ _hidl_cb(resApduBuff, sestatus);
+ phNxpEse_free(cmdApdu.p_data);
+ phNxpEse_free(rspApdu.p_data);
+
+ return Void();
+}
+
+Return<void> SecureElement::openBasicChannel(const hidl_vec<uint8_t>& aid,
+ uint8_t p2,
+ openBasicChannel_cb _hidl_cb) {
+ hidl_vec<uint8_t> result;
+
+ if (!isSeInitialized()) {
+ ESESTATUS status = seHalInit();
+ if (status != ESESTATUS_SUCCESS) {
+ ALOGE("%s: seHalInit Failed!!!", __func__);
+ _hidl_cb(result, SecureElementStatus::IOERROR);
+ return Void();
+ }
+ }
+
+ SecureElementStatus sestatus = SecureElementStatus::IOERROR;
+ ESESTATUS status = ESESTATUS_FAILED;
+ phNxpEse_data cmdApdu;
+ phNxpEse_data rspApdu;
+
+ phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+ phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+
+ cmdApdu.len = (int32_t)(5 + aid.size());
+ cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
+ if (cmdApdu.p_data != NULL) {
+ uint8_t xx = 0;
+ cmdApdu.p_data[xx++] = 0x00; // basic channel
+ cmdApdu.p_data[xx++] = 0xA4; // INS
+ cmdApdu.p_data[xx++] = 0x04; // P1
+ cmdApdu.p_data[xx++] = p2; // P2
+ cmdApdu.p_data[xx++] = aid.size(); // Lc
+ memcpy(&cmdApdu.p_data[xx], aid.data(), aid.size());
+
+ status = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+ }
+
+ if (status != ESESTATUS_SUCCESS) {
+ /* Transceive failed */
+ sestatus = SecureElementStatus::IOERROR;
+ } else {
+ uint8_t sw1 = rspApdu.p_data[rspApdu.len - 2];
+ uint8_t sw2 = rspApdu.p_data[rspApdu.len - 1];
+ /*Return response on success, empty vector on failure*/
+ /*Status is success*/
+ if ((sw1 == 0x90) && (sw2 == 0x00)) {
+ /*Copy the response including status word*/
+ result.resize(rspApdu.len);
+ memcpy(&result[0], rspApdu.p_data, rspApdu.len);
+ /*Set basic channel reference if it is not set */
+ if (!mOpenedChannels[0]) {
+ mOpenedChannels[0] = true;
+ mOpenedchannelCount++;
+ }
+ sestatus = SecureElementStatus::SUCCESS;
+ }
+ /*AID provided doesn't match any applet on the secure element*/
+ else if (sw1 == 0x6A && sw2 == 0x82) {
+ sestatus = SecureElementStatus::NO_SUCH_ELEMENT_ERROR;
+ }
+ /*Operation provided by the P2 parameter is not permitted by the applet.*/
+ else if (sw1 == 0x6A && sw2 == 0x86) {
+ sestatus = SecureElementStatus::UNSUPPORTED_OPERATION;
+ }
+ }
+
+ if (sestatus != SecureElementStatus::SUCCESS) {
+ SecureElementStatus closeStatus = SecureElementStatus::IOERROR;
+ /*If first basic channel open fails, DeInit SE*/
+ if ((mOpenedChannels[DEFAULT_BASIC_CHANNEL] == false) &&
+ (mOpenedchannelCount == 0)) {
+ closeStatus = seHalDeInit();
+ } else {
+ closeStatus = closeChannel(DEFAULT_BASIC_CHANNEL);
+ }
+ if (closeStatus != SecureElementStatus::SUCCESS) {
+ ALOGE("%s: close Failed", __func__);
+ }
+ }
+ _hidl_cb(result, sestatus);
+ phNxpEse_free(cmdApdu.p_data);
+ phNxpEse_free(rspApdu.p_data);
+ return Void();
+}
+
+Return<SecureElementStatus> SecureElement::closeChannel(uint8_t channelNumber) {
+ ESESTATUS status = ESESTATUS_FAILED;
+ SecureElementStatus sestatus = SecureElementStatus::FAILED;
+
+ phNxpEse_data cmdApdu;
+ phNxpEse_data rspApdu;
+
+ if ((channelNumber < DEFAULT_BASIC_CHANNEL) ||
+ (channelNumber >= MAX_LOGICAL_CHANNELS) ||
+ (mOpenedChannels[channelNumber] == false)) {
+ ALOGE("%s: invalid channel!!!", __func__);
+ sestatus = SecureElementStatus::FAILED;
+ } else if (channelNumber > DEFAULT_BASIC_CHANNEL) {
+ phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+ phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+ cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(5 * sizeof(uint8_t));
+ if (cmdApdu.p_data != NULL) {
+ uint8_t xx = 0;
+
+ cmdApdu.p_data[xx++] = channelNumber;
+ cmdApdu.p_data[xx++] = 0x70; // INS
+ cmdApdu.p_data[xx++] = 0x80; // P1
+ cmdApdu.p_data[xx++] = channelNumber; // P2
+ cmdApdu.p_data[xx++] = 0x00; // Lc
+ cmdApdu.len = xx;
+
+ status = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+ }
+ if (status != ESESTATUS_SUCCESS) {
+ sestatus = SecureElementStatus::FAILED;
+ } else if ((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
+ (rspApdu.p_data[rspApdu.len - 1] == 0x00)) {
+ sestatus = SecureElementStatus::SUCCESS;
+ } else {
+ sestatus = SecureElementStatus::FAILED;
+ }
+ phNxpEse_free(cmdApdu.p_data);
+ phNxpEse_free(rspApdu.p_data);
+ }
+
+ if ((channelNumber == DEFAULT_BASIC_CHANNEL) ||
+ (sestatus == SecureElementStatus::SUCCESS)) {
+ if (mOpenedChannels[channelNumber] != false) mOpenedchannelCount--;
+ mOpenedChannels[channelNumber] = false;
+ /*If there are no channels remaining close secureElement*/
+ if (mOpenedchannelCount == 0) {
+ sestatus = seHalDeInit();
+ } else {
+ sestatus = SecureElementStatus::SUCCESS;
+ }
+ }
+ return sestatus;
+}
+
+void SecureElement::serviceDied(uint64_t /*cookie*/, const wp<IBase>& /*who*/) {
+ ALOGE("%s: SecureElement serviceDied!!!", __func__);
+ SecureElementStatus sestatus = seHalDeInit();
+ if (sestatus != SecureElementStatus::SUCCESS) {
+ ALOGE("%s: seHalDeInit Faliled!!!", __func__);
+ }
+ if (mCallbackV1_0 != nullptr) {
+ mCallbackV1_0->unlinkToDeath(this);
+ mCallbackV1_0 = nullptr;
+ }
+ if (mCallbackV1_1 != nullptr) {
+ mCallbackV1_1->unlinkToDeath(this);
+ mCallbackV1_1 = nullptr;
+ }
+}
+
+bool SecureElement::isSeInitialized() { return phNxpEse_isOpen(); }
+
+ESESTATUS SecureElement::seHalInit() {
+ ESESTATUS status = ESESTATUS_SUCCESS;
+ phNxpEse_initParams initParams;
+ memset(&initParams, 0x00, sizeof(phNxpEse_initParams));
+ initParams.initMode = ESE_MODE_NORMAL;
+
+ status = phNxpEse_open(initParams);
+ if (status != ESESTATUS_SUCCESS) {
+ ALOGE("%s: SecureElement open failed!!!", __func__);
+ } else {
+ status = phNxpEse_init(initParams);
+ if (status != ESESTATUS_SUCCESS) {
+ ALOGE("%s: SecureElement init failed!!!", __func__);
+ }
+ }
+ return status;
+}
+
+Return<SecureElementStatus> SecureElement::seHalDeInit() {
+ ESESTATUS status = ESESTATUS_SUCCESS;
+ SecureElementStatus sestatus = SecureElementStatus::FAILED;
+ status = phNxpEse_deInit();
+ if (status != ESESTATUS_SUCCESS) {
+ sestatus = SecureElementStatus::FAILED;
+ } else {
+ status = phNxpEse_close();
+ if (status != ESESTATUS_SUCCESS) {
+ sestatus = SecureElementStatus::FAILED;
+ } else {
+ sestatus = SecureElementStatus::SUCCESS;
+
+ for (uint8_t xx = 0; xx < MAX_LOGICAL_CHANNELS; xx++) {
+ mOpenedChannels[xx] = false;
+ }
+ mOpenedchannelCount = 0;
+ }
+ }
+ return sestatus;
+}
+
+void SecureElement::onStateChange(bool result, std::string reason) {
+ ALOGD("%s: result: %d, reaon= %s", __func__, result, reason.c_str());
+ if (mCallbackV1_1 != nullptr) {
+ mCallbackV1_1->onStateChange_1_1(result, reason);
+ } else if (mCallbackV1_0 != nullptr) {
+ mCallbackV1_0->onStateChange(result);
+ }
+}
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace secure_element
+} // namespace hardware
+} // namespace android
diff --git a/1.1/SecureElement.h b/1.1/SecureElement.h
new file mode 100755
index 0000000..d36b03f
--- /dev/null
+++ b/1.1/SecureElement.h
@@ -0,0 +1,89 @@
+/******************************************************************************
+ *
+ * Copyright 2018 NXP
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#ifndef ANDROID_HARDWARE_SECURE_ELEMENT_V1_1_SECUREELEMENT_H
+#define ANDROID_HARDWARE_SECURE_ELEMENT_V1_1_SECUREELEMENT_H
+
+#include <android/hardware/secure_element/1.0/types.h>
+#include <android/hardware/secure_element/1.1/ISecureElement.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <string>
+
+#include "phNxpEse_Api.h"
+
+namespace android {
+namespace hardware {
+namespace secure_element {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::secure_element::V1_0::LogicalChannelResponse;
+using ::android::hardware::secure_element::V1_0::SecureElementStatus;
+using ::android::hardware::secure_element::V1_1::ISecureElement;
+using ::android::hidl::base::V1_0::IBase;
+
+#ifndef MAX_LOGICAL_CHANNELS
+#define MAX_LOGICAL_CHANNELS 0x04
+#endif
+#ifndef MIN_APDU_LENGTH
+#define MIN_APDU_LENGTH 0x04
+#endif
+#ifndef DEFAULT_BASIC_CHANNEL
+#define DEFAULT_BASIC_CHANNEL 0x00
+#endif
+
+struct SecureElement : public V1_1::ISecureElement,
+ public hidl_death_recipient {
+ SecureElement();
+ Return<void> init(
+ const sp<V1_0::ISecureElementHalCallback>& clientCallback) override;
+ Return<void> init_1_1(
+ const sp<V1_1::ISecureElementHalCallback>& clientCallback) override;
+ Return<void> getAtr(getAtr_cb _hidl_cb) override;
+ Return<bool> isCardPresent() override;
+ Return<void> transmit(const hidl_vec<uint8_t>& data,
+ transmit_cb _hidl_cb) override;
+ Return<void> openLogicalChannel(const hidl_vec<uint8_t>& aid, uint8_t p2,
+ openLogicalChannel_cb _hidl_cb) override;
+ Return<void> openBasicChannel(const hidl_vec<uint8_t>& aid, uint8_t p2,
+ openBasicChannel_cb _hidl_cb) override;
+ Return<SecureElementStatus> closeChannel(uint8_t channelNumber) override;
+ void serviceDied(uint64_t /*cookie*/, const wp<IBase>& /*who*/) override;
+ void onStateChange(bool result, std::string reason);
+
+ private:
+ uint8_t mOpenedchannelCount = 0;
+ bool mOpenedChannels[MAX_LOGICAL_CHANNELS];
+ static sp<V1_0::ISecureElementHalCallback> mCallbackV1_0;
+ static sp<V1_1::ISecureElementHalCallback> mCallbackV1_1;
+ Return<SecureElementStatus> seHalDeInit();
+ ESESTATUS seHalInit();
+ bool isSeInitialized();
+};
+
+} // namespace implementation
+} // namespace V1_1
+} // namespace secure_element
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_SECURE_ELEMENT_V1_1_SECUREELEMENT_H
diff --git a/1.1/android.hardware.secure_element@1.1-service-disabled.rc b/1.1/android.hardware.secure_element@1.1-service-disabled.rc
new file mode 100644
index 0000000..d17201f
--- /dev/null
+++ b/1.1/android.hardware.secure_element@1.1-service-disabled.rc
@@ -0,0 +1,5 @@
+service vendor.secure_element_hal_service_1_1 /vendor/bin/hw/android.hardware.secure_element@1.1-service-disabled
+ disabled
+ interface android.hardware.secure_element@1.1::ISecureElement eSE1
+ user secure_element
+ group secure_element
diff --git a/1.1/android.hardware.secure_element@1.1-service.rc b/1.1/android.hardware.secure_element@1.1-service.rc
new file mode 100644
index 0000000..388fffd
--- /dev/null
+++ b/1.1/android.hardware.secure_element@1.1-service.rc
@@ -0,0 +1,5 @@
+service vendor.secure_element_hal_service_1_1 /vendor/bin/hw/android.hardware.secure_element@1.1-service
+ class hal
+ interface android.hardware.secure_element@1.1::ISecureElement eSE1
+ user secure_element
+ group secure_element
diff --git a/Android.bp b/Android.bp
index e76951c..e29b2b9 100755
--- a/Android.bp
+++ b/Android.bp
@@ -42,7 +42,6 @@ cc_library_shared {
shared_libs: [
"android.hardware.nfc@1.0",
"android.hardware.nfc@1.1",
- "android.hardware.secure_element@1.0",
"libcutils",
"libhardware",
"libhidlbase",
@@ -70,7 +69,6 @@ cc_library_shared {
shared_libs: [
"ese_spi_nxp",
- "android.hardware.secure_element@1.0",
"libcutils",
"liblog",
"libhidlbase",
@@ -81,6 +79,35 @@ cc_library_shared {
}
cc_defaults {
+ name: "android.hardware.secure_element@1.1_defaults",
+ relative_install_path: "hw",
+ proprietary: true,
+ defaults: ["hidl_defaults"],
+ srcs: [
+ "1.1/NxpEseService.cpp",
+ "1.1/SecureElement.cpp",
+ "extns/impl/NxpEse.cpp",
+ ],
+
+ shared_libs: [
+ "android.hardware.secure_element@1.0",
+ "android.hardware.secure_element@1.1",
+ "ese_spi_nxp",
+ "libbase",
+ "ls_client",
+ "libcutils",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ "vendor.nxp.nxpese@1.0",
+ "vendor.nxp.nxpnfc@1.0",
+ ],
+}
+
+cc_defaults {
name: "android.hardware.secure_element@1.0_defaults",
relative_install_path: "hw",
proprietary: true,
@@ -119,3 +146,15 @@ cc_binary {
init_rc: ["1.0/android.hardware.secure_element@1.0-service-disabled.rc"],
defaults: ["android.hardware.secure_element@1.0_defaults"],
}
+
+cc_binary {
+ name: "android.hardware.secure_element@1.1-service",
+ init_rc: ["1.1/android.hardware.secure_element@1.1-service.rc"],
+ defaults: ["android.hardware.secure_element@1.1_defaults"],
+}
+
+cc_binary {
+ name: "android.hardware.secure_element@1.1-service-disabled",
+ init_rc: ["1.1/android.hardware.secure_element@1.1-service-disabled.rc"],
+ defaults: ["android.hardware.secure_element@1.1_defaults"],
+}
diff --git a/ls_client/inc/LsClient.h b/ls_client/inc/LsClient.h
index 01facdb..b4fa43e 100755
--- a/ls_client/inc/LsClient.h
+++ b/ls_client/inc/LsClient.h
@@ -19,7 +19,7 @@
#ifndef LSCLIENT_H_
#define LSCLIENT_H_
-#include <android/hardware/secure_element/1.0/ISecureElementHalCallback.h>
+#include <string>
typedef enum {
LSCSTATUS_SUCCESS = (0x0000),
@@ -29,18 +29,25 @@ typedef enum {
LSCSTATUS_HASH_SLOT_INVALID = (0x0007)
} LSCSTATUS;
-using ::android::hardware::secure_element::V1_0::ISecureElementHalCallback;
-
/*******************************************************************************
**
-** Function: LSC_doDownload
-**
-** Description: Perform LS during hal init
+** Function: LSC_onCompletedCallback
**
-** Returns: SUCCESS of ok
+** Description: callback function when Loader Service Scripts thread is done
**
*******************************************************************************/
-LSCSTATUS LSC_doDownload(
- const android::sp<ISecureElementHalCallback>& clientCallback);
+typedef void (*LSC_onCompletedCallback)(bool result, std::string reason,
+ void* args);
+
+/*******************************************************************************
+ **
+ ** Function: LSC_doDownload
+ **
+ ** Description: Start LS download process
+ **
+ ** Returns: SUCCESS if ok
+ **
+ *******************************************************************************/
+LSCSTATUS LSC_doDownload(LSC_onCompletedCallback callback, void* arg);
#endif /* LSCLIENT_H_ */
diff --git a/ls_client/inc/LsLib.h b/ls_client/inc/LsLib.h
index 1bb9214..b5002cc 100755
--- a/ls_client/inc/LsLib.h
+++ b/ls_client/inc/LsLib.h
@@ -510,6 +510,17 @@ LSCSTATUS LSC_UpdateLsHash(uint8_t* hash, long hashLen, uint8_t slotId);
/*******************************************************************************
**
+** Function: LSC_ReadLscInfo
+**
+** Description: Read the info of LS applet
+**
+** Returns: SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_ReadLscInfo(uint8_t* state, uint16_t* version);
+
+/*******************************************************************************
+**
** Function: Numof_lengthbytes
**
** Description: Checks the number of length bytes and assigns
diff --git a/ls_client/src/LsClient.cpp b/ls_client/src/LsClient.cpp
index 05a24ba..f7a78de 100755
--- a/ls_client/src/LsClient.cpp
+++ b/ls_client/src/LsClient.cpp
@@ -16,14 +16,19 @@
*
******************************************************************************/
#define LOG_TAG "LSClient"
-#include "LsClient.h"
+
#include <cutils/properties.h>
#include <dirent.h>
+#include <errno.h>
#include <log/log.h>
#include <openssl/evp.h>
#include <pthread.h>
#include <stdlib.h>
+#include <iomanip>
+#include <sstream>
#include <string>
+
+#include "LsClient.h"
#include "LsLib.h"
uint8_t datahex(char c);
@@ -41,9 +46,78 @@ const uint8_t LS_MAX_COUNT = 10;
const uint8_t LS_DOWNLOAD_SUCCESS = 0x00;
const uint8_t LS_DOWNLOAD_FAILED = 0x01;
-static android::sp<ISecureElementHalCallback> cCallback;
+class LSInfo {
+ public:
+ uint8_t m_status;
+ uint8_t m_version;
+ uint8_t m_mode;
+ uint8_t m_slot1_status;
+ uint8_t m_slot1_hash;
+ uint8_t m_slot2_status;
+ uint8_t m_slot2_hash;
+};
+
+static LSC_onCompletedCallback mCallback = nullptr;
+static void* mCallbackParams = NULL;
+
void* performLSDownload_thread(void* data);
static void getLSScriptSourcePrefix(std::string& prefix);
+static int compareLSHash(uint8_t* hash, uint8_t length);
+static std::string printLSStatus(int status);
+static std::string dumpLsInfo(LSInfo* info);
+
+static int compareLSHash(uint8_t* hash, uint8_t length) {
+ uint8_t ls253UpdaterScriptHash[HASH_DATA_LENGTH - 1] = {
+ 0x65, 0x80, 0xFB, 0xA0, 0xCA, 0x59, 0xAE, 0x6C, 0x71, 0x6B,
+ 0x15, 0xB1, 0xBD, 0xB1, 0x2C, 0x04, 0x29, 0x14, 0x8A, 0x8F};
+ uint8_t ls253AppletScriptHash[HASH_DATA_LENGTH - 1] = {
+ 0x71, 0x7B, 0x8D, 0x0C, 0xEA, 0xE7, 0xEC, 0xC1, 0xCF, 0x47,
+ 0x33, 0x10, 0xFE, 0x8E, 0x52, 0x5D, 0xB1, 0x43, 0x9B, 0xDE};
+ uint8_t lsFactoryScript1Hash[HASH_DATA_LENGTH - 1] = {
+ 0x4A, 0xD0, 0x37, 0xD0, 0x44, 0x5B, 0x78, 0x55, 0x17, 0x5E,
+ 0xFD, 0x87, 0x9C, 0xF1, 0x74, 0xBA, 0x77, 0xAD, 0x03, 0x62};
+ uint8_t lsFactoryScript2Hash[HASH_DATA_LENGTH - 1] = {
+ 0xA9, 0xDB, 0x03, 0x53, 0xC2, 0xD7, 0xF8, 0xFC, 0x84, 0x37,
+ 0xAF, 0xB9, 0x53, 0x06, 0x27, 0x9D, 0xE9, 0x68, 0x45, 0xEF};
+ uint8_t lsFactoryScript3Hash[HASH_DATA_LENGTH - 1] = {
+ 0xA9, 0xAE, 0x5E, 0x66, 0x92, 0x8F, 0x70, 0xBD, 0x0A, 0xC7,
+ 0x20, 0x8A, 0x6A, 0xBB, 0x63, 0xB3, 0xCA, 0x05, 0x58, 0xC1};
+ uint8_t lsFactoryScript4Hash[HASH_DATA_LENGTH - 1] = {
+ 0x64, 0x73, 0x56, 0xAE, 0x58, 0x27, 0x6C, 0x07, 0x4B, 0xBA,
+ 0x64, 0x7E, 0x6E, 0xC1, 0x97, 0xC8, 0x57, 0x17, 0x6E, 0x2D};
+ uint8_t* hashList[6] = {lsFactoryScript1Hash, lsFactoryScript2Hash,
+ lsFactoryScript3Hash, lsFactoryScript4Hash,
+ ls253UpdaterScriptHash, ls253AppletScriptHash};
+
+ if (length != HASH_DATA_LENGTH - 1) {
+ return 0xFF;
+ }
+ for (int i = 0; i < 6; i++) {
+ if (0 == memcmp(hash, hashList[i], length)) {
+ return i + 1;
+ }
+ }
+ return 0xFF;
+}
+
+static std::string dumpLsInfo(LSInfo* info) {
+ std::stringstream buff;
+ buff << std::setw(2) << std::setfill('0') << std::hex
+ << (int)(info->m_status);
+ buff << std::setw(2) << std::setfill('0') << std::hex
+ << (int)(info->m_version);
+ buff << std::setw(2) << std::setfill('0') << std::hex
+ << (int)(info->m_mode);
+ buff << std::setw(2) << std::setfill('0') << std::hex
+ << (int)(info->m_slot1_status);
+ buff << std::setw(2) << std::setfill('0') << std::hex
+ << (int)(info->m_slot1_hash);
+ buff << std::setw(2) << std::setfill('0') << std::hex
+ << (int)(info->m_slot2_status);
+ buff << std::setw(2) << std::setfill('0') << std::hex
+ << (int)(info->m_slot2_hash);
+ return buff.str();
+}
void getLSScriptSourcePrefix(std::string& prefix) {
char source_path[PROPERTY_VALUE_MAX] = {0};
@@ -92,20 +166,22 @@ LSCSTATUS LSC_Start(const char* name, const char* dest, uint8_t* pdata,
**
** Function: LSC_doDownload
**
-** Description: Start LS download process by creating thread
+** Description: Start LS download process
**
-** Returns: SUCCESS of ok
+** Returns: SUCCESS if ok
**
*******************************************************************************/
-LSCSTATUS LSC_doDownload(
- const android::sp<ISecureElementHalCallback>& clientCallback) {
+LSCSTATUS LSC_doDownload(LSC_onCompletedCallback callback, void* args) {
static const char fn[] = "LSC_doDownload";
+
+ mCallback = callback;
+ mCallbackParams = args;
+
LSCSTATUS status;
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- cCallback = clientCallback;
if (pthread_create(&thread, &attr, &performLSDownload_thread, NULL) < 0) {
ALOGE("%s: Thread creation failed", fn);
status = LSCSTATUS_FAILED;
@@ -118,6 +194,98 @@ LSCSTATUS LSC_doDownload(
/*******************************************************************************
**
+** Function: printLSStatus
+**
+** Description: print LS applet state and Slot 1 & 2 data
+**
+** Returns: LS status log
+**
+*******************************************************************************/
+std::string printLSStatus(int lsStatus) {
+ ALOGD_IF(ese_debug_enabled, "%s enter ", __func__);
+
+ uint8_t slotHashBuffer[HASH_DATA_LENGTH] = {0};
+ uint16_t length = 0;
+ uint16_t lsVersion = 0;
+ uint8_t lsMode = 0;
+ std::stringstream outStream;
+ std::stringstream outHash;
+
+ LSInfo lsInfo;
+ memset(&lsInfo, 0xFF, sizeof(LSInfo));
+ lsInfo.m_status = lsStatus;
+
+ outStream << "\nCurrent LS info:";
+ /*Read LS applet mode*/
+ LSCSTATUS status = LSC_ReadLscInfo(&lsMode, &lsVersion);
+ if (status != LSCSTATUS_SUCCESS) {
+ outStream << dumpLsInfo(&lsInfo);
+ outStream << "\nFailed to access LS applet!\n";
+ return outStream.str();
+ }
+
+ ALOGI_IF(ese_debug_enabled, "LS applet version is %d.%d", (lsVersion >> 8),
+ (lsVersion & 0xFF));
+ if (lsMode == 2) {
+ ALOGI_IF(ese_debug_enabled, "LS is in UPDATE mode!");
+ }
+ lsInfo.m_version = lsVersion & 0xFF;
+ lsInfo.m_mode = lsMode;
+
+ /*Read the hash from slot 1*/
+ status = LSC_ReadLsHash(slotHashBuffer, &length, 1);
+ if (status != LSCSTATUS_SUCCESS) {
+ ALOGI_IF(ese_debug_enabled, "Failed to read Hash value from slot 1.");
+ outStream << dumpLsInfo(&lsInfo);
+ return outStream.str();
+ }
+ if (slotHashBuffer[HASH_DATA_LENGTH - 1] == LS_DOWNLOAD_SUCCESS) {
+ ALOGI_IF(ese_debug_enabled, "LS Slot 1 passed.");
+ lsInfo.m_slot1_status = LS_DOWNLOAD_SUCCESS;
+ } else {
+ ALOGI_IF(ese_debug_enabled, "LS Slot 1 failed.");
+ lsInfo.m_slot1_status = LS_DOWNLOAD_FAILED;
+ }
+ lsInfo.m_slot1_hash = compareLSHash(slotHashBuffer, HASH_DATA_LENGTH - 1);
+ if (lsInfo.m_slot1_hash == 0xFF) {
+ outHash << "\n slot 1 hash:\n";
+ for (int i = 0; i < HASH_DATA_LENGTH - 1; i++) {
+ outHash << std::setw(2) << std::setfill('0') << std::hex
+ << (int)slotHashBuffer[i];
+ }
+ }
+
+ /*Read the hash from slot 2*/
+ status = LSC_ReadLsHash(slotHashBuffer, &length, 2);
+ if (status != LSCSTATUS_SUCCESS) {
+ ALOGI_IF(ese_debug_enabled, "Failed to read Hash value from slot 1.");
+ outStream << dumpLsInfo(&lsInfo);
+ return outStream.str();
+ }
+ if (slotHashBuffer[HASH_DATA_LENGTH - 1] == LS_DOWNLOAD_SUCCESS) {
+ ALOGI_IF(ese_debug_enabled, "LS Slot 2 passed.");
+ lsInfo.m_slot2_status = LS_DOWNLOAD_SUCCESS;
+ } else {
+ ALOGI_IF(ese_debug_enabled, "LS Slot 2 failed.");
+ lsInfo.m_slot2_status = LS_DOWNLOAD_FAILED;
+ }
+ lsInfo.m_slot2_hash = compareLSHash(slotHashBuffer, HASH_DATA_LENGTH - 1);
+ if (lsInfo.m_slot2_hash == 0xFF) {
+ outHash << "\n slot 2 hash:\n";
+ for (int i = 0; i < HASH_DATA_LENGTH - 1; i++) {
+ outHash << std::setw(2) << std::setfill('0') << std::hex
+ << (int)slotHashBuffer[i];
+ }
+ }
+
+ outStream << dumpLsInfo(&lsInfo) << outHash.str();
+
+ ALOGD_IF(ese_debug_enabled, "%s exit\n", __func__);
+ return outStream.str();
+}
+
+/*******************************************************************************
+**
** Function: performLSDownload_thread
**
** Description: Perform LS during hal init
@@ -154,8 +322,8 @@ void* performLSDownload_thread(__attribute__((unused)) void* data) {
sourcePath += ls_script_source_suffix;
FILE* fIn = fopen(sourcePath.c_str(), "rb");
if (fIn == NULL) {
- ALOGE("%s Cannot open LS script file %s\n", __func__, sourcePath.c_str());
- ALOGE("%s Error : %s", __func__, strerror(errno));
+ ALOGE("%s Cannot open LS script file %s, Error: %s\n", __func__,
+ sourcePath.c_str(), strerror(errno));
break;
}
ALOGD_IF(ese_debug_enabled, "%s File opened %s\n", __func__,
@@ -236,8 +404,11 @@ void* performLSDownload_thread(__attribute__((unused)) void* data) {
} else {
ALOGE("%s: Ese_deInit failed", __func__);
}
- cCallback->onStateChange(false);
- break;
+
+ if (mCallback != nullptr) {
+ (mCallback)(false, printLSStatus(LS_DOWNLOAD_FAILED), mCallbackParams);
+ break;
+ }
} else {
/*If current script execution is succes, update the status along with the
* hash to the applet*/
@@ -253,7 +424,9 @@ void* performLSDownload_thread(__attribute__((unused)) void* data) {
phNxpEse_free(lsHashInfo.readBuffHash);
if (status == LSCSTATUS_SUCCESS) {
- cCallback->onStateChange(true);
+ if (mCallback != nullptr) {
+ (mCallback)(true, printLSStatus(LS_DOWNLOAD_SUCCESS), mCallbackParams);
+ }
}
pthread_exit(NULL);
ALOGD_IF(ese_debug_enabled, "%s pthread_exit\n", __func__);
diff --git a/ls_client/src/LsLib.cpp b/ls_client/src/LsLib.cpp
index 9dac201..82f64f0 100755
--- a/ls_client/src/LsLib.cpp
+++ b/ls_client/src/LsLib.cpp
@@ -2130,3 +2130,57 @@ LSCSTATUS LSC_UpdateLsHash(uint8_t* hash, long hashLen, uint8_t slotId) {
phNxpEse_free(rspApdu.p_data);
return lsStatus;
}
+
+/*******************************************************************************
+**
+** Function: LSC_ReadLscInfo
+**
+** Description: Read the state of LS applet
+**
+** Returns: SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_ReadLscInfo(uint8_t* state, uint16_t* version) {
+ static const char fn[] = "LSC_ReadLscInfo";
+ phNxpEse_data cmdApdu;
+ phNxpEse_data rspApdu;
+ LSCSTATUS status = LSCSTATUS_FAILED;
+ ALOGD_IF(ese_debug_enabled, "%s: Enter ", __func__);
+
+ phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+ phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+
+ /*p_data will have channel_id (1 byte) + SelectLsc APDU*/
+ cmdApdu.len = (int32_t)(sizeof(SelectLsc) + 1);
+ cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
+ cmdApdu.p_data[0] = 0x00; // fchannel 0
+
+ memcpy(&(cmdApdu.p_data[1]), SelectLsc, sizeof(SelectLsc));
+
+ ALOGD_IF(ese_debug_enabled, "%s: Selecting Loader service applet", fn);
+
+ ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+
+ if (eseStat != ESESTATUS_SUCCESS && (rspApdu.len == 0x00)) {
+ status = LSCSTATUS_FAILED;
+ ALOGE("%s: SE transceive failed status = 0x%X", fn, status);
+ } else if (((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
+ (rspApdu.p_data[rspApdu.len - 1] == 0x00))) {
+ status = Process_SelectRsp(rspApdu.p_data, (rspApdu.len - 2));
+ if (status != LSCSTATUS_SUCCESS) {
+ ALOGE("%s: Select Lsc Rsp doesnt have a valid key; status = 0x%X", fn,
+ status);
+ } else {
+ *state = rspApdu.p_data[18];
+ *version = (rspApdu.p_data[22] << 8) | rspApdu.p_data[23];
+ }
+ } else if (rspApdu.p_data[rspApdu.len - 2] != 0x90) {
+ ALOGE("%s: Selecting Loader service applet failed", fn);
+ status = LSCSTATUS_FAILED;
+ }
+
+ ALOGD_IF(ese_debug_enabled, "%s: Exit ", __func__);
+ phNxpEse_free(cmdApdu.p_data);
+ phNxpEse_free(rspApdu.p_data);
+ return status;
+}