Support Multiple LS Script execution

run LS scripts enumerated from 1 to 9 consecutively.
Store hash of the LS Script and script execution status in
LsScriptState Applet
Read script execution status from Applet before executing
Ls Script update to make sure LsScript is executed only once.

Bug: 109824925
Test: VTS, Run LS update for 3 scripts, After execution
reboot the phone and check if scripts are executed again

Change-Id: I486043edac7cf59158004c9a9ab3a65443ee672b
(cherry picked from commit d4b09456c2c746c9f9f5ecf36246d45aee01eeaf)
diff --git a/Android.bp b/Android.bp
old mode 100644
new mode 100755
index 24fd3cd..b1ca712
--- a/Android.bp
+++ b/Android.bp
@@ -75,6 +75,7 @@
         "libhidlbase",
         "liblog",
         "libutils",
+        "libcrypto"
     ],
 }
 
diff --git a/ls_client/inc/LsClient.h b/ls_client/inc/LsClient.h
index 7c00c02..01facdb 100755
--- a/ls_client/inc/LsClient.h
+++ b/ls_client/inc/LsClient.h
@@ -24,7 +24,9 @@
 typedef enum {
   LSCSTATUS_SUCCESS = (0x0000),
   LSCSTATUS_FAILED = (0x0003),
-  LSCSTATUS_SELF_UPDATE_DONE = (0x0005)
+  LSCSTATUS_SELF_UPDATE_DONE = (0x0005),
+  LSCSTATUS_HASH_SLOT_EMPTY = (0x0006),
+  LSCSTATUS_HASH_SLOT_INVALID = (0x0007)
 } LSCSTATUS;
 
 using ::android::hardware::secure_element::V1_0::ISecureElementHalCallback;
diff --git a/ls_client/inc/LsLib.h b/ls_client/inc/LsLib.h
old mode 100644
new mode 100755
index 4aad552..d106898
--- a/ls_client/inc/LsLib.h
+++ b/ls_client/inc/LsLib.h
@@ -48,8 +48,16 @@
   int bytes_wrote;
   Lsc_ChannelInfo_t Channel_Info[10];
   uint8_t channel_cnt;
+  uint8_t initChannelNum;
 } Lsc_ImageInfo_t;
 
+typedef struct Lsc_HashInfo {
+  uint16_t readHashLen;
+  uint8_t* lsRawScriptBuf = nullptr;
+  uint8_t* lsScriptHash = nullptr;
+  uint8_t* readBuffHash = nullptr;
+} Lsc_HashInfo_t;
+
 typedef enum {
   LS_Default = 0x00,
   LS_Cert = 0x7F21,
@@ -64,6 +72,10 @@
                               0x00, 0x03, 0x96, 0x54, 0x43, 0x00, 0x00,
                               0x00, 0x01, 0x00, 0x0B, 0x00, 0x01};
 
+static uint8_t SelectLscSlotHash[] = {0x00, 0xA4, 0x04, 0x00, 0x10, 0xA0, 0x00,
+                                      0x00, 0x03, 0x96, 0x54, 0x53, 0x00, 0x00,
+                                      0x00, 0x01, 0x00, 0x60, 0x00, 0x00, 0x00};
+
 /*LSC2*/
 #define NOOFAIDS 0x03
 #define LENOFAIDS 0x16
@@ -464,6 +476,51 @@
 
 /*******************************************************************************
 **
+** Function:        LSC_CloseAllLogicalChannels
+**
+** Description:     Close all opened logical channels
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_CloseAllLogicalChannels(Lsc_ImageInfo_t* Os_info);
+
+/*******************************************************************************
+**
+** Function:        LSC_SelectLsHash
+**
+** Description:     Selects LS Hash applet
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+
+LSCSTATUS LSC_SelectLsHash();
+
+/*******************************************************************************
+**
+** Function:        LSC_ReadLsHash
+**
+** Description:     Read the LS SHA1 for the intended slot
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_ReadLsHash(uint8_t* hash, uint16_t* readHashLen, uint8_t slotId);
+
+/*******************************************************************************
+**
+** Function:        LSC_UpdateLsHash
+**
+** Description:     Updates SHA1 of LS script to the respective Slot ID
+**
+** Returns:         Update status
+**
+*******************************************************************************/
+LSCSTATUS LSC_UpdateLsHash(uint8_t* hash, long hashLen, uint8_t slotId);
+
+/*******************************************************************************
+**
 ** 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
old mode 100644
new mode 100755
index c63d340..75a7258
--- a/ls_client/src/LsClient.cpp
+++ b/ls_client/src/LsClient.cpp
@@ -19,12 +19,26 @@
 #include "LsClient.h"
 #include <dirent.h>
 #include <log/log.h>
+#include <openssl/evp.h>
 #include <pthread.h>
 #include <stdlib.h>
 #include "LsLib.h"
 
 uint8_t datahex(char c);
+unsigned char* getHASH(uint8_t* buffer, size_t buffSize);
 extern bool ese_debug_enabled;
+
+#define ls_script_source_prefix "/vendor/etc/loaderservice_updater_"
+#define ls_script_source_suffix ".lss"
+#define ls_script_output_prefix \
+  "/data/vendor/secure_element/loaderservice_updater_out_"
+#define ls_script_output_suffix ".txt"
+const size_t HASH_DATA_LENGTH = 21;
+const uint16_t HASH_STATUS_INDEX = 20;
+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;
 void* performLSDownload_thread(void* data);
 /*******************************************************************************
@@ -88,12 +102,7 @@
 **
 *******************************************************************************/
 void* performLSDownload_thread(__attribute__((unused)) void* data) {
-  ALOGD_IF(ese_debug_enabled, "%s enter:  ", __func__);
-
-  const char* lsUpdateBackupPath = "/vendor/etc/loaderservice_updater.lss";
-  const char* lsUpdateBackupOutPath =
-      "/data/vendor/secure_element/loaderservice_updater_out.txt";
-
+  ALOGD_IF(ese_debug_enabled, "%s enter  ", __func__);
   /*generated SHA-1 string for secureElementLS
   This will remain constant as handled in secureElement HAL*/
   char sha1[] = "6d583e84f2710e6b0f06beebc1a12a1083591373";
@@ -105,40 +114,115 @@
   }
 
   uint8_t resSW[4] = {0x4e, 0x02, 0x69, 0x87};
-  FILE* fIn = fopen(lsUpdateBackupPath, "rb");
-  if (fIn == NULL) {
-    ALOGE("%s Cannot open LS script file %s\n", __func__, lsUpdateBackupPath);
-    ALOGE("%s Error : %s", __func__, strerror(errno));
-    cCallback->onStateChange(true);
-  } else {
-    ALOGD_IF(ese_debug_enabled, "%s File opened %s\n", __func__,
-             lsUpdateBackupPath);
 
-    FILE* fOut = fopen(lsUpdateBackupOutPath, "wb+");
+  std::string sourcePath;
+  std::string outPath;
+  int index = 1;
+  LSCSTATUS status = LSCSTATUS_SUCCESS;
+  Lsc_HashInfo_t lsHashInfo;
+  do {
+    /*Open the script file from specified location and name*/
+    sourcePath.assign(ls_script_source_prefix);
+    sourcePath += ('0' + index);
+    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));
+      break;
+    }
+    ALOGD_IF(ese_debug_enabled, "%s File opened %s\n", __func__,
+             sourcePath.c_str());
+
+    outPath.assign(ls_script_output_prefix);
+    outPath += ('0' + index);
+    outPath += ls_script_output_suffix;
+
+    FILE* fOut = fopen(outPath.c_str(), "wb+");
     if (fOut == NULL) {
-      ALOGE("%s Failed to open file %s\n", __func__, lsUpdateBackupOutPath);
-      pthread_exit(NULL);
-      cCallback->onStateChange(true);
-      return NULL;
+      ALOGE("%s Failed to open file %s\n", __func__, outPath.c_str());
+      break;
+    }
+    /*Read the script content to a local buffer*/
+    fseek(fIn, 0, SEEK_END);
+    long lsBufSize = ftell(fIn);
+    rewind(fIn);
+    if (lsHashInfo.lsRawScriptBuf == nullptr) {
+      lsHashInfo.lsRawScriptBuf = (uint8_t*)phNxpEse_memalloc(lsBufSize + 1);
+    }
+    memset(lsHashInfo.lsRawScriptBuf, 0x00, (lsBufSize + 1));
+    fread(lsHashInfo.lsRawScriptBuf, lsBufSize, 1, fIn);
+
+    LSCSTATUS lsHashStatus = LSCSTATUS_FAILED;
+
+    /*Get 20bye SHA1 of the script*/
+    lsHashInfo.lsScriptHash =
+        getHASH(lsHashInfo.lsRawScriptBuf, (size_t)lsBufSize);
+    if (lsHashInfo.lsScriptHash == nullptr) break;
+
+    if (lsHashInfo.readBuffHash == nullptr) {
+      lsHashInfo.readBuffHash = (uint8_t*)phNxpEse_memalloc(HASH_DATA_LENGTH);
+    }
+    memset(lsHashInfo.readBuffHash, 0x00, HASH_DATA_LENGTH);
+
+    /*Read the hash from applet for specified slot*/
+    lsHashStatus =
+        LSC_ReadLsHash(lsHashInfo.readBuffHash, &lsHashInfo.readHashLen, index);
+
+    /*Check if previously script is successfully installed.
+    if yes, continue reading next script else try update wit current script*/
+    if ((lsHashStatus == LSCSTATUS_SUCCESS) &&
+        (lsHashInfo.readHashLen == HASH_DATA_LENGTH) &&
+        (0 == memcmp(lsHashInfo.lsScriptHash, lsHashInfo.readBuffHash,
+                     HASH_DATA_LENGTH)) &&
+        (lsHashInfo.readBuffHash[HASH_STATUS_INDEX] == LS_DOWNLOAD_SUCCESS)) {
+      ALOGD_IF(ese_debug_enabled, "%s LS Loader sript is already installed \n",
+               __func__);
+      continue;
     }
 
-    LSCSTATUS status = LSC_Start(lsUpdateBackupPath, lsUpdateBackupOutPath,
-                                 (uint8_t*)hash, (uint16_t)sizeof(hash), resSW);
-    ALOGD_IF(ese_debug_enabled, "%s LSC_Start completed\n", __func__);
-    if (status == LSCSTATUS_SUCCESS) {
-      cCallback->onStateChange(true);
-    } else {
-      ESESTATUS status = phNxpEse_deInit();
-      if (status == ESESTATUS_SUCCESS) {
-        status = phNxpEse_close();
-        if (status == ESESTATUS_SUCCESS) {
+    /*Uptdates current script*/
+    status = LSC_Start(sourcePath.c_str(), outPath.c_str(), (uint8_t*)hash,
+                       (uint16_t)sizeof(hash), resSW);
+    ALOGD_IF(ese_debug_enabled, "%s script %s perform done, result = %d\n",
+             __func__, sourcePath.c_str(), status);
+    if (status != LSCSTATUS_SUCCESS) {
+      lsHashInfo.lsScriptHash[HASH_STATUS_INDEX] = LS_DOWNLOAD_FAILED;
+      /*If current script updation fails, update the status with hash to the
+       * applet then clean and exit*/
+      lsHashStatus =
+          LSC_UpdateLsHash(lsHashInfo.lsScriptHash, HASH_DATA_LENGTH, index);
+      if (lsHashStatus != LSCSTATUS_SUCCESS) {
+        ALOGD_IF(ese_debug_enabled, "%s LSC_UpdateLsHash Failed\n", __func__);
+      }
+      ESESTATUS estatus = phNxpEse_deInit();
+      if (estatus == ESESTATUS_SUCCESS) {
+        estatus = phNxpEse_close();
+        if (estatus == ESESTATUS_SUCCESS) {
           ALOGD_IF(ese_debug_enabled, "%s: Ese_close success\n", __func__);
         }
       } else {
         ALOGE("%s: Ese_deInit failed", __func__);
       }
       cCallback->onStateChange(false);
+      break;
+    } else {
+      /*If current script execution is succes, update the status along with the
+       * hash to the applet*/
+      lsHashInfo.lsScriptHash[HASH_STATUS_INDEX] = LS_DOWNLOAD_SUCCESS;
+      lsHashStatus =
+          LSC_UpdateLsHash(lsHashInfo.lsScriptHash, HASH_DATA_LENGTH, index);
+      if (lsHashStatus != LSCSTATUS_SUCCESS) {
+        ALOGD_IF(ese_debug_enabled, "%s LSC_UpdateLsHash Failed\n", __func__);
+      }
     }
+  } while (++index <= LS_MAX_COUNT);
+
+  phNxpEse_free(lsHashInfo.lsRawScriptBuf);
+  phNxpEse_free(lsHashInfo.readBuffHash);
+
+  if (status == LSCSTATUS_SUCCESS) {
+    cCallback->onStateChange(true);
   }
   pthread_exit(NULL);
   ALOGD_IF(ese_debug_enabled, "%s pthread_exit\n", __func__);
@@ -147,6 +231,30 @@
 
 /*******************************************************************************
 **
+** Function:        getHASH
+**
+** Description:     generates SHA1 of given buffer
+**
+** Returns:         20 bytes of SHA1
+**
+*******************************************************************************/
+unsigned char* getHASH(uint8_t* buffer, size_t buffSize) {
+  static uint8_t outHash[HASH_DATA_LENGTH] = {0};
+  unsigned int md_len = -1;
+  const EVP_MD* md = EVP_get_digestbyname("SHA1");
+  if (NULL != md) {
+    EVP_MD_CTX mdctx;
+    EVP_MD_CTX_init(&mdctx);
+    EVP_DigestInit_ex(&mdctx, md, NULL);
+    EVP_DigestUpdate(&mdctx, buffer, buffSize);
+    EVP_DigestFinal_ex(&mdctx, outHash, &md_len);
+    EVP_MD_CTX_cleanup(&mdctx);
+  }
+  return outHash;
+}
+
+/*******************************************************************************
+**
 ** Function:        datahex
 **
 ** Description:     Converts char to uint8_t
diff --git a/ls_client/src/LsLib.cpp b/ls_client/src/LsLib.cpp
index d7abefa..d9a4772 100755
--- a/ls_client/src/LsLib.cpp
+++ b/ls_client/src/LsLib.cpp
@@ -120,6 +120,12 @@
       ALOGE("%s: exiting; status=0x0%X", fn, status);
       break;
     }
+
+    if ((seq_counter == 0x00) &&
+        update_info.Channel_Info[update_info.channel_cnt - 1].isOpend) {
+      update_info.initChannelNum =
+          update_info.Channel_Info[update_info.channel_cnt - 1].channel_id;
+    }
     seq_counter++;
   }
 
@@ -504,6 +510,10 @@
       if (status != LSCSTATUS_SUCCESS) {
         /*When the switching of LS 6320 case*/
         if (status == LSCSTATUS_SELF_UPDATE_DONE) {
+          status = LSC_CloseAllLogicalChannels(Os_info);
+          if (status != LSCSTATUS_SUCCESS) {
+            ALOGE("%s: CleanupLsUpdaterChannels failed", fn);
+          }
           status = LSCSTATUS_SUCCESS;
           goto exit;
         }
@@ -972,6 +982,9 @@
                (rspApdu.p_data[rspApdu.len - 1] == 0x00)) {
       ALOGD_IF(ese_debug_enabled, "%s: Close channel id = 0x0%x success", fn,
                Os_info->Channel_Info[cnt].channel_id);
+      if (Os_info->Channel_Info[cnt].channel_id == Os_info->initChannelNum) {
+        Os_info->initChannelNum = 0x00;
+      }
       status = LSCSTATUS_SUCCESS;
     } else {
       ALOGD_IF(ese_debug_enabled, "%s: Close channel id = 0x0%x failed", fn,
@@ -1983,3 +1996,203 @@
   fclose(fLsStatus);
   return LSCSTATUS_SUCCESS;
 }
+
+/*******************************************************************************
+**
+** Function:        LSC_CloseAllLogicalChannels
+**
+** Description:     Close all opened logical channels
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_CloseAllLogicalChannels(Lsc_ImageInfo_t* Os_info) {
+  ESESTATUS status = ESESTATUS_FAILED;
+  LSCSTATUS lsStatus = LSCSTATUS_FAILED;
+  phNxpEse_data cmdApdu;
+  phNxpEse_data rspApdu;
+
+  ALOGD_IF(ese_debug_enabled, "%s: Enter", __func__);
+  for (uint8_t channelNumber = 0x01; channelNumber < 0x04; channelNumber++) {
+    if (channelNumber == Os_info->initChannelNum) continue;
+    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) {
+      lsStatus = LSCSTATUS_FAILED;
+    } else if ((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
+               (rspApdu.p_data[rspApdu.len - 1] == 0x00)) {
+      lsStatus = LSCSTATUS_SUCCESS;
+    } else {
+      lsStatus = LSCSTATUS_FAILED;
+    }
+
+    phNxpEse_free(cmdApdu.p_data);
+    phNxpEse_free(rspApdu.p_data);
+  }
+  return lsStatus;
+}
+
+/*******************************************************************************
+**
+** Function:        LSC_SelectLsHash
+**
+** Description:     Selects LS Hash applet
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_SelectLsHash() {
+  phNxpEse_data cmdApdu;
+  phNxpEse_data rspApdu;
+  LSCSTATUS lsStatus = LSCSTATUS_FAILED;
+  ALOGD_IF(ese_debug_enabled, "%s: Enter ", __func__);
+  phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+  phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+
+  cmdApdu.len = (int32_t)(sizeof(SelectLscSlotHash));
+  cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
+  memcpy(cmdApdu.p_data, SelectLscSlotHash, sizeof(SelectLscSlotHash));
+
+  ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+
+  if ((eseStat != ESESTATUS_SUCCESS) ||
+      ((rspApdu.p_data[rspApdu.len - 2] != 0x90) &&
+       (rspApdu.p_data[rspApdu.len - 1] != 0x00))) {
+    lsStatus = LSCSTATUS_FAILED;
+  } else {
+    lsStatus = LSCSTATUS_SUCCESS;
+  }
+
+  phNxpEse_free(cmdApdu.p_data);
+  phNxpEse_free(rspApdu.p_data);
+  return lsStatus;
+}
+/*******************************************************************************
+**
+** Function:        LSC_ReadLsHash
+**
+** Description:     Read the LS SHA1 for the intended slot
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_ReadLsHash(uint8_t* hash, uint16_t* readHashLen, uint8_t slotId) {
+  phNxpEse_data cmdApdu;
+  phNxpEse_data rspApdu;
+  LSCSTATUS lsStatus = LSCSTATUS_FAILED;
+
+  lsStatus = LSC_SelectLsHash();
+  if (lsStatus != LSCSTATUS_SUCCESS) {
+    return lsStatus;
+  }
+
+  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++] = 0x80;    // CLA
+    cmdApdu.p_data[xx++] = 0x02;    // INS
+    cmdApdu.p_data[xx++] = slotId;  // P1
+    cmdApdu.p_data[xx++] = 0x00;    // P2
+    cmdApdu.len = xx;
+
+    ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+
+    if ((eseStat == ESESTATUS_SUCCESS) &&
+        ((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
+         (rspApdu.p_data[rspApdu.len - 1] == 0x00))) {
+      ALOGD_IF(ese_debug_enabled, "%s: rspApdu.len : %u", __func__,
+               rspApdu.len);
+      *readHashLen = rspApdu.len - 2;
+      memcpy(hash, rspApdu.p_data, rspApdu.len);
+
+      lsStatus = LSCSTATUS_SUCCESS;
+    } else {
+      if ((rspApdu.p_data[rspApdu.len - 2] == 0x6A) &&
+          (rspApdu.p_data[rspApdu.len - 1] == 0x86)) {
+        ALOGD_IF(ese_debug_enabled, "%s: slot id is invalid", __func__);
+        lsStatus = LSCSTATUS_HASH_SLOT_INVALID;
+      } else if ((rspApdu.p_data[rspApdu.len - 2] == 0x6A) &&
+                 (rspApdu.p_data[rspApdu.len - 1] == 0x83)) {
+        ALOGD_IF(ese_debug_enabled, "%s: slot is empty", __func__);
+        lsStatus = LSCSTATUS_HASH_SLOT_EMPTY;
+      } else {
+        lsStatus = LSCSTATUS_FAILED;
+      }
+    }
+    phNxpEse_free(cmdApdu.p_data);
+    phNxpEse_free(rspApdu.p_data);
+  }
+  return lsStatus;
+}
+
+/*******************************************************************************
+**
+** Function:        LSC_UpdateLsHash
+**
+** Description:     Updates the SHA1 for the intended slot
+**
+** Returns:         SUCCESS/FAILURE
+**
+*******************************************************************************/
+LSCSTATUS LSC_UpdateLsHash(uint8_t* hash, long hashLen, uint8_t slotId) {
+  phNxpEse_data cmdApdu;
+  phNxpEse_data rspApdu;
+  LSCSTATUS lsStatus = LSCSTATUS_FAILED;
+  ALOGD_IF(ese_debug_enabled, "%s: Enter ", __func__);
+
+  lsStatus = LSC_SelectLsHash();
+  if (lsStatus != LSCSTATUS_SUCCESS) {
+    return lsStatus;
+  }
+
+  phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
+  phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
+
+  cmdApdu.len = (int32_t)(5 + hashLen);
+  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++] = 0x80;
+    cmdApdu.p_data[xx++] = 0x01;     // INS
+    cmdApdu.p_data[xx++] = slotId;   // P1
+    cmdApdu.p_data[xx++] = 0x00;     // P2
+    cmdApdu.p_data[xx++] = hashLen;  // Lc
+    memcpy(&cmdApdu.p_data[xx], hash, hashLen);
+
+    ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
+
+    if ((eseStat == ESESTATUS_SUCCESS) &&
+        ((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
+         (rspApdu.p_data[rspApdu.len - 1] == 0x00))) {
+      lsStatus = LSCSTATUS_SUCCESS;
+    } else {
+      if ((rspApdu.p_data[rspApdu.len - 2] == 0x6A) &&
+          (rspApdu.p_data[rspApdu.len - 1] == 0x86)) {
+        ALOGD_IF(ese_debug_enabled, "%s: if slot id is invalid", __func__);
+      }
+      lsStatus = LSCSTATUS_FAILED;
+    }
+  }
+
+  ALOGD_IF(ese_debug_enabled, "%s: Exit ", __func__);
+  phNxpEse_free(cmdApdu.p_data);
+  phNxpEse_free(rspApdu.p_data);
+  return lsStatus;
+}