/*******************************************************************************
*
* 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 "LSClient"
#include <LsClient.h>
#include <LsLib.h>
#include <errno.h>
#include <log/log.h>
#include <stdlib.h>
#include <string.h>
extern bool ese_debug_enabled;
static int32_t gsTransceiveTimeout = 120000;
static uint8_t gsCmd_Buffer[64 * 1024];
static int32_t gsCmd_count = 0;
static bool gsIslastcmdLoad;
static bool gsSendBack_cmds = false;
static uint8_t* gspBuffer;
static uint8_t gsStoreData[22];
static uint8_t gsTag42Arr[17];
static uint8_t gsTag45Arr[9];
static uint8_t gsLsExecuteResp[4];
static int32_t gsResp_len = 0;
LSCSTATUS(*Applet_load_seqhandler[])
(Lsc_ImageInfo_t* pContext, LSCSTATUS status, Lsc_TranscieveInfo_t* pInfo) = {
LSC_OpenChannel, LSC_SelectLsc, LSC_StoreData, LSC_loadapplet, NULL};
/*******************************************************************************
**
** Function: Perform_LSC
**
** Description: Performs the LSC download sequence
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS Perform_LSC(const char* name, const char* dest, const uint8_t* pdata,
uint16_t len, uint8_t* respSW) {
static const char fn[] = "Perform_LSC";
ALOGD_IF(ese_debug_enabled, "%s: enter; sha-len=%d", fn, len);
if ((pdata == NULL) || (len == 0x00)) {
ALOGE("%s: Invalid SHA-data", fn);
return LSCSTATUS_FAILED;
}
gsStoreData[0] = STORE_DATA_TAG;
gsStoreData[1] = len;
memcpy(&gsStoreData[2], pdata, len);
LSCSTATUS status = LSC_update_seq_handler(Applet_load_seqhandler, name, dest);
if ((status != LSCSTATUS_SUCCESS) && (gsLsExecuteResp[2] == 0x90) &&
(gsLsExecuteResp[3] == 0x00)) {
gsLsExecuteResp[2] = LS_ABORT_SW1;
gsLsExecuteResp[3] = LS_ABORT_SW2;
}
memcpy(&respSW[0], &gsLsExecuteResp[0], 4);
ALOGD_IF(ese_debug_enabled, "%s: lsExecuteScript Response SW=%2x%2x", fn,
gsLsExecuteResp[2], gsLsExecuteResp[3]);
ALOGD_IF(ese_debug_enabled, "%s: exit; status=0x0%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: LSC_update_seq_handler
**
** Description: Performs the LSC update sequence handler sequence
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_update_seq_handler(
LSCSTATUS (*seq_handler[])(Lsc_ImageInfo_t* pContext, LSCSTATUS status,
Lsc_TranscieveInfo_t* pInfo),
const char* name, const char* dest) {
static const char fn[] = "LSC_update_seq_handler";
Lsc_ImageInfo_t update_info;
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
memset(&update_info, 0, sizeof(Lsc_ImageInfo_t));
if (dest != NULL) {
strcat(update_info.fls_RespPath, dest);
ALOGD_IF(ese_debug_enabled,
"%s: Loader Service response data path/destination: %s", fn, dest);
update_info.bytes_wrote = 0xAA;
} else {
update_info.bytes_wrote = 0x55;
}
if ((LSC_UpdateExeStatus(LS_DEFAULT_STATUS)) != true) {
return LSCSTATUS_FAILED;
}
// memcpy(update_info.fls_path, (char*)Lsc_path, sizeof(Lsc_path));
strcat(update_info.fls_path, name);
ALOGD_IF(ese_debug_enabled, "Selected applet to install is: %s",
update_info.fls_path);
uint16_t seq_counter = 0;
LSCSTATUS status = LSCSTATUS_FAILED;
Lsc_TranscieveInfo_t trans_info;
memset(&trans_info, 0, sizeof(Lsc_TranscieveInfo_t));
while ((seq_handler[seq_counter]) != NULL) {
status = (*(seq_handler[seq_counter]))(&update_info, status, &trans_info);
if (LSCSTATUS_SUCCESS != status) {
ALOGE("%s: exiting; status=0x0%X", fn, status);
break;
}
seq_counter++;
}
LSC_CloseChannel(&update_info, LSCSTATUS_FAILED, &trans_info);
ALOGD_IF(ese_debug_enabled, "%s: exit; status=0x%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: LSC_OpenChannel
**
** Description: Creates the logical channel with lsc
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_OpenChannel(Lsc_ImageInfo_t* Os_info, LSCSTATUS status,
Lsc_TranscieveInfo_t* pTranscv_Info) {
static const char fn[] = "LSC_OpenChannel";
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
if (Os_info == NULL || pTranscv_Info == NULL) {
ALOGE("%s: Invalid parameter", fn);
return LSCSTATUS_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)sizeof(OpenChannel);
cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
memcpy(cmdApdu.p_data, OpenChannel, cmdApdu.len);
ALOGD_IF(ese_debug_enabled, "%s: Calling Secure Element Transceive", fn);
ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
if (eseStat != ESESTATUS_SUCCESS && (rspApdu.len < 0x03)) {
if (rspApdu.len == 0x02)
memcpy(&gsLsExecuteResp[2], &rspApdu.p_data[rspApdu.len - 2], 2);
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))) {
memcpy(&gsLsExecuteResp[2], &rspApdu.p_data[rspApdu.len - 2], 2);
status = LSCSTATUS_FAILED;
ALOGE("%s: invalid response = 0x%X", fn, status);
} else {
uint8_t cnt = Os_info->channel_cnt;
Os_info->Channel_Info[cnt].channel_id = rspApdu.p_data[rspApdu.len - 3];
Os_info->Channel_Info[cnt].isOpend = true;
Os_info->channel_cnt++;
status = LSCSTATUS_SUCCESS;
}
phNxpEse_free(cmdApdu.p_data);
phNxpEse_free(rspApdu.p_data);
ALOGD_IF(ese_debug_enabled, "%s: exit; status=0x%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: LSC_SelectLsc
**
** Description: Creates the logical channel with lsc
** Channel_id will be used for any communication with Lsc
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_SelectLsc(Lsc_ImageInfo_t* Os_info, LSCSTATUS status,
Lsc_TranscieveInfo_t* pTranscv_Info) {
static const char fn[] = "LSC_SelectLsc";
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
if (Os_info == NULL || pTranscv_Info == NULL) {
ALOGE("%s: Invalid parameter", fn);
return LSCSTATUS_FAILED;
}
phNxpEse_data cmdApdu;
phNxpEse_data rspApdu;
phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
uint8_t selectCnt = 3;
while ((selectCnt--) > 0) {
if (selectCnt == 2) {
cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(
((ArrayOfAIDs[selectCnt - 1][0]) - 1) * sizeof(uint8_t));
cmdApdu.len = (int32_t)ArrayOfAIDs[selectCnt - 1][0];
} else {
cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(
((ArrayOfAIDs[selectCnt][0]) - 1) * sizeof(uint8_t));
cmdApdu.len = (int32_t)ArrayOfAIDs[selectCnt][0];
}
cmdApdu.p_data[0] = Os_info->Channel_Info[0].channel_id;
memcpy(&(cmdApdu.p_data[1]), &ArrayOfAIDs[selectCnt][2],
((ArrayOfAIDs[selectCnt][0]) - 1));
/*If NFC/SPI Deinitialize requested*/
ALOGD_IF(ese_debug_enabled,
"%s: Calling Secure Element Transceive with Loader service AID",
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);
break;
} 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);
}
/*If AID is found which is successfully selected break while loop*/
if (status == LSCSTATUS_SUCCESS) {
uint8_t totalLen = ArrayOfAIDs[selectCnt][0];
uint8_t cnt = 0;
int32_t wStatus = 0;
status = LSCSTATUS_FAILED;
FILE* fAidMem = fopen(AID_MEM_PATH, "w+");
if (fAidMem == NULL) {
ALOGE("Error opening AID data file for writing: %s", strerror(errno));
phNxpEse_free(cmdApdu.p_data);
return status;
}
while (cnt <= totalLen) {
wStatus = fprintf(fAidMem, "%02x", ArrayOfAIDs[selectCnt][cnt++]);
if (wStatus != 2) {
ALOGE("%s: Error writing AID data to AID_MEM file: %s", fn,
strerror(errno));
break;
}
}
if (wStatus == 2) status = LSCSTATUS_SUCCESS;
fclose(fAidMem);
break;
}
} else if (((rspApdu.p_data[rspApdu.len - 2] != 0x90))) {
/*Copy the response SW in failure case*/
memcpy(&gsLsExecuteResp[2], &(rspApdu.p_data[rspApdu.len - 2]), 2);
} else {
status = LSCSTATUS_FAILED;
}
}
phNxpEse_free(cmdApdu.p_data);
phNxpEse_free(rspApdu.p_data);
ALOGD_IF(ese_debug_enabled, "%s: exit; status=0x%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: LSC_StoreData
**
** Description: It is used to provide the LSC with an Unique
** Identifier of the Application that has triggered the LSC
*script.
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_StoreData(Lsc_ImageInfo_t* Os_info, LSCSTATUS status,
Lsc_TranscieveInfo_t* pTranscv_Info) {
static const char fn[] = "LSC_StoreData";
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
if (Os_info == NULL || pTranscv_Info == NULL) {
ALOGE("%s: Invalid parameter", fn);
return LSCSTATUS_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 + sizeof(gsStoreData));
cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
uint32_t xx = 0;
int32_t len =
gsStoreData[1] + 2; //+2 offset is for tag value and length byte
cmdApdu.p_data[xx++] = STORE_DATA_CLA | (Os_info->Channel_Info[0].channel_id);
cmdApdu.p_data[xx++] = STORE_DATA_INS;
cmdApdu.p_data[xx++] = 0x00; // P1
cmdApdu.p_data[xx++] = 0x00; // P2
cmdApdu.p_data[xx++] = len;
memcpy(&(cmdApdu.p_data[xx]), gsStoreData, len);
ALOGD_IF(ese_debug_enabled, "%s: Calling Secure Element Transceive", 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)) {
ALOGD_IF(ese_debug_enabled, "%s: STORE CMD is successful", fn);
status = LSCSTATUS_SUCCESS;
} else {
/*Copy the response SW in failure case*/
memcpy(&gsLsExecuteResp[2], &(rspApdu.p_data[rspApdu.len - 2]), 2);
status = LSCSTATUS_FAILED;
}
phNxpEse_free(cmdApdu.p_data);
phNxpEse_free(rspApdu.p_data);
ALOGD_IF(ese_debug_enabled, "%s: exit; status=0x%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: LSC_loadapplet
**
** Description: Reads the script from the file and sent to Lsc
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_loadapplet(Lsc_ImageInfo_t* Os_info, LSCSTATUS status,
Lsc_TranscieveInfo_t* pTranscv_Info) {
static const char fn[] = "LSC_loadapplet";
bool reachEOFCheck = false;
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
if (Os_info == NULL || pTranscv_Info == NULL) {
ALOGE("%s: Invalid parameter", fn);
return LSCSTATUS_FAILED;
}
if (Os_info->bytes_wrote == 0xAA) {
Os_info->fResp = fopen(Os_info->fls_RespPath, "a+");
if (Os_info->fResp == NULL) {
ALOGE("%s: Error opening response recording file <%s> for reading: %s",
fn, Os_info->fls_path, strerror(errno));
return LSCSTATUS_FAILED;
}
ALOGD_IF(ese_debug_enabled,
"%s: Response OUT FILE path is successfully created", fn);
} else {
ALOGD_IF(ese_debug_enabled,
"%s: Response Out file is optional as per input", fn);
}
Os_info->fp = fopen(Os_info->fls_path, "r");
if (Os_info->fp == NULL) {
ALOGE("%s: Error opening OS image file <%s> for reading: %s", fn,
Os_info->fls_path, strerror(errno));
return LSCSTATUS_FAILED;
}
int wResult = fseek(Os_info->fp, 0L, SEEK_END);
if (wResult) {
ALOGE("%s: Error seeking end OS image file %s", fn, strerror(errno));
goto exit;
}
Os_info->fls_size = ftell(Os_info->fp);
if (Os_info->fls_size < 0) {
ALOGE("%s: Error ftelling file %s", fn, strerror(errno));
goto exit;
}
wResult = fseek(Os_info->fp, 0L, SEEK_SET);
if (wResult) {
ALOGE("%s: Error seeking start image file %s", fn, strerror(errno));
goto exit;
}
Os_info->bytes_read = 0;
status = LSC_Check_KeyIdentifier(Os_info, status, pTranscv_Info, NULL,
LSCSTATUS_FAILED, 0);
if (status != LSCSTATUS_SUCCESS) {
goto exit;
}
uint8_t len_byte, offset;
while (!feof(Os_info->fp) && (Os_info->bytes_read < Os_info->fls_size)) {
len_byte = 0;
offset = 0;
/*Check if the certificate/ is verified or not*/
if (status != LSCSTATUS_SUCCESS) {
goto exit;
}
uint8_t temp_buf[1024];
memset(temp_buf, 0, sizeof(temp_buf));
status = LSC_ReadScript(Os_info, temp_buf);
if (status != LSCSTATUS_SUCCESS) {
goto exit;
}
/*Reset the flag in case further commands exists*/
reachEOFCheck = false;
int32_t wLen = 0;
LSCSTATUS tag40_found = LSCSTATUS_SUCCESS;
if (temp_buf[offset] == TAG_LSC_CMD_ID) {
/* start sending the packet to Lsc */
offset = offset + 1;
len_byte = Numof_lengthbytes(&temp_buf[offset], &wLen);
/* If the len data not present or len is less than or equal to 32 */
if ((len_byte == 0) || (wLen <= 32)) {
ALOGE("%s: Invalid length zero", fn);
goto exit;
}
tag40_found = LSCSTATUS_SUCCESS;
offset = offset + len_byte;
pTranscv_Info->sSendlength = wLen;
memcpy(pTranscv_Info->sSendData, &temp_buf[offset], wLen);
status = LSC_SendtoLsc(Os_info, status, pTranscv_Info, LS_Comm);
if (status != LSCSTATUS_SUCCESS) {
/*When the switching of LS 6320 case*/
if (status == LSCSTATUS_FILE_NOT_FOUND) {
/*When 6320 occurs close the existing channels*/
LSC_CloseChannel(Os_info, status, pTranscv_Info);
status = LSCSTATUS_FAILED;
status = LSC_OpenChannel(Os_info, status, pTranscv_Info);
if (status == LSCSTATUS_SUCCESS) {
ALOGD_IF(ese_debug_enabled,
"%s: SUCCESS:Post Switching LS open channel", fn);
status = LSCSTATUS_FAILED;
status = LSC_SelectLsc(Os_info, status, pTranscv_Info);
if (status == LSCSTATUS_SUCCESS) {
ALOGD_IF(ese_debug_enabled,
"%s: SUCCESS:Post Switching LS select", fn);
status = LSCSTATUS_FAILED;
status = LSC_StoreData(Os_info, status, pTranscv_Info);
if (status == LSCSTATUS_SUCCESS) {
/*Enable certificate and signature verification*/
tag40_found = LSCSTATUS_SUCCESS;
gsLsExecuteResp[2] = 0x90;
gsLsExecuteResp[3] = 0x00;
reachEOFCheck = true;
continue;
}
ALOGE("%s: Post Switching LS store data failure", fn);
}
ALOGE("%s: Post Switching LS select failure", fn);
}
ALOGE("%s: Post Switching LS failure", fn);
}
ALOGE("%s: Sending packet to lsc failed", fn);
goto exit;
}
} else if ((temp_buf[offset] == (0x7F)) &&
(temp_buf[offset + 1] == (0x21))) {
ALOGD_IF(ese_debug_enabled,
"%s: TAGID: Encountered again certificate tag 7F21", fn);
if (tag40_found == LSCSTATUS_SUCCESS) {
ALOGD_IF(ese_debug_enabled,
"%s: 2nd Script processing starts with reselect", fn);
status = LSCSTATUS_FAILED;
status = LSC_SelectLsc(Os_info, status, pTranscv_Info);
if (status == LSCSTATUS_SUCCESS) {
ALOGD_IF(ese_debug_enabled,
"%s: 2nd Script select success next store data command", fn);
status = LSCSTATUS_FAILED;
status = LSC_StoreData(Os_info, status, pTranscv_Info);
if (status == LSCSTATUS_SUCCESS) {
ALOGD_IF(ese_debug_enabled,
"%s: 2nd Script store data success next certificate "
"verification",
fn);
offset = offset + 2;
len_byte = Numof_lengthbytes(&temp_buf[offset], &wLen);
status = LSC_Check_KeyIdentifier(Os_info, status, pTranscv_Info,
temp_buf, LSCSTATUS_SUCCESS,
wLen + len_byte + 2);
}
}
/*If the certificate and signature is verified*/
if (status == LSCSTATUS_SUCCESS) {
/*If the certificate is verified for 6320 then new script starts*/
tag40_found = LSCSTATUS_FAILED;
} else {
/*If the certificate or signature verification failed*/
goto exit;
}
} else {
/*Already certificate&Sginature verified previously skip 7f21& tag 60*/
memset(temp_buf, 0, sizeof(temp_buf));
status = LSC_ReadScript(Os_info, temp_buf);
if (status != LSCSTATUS_SUCCESS) {
ALOGE("%s: Next Tag has to TAG 60 not found", fn);
goto exit;
}
if (temp_buf[offset] == TAG_JSBL_HDR_ID)
continue;
else
goto exit;
}
} else {
/*
* Invalid packet received in between stop processing packet
* return failed status
*/
status = LSCSTATUS_FAILED;
break;
}
}
if (Os_info->bytes_wrote == 0xAA) {
fclose(Os_info->fResp);
}
LSC_UpdateExeStatus(LS_SUCCESS_STATUS);
wResult = fclose(Os_info->fp);
ALOGD_IF(ese_debug_enabled, "%s: exit, status=0x%x", fn, status);
return status;
exit:
wResult = fclose(Os_info->fp);
if (Os_info->bytes_wrote == 0xAA) {
fclose(Os_info->fResp);
}
/*Script ends with SW 6320 and reached END OF FILE*/
if (reachEOFCheck == true) {
status = LSCSTATUS_SUCCESS;
LSC_UpdateExeStatus(LS_SUCCESS_STATUS);
}
ALOGD_IF(ese_debug_enabled, "%s: exit; status= 0x%X", fn, status);
return status;
}
/*******************************************************************************
**
** Function: LSC_Check_KeyIdentifier
**
** Description: Checks and validates certificate
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_Check_KeyIdentifier(Lsc_ImageInfo_t* Os_info, LSCSTATUS status,
Lsc_TranscieveInfo_t* pTranscv_Info,
uint8_t* temp_buf, LSCSTATUS flag,
int32_t wNewLen) {
static const char fn[] = "LSC_Check_KeyIdentifier";
status = LSCSTATUS_FAILED;
uint8_t read_buf[1024];
uint16_t offset = 0, len_byte = 0;
int32_t wLen;
uint8_t certf_found = LSCSTATUS_FAILED;
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
while (!feof(Os_info->fp) && (Os_info->bytes_read < Os_info->fls_size)) {
offset = 0x00;
wLen = 0;
if (flag == LSCSTATUS_SUCCESS) {
/*If the 7F21 TAG is already read: After TAG 40*/
memcpy(read_buf, temp_buf, wNewLen);
status = LSCSTATUS_SUCCESS;
flag = LSCSTATUS_FAILED;
} else {
/*If the 7F21 TAG is not read: Before TAG 40*/
status = LSC_ReadScript(Os_info, read_buf);
}
if (status != LSCSTATUS_SUCCESS) return status;
if (LSCSTATUS_SUCCESS ==
Check_Complete_7F21_Tag(Os_info, pTranscv_Info, read_buf, &offset)) {
ALOGD_IF(ese_debug_enabled, "%s: Certificate is verified", fn);
certf_found = LSCSTATUS_SUCCESS;
break;
}
/*
* The Loader Service Client ignores all subsequent commands starting by tag
* 7F21 or tag 60 until the first command starting by tag 40 is found
*/
else if (((read_buf[offset] == TAG_LSC_CMD_ID) &&
(certf_found != LSCSTATUS_SUCCESS))) {
ALOGE("%s: NOT FOUND Root entity identifier's certificate", fn);
status = LSCSTATUS_FAILED;
return status;
}
}
memset(read_buf, 0, sizeof(read_buf));
if (certf_found == LSCSTATUS_SUCCESS) {
offset = 0x00;
wLen = 0;
status = LSC_ReadScript(Os_info, read_buf);
if (status != LSCSTATUS_SUCCESS) return status;
if ((read_buf[offset] == TAG_JSBL_HDR_ID) &&
(certf_found != LSCSTATUS_FAILED)) {
// TODO check the SElect cmd response and return status accordingly
ALOGD_IF(ese_debug_enabled, "%s: TAGID: TAG_JSBL_HDR_ID", fn);
offset = offset + 1;
len_byte = Numof_lengthbytes(&read_buf[offset], &wLen);
offset = offset + len_byte;
if (read_buf[offset] == TAG_SIGNATURE_ID) {
offset = offset + 1;
len_byte = Numof_lengthbytes(&read_buf[offset], &wLen);
offset = offset + len_byte;
ALOGD_IF(ese_debug_enabled, "%s: TAGID: TAG_SIGNATURE_ID", fn);
pTranscv_Info->sSendlength = wLen + 5;
pTranscv_Info->sSendData[0] = 0x00;
pTranscv_Info->sSendData[1] = 0xA0;
pTranscv_Info->sSendData[2] = 0x00;
pTranscv_Info->sSendData[3] = 0x00;
pTranscv_Info->sSendData[4] = wLen;
memcpy(&(pTranscv_Info->sSendData[5]), &read_buf[offset], wLen);
ALOGD_IF(ese_debug_enabled, "%s: start transceive for length %ld", fn,
(long)pTranscv_Info->sSendlength);
status = LSC_SendtoLsc(Os_info, status, pTranscv_Info, LS_Sign);
if (status != LSCSTATUS_SUCCESS) {
return status;
}
}
} else if (read_buf[offset] != TAG_JSBL_HDR_ID) {
status = LSCSTATUS_FAILED;
}
} else {
ALOGE("%s : Exit certificate verification failed", fn);
}
ALOGD_IF(ese_debug_enabled, "%s: exit: status=0x%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: LSC_ReadScript
**
** Description: Reads the current line if the script
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_ReadScript(Lsc_ImageInfo_t* Os_info, uint8_t* read_buf) {
static const char fn[] = "LSC_ReadScript";
int32_t wResult = 0, wCount, wIndex = 0;
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
for (wCount = 0; (wCount < 2 && !feof(Os_info->fp)); wCount++, wIndex++) {
wResult = FSCANF_BYTE(Os_info->fp, "%2X", (unsigned int*)&read_buf[wIndex]);
}
if (wResult == 0) return LSCSTATUS_FAILED;
Os_info->bytes_read = Os_info->bytes_read + (wCount * 2);
int32_t lenOff = 1;
if ((read_buf[0] == 0x7f) && (read_buf[1] == 0x21)) {
for (wCount = 0; (wCount < 1 && !feof(Os_info->fp)); wCount++, wIndex++) {
wResult =
FSCANF_BYTE(Os_info->fp, "%2X", (unsigned int*)&read_buf[wIndex]);
}
if (wResult == 0) {
ALOGE("%s: Exit Read Script failed in 7F21 ", fn);
return LSCSTATUS_FAILED;
}
/*Read_Script from wCount*2 to wCount*1 */
Os_info->bytes_read = Os_info->bytes_read + (wCount * 2);
lenOff = 2;
} else if ((read_buf[0] == 0x40) || (read_buf[0] == 0x60)) {
lenOff = 1;
} else {
/*If TAG is neither 7F21 nor 60 nor 40 then ABORT execution*/
ALOGE("%s: Invalid TAG 0x%X found in the script", fn, read_buf[0]);
return LSCSTATUS_FAILED;
}
uint8_t len_byte = 0;
int32_t wLen;
if (read_buf[lenOff] == 0x00) {
ALOGE("%s: Invalid length zero", fn);
len_byte = 0x00;
return LSCSTATUS_FAILED;
} else if ((read_buf[lenOff] & 0x80) == 0x80) {
len_byte = read_buf[lenOff] & 0x0F;
len_byte = len_byte + 1; // 1 byte added for byte 0x81
ALOGD_IF(ese_debug_enabled, "%s: Length byte Read from 0x80 is 0x%x ", fn,
len_byte);
if (len_byte == 0x02) {
for (wCount = 0; (wCount < 1 && !feof(Os_info->fp)); wCount++, wIndex++) {
wResult =
FSCANF_BYTE(Os_info->fp, "%2X", (unsigned int*)&read_buf[wIndex]);
}
if (wResult == 0) {
ALOGE("%s: Exit Read Script failed in length 0x02 ", fn);
return LSCSTATUS_FAILED;
}
wLen = read_buf[lenOff + 1];
Os_info->bytes_read = Os_info->bytes_read + (wCount * 2);
ALOGD_IF(ese_debug_enabled,
"%s: Length of Read Script in len_byte= 0x02 is 0x%x ", fn,
wLen);
} else if (len_byte == 0x03) {
for (wCount = 0; (wCount < 2 && !feof(Os_info->fp)); wCount++, wIndex++) {
wResult =
FSCANF_BYTE(Os_info->fp, "%2X", (unsigned int*)&read_buf[wIndex]);
}
if (wResult == 0) {
ALOGE("%s: Exit Read Script failed in length 0x03 ", fn);
return LSCSTATUS_FAILED;
}
Os_info->bytes_read = Os_info->bytes_read + (wCount * 2);
wLen = read_buf[lenOff + 1]; // Length of the packet send to LSC
wLen = ((wLen << 8) | (read_buf[lenOff + 2]));
ALOGD_IF(ese_debug_enabled,
"%s: Length of Read Script in len_byte= 0x03 is 0x%x ", fn,
wLen);
} else {
/*Need to provide the support if length is more than 2 bytes*/
ALOGE("Length recived is greater than 3");
return LSCSTATUS_FAILED;
}
} else {
len_byte = 0x01;
wLen = read_buf[lenOff];
ALOGE("%s: Length of Read Script in len_byte= 0x01 is 0x%x ", fn, wLen);
}
for (wCount = 0; (wCount < wLen && !feof(Os_info->fp)); wCount++, wIndex++) {
wResult = FSCANF_BYTE(Os_info->fp, "%2X", (unsigned int*)&read_buf[wIndex]);
}
if (wResult == 0) {
ALOGE("%s: Exit Read Script failed in fscanf function ", fn);
return LSCSTATUS_FAILED;
}
Os_info->bytes_read =
Os_info->bytes_read + (wCount * 2) + 1; // not sure why 2 added
ALOGD_IF(ese_debug_enabled, "%s: exit: Num of bytes read=%d and index=%d", fn,
Os_info->bytes_read, wIndex);
return LSCSTATUS_SUCCESS;
}
/*******************************************************************************
**
** Function: LSC_SendtoEse
**
** Description: It is used to send the packet to p61
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_SendtoEse(Lsc_ImageInfo_t* Os_info, LSCSTATUS status,
Lsc_TranscieveInfo_t* pTranscv_Info) {
static const char fn[] = "LSC_SendtoEse";
bool chanl_open_cmd = false;
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
/* Bufferize_load_cmds function is implemented in JCOP */
status = Bufferize_load_cmds(Os_info, status, pTranscv_Info);
if (status != LSCSTATUS_FAILED) {
if (pTranscv_Info->sSendData[1] == 0x70) {
if (pTranscv_Info->sSendData[2] == 0x00) {
chanl_open_cmd = true;
} else {
for (uint8_t cnt = 0; cnt < Os_info->channel_cnt; cnt++) {
if (Os_info->Channel_Info[cnt].channel_id ==
pTranscv_Info->sSendData[3]) {
ALOGD_IF(ese_debug_enabled, "%s: channel 0%x closed", fn,
Os_info->Channel_Info[cnt].channel_id);
Os_info->Channel_Info[cnt].isOpend = false;
}
}
}
}
phNxpEse_data cmdApdu;
phNxpEse_data rspApdu;
phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
cmdApdu.len = (int32_t)(pTranscv_Info->sSendlength);
cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
memcpy(cmdApdu.p_data, pTranscv_Info->sSendData, cmdApdu.len);
ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
if (eseStat != ESESTATUS_SUCCESS) {
ALOGE("%s: Transceive failed; status=0x%X", fn, eseStat);
status = LSCSTATUS_FAILED;
} else {
if (chanl_open_cmd && (rspApdu.len == 0x03) &&
((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
(rspApdu.p_data[rspApdu.len - 1] == 0x00))) {
ALOGD_IF(ese_debug_enabled, "%s: open channel success", fn);
uint8_t cnt = Os_info->channel_cnt;
Os_info->Channel_Info[cnt].channel_id = rspApdu.p_data[rspApdu.len - 3];
Os_info->Channel_Info[cnt].isOpend = true;
Os_info->channel_cnt++;
}
memcpy(pTranscv_Info->sRecvData, rspApdu.p_data, rspApdu.len);
status = Process_EseResponse(pTranscv_Info, rspApdu.len, Os_info);
phNxpEse_free(cmdApdu.p_data);
phNxpEse_free(rspApdu.p_data);
}
} else if (gsSendBack_cmds == false) {
/* Workaround for issue in JCOP, send the fake response back */
int32_t recvBufferActualSize = 0x03;
pTranscv_Info->sRecvData[0] = 0x00;
pTranscv_Info->sRecvData[1] = 0x90;
pTranscv_Info->sRecvData[2] = 0x00;
status = Process_EseResponse(pTranscv_Info, recvBufferActualSize, Os_info);
} else {
if (gsIslastcmdLoad == true) {
status = Send_Backall_Loadcmds(Os_info, status, pTranscv_Info);
gsSendBack_cmds = false;
} else {
memset(gsCmd_Buffer, 0, sizeof(gsCmd_Buffer));
gsSendBack_cmds = false;
status = LSCSTATUS_FAILED;
}
}
ALOGD_IF(ese_debug_enabled, "%s: exit: status=0x%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: LSC_SendtoLsc
**
** Description: It is used to forward the packet to Lsc
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_SendtoLsc(Lsc_ImageInfo_t* Os_info, LSCSTATUS status,
Lsc_TranscieveInfo_t* pTranscv_Info, Ls_TagType tType) {
static const char fn[] = "LSC_SendtoLsc";
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
pTranscv_Info->sSendData[0] = (0x80 | Os_info->Channel_Info[0].channel_id);
pTranscv_Info->timeout = gsTransceiveTimeout;
pTranscv_Info->sRecvlength = 1024;
phNxpEse_data cmdApdu;
phNxpEse_data rspApdu;
phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
cmdApdu.len = pTranscv_Info->sSendlength;
cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
memcpy(cmdApdu.p_data, pTranscv_Info->sSendData, cmdApdu.len);
ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
if (eseStat != ESESTATUS_SUCCESS) {
ALOGE("%s: Transceive failed; status=0x%X", fn, eseStat);
status = LSCSTATUS_FAILED;
} else {
memcpy(pTranscv_Info->sRecvData, rspApdu.p_data, rspApdu.len);
status = LSC_ProcessResp(Os_info, rspApdu.len, pTranscv_Info, tType);
}
phNxpEse_free(cmdApdu.p_data);
phNxpEse_free(rspApdu.p_data);
ALOGD_IF(ese_debug_enabled, "%s: exit: status=0x%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: LSC_CloseChannel
**
** Description: Closes the previously opened logical channel
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_CloseChannel(Lsc_ImageInfo_t* Os_info, LSCSTATUS status,
Lsc_TranscieveInfo_t* pTranscv_Info) {
static const char fn[] = "LSC_CloseChannel";
status = LSCSTATUS_FAILED;
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
if (Os_info == NULL || pTranscv_Info == NULL) {
ALOGE("%s: Invalid parameter", fn);
return LSCSTATUS_FAILED;
}
for (uint8_t cnt = 0; (cnt < Os_info->channel_cnt); cnt++) {
phNxpEse_data cmdApdu;
phNxpEse_data rspApdu;
phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
cmdApdu.len = 5;
cmdApdu.p_data = (uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
if (!Os_info->Channel_Info[cnt].isOpend) continue;
uint8_t xx = 0;
cmdApdu.p_data[xx++] = Os_info->Channel_Info[cnt].channel_id;
cmdApdu.p_data[xx++] = 0x70;
cmdApdu.p_data[xx++] = 0x80;
cmdApdu.p_data[xx++] = Os_info->Channel_Info[cnt].channel_id;
cmdApdu.p_data[xx++] = 0x00;
ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
if (eseStat != ESESTATUS_SUCCESS || rspApdu.len < 2) {
ALOGD_IF(ese_debug_enabled, "%s: Transceive failed; status=0x%X", fn,
eseStat);
} else if ((rspApdu.p_data[rspApdu.len - 2] == 0x90) &&
(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);
status = LSCSTATUS_SUCCESS;
} else {
ALOGD_IF(ese_debug_enabled, "%s: Close channel id = 0x0%x failed", fn,
Os_info->Channel_Info[cnt].channel_id);
}
phNxpEse_free(cmdApdu.p_data);
phNxpEse_free(rspApdu.p_data);
}
ALOGD_IF(ese_debug_enabled, "%s: exit; status=0x0%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: LSC_ProcessResp
**
** Description: Process the response packet received from Lsc
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS LSC_ProcessResp(Lsc_ImageInfo_t* image_info, int32_t recvlen,
Lsc_TranscieveInfo_t* trans_info, Ls_TagType tType) {
static const char fn[] = "LSC_ProcessResp";
uint8_t* RecvData = trans_info->sRecvData;
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
if (RecvData == NULL && recvlen == 0x00) {
ALOGE("%s: Invalid parameter.", fn);
return LSCSTATUS_FAILED;
} else if (recvlen < 2) {
ALOGE("%s: Invalid response.", fn);
return LSCSTATUS_FAILED;
}
char sw[2];
sw[0] = RecvData[recvlen - 2];
sw[1] = RecvData[recvlen - 1];
ALOGD_IF(ese_debug_enabled, "%s: Process Response SW, status = 0x%2X%2X", fn,
sw[0], sw[1]);
/*Update the Global variable for storing response length*/
gsResp_len = recvlen;
if (sw[0] != 0x63) {
gsLsExecuteResp[2] = sw[0];
gsLsExecuteResp[3] = sw[1];
}
LSCSTATUS status = LSCSTATUS_FAILED;
if ((recvlen == 0x02) && (sw[0] == 0x90) && (sw[1] == 0x00)) {
status = Write_Response_To_OutFile(image_info, RecvData, recvlen, tType);
} else if ((recvlen > 0x02) && (sw[0] == 0x90) && (sw[1] == 0x00)) {
status = Write_Response_To_OutFile(image_info, RecvData, recvlen, tType);
} else if ((recvlen > 0x02) && (sw[0] == 0x63) && (sw[1] == 0x10)) {
static int32_t temp_len = 0;
if (temp_len != 0) {
memcpy((trans_info->sTemp_recvbuf + temp_len), RecvData, (recvlen - 2));
trans_info->sSendlength = temp_len + (recvlen - 2);
memcpy(trans_info->sSendData, trans_info->sTemp_recvbuf,
trans_info->sSendlength);
temp_len = 0;
} else {
memcpy(trans_info->sSendData, RecvData, (recvlen - 2));
trans_info->sSendlength = recvlen - 2;
}
status = LSC_SendtoEse(image_info, status, trans_info);
} else if ((recvlen > 0x02) && (sw[0] == 0x63) && (sw[1] == 0x20)) {
uint8_t aid_array[22];
aid_array[0] = recvlen + 3;
aid_array[1] = 00;
aid_array[2] = 0xA4;
aid_array[3] = 0x04;
aid_array[4] = 0x00;
aid_array[5] = recvlen - 2;
memcpy(&aid_array[6], &RecvData[0], recvlen - 2);
memcpy(&ArrayOfAIDs[2][0], &aid_array[0], recvlen + 4);
FILE* fAidMem = fopen(AID_MEM_PATH, "w");
if (fAidMem == NULL) {
ALOGE("%s: Error opening AID data for writing: %s", fn, strerror(errno));
return LSCSTATUS_FAILED;
}
/*Updating the AID_MEM with new value into AID file*/
uint8_t respLen = 0;
int32_t wStatus = 0;
while (respLen <= (recvlen + 4)) {
wStatus = fprintf(fAidMem, "%2x", aid_array[respLen++]);
if (wStatus != 2) {
ALOGE("%s: Invalid Response during fprintf; status=0x%x", fn, wStatus);
fclose(fAidMem);
break;
}
}
if (wStatus == 2) {
status = LSCSTATUS_FILE_NOT_FOUND;
} else {
status = LSCSTATUS_FAILED;
}
} else if ((recvlen >= 0x02) &&
((sw[0] != 0x90) && (sw[0] != 0x63) && (sw[0] != 0x61))) {
Write_Response_To_OutFile(image_info, RecvData, recvlen, tType);
}
ALOGD_IF(ese_debug_enabled, "%s: exit: status=0x%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: Process_EseResponse
**
** Description: It is used to process the received response packet from ESE
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS Process_EseResponse(Lsc_TranscieveInfo_t* pTranscv_Info,
int32_t recv_len, Lsc_ImageInfo_t* Os_info) {
static const char fn[] = "Process_EseResponse";
LSCSTATUS status = LSCSTATUS_SUCCESS;
uint8_t xx = 0;
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
pTranscv_Info->sSendData[xx++] =
(CLA_BYTE | Os_info->Channel_Info[0].channel_id);
pTranscv_Info->sSendData[xx++] = 0xA2;
if (recv_len <= 0xFF) {
pTranscv_Info->sSendData[xx++] = 0x80;
pTranscv_Info->sSendData[xx++] = 0x00;
pTranscv_Info->sSendData[xx++] = (uint8_t)recv_len;
memcpy(&(pTranscv_Info->sSendData[xx]), pTranscv_Info->sRecvData, recv_len);
pTranscv_Info->sSendlength = xx + recv_len;
status = LSC_SendtoLsc(Os_info, status, pTranscv_Info, LS_Comm);
} else {
while (recv_len > MAX_SIZE) {
xx = PARAM_P1_OFFSET;
pTranscv_Info->sSendData[xx++] = 0x00;
pTranscv_Info->sSendData[xx++] = 0x00;
pTranscv_Info->sSendData[xx++] = MAX_SIZE;
recv_len = recv_len - MAX_SIZE;
memcpy(&(pTranscv_Info->sSendData[xx]), pTranscv_Info->sRecvData,
MAX_SIZE);
pTranscv_Info->sSendlength = xx + MAX_SIZE;
/*
* Need not store Process eSE response's response in the out file so
* LS_Comm = 0
*/
status = LSC_SendtoLsc(Os_info, status, pTranscv_Info, LS_Comm);
if (status != LSCSTATUS_SUCCESS) {
ALOGE("%s: Sending packet to Lsc failed: status=0x%x", fn, status);
return status;
}
}
xx = PARAM_P1_OFFSET;
pTranscv_Info->sSendData[xx++] = LAST_BLOCK;
pTranscv_Info->sSendData[xx++] = 0x01;
pTranscv_Info->sSendData[xx++] = recv_len;
memcpy(&(pTranscv_Info->sSendData[xx]), pTranscv_Info->sRecvData, recv_len);
pTranscv_Info->sSendlength = xx + recv_len;
status = LSC_SendtoLsc(Os_info, status, pTranscv_Info, LS_Comm);
}
ALOGD_IF(ese_debug_enabled, "%s: exit: status=0x%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: Process_SelectRsp
**
** Description: It is used to process the received response for SELECT LSC
** cmd.
**
** Returns: Success if ok.
**
*******************************************************************************/
LSCSTATUS Process_SelectRsp(uint8_t* Recv_data, int32_t Recv_len) {
static const char fn[] = "Process_SelectRsp";
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
if (Recv_len < 2) {
ALOGE("%s: Invalid response length %d", fn, Recv_len);
return LSCSTATUS_FAILED;
}
int i = 0;
if (Recv_data[i] != TAG_SELECT_ID) {
ALOGE("%s: Invalid FCI TAG = 0x%x", fn, Recv_data[i]);
return LSCSTATUS_FAILED;
}
i++;
int len = Recv_data[i++];
if (Recv_len < len + 2) {
ALOGE("%s: Invalid response length %d", fn, Recv_len);
return LSCSTATUS_FAILED;
}
if (Recv_data[i] != TAG_LSC_ID) {
ALOGE("%s: Invalid Loader Service AID TAG ID = 0x%x", fn, Recv_data[i]);
return LSCSTATUS_FAILED;
}
i++;
len = Recv_data[i];
i = i + 1 + len; // points to next tag name A5
// points to TAG 9F08 for LS application version
if ((Recv_data[i] != TAG_LS_VER1) || (Recv_data[i + 1] != TAG_LS_VER2)) {
ALOGE("%s: Invalid LS Version = 0x%2X%2X", fn, Recv_data[i],
Recv_data[i + 1]);
return LSCSTATUS_FAILED;
}
uint8_t lsaVersionLen = 0;
i = i + 2;
lsaVersionLen = Recv_data[i];
// points to TAG 9F08 LS application version
i++;
// points to Identifier of the Root Entity key set identifier
i = i + lsaVersionLen;
if (Recv_data[i] != TAG_RE_KEYID) {
ALOGE("%s: Invalid Root entity key set TAG ID = 0x%x", fn, Recv_data[i]);
return LSCSTATUS_FAILED;
}
i = i + 2;
if (Recv_data[i] != TAG_LSRE_ID) {
ALOGE("%s: Invalid Root entity for TAG 42 = 0x%x", fn, Recv_data[i]);
return LSCSTATUS_FAILED;
}
i++;
uint8_t tag42Len = Recv_data[i];
// copy the data including length
memcpy(gsTag42Arr, &Recv_data[i], tag42Len + 1);
i = i + tag42Len + 1;
ALOGD_IF(ese_debug_enabled, "%s: gsTag42Arr %s", fn, gsTag42Arr);
if (Recv_data[i] != TAG_LSRE_SIGNID) {
ALOGE("%s: Invalid Root entity for TAG 45 = 0x%x", fn, Recv_data[i]);
return LSCSTATUS_FAILED;
}
uint8_t tag45Len = Recv_data[i + 1];
memcpy(gsTag45Arr, &Recv_data[i + 1], tag45Len + 1);
ALOGD_IF(ese_debug_enabled, "%s: Exiting", fn);
return LSCSTATUS_SUCCESS;
}
LSCSTATUS Bufferize_load_cmds(__attribute__((unused)) Lsc_ImageInfo_t* Os_info,
__attribute__((unused)) LSCSTATUS status,
Lsc_TranscieveInfo_t* pTranscv_Info) {
static const char fn[] = "Bufferize_load_cmds";
if (gsCmd_count == 0x00) {
if ((pTranscv_Info->sSendData[1] == INSTAL_LOAD_ID) &&
(pTranscv_Info->sSendData[2] == PARAM_P1_OFFSET) &&
(pTranscv_Info->sSendData[3] == 0x00)) {
ALOGD_IF(ese_debug_enabled, "%s: BUffer: install for load", fn);
gspBuffer[0] = pTranscv_Info->sSendlength;
memcpy(&gspBuffer[1], &(pTranscv_Info->sSendData[0]),
pTranscv_Info->sSendlength);
gspBuffer = gspBuffer + pTranscv_Info->sSendlength + 1;
gsCmd_count++;
return LSCSTATUS_FAILED;
}
/* Do not buffer this cmd, Send to eSE */
return LSCSTATUS_SUCCESS;
} else {
uint8_t Param_P2 = gsCmd_count - 1;
if ((pTranscv_Info->sSendData[1] == LOAD_CMD_ID) &&
(pTranscv_Info->sSendData[2] == LOAD_MORE_BLOCKS) &&
(pTranscv_Info->sSendData[3] == Param_P2)) {
ALOGD_IF(ese_debug_enabled, "%s: BUffer: load", fn);
gspBuffer[0] = pTranscv_Info->sSendlength;
memcpy(&gspBuffer[1], &(pTranscv_Info->sSendData[0]),
pTranscv_Info->sSendlength);
gspBuffer = gspBuffer + pTranscv_Info->sSendlength + 1;
gsCmd_count++;
} else if ((pTranscv_Info->sSendData[1] == LOAD_CMD_ID) &&
(pTranscv_Info->sSendData[2] == LOAD_LAST_BLOCK) &&
(pTranscv_Info->sSendData[3] == Param_P2)) {
ALOGD_IF(ese_debug_enabled, "%s: BUffer: last load", fn);
gsSendBack_cmds = true;
gspBuffer[0] = pTranscv_Info->sSendlength;
memcpy(&gspBuffer[1], &(pTranscv_Info->sSendData[0]),
pTranscv_Info->sSendlength);
gspBuffer = gspBuffer + pTranscv_Info->sSendlength + 1;
gsCmd_count++;
gsIslastcmdLoad = true;
} else {
ALOGD_IF(ese_debug_enabled, "%s: BUffer: Not a load cmd", fn);
gsSendBack_cmds = true;
gspBuffer[0] = pTranscv_Info->sSendlength;
memcpy(&gspBuffer[1], &(pTranscv_Info->sSendData[0]),
pTranscv_Info->sSendlength);
gspBuffer = gspBuffer + pTranscv_Info->sSendlength + 1;
gsIslastcmdLoad = false;
gsCmd_count++;
}
}
ALOGD_IF(ese_debug_enabled, "%s: exit", fn);
return LSCSTATUS_FAILED;
}
LSCSTATUS Send_Backall_Loadcmds(Lsc_ImageInfo_t* Os_info, LSCSTATUS status,
Lsc_TranscieveInfo_t* pTranscv_Info) {
static const char fn[] = "Send_Backall_Loadcmds";
status = LSCSTATUS_FAILED;
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
gspBuffer = gsCmd_Buffer; // Points to start of first cmd to send
if (gsCmd_count == 0x00) {
ALOGD_IF(ese_debug_enabled, "%s: No cmds stored to send to eSE", fn);
} else {
while (gsCmd_count-- > 0) {
phNxpEse_data cmdApdu;
phNxpEse_data rspApdu;
phNxpEse_memset(&cmdApdu, 0x00, sizeof(phNxpEse_data));
phNxpEse_memset(&rspApdu, 0x00, sizeof(phNxpEse_data));
cmdApdu.len = (int32_t)(gspBuffer[0]);
cmdApdu.p_data =
(uint8_t*)phNxpEse_memalloc(cmdApdu.len * sizeof(uint8_t));
gspBuffer = gspBuffer + 1 + cmdApdu.len;
memcpy(cmdApdu.p_data, &gspBuffer[1], cmdApdu.len);
ESESTATUS eseStat = phNxpEse_Transceive(&cmdApdu, &rspApdu);
memcpy(pTranscv_Info->sRecvData, rspApdu.p_data, rspApdu.len);
int32_t recvBufferActualSize = rspApdu.len;
phNxpEse_free(cmdApdu.p_data);
phNxpEse_free(rspApdu.p_data);
if (eseStat != LSCSTATUS_SUCCESS || (recvBufferActualSize < 2)) {
ALOGE("%s: Transceive failed; status=0x%X", fn, eseStat);
} else if (gsCmd_count == 0x00) {
// Last command in the buffer
if (gsIslastcmdLoad == false) {
status =
Process_EseResponse(pTranscv_Info, recvBufferActualSize, Os_info);
} else if ((recvBufferActualSize == 0x02) &&
(pTranscv_Info->sRecvData[recvBufferActualSize - 2] ==
0x90) &&
(pTranscv_Info->sRecvData[recvBufferActualSize - 1] ==
0x00)) {
recvBufferActualSize = 0x03;
pTranscv_Info->sRecvData[0] = 0x00;
pTranscv_Info->sRecvData[1] = 0x90;
pTranscv_Info->sRecvData[2] = 0x00;
status =
Process_EseResponse(pTranscv_Info, recvBufferActualSize, Os_info);
} else {
status =
Process_EseResponse(pTranscv_Info, recvBufferActualSize, Os_info);
}
} else if ((recvBufferActualSize == 0x02) &&
(pTranscv_Info->sRecvData[0] == 0x90) &&
(pTranscv_Info->sRecvData[1] == 0x00)) {
/*response ok without data, send next command in the buffer*/
} else if ((recvBufferActualSize == 0x03) &&
(pTranscv_Info->sRecvData[0] == 0x00) &&
(pTranscv_Info->sRecvData[1] == 0x90) &&
(pTranscv_Info->sRecvData[2] == 0x00)) {
/*response ok without data, send next command in the buffer*/
} else if ((pTranscv_Info->sRecvData[recvBufferActualSize - 2] != 0x90) &&
(pTranscv_Info->sRecvData[recvBufferActualSize - 1] != 0x00)) {
/*Error condition hence exiting the loop*/
status =
Process_EseResponse(pTranscv_Info, recvBufferActualSize, Os_info);
/*If the sending of Load fails reset the count*/
gsCmd_count = 0;
break;
}
}
}
memset(gsCmd_Buffer, 0, sizeof(gsCmd_Buffer));
gspBuffer = gsCmd_Buffer; // point back to start of line
gsCmd_count = 0x00;
ALOGD_IF(ese_debug_enabled, "%s: exit: status=0x%x", fn, status);
return status;
}
/*******************************************************************************
**
** Function: Numof_lengthbytes
**
** Description: Checks the number of length bytes and assigns
** length value to wLen.
**
** Returns: Number of Length bytes
**
*******************************************************************************/
uint8_t Numof_lengthbytes(uint8_t* read_buf, int32_t* pLen) {
static const char fn[] = "Numof_lengthbytes";
uint8_t len_byte = 0;
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
if (read_buf[0] == 0x00) {
ALOGE("%s: Invalid length zero", fn);
len_byte = 0x00;
} else if ((read_buf[0] & 0x80) == 0x80) {
len_byte = read_buf[0] & 0x0F;
len_byte = len_byte + 1; // 1 byte added for byte 0x81
} else {
len_byte = 0x01;
}
/* To get the length of the value field */
int32_t wLen = 0;
switch (len_byte) {
case 0:
wLen = read_buf[0];
break;
case 1:
/*1st byte is the length*/
wLen = read_buf[0];
break;
case 2:
/*2nd byte is the length*/
wLen = read_buf[1];
break;
case 3:
/*1st and 2nd bytes are length*/
wLen = read_buf[1];
wLen = ((wLen << 8) | (read_buf[2]));
break;
case 4:
/*3bytes are the length*/
wLen = read_buf[1];
wLen = ((wLen << 16) | (read_buf[2] << 8));
wLen = (wLen | (read_buf[3]));
break;
default:
ALOGE("%s: Invalid length %d.", fn, len_byte);
break;
}
*pLen = wLen;
ALOGD_IF(ese_debug_enabled, "%s: exit; len_bytes=0x0%x, Length=%d", fn,
len_byte, *pLen);
return len_byte;
}
/*******************************************************************************
**
** Function: Write_Response_To_OutFile
**
** Description: Write the response to Out file
** with length recvlen from buffer RecvData.
**
** Returns: Success if OK
**
*******************************************************************************/
LSCSTATUS Write_Response_To_OutFile(Lsc_ImageInfo_t* image_info,
uint8_t* RecvData, int32_t recvlen,
Ls_TagType tType) {
static const char fn[] = "Write_Response_to_OutFile";
ALOGD_IF(ese_debug_enabled, "%s: Enter", fn);
/*If the Response out file is NULL or Other than LS commands*/
if ((image_info->bytes_wrote == 0x55) || (tType == LS_Default)) {
return LSCSTATUS_SUCCESS;
}
uint8_t tag43Len = 1;
/*Certificate TAG occupies 2 bytes*/
if (tType == LS_Cert) {
tag43Len = 2;
}
/* |TAG|LEN| VAL |
* |61 |XX |TAG|LEN| VAL |TAG| LEN | VAL |
* |43 |1/2|7F21/60/40|44 |apduRespLen|apduResponse|
*/
int32_t tag44Len = 0;
uint8_t ucTag44[3] = {0x00, 0x00, 0x00};
int32_t tag61Len = 0;
uint8_t tag43off = 0;
uint8_t tag44off = 0;
uint8_t tagLen = 0;
uint8_t tagBuffer[12] = {0x61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
if (recvlen < 0x80) {
tag44Len = 1;
ucTag44[0] = recvlen;
tag61Len = recvlen + 4 + tag43Len;
if (tag61Len & 0x80) {
tagBuffer[1] = 0x81;
tagBuffer[2] = tag61Len;
tag43off = 3;
tag44off = 5 + tag43Len;
tagLen = tag44off + 2;
} else {
tagBuffer[1] = tag61Len;
tag43off = 2;
tag44off = 4 + tag43Len;
tagLen = tag44off + 2;
}
} else if ((recvlen >= 0x80) && (recvlen <= 0xFF)) {
ucTag44[0] = 0x81;
ucTag44[1] = recvlen;
tag61Len = recvlen + 5 + tag43Len;
tag44Len = 2;
if ((tag61Len & 0xFF00) != 0) {
tagBuffer[1] = 0x82;
tagBuffer[2] = (tag61Len & 0xFF00) >> 8;
tagBuffer[3] = (tag61Len & 0xFF);
tag43off = 4;
tag44off = 6 + tag43Len;
tagLen = tag44off + 3;
} else {
tagBuffer[1] = 0x81;
tagBuffer[2] = (tag61Len & 0xFF);
tag43off = 3;
tag44off = 5 + tag43Len;
tagLen = tag44off + 3;
}
} else if ((recvlen > 0xFF) && (recvlen <= 0xFFFF)) {
ucTag44[0] = 0x82;
ucTag44[1] = (recvlen & 0xFF00) >> 8;
ucTag44[2] = (recvlen & 0xFF);
tag44Len = 3;
tag61Len = recvlen + 6 + tag43Len;
if ((tag61Len & 0xFF00) != 0) {
tagBuffer[1] = 0x82;
tagBuffer[2] = (tag61Len & 0xFF00) >> 8;
tagBuffer[3] = (tag61Len & 0xFF);
tag43off = 4;
tag44off = 6 + tag43Len;
tagLen = tag44off + 4;
}
}
tagBuffer[tag43off] = 0x43;
tagBuffer[tag43off + 1] = tag43Len;
tagBuffer[tag44off] = 0x44;
memcpy(&tagBuffer[tag44off + 1], &ucTag44[0], tag44Len);
if (tType == LS_Cert) {
tagBuffer[tag43off + 2] = 0x7F;
tagBuffer[tag43off + 3] = 0x21;
} else if (tType == LS_Sign) {
tagBuffer[tag43off + 2] = 0x60;
} else if (tType == LS_Comm) {
tagBuffer[tag43off + 2] = 0x40;
} else {
/*Do nothing*/
}
uint8_t tempLen = 0;
LSCSTATUS wStatus = LSCSTATUS_FAILED;
int32_t status = 0;
while (tempLen < tagLen) {
status = fprintf(image_info->fResp, "%02X", tagBuffer[tempLen++]);
if (status != 2) {
ALOGE("%s: Invalid Response during fprintf; status=0x%x", fn, (status));
wStatus = LSCSTATUS_FAILED;
break;
}
}
/*Updating the response data into out script*/
int32_t respLen = 0;
while (respLen < recvlen) {
status = fprintf(image_info->fResp, "%02X", RecvData[respLen++]);
if (status != 2) {
ALOGE("%s: Invalid Response during fprintf; status=0x%x", fn, (status));
wStatus = LSCSTATUS_FAILED;
break;
}
}
if (status == 2) {
fprintf(image_info->fResp, "%s\n", "");
ALOGD_IF(ese_debug_enabled,
"%s: SUCCESS Response written to script out file", fn);
wStatus = LSCSTATUS_SUCCESS;
}
fflush(image_info->fResp);
return wStatus;
}
/*******************************************************************************
**
** Function: Check_Certificate_Tag
**
** Description: Check certificate Tag presence in script
** by 7F21 .
**
** Returns: Success if Tag found
**
*******************************************************************************/
LSCSTATUS Check_Certificate_Tag(uint8_t* read_buf, uint16_t* offset1) {
static const char fn[] = "Check_Certificate_Tag";
uint16_t offset = *offset1;
if (((read_buf[offset] << 8 | read_buf[offset + 1]) == TAG_CERTIFICATE)) {
ALOGD_IF(ese_debug_enabled, "%s: TAGID: TAG_CERTIFICATE", fn);
int32_t wLen;
offset = offset + 2;
uint16_t len_byte = Numof_lengthbytes(&read_buf[offset], &wLen);
offset = offset + len_byte;
*offset1 = offset;
if (wLen <= MAX_CERT_LEN) return LSCSTATUS_SUCCESS;
}
return LSCSTATUS_FAILED;
}
/*******************************************************************************
**
** Function: Check_SerialNo_Tag
**
** Description: Check Serial number Tag presence in script
** by 0x93 .
**
** Returns: Success if Tag found
**
*******************************************************************************/
LSCSTATUS Check_SerialNo_Tag(uint8_t* read_buf, uint16_t* offset1) {
static const char fn[] = "Check_SerialNo_Tag";
uint16_t offset = *offset1;
if (read_buf[offset] == TAG_SERIAL_NO) {
ALOGD_IF(ese_debug_enabled, "%s: TAGID: TAG_SERIAL_NO", fn);
uint8_t serNoLen = read_buf[offset + 1];
offset = offset + serNoLen + 2;
*offset1 = offset;
ALOGD_IF(ese_debug_enabled, "%s: TAG_LSROOT_ENTITY is %x", fn,
read_buf[offset]);
return LSCSTATUS_SUCCESS;
}
return LSCSTATUS_FAILED;
}
/*******************************************************************************
**
** Function: Check_LSRootID_Tag
**
** Description: Check LS root ID tag presence in script and compare with
** select response root ID value.
**
** Returns: Success if Tag found
**
*******************************************************************************/
LSCSTATUS Check_LSRootID_Tag(uint8_t* read_buf, uint16_t* offset1) {
static const char fn[] = "Check_LSRootID_Tag";
uint16_t offset = *offset1;
if (read_buf[offset] == TAG_LSRE_ID) {
ALOGD_IF(ese_debug_enabled, "%s: TAGID: TAG_LSROOT_ENTITY", fn);
if (gsTag42Arr[0] == read_buf[offset + 1]) {
uint8_t tag42Len = read_buf[offset + 1];
offset = offset + 2;
if (!memcmp(&read_buf[offset], &gsTag42Arr[1], gsTag42Arr[0])) {
ALOGD_IF(ese_debug_enabled, "%s : TAG 42 verified", fn);
offset = offset + tag42Len;
*offset1 = offset;
return LSCSTATUS_SUCCESS;
}
}
}
return LSCSTATUS_FAILED;
}
/*******************************************************************************
**
** Function: Check_CertHoldID_Tag
**
** Description: Check certificate holder ID tag presence in script.
**
** Returns: Success if Tag found
**
*******************************************************************************/
LSCSTATUS Check_CertHoldID_Tag(uint8_t* read_buf, uint16_t* offset1) {
static const char fn[] = "Check_CertHoldID_Tag";
uint16_t offset = *offset1;
if ((read_buf[offset] << 8 | read_buf[offset + 1]) == TAG_CERTFHOLD_ID) {
uint8_t certfHoldIDLen = 0;
ALOGD_IF(ese_debug_enabled, "%s: TAGID: TAG_CERTFHOLD_ID", fn);
certfHoldIDLen = read_buf[offset + 2];
offset = offset + certfHoldIDLen + 3;
if (read_buf[offset] == TAG_KEY_USAGE) {
ALOGD_IF(ese_debug_enabled, "%s: TAGID: TAG_KEY_USAGE", fn);
uint8_t keyusgLen = read_buf[offset + 1];
offset = offset + keyusgLen + 2;
*offset1 = offset;
return LSCSTATUS_SUCCESS;
}
}
return LSCSTATUS_FAILED;
}
/*******************************************************************************
**
** Function: Check_Date_Tag
**
** Description: Check date tags presence in script.
**
** Returns: Success if Tag found
**
*******************************************************************************/
LSCSTATUS Check_Date_Tag(uint8_t* read_buf, uint16_t* offset1) {
static const char fn[] = "Check_Date_Tag";
LSCSTATUS status = LSCSTATUS_FAILED;
uint16_t offset = *offset1;
if ((read_buf[offset] << 8 | read_buf[offset + 1]) == TAG_EFF_DATE) {
uint8_t effDateLen = read_buf[offset + 2];
offset = offset + 3 + effDateLen;
ALOGD_IF(ese_debug_enabled, "%s: TAGID: TAG_EFF_DATE", fn);
if ((read_buf[offset] << 8 | read_buf[offset + 1]) == TAG_EXP_DATE) {
uint8_t effExpLen = read_buf[offset + 2];
offset = offset + 3 + effExpLen;
ALOGD_IF(ese_debug_enabled, "%s: TAGID: TAG_EXP_DATE", fn);
status = LSCSTATUS_SUCCESS;
} else if (read_buf[offset] == TAG_LSRE_SIGNID) {
status = LSCSTATUS_SUCCESS;
}
} else if ((read_buf[offset] << 8 | read_buf[offset + 1]) == TAG_EXP_DATE) {
uint8_t effExpLen = read_buf[offset + 2];
offset = offset + 3 + effExpLen;
ALOGD_IF(ese_debug_enabled, "%s: TAGID: TAG_EXP_DATE", fn);
status = LSCSTATUS_SUCCESS;
} else if (read_buf[offset] == TAG_LSRE_SIGNID) {
status = LSCSTATUS_SUCCESS;
} else {
/*LSCSTATUS_FAILED*/
}
*offset1 = offset;
return status;
}
/*******************************************************************************
**
** Function: Check_45_Tag
**
** Description: Check 45 tags presence in script and compare the value
** with select response tag 45 value
**
** Returns: Success if Tag found
**
*******************************************************************************/
LSCSTATUS Check_45_Tag(uint8_t* read_buf, uint16_t* offset1,
uint8_t* tag45Len) {
static const char fn[] = "Check_45_Tag";
uint16_t offset = *offset1;
if (read_buf[offset] == TAG_LSRE_SIGNID) {
*tag45Len = read_buf[offset + 1];
offset = offset + 2;
if (gsTag45Arr[0] == *tag45Len) {
if (!memcmp(&read_buf[offset], &gsTag45Arr[1], gsTag45Arr[0])) {
*offset1 = offset;
ALOGD_IF(ese_debug_enabled,
"%s: LSC_Check_KeyIdentifier : TAG 45 verified", fn);
return LSCSTATUS_SUCCESS;
}
}
}
return LSCSTATUS_FAILED;
}
/*******************************************************************************
**
** Function: Certificate_Verification
**
** Description: Perform the certificate verification by forwarding it to
** LS applet.
**
** Returns: Success if certificate is verified
**
*******************************************************************************/
LSCSTATUS Certificate_Verification(Lsc_ImageInfo_t* Os_info,
Lsc_TranscieveInfo_t* pTranscv_Info,
uint8_t* read_buf, uint16_t* offset1,
uint8_t* tag45Len) {
static const char fn[] = "Certificate_Verification";
pTranscv_Info->sSendData[0] = 0x80;
pTranscv_Info->sSendData[1] = 0xA0;
pTranscv_Info->sSendData[2] = 0x01;
pTranscv_Info->sSendData[3] = 0x00;
int32_t wCertfLen = (read_buf[2] << 8 | read_buf[3]);
uint16_t offset = *offset1;
/*If the certificate is less than 255 bytes*/
if (wCertfLen <= 251) {
uint8_t tag7f49Off = 0;
uint8_t u7f49Len = 0;
uint8_t tag5f37Len = 0;
ALOGD_IF(ese_debug_enabled, "%s: Certificate is less than 255", fn);
offset = offset + *tag45Len;
ALOGD_IF(ese_debug_enabled, "%s: Before TAG_CCM_PERMISSION = %x", fn,
read_buf[offset]);
if (read_buf[offset] != TAG_CCM_PERMISSION) {
return LSCSTATUS_FAILED;
}
int32_t tag53Len = 0;
uint8_t len_byte = 0;
offset = offset + 1;
len_byte = Numof_lengthbytes(&read_buf[offset], &tag53Len);
offset = offset + tag53Len + len_byte;
ALOGD_IF(ese_debug_enabled, "%s: Verified TAG TAG_CCM_PERMISSION = 0x53",
fn);
if ((uint16_t)(read_buf[offset] << 8 | read_buf[offset + 1]) !=
TAG_SIG_RNS_COMP) {
return LSCSTATUS_FAILED;
}
tag7f49Off = offset;
u7f49Len = read_buf[offset + 2];
offset = offset + 3 + u7f49Len;
if (u7f49Len != 64) {
return LSCSTATUS_FAILED;
}
if ((uint16_t)(read_buf[offset] << 8 | read_buf[offset + 1]) != 0x7f49) {
return LSCSTATUS_FAILED;
}
tag5f37Len = read_buf[offset + 2];
if (read_buf[offset + 3] != 0x86 || (read_buf[offset + 4] != 65)) {
return LSCSTATUS_FAILED;
}
uint8_t tag_len_byte = Numof_lengthbytes(&read_buf[2], &wCertfLen);
pTranscv_Info->sSendData[4] = wCertfLen + 2 + tag_len_byte;
pTranscv_Info->sSendlength = wCertfLen + 7 + tag_len_byte;
memcpy(&(pTranscv_Info->sSendData[5]), &read_buf[0],
wCertfLen + 2 + tag_len_byte);
ALOGD_IF(ese_debug_enabled, "%s: start transceive for length %d", fn,
pTranscv_Info->sSendlength);
LSCSTATUS status = LSCSTATUS_FAILED;
status = LSC_SendtoLsc(Os_info, status, pTranscv_Info, LS_Cert);
if (status == LSCSTATUS_SUCCESS) {
ALOGD_IF(ese_debug_enabled, "%s: Certificate is verified", fn);
}
return status;
} else {
/*If the certificate is more than 255 bytes*/
uint8_t tag7f49Off = 0;
uint8_t u7f49Len = 0;
uint8_t tag5f37Len = 0;
ALOGD_IF(ese_debug_enabled, "%s: Certificate is greater than 255", fn);
offset = offset + *tag45Len;
ALOGD_IF(ese_debug_enabled, "%s: Before TAG_CCM_PERMISSION = %x", fn,
read_buf[offset]);
if (read_buf[offset] != TAG_CCM_PERMISSION) {
return LSCSTATUS_FAILED;
}
int32_t tag53Len = 0;
uint8_t len_byte = 0;
offset = offset + 1;
len_byte = Numof_lengthbytes(&read_buf[offset], &tag53Len);
offset = offset + tag53Len + len_byte;
ALOGD_IF(ese_debug_enabled, "%s: Verified TAG TAG_CCM_PERMISSION = 0x53",
fn);
if ((uint16_t)(read_buf[offset] << 8 | read_buf[offset + 1]) !=
TAG_SIG_RNS_COMP) {
return LSCSTATUS_FAILED;
}
tag7f49Off = offset;
u7f49Len = read_buf[offset + 2];
offset = offset + 3 + u7f49Len;
if (u7f49Len != 64) {
return LSCSTATUS_FAILED;
}
if ((uint16_t)(read_buf[offset] << 8 | read_buf[offset + 1]) != 0x7f49) {
return LSCSTATUS_FAILED;
}
tag5f37Len = read_buf[offset + 2];
if (read_buf[offset + 3] != 0x86 || (read_buf[offset + 4] != 65)) {
return LSCSTATUS_FAILED;
}
pTranscv_Info->sSendData[4] = tag7f49Off;
memcpy(&(pTranscv_Info->sSendData[5]), &read_buf[0], tag7f49Off);
pTranscv_Info->sSendlength = tag7f49Off + 5;
ALOGD_IF(ese_debug_enabled, "%s: start transceive for length %d", fn,
pTranscv_Info->sSendlength);
LSCSTATUS status = LSCSTATUS_FAILED;
status = LSC_SendtoLsc(Os_info, status, pTranscv_Info, LS_Default);
if (status != LSCSTATUS_SUCCESS) {
uint8_t* RecvData = pTranscv_Info->sRecvData;
Write_Response_To_OutFile(Os_info, RecvData, gsResp_len, LS_Cert);
return status;
}
pTranscv_Info->sSendData[2] = 0x00;
pTranscv_Info->sSendData[4] = u7f49Len + tag5f37Len + 6;
memcpy(&(pTranscv_Info->sSendData[5]), &read_buf[tag7f49Off],
u7f49Len + tag5f37Len + 6);
pTranscv_Info->sSendlength = u7f49Len + tag5f37Len + 11;
ALOGD_IF(ese_debug_enabled, "%s: start transceive for length %d", fn,
pTranscv_Info->sSendlength);
status = LSC_SendtoLsc(Os_info, status, pTranscv_Info, LS_Cert);
if (status == LSCSTATUS_SUCCESS) {
ALOGD_IF(ese_debug_enabled, "Certificate is verified");
}
return status;
}
return LSCSTATUS_FAILED;
}
/*******************************************************************************
**
** Function: Check_Complete_7F21_Tag
**
** Description: Traverses the 7F21 tag for verification of each sub tag with
** in the 7F21 tag.
**
** Returns: Success if all tags are verified
**
*******************************************************************************/
LSCSTATUS Check_Complete_7F21_Tag(Lsc_ImageInfo_t* Os_info,
Lsc_TranscieveInfo_t* pTranscv_Info,
uint8_t* read_buf, uint16_t* offset) {
static const char fn[] = "Check_Complete_7F21_Tag";
if (LSCSTATUS_SUCCESS != Check_Certificate_Tag(read_buf, offset)) {
ALOGE("%s: FAILED in Check_Certificate_Tag", fn);
return LSCSTATUS_FAILED;
}
if (LSCSTATUS_SUCCESS != Check_SerialNo_Tag(read_buf, offset)) {
ALOGE("%s: FAILED in Check_SerialNo_Tag", fn);
return LSCSTATUS_FAILED;
}
if (LSCSTATUS_SUCCESS != Check_LSRootID_Tag(read_buf, offset)) {
ALOGE("%s: FAILED in Check_LSRootID_Tag", fn);
return LSCSTATUS_FAILED;
}
if (LSCSTATUS_SUCCESS != Check_CertHoldID_Tag(read_buf, offset)) {
ALOGE("%s: FAILED in Check_CertHoldID_Tag", fn);
return LSCSTATUS_FAILED;
}
if (LSCSTATUS_SUCCESS != Check_Date_Tag(read_buf, offset)) {
ALOGE("%s: FAILED in Check_CertHoldID_Tag", fn);
return LSCSTATUS_FAILED;
}
uint8_t tag45Len = 0;
if (LSCSTATUS_SUCCESS != Check_45_Tag(read_buf, offset, &tag45Len)) {
ALOGE("%s: FAILED in Check_CertHoldID_Tag", fn);
return LSCSTATUS_FAILED;
}
if (LSCSTATUS_SUCCESS != Certificate_Verification(Os_info, pTranscv_Info,
read_buf, offset,
&tag45Len)) {
ALOGE("%s: FAILED in Certificate_Verification", fn);
return LSCSTATUS_FAILED;
}
return LSCSTATUS_SUCCESS;
}
/*******************************************************************************
**
** Function: LSC_UpdateExeStatus
**
** Description: Updates LSC status to a file
**
** Returns: true if success else false
**
*******************************************************************************/
bool LSC_UpdateExeStatus(uint16_t status) {
static const char fn[] = "LSC_UpdateExeStatus";
ALOGD_IF(ese_debug_enabled, "%s: enter", fn);
FILE* fLsStatus = fopen(LS_STATUS_PATH, "w+");
if (fLsStatus == NULL) {
ALOGE("%s: Error opening LS Status file for backup: %s", fn,
strerror(errno));
return false;
}
if ((fprintf(fLsStatus, "%04x", status)) != 4) {
ALOGE("%s: Error updating LS Status backup: %s", fn, strerror(errno));
fclose(fLsStatus);
return false;
}
fclose(fLsStatus);
ALOGD_IF(ese_debug_enabled, "%s: exit", fn);
return true;
}
/*******************************************************************************
**
** Function: Get_LsStatus
**
** Description: Interface to fetch Loader service client status to JNI,
** Services
**
** Returns: SUCCESS/FAILURE
**
*******************************************************************************/
LSCSTATUS Get_LsStatus(uint8_t* pStatus) {
static const char fn[] = "Get_LsStatus";
FILE* fLsStatus = fopen(LS_STATUS_PATH, "r");
if (fLsStatus == NULL) {
ALOGE("%s: Error opening LS Status file for backup: %s", fn,
strerror(errno));
return LSCSTATUS_FAILED;
}
uint8_t lsStatus[2] = {0x63, 0x40};
for (uint8_t loopcnt = 0; loopcnt < 2; loopcnt++) {
if ((FSCANF_BYTE(fLsStatus, "%2x", &lsStatus[loopcnt])) == 0) {
ALOGE("%s: Error updating LS Status backup: %s", fn, strerror(errno));
fclose(fLsStatus);
return LSCSTATUS_FAILED;
}
}
ALOGD_IF(ese_debug_enabled, "%s: LS Status 0x%X 0x%X", fn, lsStatus[0],
lsStatus[1]);
memcpy(pStatus, lsStatus, 2);
fclose(fLsStatus);
return LSCSTATUS_SUCCESS;
}