/* * Copyright (C) 2015 NXP Semiconductors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include pAla_Dwnld_Context_t gpAla_Dwnld_Context=NULL; extern INT32 gTransceiveTimeout; #ifdef JCOP3_WR UINT8 Cmd_Buffer[64*1024]; static INT32 cmd_count = 0; bool islastcmdLoad; bool SendBack_cmds = false; UINT8 *pBuffer; #endif BOOLEAN mIsInit; UINT8 Select_Rsp[1024]; UINT8 Jsbl_RefKey[256]; UINT8 Jsbl_keylen; #if(NXP_LDR_SVC_VER_2 == TRUE) UINT8 StoreData[22]; #else UINT8 StoreData[34]; #endif int Select_Rsp_Len; #if(NXP_LDR_SVC_VER_2 == TRUE) UINT8 lsVersionArr[2]; UINT8 tag42Arr[17]; UINT8 tag45Arr[9]; UINT8 lsExecuteResp[4]; UINT8 AID_ARRAY[22]; INT32 resp_len = 0; FILE *fAID_MEM = NULL; FILE *fLS_STATUS = NULL; UINT8 lsGetStatusArr[2]; tJBL_STATUS (*ls_GetStatus_seqhandler[])(Ala_ImageInfo_t *pContext, tJBL_STATUS status, Ala_TranscieveInfo_t *pInfo)= { ALA_OpenChannel, ALA_SelectAla, ALA_getAppletLsStatus, ALA_CloseChannel, NULL }; #endif tJBL_STATUS (*Applet_load_seqhandler[])(Ala_ImageInfo_t *pContext, tJBL_STATUS status, Ala_TranscieveInfo_t *pInfo)= { ALA_OpenChannel, ALA_SelectAla, ALA_StoreData, ALA_loadapplet, NULL }; tJBL_STATUS (*Jsblcer_id_seqhandler[])(Ala_ImageInfo_t *pContext, tJBL_STATUS status, Ala_TranscieveInfo_t *pInfo)= { ALA_OpenChannel, ALA_SelectAla, ALA_CloseChannel, NULL }; /******************************************************************************* ** ** Function: initialize ** ** Description: Initialize all member variables. ** native: Native data. ** ** Returns: True if ok. ** *******************************************************************************/ BOOLEAN initialize (IChannel_t* channel) { static const char fn [] = "Ala_initialize"; ALOGD ("%s: enter", fn); gpAla_Dwnld_Context = (pAla_Dwnld_Context_t)malloc(sizeof(Ala_Dwnld_Context_t)); if(gpAla_Dwnld_Context != NULL) { memset((void *)gpAla_Dwnld_Context, 0, (UINT32)sizeof(Ala_Dwnld_Context_t)); } else { ALOGD("%s: Memory allocation failed", fn); return (FALSE); } gpAla_Dwnld_Context->mchannel = channel; #ifdef JCOP3_WR cmd_count = 0; SendBack_cmds = false; islastcmdLoad = false; #endif #if(NXP_LDR_SVC_VER_2 == TRUE) fAID_MEM = fopen(AID_MEM_PATH,"r"); if(fAID_MEM == NULL) { ALOGD("%s: AID data file does not exists", fn); memcpy(&ArrayOfAIDs[2][1],&SelectAla[0],sizeof(SelectAla)); ArrayOfAIDs[2][0] = sizeof(SelectAla); } else { /*Change is required aidLen = 0x00*/ UINT8 aidLen = 0x00; INT32 wStatus = 0; while(!(feof(fAID_MEM))) { /*the length is not incremented*/ wStatus = FSCANF_BYTE(fAID_MEM,"%2x",&ArrayOfAIDs[2][aidLen++]); if(wStatus == 0) { ALOGE ("%s: exit: Error during read AID data", fn); fclose(fAID_MEM); return FALSE; } } ArrayOfAIDs[2][0] = aidLen - 1; fclose(fAID_MEM); } lsExecuteResp[0] = TAG_LSES_RESP; lsExecuteResp[1] = TAG_LSES_RSPLEN; lsExecuteResp[2] = LS_ABORT_SW1; lsExecuteResp[3] = LS_ABORT_SW2; #endif #ifdef JCOP3_WR pBuffer = Cmd_Buffer; #endif mIsInit = TRUE; ALOGD ("%s: exit", fn); return (TRUE); } /******************************************************************************* ** ** Function: finalize ** ** Description: Release all resources. ** ** Returns: None ** *******************************************************************************/ void finalize () { static const char fn [] = "Ala_finalize"; ALOGD ("%s: enter", fn); mIsInit = FALSE; if(gpAla_Dwnld_Context != NULL) { gpAla_Dwnld_Context->mchannel = NULL; free(gpAla_Dwnld_Context); gpAla_Dwnld_Context = NULL; } ALOGD ("%s: exit", fn); } /******************************************************************************* ** ** Function: Perform_ALA ** ** Description: Performs the ALA download sequence ** ** Returns: Success if ok. ** *******************************************************************************/ #if(NXP_LDR_SVC_VER_2 == TRUE) tJBL_STATUS Perform_ALA(const char *name,const char *dest, const UINT8 *pdata, UINT16 len, UINT8 *respSW) #else tJBL_STATUS Perform_ALA(const char *name, const UINT8 *pdata, UINT16 len) #endif { static const char fn [] = "Perform_ALA"; static const char Ala_path[] = APPLET_PATH; tJBL_STATUS status = STATUS_FAILED; ALOGD ("%s: enter; sha-len=%d", fn, len); if(mIsInit == false) { ALOGD ("%s: ALA lib is not initialized", fn); status = STATUS_FAILED; } else if((pdata == NULL) || (len == 0x00)) { ALOGD ("%s: Invalid SHA-data", fn); } else { StoreData[0] = STORE_DATA_TAG; StoreData[1] = len; memcpy(&StoreData[2], pdata, len); #if(NXP_LDR_SVC_VER_2 == TRUE) status = ALA_update_seq_handler(Applet_load_seqhandler, name, dest); if((status != STATUS_OK)&&(lsExecuteResp[2] == 0x90)&& (lsExecuteResp[3] == 0x00)) { lsExecuteResp[2] = LS_ABORT_SW1; lsExecuteResp[3] = LS_ABORT_SW2; } memcpy(&respSW[0],&lsExecuteResp[0],4); ALOGD ("%s: lsExecuteScript Response SW=%2x%2x",fn, lsExecuteResp[2], lsExecuteResp[3]); #else status = ALA_update_seq_handler(Applet_load_seqhandler, name); #endif } ALOGD("%s: exit; status=0x0%x", fn, status); return status; } #if(NXP_LDR_SVC_VER_2 == FALSE) /******************************************************************************* ** ** Function: GetJsbl_Certificate_ID ** ** Description: Performs the GetJsbl_Certificate_ID sequence ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS GetJsbl_Certificate_Refkey(UINT8 *pKey, INT32 *pKeylen) { static const char fn [] = "GetJsbl_Certificate_ID"; tJBL_STATUS status = STATUS_FAILED; ALOGD ("%s: enter", fn); if(mIsInit == false) { ALOGD ("%s: ALA lib is not initialized", fn); status = STATUS_FAILED; } else { status = JsblCerId_seq_handler(Jsblcer_id_seqhandler); if(status == STATUS_SUCCESS) { if(Jsbl_keylen != 0x00) { *pKeylen = (INT32)Jsbl_keylen; memcpy(pKey, Jsbl_RefKey, Jsbl_keylen); Jsbl_keylen = 0; } } } ALOGD("%s: exit; status=0x0%x", fn, status); return status; } /******************************************************************************* ** ** Function: JsblCerId_seq_handler ** ** Description: Performs get JSBL Certificate Identifier sequence ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS JsblCerId_seq_handler(tJBL_STATUS (*seq_handler[])(Ala_ImageInfo_t* pContext, tJBL_STATUS status, Ala_TranscieveInfo_t* pInfo)) { static const char fn[] = "JsblCerId_seq_handler"; UINT16 seq_counter = 0; Ala_ImageInfo_t update_info = (Ala_ImageInfo_t )gpAla_Dwnld_Context->Image_info; Ala_TranscieveInfo_t trans_info = (Ala_TranscieveInfo_t )gpAla_Dwnld_Context->Transcv_Info; tJBL_STATUS status = STATUS_FAILED; ALOGD("%s: enter", fn); while((seq_handler[seq_counter]) != NULL ) { status = STATUS_FAILED; status = (*(seq_handler[seq_counter]))(&update_info, status, &trans_info ); if(STATUS_SUCCESS != status) { ALOGE("%s: exiting; status=0x0%X", fn, status); break; } seq_counter++; } ALOGE("%s: exit; status=0x%x", fn, status); return status; } #else /******************************************************************************* ** ** Function: GetLs_Version ** ** Description: Performs the GetLs_Version sequence ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS GetLs_Version(UINT8 *pVersion) { static const char fn [] = "GetLs_Version"; tJBL_STATUS status = STATUS_FAILED; ALOGD ("%s: enter", fn); if(mIsInit == false) { ALOGD ("%s: ALA lib is not initialized", fn); status = STATUS_FAILED; } else { status = GetVer_seq_handler(Jsblcer_id_seqhandler); if(status == STATUS_SUCCESS) { pVersion[0] = 2; pVersion[1] = 0; memcpy(&pVersion[2], lsVersionArr, sizeof(lsVersionArr)); ALOGD("%s: GetLsVersion is =0x0%x%x", fn, lsVersionArr[0],lsVersionArr[1]); } } ALOGD("%s: exit; status=0x0%x", fn, status); return status; } /******************************************************************************* ** ** Function: Get_LsAppletStatus ** ** Description: Performs the Get_LsAppletStatus sequence ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS Get_LsAppletStatus(UINT8 *pVersion) { static const char fn [] = "GetLs_Version"; tJBL_STATUS status = STATUS_FAILED; ALOGD ("%s: enter", fn); if(mIsInit == false) { ALOGD ("%s: ALA lib is not initialized", fn); status = STATUS_FAILED; } else { status = GetLsStatus_seq_handler(ls_GetStatus_seqhandler); if(status == STATUS_SUCCESS) { pVersion[0] = lsGetStatusArr[0]; pVersion[1] = lsGetStatusArr[1]; ALOGD("%s: GetLsAppletStatus is =0x0%x%x", fn, lsGetStatusArr[0],lsGetStatusArr[1]); } } ALOGD("%s: exit; status=0x0%x", fn, status); return status; } /******************************************************************************* ** ** Function: GetVer_seq_handler ** ** Description: Performs GetVer_seq_handler sequence ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS GetVer_seq_handler(tJBL_STATUS (*seq_handler[])(Ala_ImageInfo_t* pContext, tJBL_STATUS status, Ala_TranscieveInfo_t* pInfo)) { static const char fn[] = "GetVer_seq_handler"; UINT16 seq_counter = 0; Ala_ImageInfo_t update_info = (Ala_ImageInfo_t )gpAla_Dwnld_Context->Image_info; Ala_TranscieveInfo_t trans_info = (Ala_TranscieveInfo_t )gpAla_Dwnld_Context->Transcv_Info; tJBL_STATUS status = STATUS_FAILED; ALOGD("%s: enter", fn); while((seq_handler[seq_counter]) != NULL ) { status = STATUS_FAILED; status = (*(seq_handler[seq_counter]))(&update_info, status, &trans_info ); if(STATUS_SUCCESS != status) { ALOGE("%s: exiting; status=0x0%X", fn, status); break; } seq_counter++; } ALOGE("%s: exit; status=0x%x", fn, status); return status; } /******************************************************************************* ** ** Function: GetLsStatus_seq_handler ** ** Description: Performs GetVer_seq_handler sequence ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS GetLsStatus_seq_handler(tJBL_STATUS (*seq_handler[])(Ala_ImageInfo_t* pContext, tJBL_STATUS status, Ala_TranscieveInfo_t* pInfo)) { static const char fn[] = "ls_GetStatus_seqhandler"; UINT16 seq_counter = 0; Ala_ImageInfo_t update_info = (Ala_ImageInfo_t )gpAla_Dwnld_Context->Image_info; Ala_TranscieveInfo_t trans_info = (Ala_TranscieveInfo_t )gpAla_Dwnld_Context->Transcv_Info; tJBL_STATUS status = STATUS_FAILED; ALOGD("%s: enter", fn); while((seq_handler[seq_counter]) != NULL ) { status = STATUS_FAILED; status = (*(seq_handler[seq_counter]))(&update_info, status, &trans_info ); if(STATUS_SUCCESS != status) { ALOGE("%s: exiting; status=0x0%X", fn, status); break; } seq_counter++; } ALOGE("%s: exit; status=0x%x", fn, status); return status; } #endif /******************************************************************************* ** ** Function: ALA_update_seq_handler ** ** Description: Performs the ALA update sequence handler sequence ** ** Returns: Success if ok. ** *******************************************************************************/ #if(NXP_LDR_SVC_VER_2 == TRUE) tJBL_STATUS ALA_update_seq_handler(tJBL_STATUS (*seq_handler[]) (Ala_ImageInfo_t* pContext, tJBL_STATUS status, Ala_TranscieveInfo_t* pInfo), const char *name, const char *dest) #else tJBL_STATUS ALA_update_seq_handler(tJBL_STATUS (*seq_handler[])(Ala_ImageInfo_t* pContext, tJBL_STATUS status, Ala_TranscieveInfo_t* pInfo), const char *name) #endif { static const char fn[] = "ALA_update_seq_handler"; static const char Ala_path[] = APPLET_PATH; UINT16 seq_counter = 0; Ala_ImageInfo_t update_info = (Ala_ImageInfo_t )gpAla_Dwnld_Context-> Image_info; Ala_TranscieveInfo_t trans_info = (Ala_TranscieveInfo_t )gpAla_Dwnld_Context ->Transcv_Info; tJBL_STATUS status = STATUS_FAILED; ALOGD("%s: enter", fn); #if(NXP_LDR_SVC_VER_2 == TRUE) if(dest != NULL) { strcat(update_info.fls_RespPath, dest); ALOGD("Loader Service response data path/destination: %s", dest); update_info.bytes_wrote = 0xAA; } else { update_info.bytes_wrote = 0x55; } if((ALA_UpdateExeStatus(LS_DEFAULT_STATUS))!= TRUE) { return FALSE; } #endif //memcpy(update_info.fls_path, (char*)Ala_path, sizeof(Ala_path)); strcat(update_info.fls_path, name); ALOGD("Selected applet to install is: %s", update_info.fls_path); while((seq_handler[seq_counter]) != NULL ) { status = STATUS_FAILED; status = (*(seq_handler[seq_counter]))(&update_info, status, &trans_info); if(STATUS_SUCCESS != status) { ALOGE("%s: exiting; status=0x0%X", fn, status); break; } seq_counter++; } ALA_CloseChannel(&update_info, STATUS_FAILED, &trans_info); ALOGE("%s: exit; status=0x%x", fn, status); return status; } /******************************************************************************* ** ** Function: ALA_OpenChannel ** ** Description: Creates the logical channel with ala ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS ALA_OpenChannel(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) { static const char fn[] = "ALA_OpenChannel"; bool stat = false; INT32 recvBufferActualSize = 0; IChannel_t *mchannel = gpAla_Dwnld_Context->mchannel; Os_info->channel_cnt = 0x00; ALOGD("%s: enter", fn); if(Os_info == NULL || pTranscv_Info == NULL) { ALOGD("%s: Invalid parameter", fn); } else { pTranscv_Info->timeout = gTransceiveTimeout; pTranscv_Info->sSendlength = (INT32)sizeof(OpenChannel); pTranscv_Info->sRecvlength = 1024;//(INT32)sizeof(INT32); memcpy(pTranscv_Info->sSendData, OpenChannel, pTranscv_Info->sSendlength); ALOGD("%s: Calling Secure Element Transceive", fn); stat = mchannel->transceive (pTranscv_Info->sSendData, pTranscv_Info->sSendlength, pTranscv_Info->sRecvData, pTranscv_Info->sRecvlength, recvBufferActualSize, pTranscv_Info->timeout); if(stat != TRUE && (recvBufferActualSize < 0x03)) { #if(NXP_LDR_SVC_VER_2 == TRUE) if(recvBufferActualSize == 0x02) memcpy(&lsExecuteResp[2], &pTranscv_Info->sRecvData[recvBufferActualSize-2],2); #endif status = STATUS_FAILED; ALOGE("%s: SE transceive failed status = 0x%X", fn, status); } else if(((pTranscv_Info->sRecvData[recvBufferActualSize-2] != 0x90) && (pTranscv_Info->sRecvData[recvBufferActualSize-1] != 0x00))) { #if(NXP_LDR_SVC_VER_2 == TRUE) memcpy(&lsExecuteResp[2], &pTranscv_Info->sRecvData[recvBufferActualSize-2],2); #endif status = STATUS_FAILED; ALOGE("%s: invalid response = 0x%X", fn, status); } else { UINT8 cnt = Os_info->channel_cnt; Os_info->Channel_Info[cnt].channel_id = pTranscv_Info->sRecvData[recvBufferActualSize-3]; Os_info->Channel_Info[cnt].isOpend = true; Os_info->channel_cnt++; status = STATUS_OK; } } ALOGE("%s: exit; status=0x%x", fn, status); return status; } /******************************************************************************* ** ** Function: ALA_SelectAla ** ** Description: Creates the logical channel with ala ** Channel_id will be used for any communication with Ala ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS ALA_SelectAla(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) { static const char fn[] = "ALA_SelectAla"; bool stat = false; INT32 recvBufferActualSize = 0; IChannel_t *mchannel = gpAla_Dwnld_Context->mchannel; #if(NXP_LDR_SVC_VER_2 == TRUE) UINT8 selectCnt = 3; #endif ALOGD("%s: enter", fn); if(Os_info == NULL || pTranscv_Info == NULL) { ALOGD("%s: Invalid parameter", fn); } else { pTranscv_Info->sSendData[0] = Os_info->Channel_Info[0].channel_id; pTranscv_Info->timeout = gTransceiveTimeout; pTranscv_Info->sSendlength = (INT32)sizeof(SelectAla); pTranscv_Info->sRecvlength = 1024;//(INT32)sizeof(INT32); #if(NXP_LDR_SVC_VER_2 == TRUE) while((selectCnt--) > 0) { memcpy(&(pTranscv_Info->sSendData[1]), &ArrayOfAIDs[selectCnt][2], ((ArrayOfAIDs[selectCnt][0])-1)); pTranscv_Info->sSendlength = (INT32)ArrayOfAIDs[selectCnt][0]; /*If NFC/SPI Deinitialize requested*/ #else memcpy(&(pTranscv_Info->sSendData[1]), &SelectAla[1], sizeof(SelectAla)-1); #endif ALOGD("%s: Calling Secure Element Transceive with Loader service AID", fn); stat = mchannel->transceive (pTranscv_Info->sSendData, pTranscv_Info->sSendlength, pTranscv_Info->sRecvData, pTranscv_Info->sRecvlength, recvBufferActualSize, pTranscv_Info->timeout); if(stat != TRUE && (recvBufferActualSize == 0x00)) { status = STATUS_FAILED; ALOGE("%s: SE transceive failed status = 0x%X", fn, status); #if(NXP_LDR_SVC_VER_2 == TRUE) break; #endif } else if(((pTranscv_Info->sRecvData[recvBufferActualSize-2] == 0x90) && (pTranscv_Info->sRecvData[recvBufferActualSize-1] == 0x00))) { status = Process_SelectRsp(pTranscv_Info->sRecvData, (recvBufferActualSize-2)); if(status != STATUS_OK) { ALOGE("%s: Select Ala Rsp doesnt have a valid key; status = 0x%X", fn, status); } #if(NXP_LDR_SVC_VER_2 == TRUE) /*If AID is found which is successfully selected break while loop*/ if(status == STATUS_OK) { UINT8 totalLen = ArrayOfAIDs[selectCnt][0]; UINT8 cnt = 0; INT32 wStatus= 0; status = STATUS_FAILED; fAID_MEM = fopen(AID_MEM_PATH,"w+"); if(fAID_MEM == NULL) { ALOGE("Error opening AID data file for writing: %s", strerror(errno)); return status; } while(cnt <= totalLen) { wStatus = fprintf(fAID_MEM, "%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 = STATUS_OK; fclose(fAID_MEM); break; } #endif } #if(NXP_LDR_SVC_VER_2 == TRUE) else if(((pTranscv_Info->sRecvData[recvBufferActualSize-2] != 0x90))) { /*Copy the response SW in failure case*/ memcpy(&lsExecuteResp[2], &(pTranscv_Info-> sRecvData[recvBufferActualSize-2]),2); } #endif else { status = STATUS_FAILED; } #if(NXP_LDR_SVC_VER_2 == TRUE) } #endif } ALOGE("%s: exit; status=0x%x", fn, status); return status; } /******************************************************************************* ** ** Function: ALA_StoreData ** ** Description: It is used to provide the ALA with an Unique ** Identifier of the Application that has triggered the ALA script. ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS ALA_StoreData(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) { static const char fn[] = "ALA_StoreData"; bool stat = false; INT32 recvBufferActualSize = 0; INT32 xx=0, len = 0; IChannel_t *mchannel = gpAla_Dwnld_Context->mchannel; ALOGD("%s: enter", fn); if(Os_info == NULL || pTranscv_Info == NULL) { ALOGD("%s: Invalid parameter", fn); } else { len = StoreData[1] + 2; //+2 offset is for tag value and length byte pTranscv_Info->sSendData[xx++] = STORE_DATA_CLA | (Os_info->Channel_Info[0].channel_id); pTranscv_Info->sSendData[xx++] = STORE_DATA_INS; pTranscv_Info->sSendData[xx++] = 0x00; //P1 pTranscv_Info->sSendData[xx++] = 0x00; //P2 pTranscv_Info->sSendData[xx++] = len; memcpy(&(pTranscv_Info->sSendData[xx]), StoreData, len); pTranscv_Info->timeout = gTransceiveTimeout; pTranscv_Info->sSendlength = (INT32)(xx + sizeof(StoreData)); pTranscv_Info->sRecvlength = 1024; ALOGD("%s: Calling Secure Element Transceive", fn); stat = mchannel->transceive (pTranscv_Info->sSendData, pTranscv_Info->sSendlength, pTranscv_Info->sRecvData, pTranscv_Info->sRecvlength, recvBufferActualSize, pTranscv_Info->timeout); if((stat != TRUE) && (recvBufferActualSize == 0x00)) { status = STATUS_FAILED; ALOGE("%s: SE transceive failed status = 0x%X", fn, status); } else if((pTranscv_Info->sRecvData[recvBufferActualSize-2] == 0x90) && (pTranscv_Info->sRecvData[recvBufferActualSize-1] == 0x00)) { ALOGE("STORE CMD is successful"); status = STATUS_SUCCESS; } else { #if(NXP_LDR_SVC_VER_2 == TRUE) /*Copy the response SW in failure case*/ memcpy(&lsExecuteResp[2], &(pTranscv_Info->sRecvData [recvBufferActualSize-2]),2); #endif status = STATUS_FAILED; } } ALOGE("%s: exit; status=0x%x", fn, status); return status; } /******************************************************************************* ** ** Function: ALA_loadapplet ** ** Description: Reads the script from the file and sent to Ala ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS ALA_loadapplet(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) { static const char fn [] = "ALA_loadapplet"; BOOLEAN stat = FALSE; int wResult, size =0; INT32 wIndex,wCount=0; INT32 wLen = 0; INT32 recvBufferActualSize = 0; UINT8 temp_buf[1024]; UINT8 len_byte=0, offset =0; IChannel_t *mchannel = gpAla_Dwnld_Context->mchannel; Os_info->bytes_read = 0; #if(NXP_LDR_SVC_VER_2 == TRUE) BOOLEAN reachEOFCheck = FALSE; tJBL_STATUS tag40_found = STATUS_FAILED; if(Os_info->bytes_wrote == 0xAA) { Os_info->fResp = fopen(Os_info->fls_RespPath, "a+"); if(Os_info->fResp == NULL) { ALOGE("Error opening response recording file <%s> for reading: %s", Os_info->fls_path, strerror(errno)); return status; } ALOGD("%s: Response OUT FILE path is successfully created", fn); } else { ALOGD("%s: Response Out file is optional as per input", fn); } #endif ALOGD("%s: enter", fn); if(Os_info == NULL || pTranscv_Info == NULL) { ALOGE("%s: invalid parameter", fn); return status; } Os_info->fp = fopen(Os_info->fls_path, "r"); if (Os_info->fp == NULL) { ALOGE("Error opening OS image file <%s> for reading: %s", Os_info->fls_path, strerror(errno)); return status; } wResult = fseek(Os_info->fp, 0L, SEEK_END); if (wResult) { ALOGE("Error seeking end OS image file %s", strerror(errno)); goto exit; } Os_info->fls_size = ftell(Os_info->fp); ALOGE("fls_size=%d", Os_info->fls_size); if (Os_info->fls_size < 0) { ALOGE("Error ftelling file %s", strerror(errno)); goto exit; } wResult = fseek(Os_info->fp, 0L, SEEK_SET); if (wResult) { ALOGE("Error seeking start image file %s", strerror(errno)); goto exit; } #if(NXP_LDR_SVC_VER_2 == TRUE) status = ALA_Check_KeyIdentifier(Os_info, status, pTranscv_Info, NULL, STATUS_FAILED, 0); #else status = ALA_Check_KeyIdentifier(Os_info, status, pTranscv_Info); #endif if(status != STATUS_OK) { goto exit; } while(!feof(Os_info->fp) && (Os_info->bytes_read < Os_info->fls_size)) { len_byte = 0x00; offset = 0; #if(NXP_LDR_SVC_VER_2 == TRUE) /*Check if the certificate/ is verified or not*/ if(status != STATUS_OK) { goto exit; } #endif memset(temp_buf, 0, sizeof(temp_buf)); ALOGE("%s; Start of line processing", fn); status = ALA_ReadScript(Os_info, temp_buf); if(status != STATUS_OK) { goto exit; } #if(NXP_LDR_SVC_VER_2 == TRUE) else if(status == STATUS_OK) { /*Reset the flag in case further commands exists*/ reachEOFCheck = FALSE; } #endif if(temp_buf[offset] == TAG_ALA_CMD_ID) { /* * start sending the packet to Ala * */ offset = offset+1; len_byte = Numof_lengthbytes(&temp_buf[offset], &wLen); #if(NXP_LDR_SVC_VER_2 == TRUE) /*If the len data not present or * len is less than or equal to 32*/ if((len_byte == 0)||(wLen <= 32)) #else if((len_byte == 0)) #endif { ALOGE("Invalid length zero"); #if(NXP_LDR_SVC_VER_2 == TRUE) goto exit; #else return status; #endif } else { #if(NXP_LDR_SVC_VER_2 == TRUE) tag40_found = STATUS_OK; #endif offset = offset+len_byte; pTranscv_Info->sSendlength = wLen; memcpy(pTranscv_Info->sSendData, &temp_buf[offset], wLen); } #if(NXP_LDR_SVC_VER_2 == TRUE) status = ALA_SendtoAla(Os_info, status, pTranscv_Info, LS_Comm); #else status = ALA_SendtoAla(Os_info, status, pTranscv_Info); #endif if(status != STATUS_OK) { #if(NXP_LDR_SVC_VER_2 == TRUE) /*When the switching of LS 6320 case*/ if(status == STATUS_FILE_NOT_FOUND) { /*When 6320 occurs close the existing channels*/ ALA_CloseChannel(Os_info,status,pTranscv_Info); status = STATUS_FAILED; status = ALA_OpenChannel(Os_info,status,pTranscv_Info); if(status == STATUS_OK) { ALOGD("SUCCESS:Post Switching LS open channel"); status = STATUS_FAILED; status = ALA_SelectAla(Os_info,status,pTranscv_Info); if(status == STATUS_OK) { ALOGD("SUCCESS:Post Switching LS select"); status = STATUS_FAILED; status = ALA_StoreData(Os_info,status,pTranscv_Info); if(status == STATUS_OK) { /*Enable certificate and signature verification*/ tag40_found = STATUS_OK; lsExecuteResp[2] = 0x90; lsExecuteResp[3] = 0x00; reachEOFCheck = TRUE; continue; } ALOGE("Post Switching LS store data failure"); } ALOGE("Post Switching LS select failure"); } ALOGE("Post Switching LS failure"); } ALOGE("Sending packet to ala failed"); goto exit; #else return status; #endif } } #if(NXP_LDR_SVC_VER_2 == TRUE) else if((temp_buf[offset] == (0x7F))&&(temp_buf[offset+1] == (0x21))) { ALOGD("TAGID: Encountered again certificate tag 7F21"); if(tag40_found == STATUS_OK) { ALOGD("2nd Script processing starts with reselect"); status = STATUS_FAILED; status = ALA_SelectAla(Os_info,status,pTranscv_Info); if(status == STATUS_OK) { ALOGD("2nd Script select success next store data command"); status = STATUS_FAILED; status = ALA_StoreData(Os_info,status,pTranscv_Info); if(status == STATUS_OK) { ALOGD("2nd Script store data success next certificate verification"); offset = offset+2; len_byte = Numof_lengthbytes(&temp_buf[offset], &wLen); status = ALA_Check_KeyIdentifier(Os_info, status, pTranscv_Info, temp_buf, STATUS_OK, wLen+len_byte+2); } } /*If the certificate and signature is verified*/ if(status == STATUS_OK) { /*If the certificate is verified for 6320 then new * script starts*/ tag40_found = STATUS_FAILED; } /*If the certificate or signature verification failed*/ else{ goto exit; } } /*Already certificate&Sginature verified previously skip 7f21& tag 60*/ else { memset(temp_buf, 0, sizeof(temp_buf)); status = ALA_ReadScript(Os_info, temp_buf); if(status != STATUS_OK) { 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; } } #endif else { /* * Invalid packet received in between stop processing packet * return failed status * */ status = STATUS_FAILED; break; } } #if(NXP_LDR_SVC_VER_2 == TRUE) if(Os_info->bytes_wrote == 0xAA) { fclose(Os_info->fResp); } ALA_UpdateExeStatus(LS_SUCCESS_STATUS); #endif wResult = fclose(Os_info->fp); ALOGE("%s exit;End of Load Applet; status=0x%x",fn, status); return status; exit: wResult = fclose(Os_info->fp); #if(NXP_LDR_SVC_VER_2 == TRUE) if(Os_info->bytes_wrote == 0xAA) { fclose(Os_info->fResp); } /*Script ends with SW 6320 and reached END OF FILE*/ if(reachEOFCheck == TRUE) { status = STATUS_OK; ALA_UpdateExeStatus(LS_SUCCESS_STATUS); } #endif ALOGE("%s close fp and exit; status= 0x%X", fn,status); return status; } /******************************************************************************* ** ** Function: ALA_ProcessResp ** ** Description: Process the response packet received from Ala ** ** Returns: Success if ok. ** *******************************************************************************/ #if(NXP_LDR_SVC_VER_2 == TRUE) tJBL_STATUS ALA_Check_KeyIdentifier(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info, UINT8* temp_buf, tJBL_STATUS flag, INT32 wNewLen) #else tJBL_STATUS ALA_Check_KeyIdentifier(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) #endif { static const char fn[] = "ALA_Check_KeyIdentifier"; #if(NXP_LDR_SVC_VER_2 == TRUE) UINT16 offset = 0x00, len_byte=0; #else UINT8 offset = 0x00, len_byte=0; #endif tJBL_STATUS key_found = STATUS_FAILED; status = STATUS_FAILED; UINT8 read_buf[1024]; bool stat = false; INT32 wLen, recvBufferActualSize=0; IChannel_t *mchannel = gpAla_Dwnld_Context->mchannel; #if(NXP_LDR_SVC_VER_2 == TRUE) UINT8 certf_found = STATUS_FAILED; UINT8 sign_found = STATUS_FAILED; #endif ALOGD("%s: enter", fn); #if(NXP_LDR_SVC_VER_2 == TRUE) while(!feof(Os_info->fp) && (Os_info->bytes_read < Os_info->fls_size)) { offset = 0x00; wLen = 0; if(flag == STATUS_OK) { /*If the 7F21 TAG is already read: After TAG 40*/ memcpy(read_buf, temp_buf, wNewLen); status = STATUS_OK; flag = STATUS_FAILED; } else { /*If the 7F21 TAG is not read: Before TAG 40*/ status = ALA_ReadScript(Os_info, read_buf); } if(status != STATUS_OK) return status; if(STATUS_OK == Check_Complete_7F21_Tag(Os_info,pTranscv_Info, read_buf, &offset)) { ALOGD("%s: Certificate is verified", fn); certf_found = STATUS_OK; 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_ALA_CMD_ID)&&(certf_found != STATUS_OK))) { ALOGE("%s: NOT FOUND Root entity identifier's certificate", fn); status = STATUS_FAILED; return status; } } #endif #if(NXP_LDR_SVC_VER_2 == TRUE) memset(read_buf, 0, sizeof(read_buf)); if(certf_found == STATUS_OK) { #else while(!feof(Os_info->fp)) { #endif offset = 0x00; wLen = 0; status = ALA_ReadScript(Os_info, read_buf); if(status != STATUS_OK) return status; #if(NXP_LDR_SVC_VER_2 == TRUE) else status = STATUS_FAILED; if((read_buf[offset] == TAG_JSBL_HDR_ID)&& (certf_found != STATUS_FAILED)&&(sign_found != STATUS_OK)) #else if(read_buf[offset] == TAG_JSBL_HDR_ID && key_found != STATUS_OK) #endif { //TODO check the SElect cmd response and return status accordingly ALOGD("TAGID: TAG_JSBL_HDR_ID"); offset = offset+1; len_byte = Numof_lengthbytes(&read_buf[offset], &wLen); offset = offset + len_byte; #if(NXP_LDR_SVC_VER_2 == FALSE) if(read_buf[offset] == TAG_JSBL_KEY_ID) { ALOGE("TAGID: TAG_JSBL_KEY_ID"); offset = offset+1; wLen = read_buf[offset]; offset = offset+1; key_found = memcmp(&read_buf[offset], Select_Rsp, Select_Rsp_Len); if(key_found == STATUS_OK) { ALOGE("Key is matched"); offset = offset + wLen; #endif if(read_buf[offset] == TAG_SIGNATURE_ID) { #if(NXP_LDR_SVC_VER_2 == TRUE) offset = offset+1; len_byte = Numof_lengthbytes(&read_buf[offset], &wLen); offset = offset + len_byte; #endif ALOGE("TAGID: TAG_SIGNATURE_ID"); #if(NXP_LDR_SVC_VER_2 == TRUE) 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); #else offset = offset+1; wLen = 0; len_byte = Numof_lengthbytes(&read_buf[offset], &wLen); if(len_byte == 0) { ALOGE("Invalid length zero"); return STATUS_FAILED; } else { offset = offset+len_byte; pTranscv_Info->sSendlength = wLen; memcpy(pTranscv_Info->sSendData, &read_buf[offset], wLen); } #endif ALOGE("%s: start transceive for length %ld", fn, pTranscv_Info->sSendlength); #if(NXP_LDR_SVC_VER_2 == TRUE) status = ALA_SendtoAla(Os_info, status, pTranscv_Info, LS_Sign); #else status = ALA_SendtoAla(Os_info, status, pTranscv_Info); #endif if(status != STATUS_OK) { return status; } #if(NXP_LDR_SVC_VER_2 == TRUE) else { sign_found = STATUS_OK; } #endif } #if(NXP_LDR_SVC_VER_2 == FALSE) } else { /* * Discard the packet and goto next line * */ } } else { ALOGE("Invalid Tag ID"); status = STATUS_FAILED; break; } #endif } #if(NXP_LDR_SVC_VER_2 == TRUE) else if(read_buf[offset] != TAG_JSBL_HDR_ID ) { status = STATUS_FAILED; } #else else if(read_buf[offset] == TAG_ALA_CMD_ID && key_found == STATUS_OK) { /*Key match is success and start sending the packet to Ala * return status ok * */ ALOGE("TAGID: TAG_ALA_CMD_ID"); offset = offset+1; wLen = 0; len_byte = Numof_lengthbytes(&read_buf[offset], &wLen); if(len_byte == 0) { ALOGE("Invalid length zero"); return STATUS_FAILED; } else { offset = offset+len_byte; pTranscv_Info->sSendlength = wLen; memcpy(pTranscv_Info->sSendData, &read_buf[offset], wLen); } status = ALA_SendtoAla(Os_info, status, pTranscv_Info); break; } else if(read_buf[offset] == TAG_JSBL_HDR_ID && key_found == STATUS_OK) { /*Key match is success * Discard the packets untill we found header T=0x40 * */ } else { /*Invalid header*/ status = STATUS_FAILED; break; } #endif #if(NXP_LDR_SVC_VER_2 == FALSE) } #else } else { ALOGE("%s : Exit certificate verification failed", fn); } #endif ALOGD("%s: exit: status=0x%x", fn, status); return status; } /******************************************************************************* ** ** Function: ALA_ReadScript ** ** Description: Reads the current line if the script ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS ALA_ReadScript(Ala_ImageInfo_t *Os_info, UINT8 *read_buf) { static const char fn[]="ALA_ReadScript"; INT32 wCount, wLen, wIndex = 0; UINT8 len_byte = 0; int wResult = 0; tJBL_STATUS status = STATUS_FAILED; INT32 lenOff = 1; ALOGD("%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 STATUS_FAILED; Os_info->bytes_read = Os_info->bytes_read + (wCount*2); #if(NXP_LDR_SVC_VER_2 == TRUE) 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 STATUS_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; } /*If TAG is neither 7F21 nor 60 nor 40 then ABORT execution*/ else { ALOGE("Invalid TAG 0x%X found in the script", read_buf[0]); return STATUS_FAILED; } #endif if(read_buf[lenOff] == 0x00) { ALOGE("Invalid length zero"); len_byte = 0x00; return STATUS_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("%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 STATUS_FAILED; } wLen = read_buf[lenOff+1]; Os_info->bytes_read = Os_info->bytes_read + (wCount*2); ALOGD("%s: Length of Read Script in len_byte= 0x02 is 0x%lx ", 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 STATUS_FAILED; } Os_info->bytes_read = Os_info->bytes_read + (wCount*2); wLen = read_buf[lenOff+1]; //Length of the packet send to ALA wLen = ((wLen << 8) | (read_buf[lenOff+2])); ALOGD("%s: Length of Read Script in len_byte= 0x03 is 0x%lx ", fn, wLen); } else { /*Need to provide the support if length is more than 2 bytes*/ ALOGE("Length recived is greater than 3"); return STATUS_FAILED; } } else { len_byte = 0x01; wLen = read_buf[lenOff]; ALOGE("%s: Length of Read Script in len_byte= 0x01 is 0x%lx ", 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 status; } else { #if(NXP_LDR_SVC_VER_2 == TRUE) Os_info->bytes_read = Os_info->bytes_read + (wCount*2)+1; //not sure why 2 added #else Os_info->bytes_read = Os_info->bytes_read + (wCount*2)+2; //not sure why 2 added #endif status = STATUS_OK; } ALOGD("%s: exit: status=0x%x; Num of bytes read=%d and index=%ld", fn, status, Os_info->bytes_read,wIndex); return status; } /******************************************************************************* ** ** Function: ALA_SendtoEse ** ** Description: It is used to send the packet to p61 ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS ALA_SendtoEse(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) { static const char fn [] = "ALA_SendtoEse"; bool stat =false, chanl_open_cmd = false; UINT8 xx=0; status = STATUS_FAILED; INT32 recvBufferActualSize=0, recv_len = 0; IChannel_t *mchannel = gpAla_Dwnld_Context->mchannel; ALOGD("%s: enter", fn); #ifdef JCOP3_WR /* * Bufferize_load_cmds function is implemented in JCOP * */ status = Bufferize_load_cmds(Os_info, status, pTranscv_Info); if(status != STATUS_FAILED) { #endif if(pTranscv_Info->sSendData[1] == 0x70) { if(pTranscv_Info->sSendData[2] == 0x00) { ALOGE("Channel open"); chanl_open_cmd = true; } else { ALOGE("Channel close"); for(UINT8 cnt=0; cnt < Os_info->channel_cnt; cnt++) { if(Os_info->Channel_Info[cnt].channel_id == pTranscv_Info->sSendData[3]) { ALOGE("Closed channel id = 0x0%x", Os_info->Channel_Info[cnt].channel_id); Os_info->Channel_Info[cnt].isOpend = false; } } } } pTranscv_Info->timeout = gTransceiveTimeout; pTranscv_Info->sRecvlength = 1024; stat = mchannel->transceive(pTranscv_Info->sSendData, pTranscv_Info->sSendlength, pTranscv_Info->sRecvData, pTranscv_Info->sRecvlength, recvBufferActualSize, pTranscv_Info->timeout); if(stat != TRUE) { ALOGE("%s: Transceive failed; status=0x%X", fn, stat); } else { if(chanl_open_cmd == true) { if((recvBufferActualSize == 0x03) && ((pTranscv_Info->sRecvData[recvBufferActualSize-2] == 0x90) && (pTranscv_Info->sRecvData[recvBufferActualSize-1] == 0x00))) { ALOGE("open channel success"); UINT8 cnt = Os_info->channel_cnt; Os_info->Channel_Info[cnt].channel_id = pTranscv_Info->sRecvData[recvBufferActualSize-3]; Os_info->Channel_Info[cnt].isOpend = true; Os_info->channel_cnt++; } else { ALOGE("channel open faield"); } } status = Process_EseResponse(pTranscv_Info, recvBufferActualSize, Os_info); } #ifdef JCOP3_WR } else if(SendBack_cmds == false) { /* * Workaround for issue in JCOP * Send the fake response back * */ 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(NXP_LDR_SVC_VER_2 == TRUE) if(islastcmdLoad == true) { status = Send_Backall_Loadcmds(Os_info, status, pTranscv_Info); SendBack_cmds = false; }else { memset(Cmd_Buffer, 0, sizeof(Cmd_Buffer)); SendBack_cmds = false; status = STATUS_FAILED; } #else status = Send_Backall_Loadcmds(Os_info, status, pTranscv_Info); SendBack_cmds = false; #endif } #endif ALOGD("%s: exit: status=0x%x", fn, status); return status; } /******************************************************************************* ** ** Function: ALA_SendtoAla ** ** Description: It is used to forward the packet to Ala ** ** Returns: Success if ok. ** *******************************************************************************/ #if(NXP_LDR_SVC_VER_2 == TRUE) tJBL_STATUS ALA_SendtoAla(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info, Ls_TagType tType) #else tJBL_STATUS ALA_SendtoAla(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) #endif { static const char fn [] = "ALA_SendtoAla"; bool stat =false; status = STATUS_FAILED; INT32 recvBufferActualSize = 0; IChannel_t *mchannel = gpAla_Dwnld_Context->mchannel; ALOGD("%s: enter", fn); #if(NXP_LDR_SVC_VER_2 == TRUE) pTranscv_Info->sSendData[0] = (0x80 | Os_info->Channel_Info[0].channel_id); #else pTranscv_Info->sSendData[0] = (pTranscv_Info->sSendData[0] | Os_info->Channel_Info[0].channel_id); #endif pTranscv_Info->timeout = gTransceiveTimeout; pTranscv_Info->sRecvlength = 1024; stat = mchannel->transceive(pTranscv_Info->sSendData, pTranscv_Info->sSendlength, pTranscv_Info->sRecvData, pTranscv_Info->sRecvlength, recvBufferActualSize, pTranscv_Info->timeout); if(stat != TRUE) { ALOGE("%s: Transceive failed; status=0x%X", fn, stat); } else { #if(NXP_LDR_SVC_VER_2 == TRUE) status = ALA_ProcessResp(Os_info, recvBufferActualSize, pTranscv_Info, tType); #else status = ALA_ProcessResp(Os_info, recvBufferActualSize, pTranscv_Info); #endif } ALOGD("%s: exit: status=0x%x", fn, status); return status; } /******************************************************************************* ** ** Function: ALA_CloseChannel ** ** Description: Closes the previously opened logical channel ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS ALA_CloseChannel(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) { static const char fn [] = "ALA_CloseChannel"; status = STATUS_FAILED; bool stat = false; UINT8 xx =0; INT32 recvBufferActualSize = 0; IChannel_t *mchannel = gpAla_Dwnld_Context->mchannel; UINT8 cnt = 0; ALOGD("%s: enter",fn); if(Os_info == NULL || pTranscv_Info == NULL) { ALOGE("Invalid parameter"); } else { for(cnt =0; (cnt < Os_info->channel_cnt); cnt++) { if(Os_info->Channel_Info[cnt].isOpend == false) continue; xx = 0; pTranscv_Info->sSendData[xx++] = Os_info->Channel_Info[cnt].channel_id; pTranscv_Info->sSendData[xx++] = 0x70; pTranscv_Info->sSendData[xx++] = 0x80; pTranscv_Info->sSendData[xx++] = Os_info->Channel_Info[cnt].channel_id; pTranscv_Info->sSendData[xx++] = 0x00; pTranscv_Info->sSendlength = xx; pTranscv_Info->timeout = gTransceiveTimeout; pTranscv_Info->sRecvlength = 1024; stat = mchannel->transceive(pTranscv_Info->sSendData, pTranscv_Info->sSendlength, pTranscv_Info->sRecvData, pTranscv_Info->sRecvlength, recvBufferActualSize, pTranscv_Info->timeout); if(stat != TRUE && recvBufferActualSize < 2) { ALOGE("%s: Transceive failed; status=0x%X", fn, stat); } else if((pTranscv_Info->sRecvData[recvBufferActualSize-2] == 0x90) && (pTranscv_Info->sRecvData[recvBufferActualSize-1] == 0x00)) { ALOGE("Close channel id = 0x0%x is success", Os_info->Channel_Info[cnt].channel_id); status = STATUS_OK; } else { ALOGE("Close channel id = 0x0%x is failed", Os_info->Channel_Info[cnt].channel_id); } } } ALOGD("%s: exit; status=0x0%x", fn, status); return status; } /******************************************************************************* ** ** Function: ALA_ProcessResp ** ** Description: Process the response packet received from Ala ** ** Returns: Success if ok. ** *******************************************************************************/ #if(NXP_LDR_SVC_VER_2 == TRUE) tJBL_STATUS ALA_ProcessResp(Ala_ImageInfo_t *image_info, INT32 recvlen, Ala_TranscieveInfo_t *trans_info, Ls_TagType tType) #else tJBL_STATUS ALA_ProcessResp(Ala_ImageInfo_t *image_info, INT32 recvlen, Ala_TranscieveInfo_t *trans_info) #endif { static const char fn [] = "ALA_ProcessResp"; tJBL_STATUS status = STATUS_FAILED; static INT32 temp_len = 0; UINT8* RecvData = trans_info->sRecvData; UINT8 xx =0; char sw[2]; ALOGD("%s: enter", fn); if(RecvData == NULL && recvlen == 0x00) { ALOGE("%s: Invalid parameter: status=0x%x", fn, status); return status; } else if(recvlen >= 2) { sw[0] = RecvData[recvlen-2]; sw[1] = RecvData[recvlen-1]; } else { ALOGE("%s: Invalid response; status=0x%x", fn, status); return status; } #if(NXP_LDR_SVC_VER_2 == TRUE) /*Update the Global variable for storing response length*/ resp_len = recvlen; if((sw[0] != 0x63)) { lsExecuteResp[2] = sw[0]; lsExecuteResp[3] = sw[1]; ALOGD("%s: Process Response SW; status = 0x%x", fn, sw[0]); ALOGD("%s: Process Response SW; status = 0x%x", fn, sw[1]); } #endif if((recvlen == 0x02) && (sw[0] == 0x90) && (sw[1] == 0x00)) { #if(NXP_LDR_SVC_VER_2 == TRUE) tJBL_STATUS wStatus = STATUS_FAILED; ALOGE("%s: Before Write Response", fn); wStatus = Write_Response_To_OutFile(image_info, RecvData, recvlen, tType); if(wStatus != STATUS_FAILED) #endif status = STATUS_OK; } else if((recvlen > 0x02) && (sw[0] == 0x90) && (sw[1] == 0x00)) { #if(NXP_LDR_SVC_VER_2 == TRUE) tJBL_STATUS wStatus = STATUS_FAILED; ALOGE("%s: Before Write Response", fn); wStatus = Write_Response_To_OutFile(image_info, RecvData, recvlen, tType); if(wStatus != STATUS_FAILED) status = STATUS_OK; #else 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 = ALA_SendtoEse(image_info, status, trans_info); #endif } #if(NXP_LDR_SVC_VER_2 == FALSE) else if ((recvlen > 0x02) && (sw[0] == 0x61)) { memcpy((trans_info->sTemp_recvbuf+temp_len), RecvData, (recvlen-2)); temp_len = temp_len + recvlen-2; trans_info->sSendData[xx++] = image_info->Channel_Info[0].channel_id; trans_info->sSendData[xx++] = 0xC0; trans_info->sSendData[xx++] = 0x00; trans_info->sSendData[xx++] = 0x00; trans_info->sSendData[xx++] = sw[1]; trans_info->sSendlength = xx; status = ALA_SendtoAla(image_info, status, trans_info); } #endif #if(NXP_LDR_SVC_VER_2 == TRUE) else if ((recvlen > 0x02) && (sw[0] == 0x63) && (sw[1] == 0x10)) { 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 = ALA_SendtoEse(image_info, status, trans_info); } else if ((recvlen > 0x02) && (sw[0] == 0x63) && (sw[1] == 0x20)) { UINT8 respLen = 0; INT32 wStatus = 0; 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); fAID_MEM = fopen(AID_MEM_PATH,"w"); if (fAID_MEM == NULL) { ALOGE("Error opening AID data for writing: %s",strerror(errno)); return status; } /*Updating the AID_MEM with new value into AID file*/ while(respLen <= (recvlen+4)) { wStatus = fprintf(fAID_MEM, "%2x", AID_ARRAY[respLen++]); if(wStatus != 2) { ALOGE("%s: Invalid Response during fprintf; status=0x%x", fn, status); fclose(fAID_MEM); break; } } if(wStatus == 2) { status = STATUS_FILE_NOT_FOUND; } else { status = STATUS_FAILED; } } else if((recvlen >= 0x02) &&( (sw[0] != 0x90) && (sw[0] != 0x63)&&(sw[0] != 0x61))) { tJBL_STATUS wStatus = STATUS_FAILED; wStatus = Write_Response_To_OutFile(image_info, RecvData, recvlen, tType); //if(wStatus != STATUS_FAILED) //status = STATUS_OK; } #endif ALOGD("%s: exit: status=0x%x", fn, status); return status; } /******************************************************************************* ** ** Function: ALA_SendtoEse ** ** Description: It is used to process the received response packet from p61 ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS Process_EseResponse(Ala_TranscieveInfo_t *pTranscv_Info, INT32 recv_len, Ala_ImageInfo_t *Os_info) { static const char fn[] = "Process_EseResponse"; tJBL_STATUS status = STATUS_OK; UINT8 xx = 0; ALOGD("%s: enter", fn); pTranscv_Info->sSendData[xx++] = (CLA_BYTE | Os_info->Channel_Info[0].channel_id); #if(NXP_LDR_SVC_VER_2 == TRUE) pTranscv_Info->sSendData[xx++] = 0xA2; #else pTranscv_Info->sSendData[xx++] = 0xA0; #endif if(recv_len <= 0xFF) { #if(NXP_LDR_SVC_VER_2 == TRUE) pTranscv_Info->sSendData[xx++] = 0x80; #else pTranscv_Info->sSendData[xx++] = ONLY_BLOCK; #endif pTranscv_Info->sSendData[xx++] = 0x00; pTranscv_Info->sSendData[xx++] = (UINT8)recv_len; memcpy(&(pTranscv_Info->sSendData[xx]),pTranscv_Info->sRecvData,recv_len); pTranscv_Info->sSendlength = xx+ recv_len; #if(NXP_LDR_SVC_VER_2) status = ALA_SendtoAla(Os_info, status, pTranscv_Info, LS_Comm); #else status = ALA_SendtoAla(Os_info, status, pTranscv_Info); #endif } else { while(recv_len > MAX_SIZE) { xx = PARAM_P1_OFFSET; #if(NXP_LDR_SVC_VER_2 == TRUE) pTranscv_Info->sSendData[xx++] = 0x00; #else pTranscv_Info->sSendData[xx++] = FIRST_BLOCK; #endif 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; #if(NXP_LDR_SVC_VER_2 == TRUE) /*Need not store Process eSE response's response in the out file so * LS_Comm = 0*/ status = ALA_SendtoAla(Os_info, status, pTranscv_Info, LS_Comm); #else status = ALA_SendtoAla(Os_info, status, pTranscv_Info); #endif if(status != STATUS_OK) { ALOGE("Sending packet to Ala failed: status=0x%x", 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; #if(NXP_LDR_SVC_VER_2 == TRUE) status = ALA_SendtoAla(Os_info, status, pTranscv_Info, LS_Comm); #else status = ALA_SendtoAla(Os_info, status, pTranscv_Info); #endif } ALOGD("%s: exit: status=0x%x", fn, status); return status; } /******************************************************************************* ** ** Function: Process_SelectRsp ** ** Description: It is used to process the received response for SELECT ALA cmd ** ** Returns: Success if ok. ** *******************************************************************************/ tJBL_STATUS Process_SelectRsp(UINT8* Recv_data, INT32 Recv_len) { static const char fn[]="Process_SelectRsp"; tJBL_STATUS status = STATUS_FAILED; int i = 0, len=0; ALOGE("%s: enter", fn); if(Recv_data[i] == TAG_SELECT_ID) { ALOGD("TAG: TAG_SELECT_ID"); i = i +1; len = Recv_data[i]; i = i+1; if(Recv_data[i] == TAG_ALA_ID) { ALOGD("TAG: TAG_ALA_ID"); i = i+1; len = Recv_data[i]; i = i + 1 + len; //points to next tag name A5 #if(NXP_LDR_SVC_VER_2 == TRUE) //points to TAG 9F08 for LS application version if((Recv_data[i] == TAG_LS_VER1)&&(Recv_data[i+1] == TAG_LS_VER2)) { UINT8 lsaVersionLen = 0; ALOGD("TAG: TAG_LS_APPLICATION_VER"); i = i+2; lsaVersionLen = Recv_data[i]; //points to TAG 9F08 LS application version i = i+1; memcpy(lsVersionArr, &Recv_data[i],lsaVersionLen); //points to Identifier of the Root Entity key set identifier i = i+lsaVersionLen; if(Recv_data[i] == TAG_RE_KEYID) { UINT8 rootEntityLen = 0; i = i+1; rootEntityLen = Recv_data[i]; i = i+1; if(Recv_data[i] == TAG_LSRE_ID) { UINT8 tag42Len = 0; i = i+1; tag42Len = Recv_data[i]; //copy the data including length memcpy(tag42Arr, &Recv_data[i], tag42Len+1); i = i+tag42Len+1; if(Recv_data[i] == TAG_LSRE_SIGNID) { UINT8 tag45Len = Recv_data[i+1]; memcpy(tag45Arr, &Recv_data[i+1],tag45Len+1); status = STATUS_OK; } else { ALOGE("Invalid Root entity for TAG 45 = 0x%x; " "status=0x%x", Recv_data[i], status); return status; } } else { ALOGE("Invalid Root entity for TAG 42 = 0x%x; " "status=0x%x", Recv_data[i], status); return status; } } else { ALOGE("Invalid Root entity key set TAG ID = 0x%x; " "status=0x%x", Recv_data[i], status); return status; } } } else { ALOGE("Invalid Loader Service AID TAG ID = 0x%x; status=0x%x", Recv_data[i], status); return status; } } else { ALOGE("Invalid FCI TAG = 0x%x; status=0x%x", Recv_data[i], status); return status; } #else if(Recv_data[i] == TAG_PRO_DATA_ID) { ALOGE("TAG: TAG_PRO_DATA_ID"); i = i+1; len = Recv_data[i]; i = i + 1; //points to next tag name 61 } } } else { /* * Invalid start of TAG Name found * */ ALOGE("Invalid TAG ID = 0x%x; status=0x%x", Recv_data[i], status); return status; } if((i < Recv_len) && (Recv_data[i] == TAG_JSBL_KEY_ID)) { /* * Valid Key is found * Copy the data into Select_Rsp * */ ALOGE("Valid key id is found"); i = i +1; len = Recv_data[i]; if(len != 0x00) { i = i+1; memcpy(Select_Rsp, &Recv_data[i], len); Select_Rsp_Len = len; status = STATUS_OK; } /* * Identifier of the certificate storing * JSBL encryption key * */ i = i + len; if(Recv_data[i] == TAG_JSBL_CER_ID) { i = i+1; len = Recv_data[i]; if(len != 0x00) { i = i+1; Jsbl_keylen = len; memcpy(Jsbl_RefKey, &Recv_data[i], len); } } } #endif ALOGE("%s: Exiting status = 0x%x", fn, status); return status; } #ifdef JCOP3_WR tJBL_STATUS Bufferize_load_cmds(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) { static const char fn[] = "Bufferize_load_cmds"; UINT8 Param_P2; status = STATUS_FAILED; if(cmd_count == 0x00) { if((pTranscv_Info->sSendData[1] == INSTAL_LOAD_ID) && (pTranscv_Info->sSendData[2] == PARAM_P1_OFFSET) && (pTranscv_Info->sSendData[3] == 0x00)) { ALOGE("BUffer: install for load"); pBuffer[0] = pTranscv_Info->sSendlength; memcpy(&pBuffer[1], &(pTranscv_Info->sSendData[0]), pTranscv_Info->sSendlength); pBuffer = pBuffer + pTranscv_Info->sSendlength + 1; cmd_count++; } else { /* * Do not buffer this cmd * Send this command to eSE * */ status = STATUS_OK; } } else { Param_P2 = cmd_count -1; if((pTranscv_Info->sSendData[1] == LOAD_CMD_ID) && (pTranscv_Info->sSendData[2] == LOAD_MORE_BLOCKS) && (pTranscv_Info->sSendData[3] == Param_P2)) { ALOGE("BUffer: load"); pBuffer[0] = pTranscv_Info->sSendlength; memcpy(&pBuffer[1], &(pTranscv_Info->sSendData[0]), pTranscv_Info->sSendlength); pBuffer = pBuffer + pTranscv_Info->sSendlength + 1; cmd_count++; } else if((pTranscv_Info->sSendData[1] == LOAD_CMD_ID) && (pTranscv_Info->sSendData[2] == LOAD_LAST_BLOCK) && (pTranscv_Info->sSendData[3] == Param_P2)) { ALOGE("BUffer: last load"); SendBack_cmds = true; pBuffer[0] = pTranscv_Info->sSendlength; memcpy(&pBuffer[1], &(pTranscv_Info->sSendData[0]), pTranscv_Info->sSendlength); pBuffer = pBuffer + pTranscv_Info->sSendlength + 1; cmd_count++; islastcmdLoad = true; } else { ALOGE("BUffer: Not a load cmd"); SendBack_cmds = true; pBuffer[0] = pTranscv_Info->sSendlength; memcpy(&pBuffer[1], &(pTranscv_Info->sSendData[0]), pTranscv_Info->sSendlength); pBuffer = pBuffer + pTranscv_Info->sSendlength + 1; islastcmdLoad = false; cmd_count++; } } ALOGE("%s: exit; status=0x%x", fn, status); return status; } tJBL_STATUS Send_Backall_Loadcmds(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) { static const char fn [] = "Send_Backall_Loadcmds"; bool stat =false; UINT8 xx=0; status = STATUS_FAILED; INT32 recvBufferActualSize=0, recv_len = 0; IChannel_t *mchannel = gpAla_Dwnld_Context->mchannel; ALOGD("%s: enter", fn); pBuffer = Cmd_Buffer; // Points to start of first cmd to send if(cmd_count == 0x00) { ALOGE("No cmds to stored to send to eSE"); } else { while(cmd_count-- > 0) { pTranscv_Info->sSendlength = pBuffer[0]; memcpy(pTranscv_Info->sSendData, &pBuffer[1], pTranscv_Info->sSendlength); pBuffer = pBuffer + 1 + pTranscv_Info->sSendlength; stat = mchannel->transceive(pTranscv_Info->sSendData, pTranscv_Info->sSendlength, pTranscv_Info->sRecvData, pTranscv_Info->sRecvlength, recvBufferActualSize, pTranscv_Info->timeout); if(stat != TRUE || (recvBufferActualSize < 2)) { ALOGE("%s: Transceive failed; status=0x%X", fn, stat); } else if(cmd_count == 0x00) //Last command in the buffer { if (islastcmdLoad == 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)) { /*Do not do anything * 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)) { /*Do not do anything * Send next cmd 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*/ cmd_count=0; break; } } } memset(Cmd_Buffer, 0, sizeof(Cmd_Buffer)); pBuffer = Cmd_Buffer; //point back to start of line cmd_count = 0x00; ALOGD("%s: exit: status=0x%x", fn, status); return status; } #endif /******************************************************************************* ** ** Function: Numof_lengthbytes ** ** Description: Checks the number of length bytes and assigns ** length value to wLen. ** ** Returns: Number of Length bytes ** *******************************************************************************/ UINT8 Numof_lengthbytes(UINT8 *read_buf, INT32 *pLen) { static const char fn[]= "Numof_lengthbytes"; UINT8 len_byte=0, i=0; INT32 wLen = 0; ALOGE("%s:enter", fn); if(read_buf[i] == 0x00) { ALOGE("Invalid length zero"); len_byte = 0x00; } else if((read_buf[i] & 0x80) == 0x80) { len_byte = read_buf[i] & 0x0F; len_byte = len_byte +1; //1 byte added for byte 0x81 } else { len_byte = 0x01; } /* * To get the length of the value field * */ 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("default case"); break; } *pLen = wLen; ALOGE("%s:exit; len_bytes=0x0%x, Length=%ld", fn, len_byte, *pLen); return len_byte; } #if(NXP_LDR_SVC_VER_2 == TRUE) /******************************************************************************* ** ** Function: Write_Response_To_OutFile ** ** Description: Write the response to Out file ** with length recvlen from buffer RecvData. ** ** Returns: Success if OK ** *******************************************************************************/ tJBL_STATUS Write_Response_To_OutFile(Ala_ImageInfo_t *image_info, UINT8* RecvData, INT32 recvlen, Ls_TagType tType) { INT32 respLen = 0; tJBL_STATUS wStatus = STATUS_FAILED; static const char fn [] = "Write_Response_to_OutFile"; INT32 status = 0; UINT8 tagBuffer[12] = {0x61,0,0,0,0,0,0,0,0,0,0,0}; INT32 tag44Len = 0; INT32 tag61Len = 0; UINT8 tag43Len = 1; UINT8 tag43off = 0; UINT8 tag44off = 0; UINT8 ucTag44[3] = {0x00,0x00,0x00}; UINT8 tagLen = 0; UINT8 tempLen = 0; /*If the Response out file is NULL or Other than LS commands*/ if((image_info->bytes_wrote == 0x55)||(tType == LS_Default)) { return STATUS_OK; } /*Certificate TAG occupies 2 bytes*/ if(tType == LS_Cert) { tag43Len = 2; } ALOGE("%s: Enter", fn); /* |TAG | LEN(BERTLV)| VAL | * | 61 | XX | TAG | LEN | VAL | TAG | LEN(BERTLV) | VAL | * | 43 | 1/2 | 7F21/60/40 | 44 | apduRespLen | apduResponse | **/ 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*/ } while(tempLen < tagLen) { status = fprintf(image_info->fResp, "%02X", tagBuffer[tempLen++]); if(status != 2) { ALOGE("%s: Invalid Response during fprintf; status=0x%lx", fn, (status)); wStatus = STATUS_FAILED; break; } } /*Updating the response data into out script*/ while(respLen < recvlen) { status = fprintf(image_info->fResp, "%02X", RecvData[respLen++]); if(status != 2) { ALOGE("%s: Invalid Response during fprintf; status=0x%lx", fn, (status)); wStatus = STATUS_FAILED; break; } } if((status == 2)) { fprintf(image_info->fResp, "%s\n", ""); ALOGE("%s: SUCCESS Response written to script out file; status=0x%lx", fn, (status)); wStatus = STATUS_OK; } return wStatus; } /******************************************************************************* ** ** Function: Check_Certificate_Tag ** ** Description: Check certificate Tag presence in script ** by 7F21 . ** ** Returns: Success if Tag found ** *******************************************************************************/ tJBL_STATUS Check_Certificate_Tag(UINT8 *read_buf, UINT16 *offset1) { tJBL_STATUS status = STATUS_FAILED; UINT16 len_byte = 0; INT32 wLen, recvBufferActualSize=0; UINT16 offset = *offset1; if(((read_buf[offset]<<8|read_buf[offset+1]) == TAG_CERTIFICATE)) { ALOGD("TAGID: TAG_CERTIFICATE"); offset = offset+2; len_byte = Numof_lengthbytes(&read_buf[offset], &wLen); offset = offset + len_byte; *offset1 = offset; if(wLen <= MAX_CERT_LEN) status = STATUS_OK; } return status; } /******************************************************************************* ** ** Function: Check_SerialNo_Tag ** ** Description: Check Serial number Tag presence in script ** by 0x93 . ** ** Returns: Success if Tag found ** *******************************************************************************/ tJBL_STATUS Check_SerialNo_Tag(UINT8 *read_buf, UINT16 *offset1) { tJBL_STATUS status = STATUS_FAILED; UINT16 offset = *offset1; static const char fn[] = "Check_SerialNo_Tag"; if((read_buf[offset] == TAG_SERIAL_NO)) { ALOGD("TAGID: TAG_SERIAL_NO"); UINT8 serNoLen = read_buf[offset+1]; offset = offset + serNoLen + 2; *offset1 = offset; ALOGD("%s: TAG_LSROOT_ENTITY is %x", fn, read_buf[offset]); status = STATUS_OK; } return status; } /******************************************************************************* ** ** 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 ** *******************************************************************************/ tJBL_STATUS Check_LSRootID_Tag(UINT8 *read_buf, UINT16 *offset1) { tJBL_STATUS status = STATUS_FAILED; UINT16 offset = *offset1; if(read_buf[offset] == TAG_LSRE_ID) { ALOGD("TAGID: TAG_LSROOT_ENTITY"); if(tag42Arr[0] == read_buf[offset+1]) { UINT8 tag42Len = read_buf[offset+1]; offset = offset+2; status = memcmp(&read_buf[offset],&tag42Arr[1],tag42Arr[0]); ALOGD("ALA_Check_KeyIdentifier : TAG 42 verified"); if(status == STATUS_OK) { ALOGD("ALA_Check_KeyIdentifier : Loader service root entity " "ID is matched"); offset = offset+tag42Len; *offset1 = offset; } } } return status; } /******************************************************************************* ** ** Function: Check_CertHoldID_Tag ** ** Description: Check certificate holder ID tag presence in script. ** ** Returns: Success if Tag found ** *******************************************************************************/ tJBL_STATUS Check_CertHoldID_Tag(UINT8 *read_buf, UINT16 *offset1) { tJBL_STATUS status = STATUS_FAILED; UINT16 offset = *offset1; if((read_buf[offset]<<8|read_buf[offset+1]) == TAG_CERTFHOLD_ID) { UINT8 certfHoldIDLen = 0; ALOGD("TAGID: TAG_CERTFHOLD_ID"); certfHoldIDLen = read_buf[offset+2]; offset = offset+certfHoldIDLen+3; if(read_buf[offset] == TAG_KEY_USAGE) { UINT8 keyusgLen = 0; ALOGD("TAGID: TAG_KEY_USAGE"); keyusgLen = read_buf[offset+1]; offset = offset+keyusgLen+2; *offset1 = offset; status = STATUS_OK; } } return status; } /******************************************************************************* ** ** Function: Check_Date_Tag ** ** Description: Check date tags presence in script. ** ** Returns: Success if Tag found ** *******************************************************************************/ tJBL_STATUS Check_Date_Tag(UINT8 *read_buf, UINT16 *offset1) { tJBL_STATUS status = STATUS_OK; UINT16 offset = *offset1; if((read_buf[offset]<<8|read_buf[offset+1]) == TAG_EFF_DATE) { UINT8 effDateLen = read_buf[offset+2]; offset = offset+3+effDateLen; ALOGD("TAGID: TAG_EFF_DATE"); if((read_buf[offset]<<8|read_buf[offset+1]) == TAG_EXP_DATE) { UINT8 effExpLen = read_buf[offset+2]; offset = offset+3+effExpLen; ALOGD("TAGID: TAG_EXP_DATE"); status = STATUS_OK; }else if(read_buf[offset] == TAG_LSRE_SIGNID) { status = STATUS_OK; } } else if((read_buf[offset]<<8|read_buf[offset+1]) == TAG_EXP_DATE) { UINT8 effExpLen = read_buf[offset+2]; offset = offset+3+effExpLen; ALOGD("TAGID: TAG_EXP_DATE"); status = STATUS_OK; }else if(read_buf[offset] == TAG_LSRE_SIGNID) { status = STATUS_OK; } else { /*STATUS_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 ** *******************************************************************************/ tJBL_STATUS Check_45_Tag(UINT8 *read_buf, UINT16 *offset1, UINT8 *tag45Len) { tJBL_STATUS status = STATUS_FAILED; UINT16 offset = *offset1; if(read_buf[offset] == TAG_LSRE_SIGNID) { *tag45Len = read_buf[offset+1]; offset = offset+2; if(tag45Arr[0] == *tag45Len) { status = memcmp(&read_buf[offset],&tag45Arr[1],tag45Arr[0]); if(status == STATUS_OK) { ALOGD("ALA_Check_KeyIdentifier : TAG 45 verified"); *offset1 = offset; } } } return status; } /******************************************************************************* ** ** Function: Certificate_Verification ** ** Description: Perform the certificate verification by forwarding it to ** LS applet. ** ** Returns: Success if certificate is verified ** *******************************************************************************/ tJBL_STATUS Certificate_Verification(Ala_ImageInfo_t *Os_info, Ala_TranscieveInfo_t *pTranscv_Info, UINT8 *read_buf, UINT16 *offset1, UINT8 *tag45Len) { tJBL_STATUS status = STATUS_FAILED; UINT16 offset = *offset1; INT32 wCertfLen = (read_buf[2]<<8|read_buf[3]); tJBL_STATUS certf_found = STATUS_FAILED; static const char fn[] = "Certificate_Verification"; UINT8 tag_len_byte = Numof_lengthbytes(&read_buf[2], &wCertfLen); pTranscv_Info->sSendData[0] = 0x80; pTranscv_Info->sSendData[1] = 0xA0; pTranscv_Info->sSendData[2] = 0x01; pTranscv_Info->sSendData[3] = 0x00; /*If the certificate is less than 255 bytes*/ if(wCertfLen <= 251) { UINT8 tag7f49Off = 0; UINT8 u7f49Len = 0; UINT8 tag5f37Len = 0; ALOGD("Certificate is greater than 255"); offset = offset+*tag45Len; ALOGD("%s: Before TAG_CCM_PERMISSION = %x",fn, read_buf[offset]); if(read_buf[offset] == TAG_CCM_PERMISSION) { INT32 tag53Len = 0; UINT8 len_byte = 0; offset =offset+1; len_byte = Numof_lengthbytes(&read_buf[offset], &tag53Len); offset = offset+tag53Len+len_byte; ALOGD("%s: Verified TAG TAG_CCM_PERMISSION = 0x53",fn); if((UINT16)(read_buf[offset]<<8|read_buf[offset+1]) == TAG_SIG_RNS_COMP) { tag7f49Off = offset; u7f49Len = read_buf[offset+2]; offset = offset+3+u7f49Len; if(u7f49Len != 64) { return STATUS_FAILED; } if((UINT16)(read_buf[offset]<<8|read_buf[offset+1]) == 0x7f49) { tag5f37Len = read_buf[offset+2]; if(read_buf[offset+3] != 0x86 || (read_buf[offset+4] != 65)) { return STATUS_FAILED; } } else { return STATUS_FAILED; } } else { return STATUS_FAILED; } } else { return STATUS_FAILED; } 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("%s: start transceive for length %ld", fn, pTranscv_Info-> sSendlength); status = ALA_SendtoAla(Os_info, status, pTranscv_Info,LS_Cert); if(status != STATUS_OK) { return status; } else { certf_found = STATUS_OK; ALOGD("Certificate is verified"); return status; } } /*If the certificate is more than 255 bytes*/ else { UINT8 tag7f49Off = 0; UINT8 u7f49Len = 0; UINT8 tag5f37Len = 0; ALOGD("Certificate is greater than 255"); offset = offset+*tag45Len; ALOGD("%s: Before TAG_CCM_PERMISSION = %x",fn, read_buf[offset]); if(read_buf[offset] == TAG_CCM_PERMISSION) { INT32 tag53Len = 0; UINT8 len_byte = 0; offset =offset+1; len_byte = Numof_lengthbytes(&read_buf[offset], &tag53Len); offset = offset+tag53Len+len_byte; ALOGD("%s: Verified TAG TAG_CCM_PERMISSION = 0x53",fn); if((UINT16)(read_buf[offset]<<8|read_buf[offset+1]) == TAG_SIG_RNS_COMP) { tag7f49Off = offset; u7f49Len = read_buf[offset+2]; offset = offset+3+u7f49Len; if(u7f49Len != 64) { return STATUS_FAILED; } if((UINT16)(read_buf[offset]<<8|read_buf[offset+1]) == 0x7f49) { tag5f37Len = read_buf[offset+2]; if(read_buf[offset+3] != 0x86 || (read_buf[offset+4] != 65)) { return STATUS_FAILED; } } else { return STATUS_FAILED; } pTranscv_Info->sSendData[4] = tag7f49Off; memcpy(&(pTranscv_Info->sSendData[5]), &read_buf[0], tag7f49Off); pTranscv_Info->sSendlength = tag7f49Off+5; ALOGD("%s: start transceive for length %ld", fn, pTranscv_Info->sSendlength); status = ALA_SendtoAla(Os_info, status, pTranscv_Info,LS_Default); if(status != STATUS_OK) { UINT8* RecvData = pTranscv_Info->sRecvData; Write_Response_To_OutFile(Os_info, RecvData, resp_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("%s: start transceive for length %ld", fn, pTranscv_Info->sSendlength); status = ALA_SendtoAla(Os_info, status, pTranscv_Info,LS_Cert); if(status != STATUS_OK) { return status; } else { ALOGD("Certificate is verified"); certf_found = STATUS_OK; return status; } } else { return STATUS_FAILED; } } else { return STATUS_FAILED; } } return status; } /******************************************************************************* ** ** 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 ** *******************************************************************************/ tJBL_STATUS Check_Complete_7F21_Tag(Ala_ImageInfo_t *Os_info, Ala_TranscieveInfo_t *pTranscv_Info, UINT8 *read_buf, UINT16 *offset) { static const char fn[] = "Check_Complete_7F21_Tag"; UINT8 tag45Len = 0; if(STATUS_OK == Check_Certificate_Tag(read_buf, offset)) { if(STATUS_OK == Check_SerialNo_Tag(read_buf, offset)) { if(STATUS_OK == Check_LSRootID_Tag(read_buf, offset)) { if(STATUS_OK == Check_CertHoldID_Tag(read_buf, offset)) { if(STATUS_OK == Check_Date_Tag(read_buf, offset)) { UINT8 tag45Len = 0; if(STATUS_OK == Check_45_Tag(read_buf, offset, &tag45Len)) { if(STATUS_OK == Certificate_Verification( Os_info, pTranscv_Info, read_buf, offset, &tag45Len)) { return STATUS_OK; } }else{ ALOGE("%s: FAILED in Check_45_Tag", fn);} }else{ ALOGE("%s: FAILED in Check_Date_Tag", fn);} }else{ ALOGE("%s: FAILED in Check_CertHoldID_Tag", fn);} }else{ ALOGE("%s: FAILED in Check_LSRootID_Tag", fn);} }else{ ALOGE("%s: FAILED in Check_SerialNo_Tag", fn);} } else { ALOGE("%s: FAILED in Check_Certificate_Tag", fn); } return STATUS_FAILED; } BOOLEAN ALA_UpdateExeStatus(UINT16 status) { fLS_STATUS = fopen(LS_STATUS_PATH, "w+"); ALOGD("enter: ALA_UpdateExeStatus"); if(fLS_STATUS == NULL) { ALOGE("Error opening LS Status file for backup: %s",strerror(errno)); return FALSE; } if((fprintf(fLS_STATUS, "%04x",status)) != 4) { ALOGE("Error updating LS Status backup: %s",strerror(errno)); fclose(fLS_STATUS); return FALSE; } ALOGD("exit: ALA_UpdateExeStatus"); fclose(fLS_STATUS); return TRUE; } /******************************************************************************* ** ** Function: ALA_getAppletLsStatus ** ** Description: Interface to fetch Loader service Applet status to JNI, Services ** ** Returns: SUCCESS/FAILURE ** *******************************************************************************/ tJBL_STATUS ALA_getAppletLsStatus(Ala_ImageInfo_t *Os_info, tJBL_STATUS status, Ala_TranscieveInfo_t *pTranscv_Info) { static const char fn[] = "ALA_getAppletLsStatus"; bool stat = false; INT32 recvBufferActualSize = 0; IChannel_t *mchannel = gpAla_Dwnld_Context->mchannel; ALOGD("%s: enter", fn); if(Os_info == NULL || pTranscv_Info == NULL) { ALOGD("%s: Invalid parameter", fn); } else { pTranscv_Info->sSendData[0] = STORE_DATA_CLA | Os_info->Channel_Info[0].channel_id; pTranscv_Info->timeout = gTransceiveTimeout; pTranscv_Info->sSendlength = (INT32)sizeof(GetData); pTranscv_Info->sRecvlength = 1024;//(INT32)sizeof(INT32); memcpy(&(pTranscv_Info->sSendData[1]), &GetData[1], ((sizeof(GetData))-1)); ALOGD("%s: Calling Secure Element Transceive with GET DATA apdu", fn); stat = mchannel->transceive (pTranscv_Info->sSendData, pTranscv_Info->sSendlength, pTranscv_Info->sRecvData, pTranscv_Info->sRecvlength, recvBufferActualSize, pTranscv_Info->timeout); if((stat != TRUE) && (recvBufferActualSize == 0x00)) { status = STATUS_FAILED; ALOGE("%s: SE transceive failed status = 0x%X", fn, status); } else if((pTranscv_Info->sRecvData[recvBufferActualSize-2] == 0x90) && (pTranscv_Info->sRecvData[recvBufferActualSize-1] == 0x00)) { ALOGE("STORE CMD is successful"); if((pTranscv_Info->sRecvData[0] == 0x46 )&& (pTranscv_Info->sRecvData[1] == 0x01 )) { if((pTranscv_Info->sRecvData[2] == 0x01)) { lsGetStatusArr[0]=0x63;lsGetStatusArr[1]=0x40; ALOGE("%s: Script execution status FAILED", fn); } else if((pTranscv_Info->sRecvData[2] == 0x00)) { lsGetStatusArr[0]=0x90;lsGetStatusArr[1]=0x00; ALOGE("%s: Script execution status SUCCESS", fn); } else { lsGetStatusArr[0]=0x90;lsGetStatusArr[1]=0x00; ALOGE("%s: Script execution status UNKNOWN", fn); } } else { lsGetStatusArr[0]=0x90;lsGetStatusArr[1]=0x00; ALOGE("%s: Script execution status UNKNOWN", fn); } status = STATUS_SUCCESS; } else { status = STATUS_FAILED; } ALOGE("%s: exit; status=0x%x", fn, status); } return status; } /******************************************************************************* ** ** Function: Get_LsStatus ** ** Description: Interface to fetch Loader service client status to JNI, Services ** ** Returns: SUCCESS/FAILURE ** *******************************************************************************/ tJBL_STATUS Get_LsStatus(UINT8 *pStatus) { tJBL_STATUS status = STATUS_FAILED; UINT8 lsStatus[2] = {0x63,0x40}; UINT8 loopcnt = 0; fLS_STATUS = fopen(LS_STATUS_PATH, "r"); if(fLS_STATUS == NULL) { ALOGE("Error opening LS Status file for backup: %s",strerror(errno)); return status; } for(loopcnt=0;loopcnt<2;loopcnt++) { if((FSCANF_BYTE(fLS_STATUS, "%2x", &lsStatus[loopcnt])) == 0) { ALOGE("Error updating LS Status backup: %s",strerror(errno)); fclose(fLS_STATUS); return status; } } ALOGD("enter: ALA_getLsStatus 0x%X 0x%X",lsStatus[0],lsStatus[1] ); memcpy(pStatus, lsStatus, 2); fclose(fLS_STATUS); return STATUS_OK; } #endif